# DQN Named Dimensions Registry **Invariant 8 enforcement.** Every semantic index has a named constant. Raw indices (`[0]`, `[6]`, `[23]`) appear ONLY at definition sites. Consumer code always uses the named constant. ## State vector offsets Defined in `crates/ml/src/cuda_pipeline/state_layout.cuh` and mirrored in Rust via `ml-core::state_layout`. | Constant | Value | Meaning | |---|---|---| | `SL_STATE_DIM` | 112 | Total state vector length (D.6 Plan 2 Task 6A: was 104) | | `SL_STATE_DIM_PADDED` | 128 | Padded for cuBLAS K-tile alignment | | `SL_MARKET_DIM` | 42 | Market-feature block width | | `SL_OFI_DIM` | 32 | OFI block width | | `SL_MTF_DIM` | 16 | Multi-timeframe block width | | `SL_PORTFOLIO_BASE_DIM` | 8 | Portfolio-base block width | | `SL_PORTFOLIO_PLAN_DIM` | 7 | Plan-ISV block width (D.6 Plan 2 Task 6A: was 6) | | `SL_MARKET_START` | 0 | | | `SL_OFI_START` | 42 | | | `SL_MTF_START` | 74 | | | `SL_PORTFOLIO_START` | 90 | | | `SL_PLAN_ISV_START` | 98 | | ## Portfolio state slots (ps[0..PS_STRIDE=38)) Defined in `crates/ml/src/cuda_pipeline/state_layout.cuh` (PS_* constants). Consumer code uses the named constants; raw `ps[N]` access outside definition sites is a lint violation (Invariant 8). Slots 3-6 and 22 also carry legacy named aliases in `experience_kernels.cu` (DSR_A_SLOT etc.) retained for in-file use; PS_* names are the canonical cross-file form. | Index | Constant | Meaning | |---|---|---| | 0 | `PS_POSITION` | Current contract position (signed) | | 1 | `PS_CASH` | Cash balance | | 2 | `PS_PORTFOLIO_VALUE` | Mark-to-market total (cash + pos×price) | | 3 | `PS_DSR_A` | EMA of realised trade returns (DSR) | | 4 | `PS_DSR_B` | EMA of squared trade returns (DSR) | | 5 | `PS_DSR_TRADE_COUNT` | Completed trades counter (DSR warmup) | | 6 | `PS_PREV_CLOSE` | Prev bar raw_close for DSR per-bar returns | | 7 | `PS_PEAK_EQUITY` | High-water mark (init to initial_capital) | | 8 | `PS_FLAT_COUNTER` | Consecutive flat steps | | 9 | `PS_PREV_EQUITY` | Equity at previous step | | 10 | `PS_HOLD_TIME` | Consecutive steps with position | | 11 | `PS_REALIZED_PNL` | Cumulative realised PnL | | 12 | `PS_ENTRY_PRICE` | Price when trade was entered | | 13 | `PS_TRADE_START_PNL` | Realised PnL snapshot at trade entry | | 14 | `PS_KELLY_WIN_COUNT` | Kelly: number of profitable trade exits | | 15 | `PS_KELLY_LOSS_COUNT` | Kelly: number of losing trade exits | | 16 | `PS_KELLY_SUM_WINS` | Kelly: cumulative profit from winners | | 17 | `PS_KELLY_SUM_LOSSES` | Kelly: cumulative \|loss\| from losers | | 18 | `PS_KELLY_SUM_RETURNS` | Kelly: cumulative net returns (for mu) | | 19 | `PS_KELLY_SUM_SQ_RETURNS` | Kelly: cumulative squared returns (sigma^2) | | 20 | `PS_INTRA_TRADE_MAX_DD` | Worst intra-trade drawdown (v8 reward) | | 21 | `PS_INTRA_TRADE_MAX_PNL` | Best intra-trade unrealised PnL (hindsight) | | 22 | `PS_PREV_MID` | Prev bar MBP-10 mid-price | | 23 | `PS_PLAN_TARGET_BARS` | plan: max hold bars (>0.5 = plan active) | | 24 | `PS_PLAN_PROFIT_TARGET` | plan: raw profit threshold | | 25 | `PS_PLAN_STOP_LOSS` | plan: raw stop threshold | | 26 | `PS_PLAN_SCALE_AGGRESSION` | plan: position ramp speed | | 27 | `PS_PLAN_CONVICTION` | plan: conviction at entry [0,1] | | 28 | `PS_PLAN_ASYMMETRY` | plan: profit/stop asymmetry | | 29 | `PS_PLAN_ENTRY_REGIME` | plan: regime_stability at entry | | 30-37 | `PS_OFI_PREV_BASE + k` | Prev-bar OFI scratch for delta computation | | 38 | `PS_STRIDE` | Total portfolio state stride (=PORTFOLIO_STRIDE) | ## Plan_isv dimensions (plan_isv[0..7)) D.6 Plan 2 Task 6A landed: 7th dimension `PLAN_ISV_REMAINING_FRACTION` added. These constants live alongside `SL_PLAN_ISV_START` in `state_layout.cuh`. | Index | Constant | Meaning | |---|---|---| | 0 | `PLAN_ISV_PROGRESS` | hold_time / target_bars (clamped 2.0) | | 1 | `PLAN_ISV_PNL_VS_TARGET` | unrealized / (target × equity) | | 2 | `PLAN_ISV_PNL_VS_STOP` | -unrealized / (stop × equity) | | 3 | `PLAN_ISV_ENTRY_CONVICTION` | conviction at entry | | 4 | `PLAN_ISV_CONVICTION_DRIFT` | current conviction − entry conviction | | 5 | `PLAN_ISV_REGIME_SHIFT` | \|isv[11] − entry_stability\| | | 6 | `PLAN_ISV_REMAINING_FRACTION` | max(0, min(1, (target_bars − hold_time) / target_bars)) when plan active, else 0 — temporal pressure signal | ## Plan_params output (plan_params[0..6)) From the trade_plan MLP output. | Index | Constant | Meaning | |---|---|---| | 0 | `PLAN_PARAM_TARGET_BARS` | | | 1 | `PLAN_PARAM_PROFIT_TARGET` | | | 2 | `PLAN_PARAM_STOP_LOSS` | | | 3 | `PLAN_PARAM_SCALE_AGGRESSION` | | | 4 | `PLAN_PARAM_CONVICTION` | | | 5 | `PLAN_PARAM_ASYMMETRY` | | ## Branch indices (4-branch factored action) | Index | Constant | Meaning | |---|---|---| | 0 | `BRANCH_DIR` | Direction branch (4 actions) | | 1 | `BRANCH_MAG` | Magnitude branch (3 actions) | | 2 | `BRANCH_ORD` | Order-type branch (3 actions) | | 3 | `BRANCH_URG` | Urgency branch (3 actions) | ## Direction action sub-indices | Index | Constant | Meaning | |---|---|---| | 0 | `DIR_SHORT` | Open short (or close long + open short) | | 1 | `DIR_HOLD` | Keep current position (no-op on position) | | 2 | `DIR_LONG` | Open long (or close short + open long) | | 3 | `DIR_FLAT` | Close any position to zero | ## Magnitude action sub-indices | Index | Constant | Meaning | |---|---|---| | 0 | `MAG_QUARTER` | 0.25× max_position | | 1 | `MAG_HALF` | 0.50× max_position | | 2 | `MAG_FULL` | 1.00× max_position | ## Branch FC input strides (direction- vs OFI-conditioned) The four branch FC heads (`w_b{0,1,2,3}fc`) and their gate twins (`w_gate_{0,1,2,3}`) have different input strides depending on what each branch concatenates onto the trunk activation: | Branch (d) | Constant role | Input stride | Conditioning | |---|---|---|---| | 0 (Direction) | trunk only | `shared_h2` | none | | 1 (Magnitude) | mag_concat | `shared_h2 + branch_0_size` | direction-conditioned (concat of `h_s2` + per-direction Q values, 4 in production) | | 2 (Order) | ord_concat | `shared_h2 + 3` | OFI-conditioned (concat of `vsn_masked` + 3 OFI features) | | 3 (Urgency) | urg_concat | `shared_h2 + 3` | OFI-conditioned (concat of `vsn_masked` + 3 OFI features) | **Invariant (off-by-one trap).** The `+3` constant is overloaded: in the OFI branches it's a literal (3 features per branch from `concat_ofi_features`), but in the magnitude branch it must derive from `branch_0_size` (since 4-direction S/H/L/F was added). Buffers, weight tensors, GEMM cache shapes, accumulator strides, and dX backward dims all share this contract — see commit fixing mag_concat_qdir OOB (compute-sanitizer caught 1679 errors). Direction-conditioned sites: `w_b1fc`, `w_gate_1`, `mag_concat_buf`, `d_mag_concat_buf`. OFI-conditioned sites: `w_b{2,3}fc`, `w_gate_{2,3}`, `{ord,urg}_concat_buf`, `d_{ord,urg}_concat_buf`. ## Commit history - Task 4A (ps[0..PS_STRIDE) constants): commit 144c85b85 - Task 4B (plan_isv[0..6) constants): commit 741cb48d5 - Task 4C (plan_params[0..6) constants): commit 0ac83479e - Task 4D (BRANCH_* constants): commit 11755632b - Task 4E (DIR_* direction sub-indices): commit c64fde0be - Task 4F (MAG_* magnitude sub-indices): commit 537e18b84 - Task 4 gap-fix (3 review issues): experience_kernels.cu lines 1148-1152 and 1194 missed by sed sweep (ps_base_plan+N syntax), replaced with PS_PLAN_TARGET_BARS/PS_POSITION/DIR_LONG/ DIR_SHORT/DIR_FLAT; ml-core state_layout.rs Rust mirror added for all Task 4 constants (PS_*/PLAN_ISV_*/PLAN_PARAM_*/BRANCH_*/DIR_*/MAG_*, 46 constants total).