From d144171b92e2829a2e7b0ab01efc2d0d7125ed36 Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Fri, 17 Apr 2026 09:35:08 +0200 Subject: [PATCH] feat(plan): track intra_trade_max_pnl in ps[21] for hindsight labels (N18) Max unrealized P&L tracked each bar during trade. Enables hindsight plan learning: compare plan's profit_target vs actual max P&L. The plan head learns optimal targets from what was achievable. Reset on trade entry, reversal, and episode hard/soft reset. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/ml/src/cuda_pipeline/experience_kernels.cu | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/ml/src/cuda_pipeline/experience_kernels.cu b/crates/ml/src/cuda_pipeline/experience_kernels.cu index 9d4864fae..445bcabbb 100644 --- a/crates/ml/src/cuda_pipeline/experience_kernels.cu +++ b/crates/ml/src/cuda_pipeline/experience_kernels.cu @@ -34,7 +34,7 @@ * [10] hold_time — consecutive steps with position (total, not just losing) * [11] realized_pnl — cumulative realized PnL * [20] intra_trade_max_dd — worst unrealized drawdown during current trade (v8) - * [21] (reserved) — was last_trade_t (clustering stats, slot retained) + * [21] intra_trade_max_pnl — best unrealized P&L during current trade (hindsight) * [22] (reserved) — was interval_sum (clustering stats, slot retained) * [23] plan_target_bars — 0=no plan, >0=active plan max hold bars * [24] plan_profit_target — raw profit threshold % @@ -1499,6 +1499,7 @@ extern "C" __global__ void experience_env_step( ps[28] = pp[5]; /* asymmetry */ /* Store entry regime_stability for drift detection (P12). */ ps[29] = (isv_signals_ptr != NULL) ? isv_signals_ptr[11] : 1.0f; + ps[21] = 0.0f; /* reset max P&L for new trade */ /* Apply conviction to position size — scale by readiness for smooth ramp */ position *= fmaxf(ps[27] * readiness, 0.1f); } @@ -1618,9 +1619,11 @@ extern "C" __global__ void experience_env_step( float intra_trade_max_dd = (ps[20]); if (entering_trade) { intra_trade_max_dd = 0.0f; + ps[21] = 0.0f; /* reset max P&L for new trade */ } if (reversing_trade) { intra_trade_max_dd = 0.0f; + ps[21] = 0.0f; /* reset max P&L for reversed trade */ } if (fabsf(position) > 0.001f && entry_price > 0.0f) { float unrealized = (position > 0.0f) @@ -1628,6 +1631,11 @@ extern "C" __global__ void experience_env_step( : (entry_price - raw_close) / entry_price; float current_dd = fminf(unrealized, 0.0f); intra_trade_max_dd = fminf(intra_trade_max_dd, current_dd); + + /* Track best unrealized P&L during trade (for hindsight plan labels) */ + float pnl_pct = (raw_close - entry_price) / fmaxf(fabsf(entry_price), 1.0f) + * ((position > 0.0f) ? 1.0f : -1.0f); + ps[21] = fmaxf(ps[21], pnl_pct); /* max P&L during trade */ } /* Idle counter (flat bars) — used for state features, no penalty */ @@ -1956,7 +1964,7 @@ extern "C" __global__ void experience_env_step( ps[18] = (sum_returns); /* Kelly continuous: sum returns */ ps[19] = (sum_sq_returns); /* Kelly continuous: sum returns^2 */ ps[20] = (intra_trade_max_dd); /* v7: intra-trade max drawdown */ - /* ps[21], ps[22]: reserved (formerly clustering stats, retained for slot stability) */ + /* ps[22]: reserved (formerly clustering stats, retained for slot stability) */ /* ---- NO global reward clamp ---- */ /* Reward v7: sparse trade-completion with asymmetric soft-clamp. @@ -2148,6 +2156,7 @@ extern "C" __global__ void experience_env_step( ps[18] = 0.0f; ps[19] = 0.0f; ps[20] = 0.0f; /* intra_trade_max_dd */ + ps[21] = 0.0f; /* intra_trade_max_pnl */ ps[23] = 0.0f; ps[24] = 0.0f; ps[25] = 0.0f; ps[26] = 0.0f; ps[27] = 0.0f; ps[28] = 0.0f; ps[29] = 0.0f; /* plan slots zeroed */ @@ -2161,6 +2170,7 @@ extern "C" __global__ void experience_env_step( ps[12] = 0.0f; /* entry_price — no active trade */ ps[13] = (ps[11]); /* trade_start_pnl = current realized_pnl */ ps[20] = 0.0f; /* intra_trade_max_dd — reset for next trade */ + ps[21] = 0.0f; /* intra_trade_max_pnl — reset for next trade */ ps[23] = 0.0f; ps[24] = 0.0f; ps[25] = 0.0f; ps[26] = 0.0f; ps[27] = 0.0f; ps[28] = 0.0f; ps[29] = 0.0f; /* plan slots zeroed on trade complete */