diff --git a/crates/ml-core/src/state_layout.rs b/crates/ml-core/src/state_layout.rs index 693ace804..af37ad91d 100644 --- a/crates/ml-core/src/state_layout.rs +++ b/crates/ml-core/src/state_layout.rs @@ -53,3 +53,99 @@ const _: () = assert!(PADDING_START + PADDING_DIM == STATE_DIM, "layout must sum const _: () = assert!(STATE_DIM % 8 == 0, "STATE_DIM must be 8-aligned for tensor cores"); const _: () = assert!(STATE_DIM_PADDED % 128 == 0, "STATE_DIM_PADDED must be 128-aligned for cuBLAS"); const _: () = assert!(STATE_DIM <= STATE_DIM_PADDED, "STATE_DIM must fit within padded width"); + +// ──────────────────────────────────────────────────────────────────────────── +// Mirrors of crates/ml/src/cuda_pipeline/state_layout.cuh PS_* constants. +// Task 4A of Plan 1. Invariant 8. +// ──────────────────────────────────────────────────────────────────────────── + +pub const PS_POSITION: usize = 0; // current contract position (signed) +pub const PS_CASH: usize = 1; // cash balance +pub const PS_PORTFOLIO_VALUE: usize = 2; // mark-to-market total (cash + pos*price) +pub const PS_DSR_A: usize = 3; // EMA of realised trade returns (DSR) +pub const PS_DSR_B: usize = 4; // EMA of squared trade returns (DSR) +pub const PS_DSR_TRADE_COUNT: usize = 5; // completed trades counter (DSR warmup) +pub const PS_PREV_CLOSE: usize = 6; // prev bar raw_close for DSR per-bar returns +pub const PS_PEAK_EQUITY: usize = 7; // high-water mark (init to initial_capital) +pub const PS_FLAT_COUNTER: usize = 8; // consecutive flat steps +pub const PS_PREV_EQUITY: usize = 9; // equity at previous step +pub const PS_HOLD_TIME: usize = 10; // consecutive steps with position +pub const PS_REALIZED_PNL: usize = 11; // cumulative realised PnL +pub const PS_ENTRY_PRICE: usize = 12; // price when trade was entered +pub const PS_TRADE_START_PNL: usize = 13; // realized_pnl snapshot at trade entry +pub const PS_KELLY_WIN_COUNT: usize = 14; // Kelly: number of profitable trade exits +pub const PS_KELLY_LOSS_COUNT: usize = 15; // Kelly: number of losing trade exits +pub const PS_KELLY_SUM_WINS: usize = 16; // Kelly: cumulative profit from winners +pub const PS_KELLY_SUM_LOSSES: usize = 17; // Kelly: cumulative |loss| from losers +pub const PS_KELLY_SUM_RETURNS: usize = 18; // Kelly: cumulative net returns (for mu) +pub const PS_KELLY_SUM_SQ_RETURNS: usize = 19; // Kelly: cumulative squared returns (sigma^2) +pub const PS_INTRA_TRADE_MAX_DD: usize = 20; // worst unrealised drawdown during trade (v8) +pub const PS_INTRA_TRADE_MAX_PNL: usize = 21; // best unrealised P&L during trade (hindsight) +pub const PS_PREV_MID: usize = 22; // prev bar MBP-10 mid-price +pub const PS_PLAN_TARGET_BARS: usize = 23; // plan: max hold bars (>0.5 = plan active) +pub const PS_PLAN_PROFIT_TARGET: usize = 24; // plan: raw profit threshold +pub const PS_PLAN_STOP_LOSS: usize = 25; // plan: raw stop threshold +pub const PS_PLAN_SCALE_AGGRESSION: usize = 26; // plan: position ramp speed +pub const PS_PLAN_CONVICTION: usize = 27; // plan: conviction at entry [0,1] +pub const PS_PLAN_ASYMMETRY: usize = 28; // plan: profit/stop asymmetry +pub const PS_PLAN_ENTRY_REGIME: usize = 29; // plan: regime_stability at entry +pub const PS_OFI_PREV_BASE: usize = 30; // first OFI prev-bar slot (stride 8: [30..37]) +pub const PS_STRIDE: usize = 38; // total portfolio state stride (== PORTFOLIO_STRIDE) + +// ──────────────────────────────────────────────────────────────────────────── +// Mirrors of PLAN_ISV_* constants (plan_isv[0..PLAN_ISV_DIM=6)). +// Task 4B of Plan 1. Invariant 8. +// ──────────────────────────────────────────────────────────────────────────── + +pub const PLAN_ISV_PROGRESS: usize = 0; // hold_time / target_bars (clamped to 2.0) +pub const PLAN_ISV_PNL_VS_TARGET: usize = 1; // unrealized / (profit_target × equity) +pub const PLAN_ISV_PNL_VS_STOP: usize = 2; // -unrealized / (stop_loss × equity) +pub const PLAN_ISV_ENTRY_CONVICTION: usize = 3; // conviction at trade entry [0, 1] +pub const PLAN_ISV_CONVICTION_DRIFT: usize = 4; // current conviction − entry conviction +pub const PLAN_ISV_REGIME_SHIFT: usize = 5; // |isv[11] − entry_regime_stability| +pub const PLAN_ISV_DIM: usize = 6; + +// ──────────────────────────────────────────────────────────────────────────── +// Mirrors of PLAN_PARAM_* constants (plan_params[0..PLAN_PARAM_DIM=6)). +// Task 4C of Plan 1. Invariant 8. +// ──────────────────────────────────────────────────────────────────────────── + +pub const PLAN_PARAM_TARGET_BARS: usize = 0; // max hold bars +pub const PLAN_PARAM_PROFIT_TARGET: usize = 1; // raw profit threshold % +pub const PLAN_PARAM_STOP_LOSS: usize = 2; // raw stop loss threshold % +pub const PLAN_PARAM_SCALE_AGGRESSION: usize = 3; // position ramp speed +pub const PLAN_PARAM_CONVICTION: usize = 4; // position size fraction [0, 1] +pub const PLAN_PARAM_ASYMMETRY: usize = 5; // profit/stop ratio +pub const PLAN_PARAM_DIM: usize = 6; + +// ──────────────────────────────────────────────────────────────────────────── +// Mirrors of BRANCH_* constants (4-branch factored action). +// Task 4D of Plan 1. Invariant 8. +// ──────────────────────────────────────────────────────────────────────────── + +pub const BRANCH_DIR: usize = 0; // direction branch (4 actions: Short/Hold/Long/Flat) +pub const BRANCH_MAG: usize = 1; // magnitude branch (3 actions: Quarter/Half/Full) +pub const BRANCH_ORD: usize = 2; // order-type branch (3 actions) +pub const BRANCH_URG: usize = 3; // urgency branch (3 actions) +pub const NUM_BRANCHES: usize = 4; + +// ──────────────────────────────────────────────────────────────────────────── +// Mirrors of DIR_* constants (direction action sub-indices). +// Task 4E of Plan 1. Invariant 8. +// ──────────────────────────────────────────────────────────────────────────── + +pub const DIR_SHORT: usize = 0; // open/maintain short position +pub const DIR_HOLD: usize = 1; // keep current position (no-op) +pub const DIR_LONG: usize = 2; // open/maintain long position +pub const DIR_FLAT: usize = 3; // close all positions to zero +pub const NUM_DIRECTIONS: usize = 4; + +// ──────────────────────────────────────────────────────────────────────────── +// Mirrors of MAG_* constants (magnitude action sub-indices). +// Task 4F of Plan 1. Invariant 8. +// ──────────────────────────────────────────────────────────────────────────── + +pub const MAG_QUARTER: usize = 0; // 0.25× max_position +pub const MAG_HALF: usize = 1; // 0.50× max_position +pub const MAG_FULL: usize = 2; // 1.00× max_position +pub const NUM_MAGNITUDES: usize = 3; diff --git a/crates/ml/src/cuda_pipeline/experience_kernels.cu b/crates/ml/src/cuda_pipeline/experience_kernels.cu index ce1975201..7beadba05 100644 --- a/crates/ml/src/cuda_pipeline/experience_kernels.cu +++ b/crates/ml/src/cuda_pipeline/experience_kernels.cu @@ -1145,11 +1145,11 @@ extern "C" __global__ void experience_action_select( /* Plan direction lock: during active plan, force current direction */ if (portfolio_states != NULL) { int ps_base_plan = i * PORTFOLIO_STRIDE; - int has_plan_active = (portfolio_states[ps_base_plan + 23] > 0.5f); + int has_plan_active = (portfolio_states[ps_base_plan + PS_PLAN_TARGET_BARS] > 0.5f); if (has_plan_active) { - float cur_pos_plan = portfolio_states[ps_base_plan + 0]; - if (cur_pos_plan > 0.001f) dir_idx = 2; /* Long locked */ - else if (cur_pos_plan < -0.001f) dir_idx = 0; /* Short locked */ + float cur_pos_plan = portfolio_states[ps_base_plan + PS_POSITION]; + if (cur_pos_plan > 0.001f) dir_idx = DIR_LONG; + else if (cur_pos_plan < -0.001f) dir_idx = DIR_SHORT; } } @@ -1191,7 +1191,7 @@ extern "C" __global__ void experience_action_select( * how confident the contrarian direction is — useful for position sizing * consistently with the action actually being taken. */ if (out_q_gaps != NULL) { - int flat_idx = 3; /* Flat = index 3 for direction(4): Short(0)/Hold(1)/Long(2)/Flat(3) */ + int flat_idx = DIR_FLAT; /* Flat direction's Q-value index within the 4-way direction branch */ float q_sign_local = (contrarian_active != 0) ? -1.0f : 1.0f; /* Find best action under the (possibly negated) Q. */ int best_idx = 0; diff --git a/docs/dqn-named-dims.md b/docs/dqn-named-dims.md index c0ca84345..d7ac9ae4a 100644 --- a/docs/dqn-named-dims.md +++ b/docs/dqn-named-dims.md @@ -124,3 +124,7 @@ From the trade_plan MLP output. - 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).