Assertion 7 runs DqnStrategy through ValidationHarness with real
6E.FUT data to verify the full train->validate pipeline works
end-to-end. Produces 15 folds with finite Sharpe ratio.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Assertions verified on real 6E.FUT data:
1. All 20 epochs complete (no premature early stopping)
2. Loss decreases >5% (gradient flow works) — actual: 22.4%
3. All per-epoch losses are finite (no NaN/Inf)
4. Q-value divergence (model develops action preferences)
5. Checkpoint round-trip (save/load weight integrity)
6. Epsilon decayed below 0.5 (exploration schedule ran)
Also fixes divide-by-zero in triple_barrier.rs:103 when
entry_price_cents is zero (guard in both barrier tracker
and trainer caller).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add public accessor methods for smoke test verification:
- loss_history() — per-epoch training loss
- val_loss_history() — per-epoch validation loss
- get_agent_epsilon() — current epsilon from DQN agent
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Single integration test that verifies the complete train → checkpoint →
validate pipeline works on real 6E.FUT data. 7 assertions covering
loss convergence, Q-value divergence, checkpoint round-trip, epsilon
decay, and Sharpe improvement vs untrained baseline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed across 66 files:
- 49 instances of "// use crate::safe_operations; // DISABLED"
- 11 instances of "// use error_handling::{...}; // crate doesn't exist"
- 2 instances of "// use crate::Optimizer; // not available"
- 5 disabled test placeholder blocks (/* ... */) in ensemble/
- 1 disabled From impl in lib.rs (38 lines)
- 1 disabled test module in model.rs (113 lines)
- 1 disabled code block in integration/distillation.rs (41 lines)
- Various other disabled imports with explanation comments
All of this code references modules/crates that were removed during
prior refactoring waves and is preserved in git history. Removing it
reduces noise and makes the codebase easier to navigate.
1922 lib tests passing, compilation clean.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PPO's circuit_breaker.rs was a 276-line copy-paste of DQN's version
(only difference: "PPO" vs "DQN" in log messages). Since ppo/ppo.rs
already imports from dqn::circuit_breaker, the PPO copy was dead code.
Replace with a 6-line re-export module. Tests still pass via the
canonical DQN implementation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removes dead code across 28 files:
- 31 commented-out "DISABLED" import lines (mostly safe_operations, error_handling)
- Commented-out module declarations in lib.rs (deployment, model_loader_integration, tests)
- Commented-out re-exports in lib.rs (training_pipeline, deployment::ModelVersion)
- Commented-out adaptive strategy modules in regime/mod.rs
All are in git history if ever needed. Net -74 lines removed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces ml/src/types/ohlcv.rs as the single source of truth for
OHLCVBar (DateTime<Utc>, f64). Replaces 13 identical struct definitions
scattered across features/, regime/, real_data_loader, and evaluation/.
The f32 backtesting variant in evaluation/metrics.rs is renamed to
OHLCVBarF32 to distinguish it from the canonical type. The regime_adx.rs
i64-timestamp variant was safely migrated since its timestamp field was
never accessed. The orchestrator's Bar alias is replaced with OHLCVBar.
39 files changed, -151 net lines removed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Created ml/src/types/ohlcv.rs as the single source of truth for OHLCVBar
(DateTime<Utc> timestamp, f64 OHLCV fields). Replaced all 13 duplicate
definitions across features/, regime/, real_data_loader, and evaluation/
with imports from crate::types::OHLCVBar.
Key changes:
- New: ml/src/types/mod.rs + ohlcv.rs with canonical OHLCVBar
(derives: Debug, Clone, Copy, PartialEq, Serialize, Deserialize + Default)
- Renamed: evaluation::metrics::OHLCVBar → OHLCVBarF32 (genuinely
different type: f32 fields, i64 timestamp for compact backtesting)
- Eliminated all import aliases (ExtractionOHLCVBar, RegimeOHLCVBar,
PriceOHLCVBar, VolumeOHLCVBar) in dbn_sequence_loader.rs and pipeline.rs
- Renamed regime::orchestrator::Bar → OHLCVBar (same fields, just aliased)
- Updated 39 files total (13 definitions removed, imports normalized)
1883 lib tests passing, compilation clean.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Runs full ValidationHarness on actual Databento 6E.FUT 1-minute OHLCV
bars (~30k bars). Extracts 15-dim features (5 OHLCV + 10 technical
indicators), configures DQN with walk-forward validation, and prints
a detailed report including DSR, PBO, permutation test, and per-regime
breakdown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Critical fixes found during pre-GPU-test code audit:
- DSR SE formula: (kurt-1)/4 → kurt/4 for excess kurtosis input
- PBO CSCV: replace circular fold ranking with IS/OOS mean comparison
- DqnStrategy evaluate: fix off-by-one (loop over returns, not bars)
- DqnStrategy action mapping: handle small num_actions (3→5) directly
instead of FactoredAction decomposition (which maps all to Short100)
- Walk-forward: document rolling window as deliberate design choice
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move validation.rs to validation/financial.rs, create validation/mod.rs
with re-exports for backward compatibility, and remove orphan
numerical_tests.rs that referenced nonexistent types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fixed τ=0.005 Polyak averaging with cosine-annealed EMA schedule
(BYOL/MoCo v3). τ(t) = τ_final - (τ_final - τ_base)·(cos(πt/T)+1)/2.
Early training: τ ≈ 0.005 (fast adaptation while model is learning)
Late training: τ ≈ 0.0005 (stability to prevent bootstrap error drift)
This is critical for offline RL — fixed τ causes target drift that
accumulates over training since we can't collect corrective data.
CQL handles Q-value overestimation; annealed EMA handles target stability.
New config fields: tau_final, tau_anneal_steps. Set tau_anneal_steps=0
to revert to fixed τ behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 3 integration tests verifying the complete IQN+CQL training pipeline:
full training loop with both features, IQN-only mode, and CVaR risk-aware
action selection. Module re-exports for QuantileConfig/QuantileNetwork
were already present from Wave 26.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add copy_weights_from() to QuantileNetwork for target sync. Wire IQN
target updates into both Polyak averaging (soft) and hard copy (legacy)
update paths in train_step(). Also fix agent.rs tests that still
referenced state_dim=52 after consolidation to 51.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire IQN into select_action() greedy branch. When use_iqn is enabled,
computes quantile-based Q-values via uniform quantile sampling. CVaR mode
(use_cvar_action_selection) optimizes for worst-case outcomes instead of
mean, providing risk-averse action selection for conservative trading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 3-way loss branch in train_step(): IQN > C51 > scalar. The IQN path
implements Dabney et al. 2018b using quantile Huber loss — no scatter_add
needed (bypasses Candle BUG #36). Also adds get_state_embedding() helper
to extract base Q-network hidden layer outputs for IQN, stores VarMap in
QuantileNetwork for optimizer access, and includes IQN vars in optimizer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add iqn_network and iqn_target_network as Option<QuantileNetwork> fields
to the DQN struct. When use_iqn is enabled, DQN::new() creates both networks
with QuantileConfig derived from DQNConfig (embed_dim from last hidden layer).
Each network gets its own VarMap for independent parameter tracking.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix NaN panic at dqn.rs:1716 with unwrap_or(Ordering::Equal)
- Fix Adam epsilon 1e-8 → 1.5e-4 per Hessel et al. 2018
- Remove duplicate DistributionalType enum from quantile_regression.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Research-validated design for fixing critical DQN issues:
- CQL regularization for offline RL training on historical data
- IQN integration replacing broken C51 (Candle scatter_add bug)
- CVaR risk-aware action selection
- State dimension consolidation (51 is canonical)
- NaN panic fix, Adam epsilon fix per Rainbow paper
Verified against 20+ papers and 2026 SOTA.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract ~1,300 lines from the 4,755-line trainer.rs into four focused
sub-modules to improve maintainability and code navigation:
- monitoring.rs (290 lines): TrainingMonitor for per-epoch reward,
action, and Q-value tracking with health validation
- data_loading.rs (719 lines): Parquet/DBN data loading, MBP-10 OFI
integration, feature caching, and preprocessing pipeline
- risk.rs (145 lines): Volatility-adjusted epsilon, risk-adjusted
rewards, Kelly criterion sizing, and risk tracker updates
- features.rs (211 lines): Full feature extraction (51-dim), feature
statistics calculation, z-score normalization, synthetic features
All public API paths preserved via mod.rs re-exports. Fields accessed
across module boundaries changed to pub(crate) visibility.
Verified: cargo check --workspace (0 errors), cargo test -p ml --lib
(1,817 passed, 0 failed).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dimension was reduced from 54 to 51 in WAVE 10. All usages now
use FeatureVector ([f64; 51]) directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Delete lib_test.rs (no mod declaration — true orphan)
- Delete dqn/tests/factored_integration_tests.rs (not declared in tests/mod.rs)
- Delete hyperopt/adapters/tests/ (not declared in adapters/mod.rs)
- Delete integration_test.rs, test_common.rs, test_fixtures.rs (declared
in lib.rs but had zero imports — dead code that compiles but nobody uses)
- Inline test symbol data that was pulled from test_fixtures
- Remove include!("tests/dqn_wave26_params_test.rs") from hyperopt dqn adapter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Files had zero imports across the entire workspace:
- error_consolidated.rs, operations.rs, operations_safe.rs, ops_production.rs
- dqn/multi_step_new.rs, reward_elite.rs, reward_coordinator.rs
- dqn/intrinsic_rewards.rs, reward_simple_pnl.rs, reward_sharpe_tests.rs
- dqn/reward/tests/ (orphaned duplicate)
Also removed 5 dead pub mod declarations from lib.rs and dqn/mod.rs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove 1,307 AI-generated markdown files (984 in docs/, 323 in archive/).
No code references these files. Plans directory preserved.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
16-task bottom-up execution plan with exact file paths, commands,
and safety gates. Covers: doc purge, dead code removal, module
consolidation, test reorganization, file splitting, and folder
restructuring.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comprehensive cleanup plan covering: documentation purge, dead code
removal (~4,846 lines across 11 files), module consolidation,
test reorganization, large file splitting, and folder restructuring.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements critical P0.1 gap from DQN 2025 upgrade roadmap to address
overfitting in hyperopt/trainer by enabling proper weight decay in AdamW.
Changes:
- Add weight_decay field to DQNHyperparameters (default: 1e-4)
- Wire weight_decay to AdamW via Decay::DecoupledWeightDecay at 3 optimizer
initialization points in agent.rs
- Expand hyperopt search space to 40D with weight_decay [1e-5, 1e-3] log scale
- Update from_continuous(), to_continuous(), param_names() for roundtrip
This enables the modern best practice of decoupled weight decay (AdamW paper)
which prevents co-adaptation of network weights and improves generalization.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add comprehensive logging utilities for DQN training with best practices:
- LoggingConfig: Configurable log levels, intervals, and sampling rates
- MetricsAggregator: Windowed statistics (mean, std_dev) for training metrics
- SampledLogger: Rate-limited logging for high-frequency events
Key features:
- Structured logging with tracing crate (info/debug/trace hierarchy)
- 23 unit tests for full coverage
- Integration with existing DQN training pipeline
Bug fixes:
- Fix u8 overflow in prioritized_replay.rs test (500 > u8::MAX)
- Fix GradStore assertion in residual.rs (no is_empty method)
- Fix Tensor::get() Option/Result handling in quantile_regression.rs
- Fix Device PartialEq comparison in ensemble_network.rs
Documentation:
- Add Rust logging best practices guide for ML training
- Add DQN logging analysis and design summary
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update DQN trainer with gradient collapse detection warmup
- Add portfolio tracker improvements
- Include hyperopt trial results (multiple Sharpe ratio experiments)
- Add new test files for action/position sign convention, early stopping,
cash reserve bugs, and portfolio execution
- Update trained model files
- Add Claude Code configuration and skills
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
WAVE 24: Gradient collapse threshold too strict for cold start
Problem: 100-epoch runs terminated at step 5 due to false gradient collapse
detection despite using verified hyperparameters (LR=6.6e-5, Sharpe 2.0203)
Root Cause: Threshold (0.006615 = 0.1 × LR × 1000) expects large gradients
from step 1, but cold-start training has naturally small norms (0.0001-0.001)
during replay buffer filling
Solution: Skip gradient collapse check for first 20% of buffer capacity
- Warmup steps = replay_buffer_capacity × 0.2
- Example: 54,255 buffer → 10,851 warmup steps
- Check activates only after sufficient experience collected
Fix Location: ml/src/dqn/dqn.rs line 1691
- Changed: self.config.buffer_size (doesn't exist on WorkingDQNConfig)
- To: self.config.replay_buffer_capacity (correct field, cast to u64)
Validation:
- Quick test (15 epochs): ✅ PASSED - zero gradient collapse warnings
- Full test (100 epochs): ✅ PASSED - no false positive at step 5
- Warmup period correctly deferred check until step 10,851
Impact: Unblocks 100-epoch+ production training runs
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Added WAVE 23 section to Recent Updates with all three priorities:
- Early Stopping Termination Bug (FIXED)
- 80/20 Train/Test Split (VERIFIED WORKING)
- MBP-10 Feature Caching (COMPLETE)
Updated system status header with Feature Caching and Early Stopping status.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>