CRITICAL FINDINGS from 3-trial validation: - 85,120 gradient clipping warnings (81.6% of logs) - REGRESSION - Rainbow features DISABLED: use_dueling=false, use_distributional=false, use_noisy_nets=false - Negative Q-values confirmed: HOLD -1000 to -3250 - Performance: Sharpe 0.29 (target 0.77) Changes: - Fixed N-Step compilation (7/7 tests passing) - Fixed Distributional compilation (6/6 tests passing) - Fixed Dueling CUDA errors (10/10 tests passing) - Added TDD validation for state_dim=225 - Total: 23/23 Wave 11 tests passing (100%) Issues requiring investigation: 1. Why are Dueling/Distributional/Noisy disabled in hyperopt? 2. Why gradient explosion despite previous fixes? 3. Test coverage gaps - unit tests pass but integration fails 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
89 lines
3.4 KiB
Rust
89 lines
3.4 KiB
Rust
//! Transaction Cost Tests for PPO
|
|
//!
|
|
//! Test-driven development (TDD) - Tests written FIRST before implementation.
|
|
//! These tests verify that PPO transaction cost calculations match DQN behavior.
|
|
|
|
use ml::ppo::transaction_costs::{calculate_transaction_cost, OrderType};
|
|
|
|
#[test]
|
|
fn test_transaction_cost_maker_fee() {
|
|
// LimitMaker: 0.05% (0.0005)
|
|
let trade_value = 10_000.0; // $10,000 trade
|
|
let cost = calculate_transaction_cost(OrderType::LimitMaker, trade_value);
|
|
|
|
// Expected: 0.0005 * 10,000 = $5.00
|
|
assert_eq!(cost, 5.0, "LimitMaker fee should be 0.05%");
|
|
|
|
// Test larger trade
|
|
let large_trade = 100_000.0; // $100K trade
|
|
let large_cost = calculate_transaction_cost(OrderType::LimitMaker, large_trade);
|
|
assert_eq!(large_cost, 50.0, "LimitMaker fee on $100K should be $50");
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_cost_taker_fee() {
|
|
// Market: 0.15% (0.0015)
|
|
let trade_value = 10_000.0; // $10,000 trade
|
|
let cost = calculate_transaction_cost(OrderType::Market, trade_value);
|
|
|
|
// Expected: 0.0015 * 10,000 = $15.00
|
|
assert_eq!(cost, 15.0, "Market fee should be 0.15%");
|
|
|
|
// Test smaller trade
|
|
let small_trade = 1_000.0; // $1K trade
|
|
let small_cost = calculate_transaction_cost(OrderType::Market, small_trade);
|
|
assert_eq!(small_cost, 1.5, "Market fee on $1K should be $1.50");
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_cost_ioc_fee() {
|
|
// IoC (Immediate-or-Cancel): 0.10% (0.0010)
|
|
let trade_value = 10_000.0; // $10,000 trade
|
|
let cost = calculate_transaction_cost(OrderType::IoC, trade_value);
|
|
|
|
// Expected: 0.0010 * 10,000 = $10.00
|
|
assert_eq!(cost, 10.0, "IoC fee should be 0.10%");
|
|
|
|
// Test edge case: zero trade value
|
|
let zero_cost = calculate_transaction_cost(OrderType::IoC, 0.0);
|
|
assert_eq!(zero_cost, 0.0, "Zero trade value should have zero cost");
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_cost_negative_trade_value() {
|
|
// Transaction costs should be based on absolute value
|
|
let trade_value = -10_000.0; // Negative trade value (shouldn't happen, but test defensively)
|
|
let cost = calculate_transaction_cost(OrderType::Market, trade_value);
|
|
|
|
// Expected: 0.0015 * |-10,000| = $15.00
|
|
assert_eq!(cost, 15.0, "Transaction cost should use absolute trade value");
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_cost_fee_ordering() {
|
|
// Verify fee ordering: Market (0.15%) > IoC (0.10%) > LimitMaker (0.05%)
|
|
let trade_value = 10_000.0;
|
|
|
|
let market_cost = calculate_transaction_cost(OrderType::Market, trade_value);
|
|
let ioc_cost = calculate_transaction_cost(OrderType::IoC, trade_value);
|
|
let maker_cost = calculate_transaction_cost(OrderType::LimitMaker, trade_value);
|
|
|
|
assert!(market_cost > ioc_cost, "Market fee should be higher than IoC");
|
|
assert!(ioc_cost > maker_cost, "IoC fee should be higher than LimitMaker");
|
|
assert_eq!(market_cost, 15.0, "Market: 0.15%");
|
|
assert_eq!(ioc_cost, 10.0, "IoC: 0.10%");
|
|
assert_eq!(maker_cost, 5.0, "LimitMaker: 0.05%");
|
|
}
|
|
|
|
#[test]
|
|
fn test_transaction_cost_large_values() {
|
|
// Test with large trade values to verify no overflow
|
|
let large_trade = 1_000_000.0; // $1M trade
|
|
|
|
let market_cost = calculate_transaction_cost(OrderType::Market, large_trade);
|
|
assert_eq!(market_cost, 1_500.0, "Market fee on $1M should be $1,500");
|
|
|
|
let maker_cost = calculate_transaction_cost(OrderType::LimitMaker, large_trade);
|
|
assert_eq!(maker_cost, 500.0, "LimitMaker fee on $1M should be $500");
|
|
}
|