refactor(dqn-v2): Invariant 8 — named constants for plan_params[0..6)

Add PLAN_PARAM_* constants to state_layout.cuh and replace raw
plan_params/pp slot accesses in experience_kernels.cu and
backtest_plan_kernel.cu.

Sites migrated: pp[0..5] in both files (12 sites), plan_params_ptr
indexed accesses at slots 0, 1, 4 in experience_kernels.cu (4 sites),
plan_params[w*6+4] in backtest_plan_kernel.cu (1 site). Loop variable
pp[p] in noisy-plan path left as-is (p is a runtime loop counter, not
a literal slot index).

No behavioural change; pure refactor.

Plan 1 Task 4C. Spec §3 Invariant 8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-04-24 11:22:24 +02:00
parent f36b1bde7a
commit a5a67ad19a
4 changed files with 33 additions and 19 deletions

View File

@@ -118,12 +118,12 @@ extern "C" __global__ void backtest_plan_state_isv(
float active_tgt = plan_state[w * 7 + 0];
if (in_position && active_tgt < 0.5f) {
const float* pp = plan_params + w * 6;
plan_state[w * 7 + 0] = pp[0]; /* target_bars */
plan_state[w * 7 + 1] = pp[1]; /* profit_target */
plan_state[w * 7 + 2] = pp[2]; /* stop_loss */
plan_state[w * 7 + 3] = pp[3]; /* scale_aggression */
plan_state[w * 7 + 4] = pp[4]; /* conviction (at entry) */
plan_state[w * 7 + 5] = pp[5]; /* asymmetry */
plan_state[w * 7 + 0] = pp[PLAN_PARAM_TARGET_BARS]; /* target_bars */
plan_state[w * 7 + 1] = pp[PLAN_PARAM_PROFIT_TARGET]; /* profit_target */
plan_state[w * 7 + 2] = pp[PLAN_PARAM_STOP_LOSS]; /* stop_loss */
plan_state[w * 7 + 3] = pp[PLAN_PARAM_SCALE_AGGRESSION]; /* scale_aggression */
plan_state[w * 7 + 4] = pp[PLAN_PARAM_CONVICTION]; /* conviction (at entry) */
plan_state[w * 7 + 5] = pp[PLAN_PARAM_ASYMMETRY]; /* asymmetry */
plan_state[w * 7 + 6] = (isv_signals != nullptr)
? isv_signals[11] : 1.0f; /* regime_stability at entry */
}
@@ -162,7 +162,7 @@ extern "C" __global__ void backtest_plan_state_isv(
/* [4] Conviction drift: current MLP conviction - entry conviction */
pisv[PLAN_ISV_CONVICTION_DRIFT] = (plan_tgt_bars > 0.5f)
? (plan_params[w * 6 + 4] - plan_conv_ent) : 0.0f;
? (plan_params[w * 6 + PLAN_PARAM_CONVICTION] - plan_conv_ent) : 0.0f;
/* [5] Regime shift magnitude since entry */
pisv[PLAN_ISV_REGIME_SHIFT] = (isv_signals != nullptr && plan_tgt_bars > 0.5f)

View File

@@ -608,7 +608,7 @@ extern "C" __global__ void experience_state_gather(
* Negative drift = model's thesis is weakening → exit signal.
* Only meaningful when a plan is active (ps[PS_PLAN_TARGET_BARS] > 0.5). */
plan_isv[PLAN_ISV_CONVICTION_DRIFT] = (plan_params_ptr != NULL && ps[PS_PLAN_TARGET_BARS] > 0.5f)
? (plan_params_ptr[i * 6 + 4] - ps[PS_PLAN_CONVICTION]) /* conviction drift */
? (plan_params_ptr[i * 6 + PLAN_PARAM_CONVICTION] - ps[PS_PLAN_CONVICTION]) /* conviction drift */
: 0.0f;
/* Regime shift since entry — |regime_stability_now - regime_stability_at_entry|.
@@ -1788,12 +1788,12 @@ extern "C" __global__ void experience_env_step(
if (was_flat_plan && now_positioned_plan && plan_enabled) {
const float* pp = plan_params_ptr + i * 6;
ps[PS_PLAN_TARGET_BARS] = pp[0]; /* target_bars */
ps[PS_PLAN_PROFIT_TARGET] = pp[1]; /* profit_target */
ps[PS_PLAN_STOP_LOSS] = pp[2]; /* stop_loss */
ps[PS_PLAN_SCALE_AGGRESSION] = pp[3]; /* scale_aggression */
ps[PS_PLAN_CONVICTION] = pp[4]; /* conviction */
ps[PS_PLAN_ASYMMETRY] = pp[5]; /* asymmetry */
ps[PS_PLAN_TARGET_BARS] = pp[PLAN_PARAM_TARGET_BARS]; /* target_bars */
ps[PS_PLAN_PROFIT_TARGET] = pp[PLAN_PARAM_PROFIT_TARGET]; /* profit_target */
ps[PS_PLAN_STOP_LOSS] = pp[PLAN_PARAM_STOP_LOSS]; /* stop_loss */
ps[PS_PLAN_SCALE_AGGRESSION] = pp[PLAN_PARAM_SCALE_AGGRESSION]; /* scale_aggression */
ps[PS_PLAN_CONVICTION] = pp[PLAN_PARAM_CONVICTION]; /* conviction */
ps[PS_PLAN_ASYMMETRY] = pp[PLAN_PARAM_ASYMMETRY]; /* asymmetry */
/* Store entry regime_stability for drift detection (P12). */
ps[PS_PLAN_ENTRY_REGIME] = (isv_signals_ptr != NULL) ? isv_signals_ptr[11] : 1.0f;
ps[PS_INTRA_TRADE_MAX_PNL] = 0.0f; /* reset max P&L for new trade */
@@ -1807,14 +1807,14 @@ extern "C" __global__ void experience_env_step(
* When model is highly confident (readiness ≥ 0.7) and conviction changes
* significantly, update the stored plan. The model learns WHEN to revise. */
if (has_plan && fabsf(position) > 0.001f && readiness >= 0.7f && plan_params_ptr != NULL) {
float conv_now = plan_params_ptr[i * 6 + 4];
float conv_now = plan_params_ptr[i * 6 + PLAN_PARAM_CONVICTION];
float conv_entry = ps[PS_PLAN_CONVICTION];
if (conv_now > conv_entry * 1.3f) {
/* Conviction increased 30%+ → thesis strengthening → extend plan */
float new_target = plan_params_ptr[i * 6 + 0];
float new_target = plan_params_ptr[i * 6 + PLAN_PARAM_TARGET_BARS];
ps[PS_PLAN_TARGET_BARS] = fmaxf(ps[PS_PLAN_TARGET_BARS], new_target); /* only extend, never shorten from conviction increase */
ps[PS_PLAN_PROFIT_TARGET] = fmaxf(ps[PS_PLAN_PROFIT_TARGET], plan_params_ptr[i * 6 + 1]); /* widen profit target */
ps[PS_PLAN_PROFIT_TARGET] = fmaxf(ps[PS_PLAN_PROFIT_TARGET], plan_params_ptr[i * 6 + PLAN_PARAM_PROFIT_TARGET]); /* widen profit target */
} else if (conv_now < conv_entry * 0.4f) {
/* Conviction dropped 60%+ → thesis collapsing → shorten plan to exit soon */
ps[PS_PLAN_TARGET_BARS] = fminf(ps[PS_PLAN_TARGET_BARS], hold_time + 3.0f); /* exit within 3 bars */
@@ -2397,7 +2397,7 @@ extern "C" __global__ void experience_env_step(
if (plan_params_ptr != NULL && fabsf(reward) > 1e-8f) {
float readiness_val = (readiness_ptr != NULL) ? readiness_ptr[0] : 0.0f;
float conviction = (readiness_val >= 0.5f)
? plan_params_ptr[i * 6 + 4] /* [0, 1] from plan head */
? plan_params_ptr[i * 6 + PLAN_PARAM_CONVICTION] /* [0, 1] from plan head */
: 1.0f; /* identity until plan matures */
reward *= conviction;
}

View File

@@ -81,6 +81,19 @@
#define PLAN_ISV_REGIME_SHIFT 5 // |isv[11] entry_regime_stability|
#define PLAN_ISV_DIM 6
// ────────────────────────────────────────────────────────────────────────────
// Plan MLP output slot indices (plan_params[0..PLAN_PARAM_DIM=6)).
// Invariant 8: every slot has a named constant.
// Used for pp[N] and plan_params_ptr[i * 6 + N] access patterns.
// ────────────────────────────────────────────────────────────────────────────
#define PLAN_PARAM_TARGET_BARS 0 // max hold bars
#define PLAN_PARAM_PROFIT_TARGET 1 // raw profit threshold %
#define PLAN_PARAM_STOP_LOSS 2 // raw stop loss threshold %
#define PLAN_PARAM_SCALE_AGGRESSION 3 // position ramp speed
#define PLAN_PARAM_CONVICTION 4 // position size fraction [0, 1]
#define PLAN_PARAM_ASYMMETRY 5 // profit/stop ratio
#define PLAN_PARAM_DIM 6
// ── Compile-time checks ──
static_assert(SL_PADDING_START + SL_PADDING_DIM == SL_STATE_DIM,
"State layout dimensions must sum to SL_STATE_DIM");

View File

@@ -119,4 +119,5 @@ From the trade_plan MLP output.
## Commit history
- Task 4A (ps[0..PS_STRIDE) constants): commit 144c85b85
- Task 4B (plan_isv[0..6) constants): commit <SHA>
- Task 4B (plan_isv[0..6) constants): commit 741cb48d5
- Task 4C (plan_params[0..6) constants): commit <SHA>