Commit Graph

12 Commits

Author SHA1 Message Date
jgrusewski
9aad6ff60e refactor: remove max_training_steps_per_epoch — always train full dataset
Epoch duration self-balances: bigger GPU → bigger auto-scaled batch →
fewer steps per epoch. The manual cap created 7 different values
(0, 8, 64, 100, 200, 300, 2000) across configs/tests/examples, making
behavior inconsistent between environments.

Removed from: DQNHyperparameters, training profiles (smoketest,
localdev, production), CLI args, Argo templates, hyperopt adapter,
all test overrides, supervised example.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 14:41:16 +02:00
jgrusewski
f6caf61252 fix(training): 4 metric quality fixes — buffer, episodes, hyperopt, Q-stats
1. Localdev config: gpu_n_episodes 32→64, gpu_timesteps 100→200
   (12,800 exp/epoch, 4x more → stable Sharpe estimation)

2. Localdev config: buffer_size 10K→50K, min_replay_size 100→500
   (fills over ~4 epochs instead of <1, reduces overfitting)

3. Hyperopt: added CampaignConfig::dqn_localdev() (10 trials × 20 epochs),
   updated test_local_hyperopt to use it with env var overrides
   (FOXHUNT_HYPEROPT_TRIALS, FOXHUNT_HYPEROPT_EPOCHS)

4. Q-value range: was [X,X] every epoch because:
   - train_step.rs Q-stats code was DEAD (training loop uses
     fused.run_full_step() directly, not self.train_step())
   - Only sampled 10 experiences for Q-stats (tiny batch → tight range)
   Fix: reduce_current_q_stats() reads the training batch's q_out_buf
   directly (64 samples, no extra forward pass), wired into the training
   loop's inner step. q_stats_kernel.cu converted to f32 arithmetic.
   Now shows real variation: [-5.25, 5.03] instead of [2.80, 2.80]

Removed dead Q-estimation code from train_step.rs (was never reached
in the fused GPU training path).

11/11 smoke tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:06:09 +02:00
jgrusewski
d485dde5a2 fix: eliminate NVRTC, fix evaluator SIGSEGV, 22D search space, trade physics
Major changes:
- Eliminate ALL runtime NVRTC: c51_loss + mse_loss kernels converted to
  precompiled cubins with runtime num_atoms/v_min/v_max/branch params
- Fix evaluator SIGSEGV: rng_states/q_gaps sized for chunked batch (cn)
  not n_windows; NULL pointer guard in action_select kernel
- Add trade_physics.cuh shared header for train/eval consistency
- Add equity circuit breaker (25% DD from peak) + margin-aware position cap
- Consolidate 46D→22D hyperopt search space, enable ensemble by default
- Fix trade counting: use exposure index not factored action
- Fix Calmar overflow: clamp to ±100 in kernel
- Softer CVaR penalty (cap 3.0 not 10.0) for undertrained models
- Fix win_rate display (ratio→percentage)
- Remove dead code (normalize_reward, calculate_completion_penalty)
- Add tracing subscriber to hyperopt test for visible metrics
- Per-chunk sync in evaluator for reliable error reporting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 00:33:05 +01:00
jgrusewski
65cc0175ac fix: attention kernel shared memory underallocation — hardcoded [128] vs dynamic d
Forward kernel has shared_concat[128] (512 bytes) but Rust allocated d*4
bytes. With d=72: 288 < 512 → shared memory overflow. Same for backward
(concat[128] + d_proj[128] = 1024 bytes vs d*8).

Fix: use d.max(128) for shared memory sizing.
Also: revert c51/mse to runtime NVRTC (NUM_ATOMS controls loop bounds).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 08:39:09 +01:00
jgrusewski
4ab8ca0162 fix: parameterize IQN_SHARED_H1 + IQN_HIDDEN in all 9 IQN kernels
Build-time #define was 256 but runtime config can be 128 (hidden_dim_base).
Caused CUDA_ERROR_ILLEGAL_ADDRESS in IQN trunk gradient. Now passed as
kernel params matching the STATE_DIM parameterization pattern.

Also: warn→error for training failures in optimizer, eprintln for debugging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 01:55:52 +01:00
jgrusewski
b555aafe77 feat: wire MBP-10 + trades data into hyperopt campaign config
Adds mbp10_data_dir and trades_data_dir to CampaignConfig, passed to
DQNTrainer via with_ofi_data_dirs(). Enables OFI features (VPIN,
Kyle's Lambda, etc.) in hyperopt campaigns. dqn_full() now defaults
to 50 epochs/trial for baseline runs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 20:38:56 +01:00
jgrusewski
80f701f5d4 wip: hyperopt adapter needs update for removed use_ fields + new reward_scale
The DQNTrainer adapter in hyperopt silently returns penalty (1000000)
because build_hyperparams() fails with the cleaned config struct.
Needs: update DQNParams→DQNHyperparameters mapping for removed use_
booleans and new reward_scale field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 10:44:40 +01:00
jgrusewski
04d8802c94 refactor: remove 8 always-on use_ booleans — features are mandatory
Remove use_double_dqn, use_dueling, use_per, use_branching,
use_distributional, use_noisy_nets, use_huber_loss, and use_cql
from DQNConfig, DQNHyperparameters, and DqnParams structs.

These features are always enabled (Rainbow DQN standard). The boolean
flags were dead code — every constructor set them to true, and the
only code paths that set them to false were in tests that disabled
features for simplicity. With the fields removed, the features are
unconditionally active, eliminating ~490 lines of dead configuration.

Key changes:
- Struct field declarations removed from 3 core config structs
- Conditional branches (if use_X { ... } else { ... }) simplified:
  dueling/branching/PER network creation is now unconditional
- Checkpoint metadata hardcodes "true" for backward compatibility
- Hyperopt search space index 11 (use_branching) fixed at 1.0
- TOML/YAML config files cleaned of removed fields
- Tests that toggled these flags updated or rewritten

45 files changed, -487 net lines. Zero new test failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 09:45:54 +01:00
jgrusewski
eceaf45b11 feat: --full mode for 3-phase hyperopt pipeline (BC → RL → Refinement)
- CampaignMode enum: Quick, Standard, Full
- dqn_full() constructor: 20 trials × 100 epochs (covers all 3 phases)
- fxt tune start --full flag: auto-sets 20 trials, 100 epochs
- Phase 1 (BC): MSE warmup + expert demos + DT pretrain
- Phase 2 (RL): all 25 features, C51 ramp, HER
- Phase 3 (Refine): pure C51, shrink-and-perturb

Usage: fxt tune start --model dqn --full --gpu

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:44:41 +01:00
jgrusewski
5e7cb5d9ff fix: backtest metrics — multiplicative compounding, chunked drawdown, per-trade win rate
6 bugs in backtest_metrics_kernel.cu:
1. Additive return accumulation → multiplicative (equity *= 1+r)
2. Absolute drawdown → fractional ((peak-current)/peak)
3. Total return from additive sum → from compounded equity
4. Strided bar processing → consecutive chunks (correct drawdown)
5. (Sharpe unchanged — arithmetic mean is correct)
6. Per-bar win count → per-trade win tracking

Before: Return=17975%, MaxDD=100% (impossible). After: honest metrics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:09:56 +01:00
jgrusewski
33cc076eb3 refactor(ml): move compute primitives to ml-core (5b)
Move optimizers, gradient_accumulation, gradient_utils, cuda_compat,
tensor_ops, and gpu (device config, capabilities, memory profiling) to
ml-core. These are shared compute primitives used by all models.

Also commit module files for core types (common, config, error, model,
traits, types) that were moved from ml to ml-core in task 5a but left
staged without being committed.

Notable changes:
- resolve_batch_size() stays in ml (new batch_size_resolver module)
  because it depends on memory_optimization::auto_batch_size which
  has not yet moved to ml-core
- FactoredAction legacy bridge converted from inherent impl to
  extension trait (FactoredActionLegacy) since FactoredAction is now
  defined in ml-core, not ml
- candle-optimisers added to ml-core dependencies (needed by Adam)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:13:41 +01:00
jgrusewski
9c3d741a08 refactor: restructure repo — crates/, bin/, testing/ layout
Move 17 library crates into crates/, CLI binary into bin/fxt,
consolidate 10 test crates into testing/, split config crate
from deployment config files.

Root directory reduced from 38+ to ~17 directories.
All Cargo.toml paths and build.rs proto refs updated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:56:00 +01:00