feat(dqn-v2): B.2 ISV-driven trade-attempt bonus — novelty at Flat→Positioned
Plan 3 Task 3.
ISV tail-append:
- [71] TRADE_ATTEMPT_RATE_EMA — Flat→Positioned transition rate EMA
(GPU-written by trade_attempt_rate_ema_update, adaptive α)
- [72] TRADE_TARGET_RATE — reference rate, CPU-frozen at epoch 5
- Fingerprint shifted [69,70] → [73,74]; ISV_TOTAL_DIM 71 → 75
Producer kernel (trade_rate_ema_kernel.cu):
- Single-block reduction of flat_to_pos_per_sample [N*L] (no atomicAdd)
- Adaptive EMA: α = α_base × (1 + 0.5 × |clamp(sharpe, -2, 2)|)
- α_base = 0.05 (matches reward_component_ema convention)
- Launched from training_loop alongside reward_component_ema
Consumer (experience_env_step):
- Flat→Positioned site: novelty = max(0, 1 - attempt/target)
- bonus = conviction_core × vol_proxy × novelty
- reward += shaping_scale × bonus; rc[5] captures bonus for ISV[68]
- Explicit freeze gate: target_raw > 1e-6f, so bonus is structurally
inert pre-freeze (prevents spurious novelty=1.0 on epoch-1 when
attempt_rate is still 0)
Epoch-5 freeze (training_loop):
- measured = ISV[TRADE_ATTEMPT_RATE_EMA]; floor at 0.001
- Prevents novelty from sticking at 1.0 post-freeze
StateResetRegistry: both slots registered as FoldReset with per-slot
reset dispatch arms in training_loop's fold-boundary path.
Smoke: multi_fold_convergence passes (fold 2 best Sharpe 87.55 —
slightly above Task 2 baseline 85.6, within noise; bonus inert
in 5-epoch smoke so training matches pre-B.2 baseline as designed).
cargo check clean at 11 warnings baseline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -59,6 +59,8 @@
|
||||
| `trainers/dqn/monitors/reward_component_monitor.rs` | Read-only observer for `reward_component_ema` kernel output (ISV slots 63..69); consumers: HEALTH_DIAG `reward_split` line + `controller_activity` smoke fire-rate tracking | Wired | Plan 3 Task 1 C.2 | — |
|
||||
| `cuda_pipeline/reward_component_ema_kernel.cu` | `GpuExperienceCollector::launch_reward_component_ema_inplace` → `training_loop.rs` (called after `reward_contrib_fractions`, before HEALTH_DIAG); reads `reward_components_per_sample [N*L, 6]`, writes ISV[63..69) adaptive EMA (α=0.05) | Wired | Plan 3 Task 1 C.2 — hot-path (per-step); single-block 6-thread kernel | — |
|
||||
| B.1 Flat opp-cost ISV scaling (`experience_kernels.cu` Flat branch) | `experience_env_step` kernel (Flat position=0, not segment_complete branch); writes `rc[4]` to `reward_components_per_sample`; consumed by `reward_component_ema` → ISV[67] | Wired | Plan 3 Task 2 B.1 — opp-cost multiplied by `isv_signals_ptr[21]` (Q_DIR_ABS_REF_INDEX, EMA of max(|Q_mean|) across direction bins). Self-scaling: as Q magnitudes drift during training, opp-cost tracks proportionally. Floor 1e-3 for cold-start. No tuned multiplier. | — |
|
||||
| `cuda_pipeline/trade_rate_ema_kernel.cu` | `GpuExperienceCollector::launch_trade_attempt_rate_ema_inplace` → `training_loop.rs` (called alongside `launch_reward_component_ema_inplace` each epoch); reads `flat_to_pos_per_sample [N*L]`, reduces count on-GPU, writes ISV[TRADE_ATTEMPT_RATE_EMA_INDEX=71] adaptive EMA (α=α_base × (1+0.5×\|sharpe\|), α_base=0.05) | Wired | Plan 3 Task 3 B.2 — cold-path (per-epoch); single-block 1-thread reduction + EMA. No atomicAdd. | — |
|
||||
| B.2 Flat→Positioned novelty bonus (`experience_kernels.cu` trade-lifecycle block) | `experience_env_step` kernel (entering_trade path, AFTER opp-cost branch, BEFORE drawdown penalty); writes `rc[5]` and adds `shaping_scale × bonus` to `reward`; consumed by `reward_component_ema` → ISV[68] and drives PopArt denominator via `total_reward_per_sample` | Wired | Plan 3 Task 3 B.2 — novelty = max(0, 1 − ISV[71]/max(1e-4, ISV[72])); bonus = conviction_core × vol_proxy × novelty; `TRADE_TARGET_RATE` frozen at epoch 5 from measured attempt-EMA (min 0.001). No tuned multiplier. | — |
|
||||
|
||||
## CUDA Pipeline — Rust Wrappers
|
||||
|
||||
@@ -239,18 +241,20 @@ Updated after Task 6 cleanup (2026-04-24): 5 confirmed-orphan files deleted, 3 O
|
||||
|
||||
Plan 3 Task 1 C.2 (2026-04-24): `reward_component_ema_kernel.cu` + `RewardComponentMonitor` added. 6 ISV reward-EMA slots [63..69) allocated; fingerprint shifted [61..63) → [69..71); `ISV_TOTAL_DIM` 63 → 71. `experience_kernels.cu` extended with `reward_components_per_sample [N*L, 6]` output parameter. 2 new Wired rows.
|
||||
|
||||
Plan 3 Task 3 B.2 (2026-04-24): `trade_rate_ema_kernel.cu` added. 2 new ISV slots [71] TRADE_ATTEMPT_RATE_EMA and [72] TRADE_TARGET_RATE; fingerprint shifted [69..71) → [73..75); `ISV_TOTAL_DIM` 71 → 75. `experience_kernels.cu` gains `flat_to_pos_per_sample [N*L]` output + 2 ISV slot-idx scalar parameters; a novelty-scaled bonus (conviction × vol_proxy × novelty) is added to reward and captured in `rc[5]` at every Flat→Positioned transition. TRADE_TARGET_RATE frozen in `training_loop.rs` at epoch 5 from measured attempt-EMA (min 0.001). 2 new Wired rows.
|
||||
|
||||
Plan 1 Tasks 12/15/16 + pre-allocation (2026-04-24): No new modules added. Changes are ISV slot allocation + consumer migration only. Task 15 confirmed no-op (`IQL_BRANCH_SCALE_FLOOR_INDEX` already serves conviction-floor role). Tasks 12 and 16 migrate `cql_alpha` and plan-threshold consumers from config fields / hardcoded literals to ISV slots. 8 new ISV slots allocated ([39..47)); fingerprint tail moves from [37..39) to [47..49); `ISV_TOTAL_DIM` 39 → 49. `GpuDqnTrainConfig` gains `total_epochs` field (written to `TOTAL_EPOCHS_INDEX` at construction). `write_isv_signal_at` bound extended from `ISV_DIM` to `ISV_TOTAL_DIM` to allow writes beyond slot 22.
|
||||
|
||||
Plan 2 Task 6B D.3 (2026-04-24): IQL value head widened from 1 to 2 outputs (V_short + V_long). `v_out_buf` shape `[B]` → `[B*2]`. `gemm_fwd_v` M=1→2, `gemm_bwd_dw3` M=1→2, `gemm_bwd_dh2` K=1→2. `W3` param block `[H*1]` → `[H*2]`, `b3` `[1]` → `[2]`. `total_params` += H+1. `iql_expectile_loss` kernel extended with `num_heads` argument. 4 consumer kernels in `iql_value_kernel.cu` updated to read `v_out[b*2+0] + v_out[b*2+1]`. Checkpoint compat break — retrain required.
|
||||
|
||||
| Classification | Count |
|
||||
|---|---|
|
||||
| Wired | 77 |
|
||||
| Wired | 79 |
|
||||
| Partial | 10 |
|
||||
| Orphan (held for follow-up) | 3 |
|
||||
| Ghost | 0 |
|
||||
| OUT-of-DQN-scope | 17 |
|
||||
| **Total** | **107** |
|
||||
| **Total** | **109** |
|
||||
|
||||
The 3 remaining Orphan rows are:
|
||||
- `cuda_pipeline/gpu_statistics.rs` + `statistics_kernel.cu` — held for Plan 2 D.2 wire-or-delete decision.
|
||||
|
||||
@@ -15,7 +15,7 @@ at the head would displace those live signals and require shifting every upstrea
|
||||
literal in `experience_kernels.cu`. The fingerprint moves to the new tail each time
|
||||
new slots are appended to the bus.
|
||||
|
||||
**Current `ISV_TOTAL_DIM`:** 71 (Plan 1 + Plan 2 Task 1 C.1 + Plan 2 Task 3 D.2 per-branch gamma + Plan 2 Task 6C D.8 TLOB + Plan 3 Task 1 C.2 reward-component EMAs). Post-full DQN v2 rollout: 72.
|
||||
**Current `ISV_TOTAL_DIM`:** 75 (Plan 1 + Plan 2 Task 1 C.1 + Plan 2 Task 3 D.2 per-branch gamma + Plan 2 Task 6C D.8 TLOB + Plan 3 Task 1 C.2 reward-component EMAs + Plan 3 Task 3 B.2 trade-attempt novelty). Post-full DQN v2 rollout: 75+.
|
||||
|
||||
| Index | Name constant | Type | Producer | Consumers | Reset-category | Notes |
|
||||
|---|---|---|---|---|---|---|
|
||||
@@ -67,8 +67,10 @@ new slots are appended to the bus.
|
||||
| [64] | `REWARD_CF_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|counterfactual reward\| across batch (α=0.05). Zero until Plan 3 B.1. |
|
||||
| [65] | `REWARD_TRAIL_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|trail reward\| across batch (α=0.05). Structural placeholder; populated by Plan 3 B.2. |
|
||||
| [66] | `REWARD_MICRO_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|OFI micro-reward\| across batch (α=0.05). Populated via `rc[3]` in `experience_env_step`. |
|
||||
| [67] | `REWARD_OPP_COST_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|opportunity-cost reward\| across batch (α=0.05). Structural placeholder; populated by Plan 3 C.4. |
|
||||
| [68] | `REWARD_BONUS_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|bonus reward\| across batch (α=0.05). Structural placeholder; populated by Plan 3 D.4. |
|
||||
| [69] | `ISV_LAYOUT_FINGERPRINT_LO_INDEX` | u32 bits (in f32) | construct | check_layout_fingerprint | SchemaContract | Low 32 bits of u64 FNV-1a structural hash. Fail-fast on mismatch — NOT a version number, no migration path. |
|
||||
| [70] | `ISV_LAYOUT_FINGERPRINT_HI_INDEX` | u32 bits (in f32) | construct | check_layout_fingerprint | SchemaContract | High 32 bits of u64 FNV-1a structural hash. |
|
||||
| [71) | (reserved for DQN v2) | | | | | Allocated incrementally by Plans 3-5 |
|
||||
| [67] | `REWARD_OPP_COST_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|opportunity-cost reward\| across batch (α=0.05). Populated by Plan 3 B.1 at the Flat-branch opp-cost site. |
|
||||
| [68] | `REWARD_BONUS_EMA_INDEX` | f32 | GPU `reward_component_ema` kernel (Plan 3 C.2) | HEALTH_DIAG `reward_split`, `RewardComponentMonitor` | FoldReset | EMA of mean \|bonus reward\| across batch (α=0.05). Populated by Plan 3 B.2 at the Flat→Positioned site (rc[5]). |
|
||||
| [71] | `TRADE_ATTEMPT_RATE_EMA_INDEX` | f32 | GPU `trade_attempt_rate_ema_update` kernel (Plan 3 B.2) | `experience_env_step` Flat→Positioned bonus path | FoldReset | EMA of Flat→Positioned transition rate (0..1). Adaptive α = α_base × (1 + 0.5×\|clamp(sharpe, -2, 2)\|). α_base = 0.05. Zero at construction and fold boundary. |
|
||||
| [72] | `TRADE_TARGET_RATE_INDEX` | f32 | CPU `training_loop` (epoch 5 freeze) | `experience_env_step` novelty computation | FoldReset | Reference rate for novelty = max(0, 1 - attempt/target). Frozen at epoch 5 from measured TRADE_ATTEMPT_RATE_EMA (min 0.001). Pre-freeze the slot is 0 and the bonus site gates on `target_raw > 1e-6f`, so the reward term is structurally inert until the freeze fires. |
|
||||
| [73] | `ISV_LAYOUT_FINGERPRINT_LO_INDEX` | u32 bits (in f32) | construct | check_layout_fingerprint | SchemaContract | Low 32 bits of u64 FNV-1a structural hash. Fail-fast on mismatch — NOT a version number, no migration path. Shifted 69→73 by Plan 3 Task 3 B.2. |
|
||||
| [74] | `ISV_LAYOUT_FINGERPRINT_HI_INDEX` | u32 bits (in f32) | construct | check_layout_fingerprint | SchemaContract | High 32 bits of u64 FNV-1a structural hash. Shifted 70→74 by Plan 3 Task 3 B.2. |
|
||||
| [75) | (reserved for DQN v2) | | | | | Allocated incrementally by Plans 3-5 |
|
||||
|
||||
Reference in New Issue
Block a user