Files
foxhunt/ml/examples/inspect_dbn_raw.rs
jgrusewski f5947c2b22 Wave 16S-V11: Bug #8 fix + P2-A/B implementation
Bug #8 (CRITICAL): Fixed action selection frequency catastrophe
- Root cause: execute_action called during training (522,713 orders/epoch)
- Fix: Removed execute_action from experience collection loop (line 928-936)
- Impact: 522,713 → 0 orders/epoch (100% reduction)
- Transaction costs: $338K → $0 (eliminated)
- Test suite: ml/tests/action_selection_frequency_test.rs (3/3 passing)

P2-A: Configurable Initial Capital
- CLI argument: --initial-capital (default: $100K, min: $1K)
- Files modified: trainers/dqn.rs, train_dqn.rs, hyperopt adapter
- Test suite: ml/tests/configurable_capital_test.rs (8/8 passing)
- Supports: Small accounts ($10K), Standard ($100K), Institutional ($500K+)

P2-B: Cash Reserve Requirement
- CLI argument: --cash-reserve-percent (default: 0%, range: 0-100%)
- Reserve enforcement: BUY trades only (SELL always allowed)
- Dynamic reserve adjusts with portfolio value
- Files modified: portfolio_tracker.rs (70 lines), trainers/dqn.rs, train_dqn.rs
- Test suite: ml/tests/cash_reserve_requirement_test.rs (10/10 passing)

Test Status: 21/21 core tests passing (P2-C deferred due to API mismatch)

Wave 16S-V11 Agents:
- Agent #1: Bug #8 investigation (transaction cost analysis)
- Agent #2: P2-A implementation (configurable capital)
- Agent #3: P2-B implementation + test fix (cash reserve)
- Agent #4: Integration validation (certification report)
2025-11-12 23:05:51 +01:00

98 lines
3.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Wave 16S-P3: DBN Raw Price Inspector
// Investigates 60.7% data corruption by examining raw i64 values from DBN files
// Hypothesis: 1e-9 scaling is incorrect, prices might use different scaling factor
use dbn::decode::dbn::Decoder;
use dbn::decode::{DbnMetadata, DecodeRecordRef};
use std::fs::File;
use std::io::BufReader;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let files = vec![
"test_data/ES_FUT_180d.dbn",
"test_data/6E_FUT_180d.dbn",
"test_data/ZN_FUT_180d.dbn",
];
for file_path in files {
println!("\n{}", "=".repeat(80));
println!("📂 File: {}", file_path);
println!("{}", "=".repeat(80));
let file = File::open(file_path)?;
let reader = BufReader::new(file);
let mut decoder = Decoder::new(reader)?;
let metadata = decoder.metadata();
println!("Metadata:");
println!(" Dataset: {:?}", metadata.dataset);
println!(" Schema: {:?}", metadata.schema);
println!(" Symbols: {:?}", metadata.symbols);
println!(" SType In: {:?}", metadata.stype_in);
println!(" SType Out: {:?}", metadata.stype_out);
let mut count = 0;
let mut prices_1e9 = Vec::new();
let mut prices_1e_minus_9 = Vec::new();
let mut prices_raw = Vec::new();
loop {
match decoder.decode_record_ref() {
Ok(Some(record)) => {
count += 1;
let record_enum = record.as_enum()?;
if let dbn::RecordRefEnum::Ohlcv(ohlcv) = record_enum {
let close_raw = ohlcv.close;
let close_1e9 = close_raw as f64 * 1e-9;
let close_1e_minus_9 = close_raw as f64 / 1e9; // Alternative interpretation
if count <= 5 {
println!("\nRecord #{}", count);
println!(" Raw i64: {:20} (0x{:016X})", close_raw, close_raw as u64);
println!(" × 1e-9: {:20.10} (current implementation)", close_1e9);
println!(" ÷ 1e9: {:20.10} (alternative)", close_1e_minus_9);
println!(" As cents: {:20.2} (close_raw / 100.0)", close_raw as f64 / 100.0);
println!(" As ticks: {:20.2} (close_raw / 4.0)", close_raw as f64 / 4.0);
}
prices_raw.push(close_raw);
prices_1e9.push(close_1e9);
prices_1e_minus_9.push(close_1e_minus_9);
if count >= 100 {
break;
}
}
}
Ok(None) => break,
Err(e) => return Err(e.into()),
}
}
if !prices_1e9.is_empty() {
println!("\n📊 Statistics (first 100 OHLCV bars):");
println!(" Raw i64 range: {} to {}",
prices_raw.iter().min().unwrap(),
prices_raw.iter().max().unwrap());
println!(" × 1e-9 range: {:.6} to {:.6}",
prices_1e9.iter().cloned().fold(f64::INFINITY, f64::min),
prices_1e9.iter().cloned().fold(f64::NEG_INFINITY, f64::max));
println!(" ÷ 1e9 range: {:.2} to {:.2}",
prices_1e_minus_9.iter().cloned().fold(f64::INFINITY, f64::min),
prices_1e_minus_9.iter().cloned().fold(f64::NEG_INFINITY, f64::max));
// Check for negative raw values
let negative_count = prices_raw.iter().filter(|&&x| x < 0).count();
if negative_count > 0 {
println!("\n ⚠️ WARNING: {} negative raw i64 values found! ({:.1}%)",
negative_count,
(negative_count as f64 / prices_raw.len() as f64) * 100.0);
}
}
}
Ok(())
}