refactor(dqn-v2): Task 4 gap-fix — missed sites + Rust mirror
Follow-up to Plan 1 Task 4 sub-commits 4A-4F. Addresses 3 issues
surfaced by code review:
1. experience_kernels.cu:1148-1152 — 4 raw literals missed by Task 4A/4E
sed sweep (the block uses portfolio_states[ps_base_plan + N] syntax
rather than ps[N], so sed targeting \bps\[ didn't match).
Fixes: ps_base_plan + 23 -> PS_PLAN_TARGET_BARS, + 0 -> PS_POSITION,
dir_idx = 2 -> DIR_LONG, dir_idx = 0 -> DIR_SHORT.
2. experience_kernels.cu:1194 — flat_idx = 3 replaced with DIR_FLAT.
3. crates/ml-core/src/state_layout.rs — Rust mirror added for every
Task 4 constant (PS_*, PLAN_ISV_*, PLAN_PARAM_*, BRANCH_*, DIR_*,
MAG_*) matching cuh byte-for-byte. Closes the half-applied Invariant
8 gap for the Rust side.
No behavioural change. Pure refactor.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user