feat(plan): PORTFOLIO_STRIDE 23→30 — 7 plan slots ps[23-29]
Plan slots: target_bars, profit_target, stop_loss, scale_aggression, conviction, asymmetry, counter_plan_q. Zeroed on episode reset. Fixed hardcoded i*23 references. All CUDA + Rust files updated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
* [market_dim .. market_dim+3) : portfolio features (value_norm, position, cash_norm)
|
||||
* [market_dim+3 .. state_dim) : zero-pad for tensor-core alignment
|
||||
*
|
||||
* Portfolio state layout used by experience kernels ([N, PORTFOLIO_STRIDE=23]):
|
||||
* Portfolio state layout used by experience kernels ([N, PORTFOLIO_STRIDE=30]):
|
||||
* [0] position — current contract position (signed)
|
||||
* [1] cash — cash balance
|
||||
* [2] portfolio_value — mark-to-market total value (cash + position * price)
|
||||
@@ -36,6 +36,13 @@
|
||||
* [20] intra_trade_max_dd — worst unrealized drawdown during current trade (v8)
|
||||
* [21] (reserved) — was last_trade_t (clustering stats, slot retained)
|
||||
* [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 %
|
||||
* [25] plan_stop_loss — raw stop loss threshold %
|
||||
* [26] plan_scale_aggression — position ramp speed
|
||||
* [27] plan_conviction — position size fraction
|
||||
* [28] plan_asymmetry — profit/stop ratio
|
||||
* [29] counter_plan_q — opposite direction Q at entry
|
||||
*
|
||||
* Branching DQN (Tavakoli et al., 2018) — 4-branch hierarchical:
|
||||
* 4 independent advantage heads: direction (b0_size=3), magnitude (b1_size=3),
|
||||
@@ -52,10 +59,10 @@
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Portfolio stride for experience kernels (23 bf16 per episode). */
|
||||
/* Portfolio stride for experience kernels (30 floats per episode). */
|
||||
/* portfolio_sim_kernel uses its own stride of 8 — do NOT change it. */
|
||||
/* ------------------------------------------------------------------ */
|
||||
#define PORTFOLIO_STRIDE 23
|
||||
#define PORTFOLIO_STRIDE 30
|
||||
#define DSR_A_SLOT 3
|
||||
#define DSR_B_SLOT 4
|
||||
#define DSR_TRADE_COUNT_SLOT 5
|
||||
@@ -771,7 +778,7 @@ extern "C" __global__ void experience_action_select(
|
||||
int in_hold = 0;
|
||||
float cur_position = 0.0f;
|
||||
if (min_hold_bars > 0 && portfolio_states != NULL) {
|
||||
int ps_base = i * 23; /* PORTFOLIO_STRIDE = 23 */
|
||||
int ps_base = i * PORTFOLIO_STRIDE;
|
||||
float hold_time_val = portfolio_states[ps_base + 10];
|
||||
cur_position = portfolio_states[ps_base + 0];
|
||||
/* Adaptive hold: base + ISV-driven extension (same formula as Layer 2) */
|
||||
@@ -1032,7 +1039,7 @@ extern "C" __global__ void experience_action_select(
|
||||
* [2] raw_close — raw close price (for position cost + tx)
|
||||
* [3] raw_next — raw next-bar close (UNUSED in reward path)
|
||||
*
|
||||
* portfolio_states layout: [N, PORTFOLIO_STRIDE=23] (read-write, bf16)
|
||||
* portfolio_states layout: [N, PORTFOLIO_STRIDE=30] (read-write, float)
|
||||
* See file header for field definitions.
|
||||
*/
|
||||
extern "C" __global__ void experience_env_step(
|
||||
@@ -1179,7 +1186,7 @@ extern "C" __global__ void experience_env_step(
|
||||
/* Guard against degenerate prices from data gaps. */
|
||||
if (raw_close <= 0.0f) raw_close = 1.0f;
|
||||
|
||||
/* ---- Read full portfolio state (PORTFOLIO_STRIDE=23) ---- */
|
||||
/* ---- Read full portfolio state (PORTFOLIO_STRIDE=30) ---- */
|
||||
/* Portfolio arithmetic uses float accumulators because trade physics
|
||||
* functions (execute_trade, apply_margin_cap, etc.) in trade_physics.cuh
|
||||
* are all float. Converting the entire physics engine to bf16 would
|
||||
@@ -1796,7 +1803,7 @@ extern "C" __global__ void experience_env_step(
|
||||
reward += position_entropy_weight * combined_entropy;
|
||||
}
|
||||
|
||||
/* ---- Update full portfolio state (PORTFOLIO_STRIDE=23) ---- */
|
||||
/* ---- Update full portfolio state (PORTFOLIO_STRIDE=30) ---- */
|
||||
ps[0] = (position);
|
||||
ps[1] = (cash);
|
||||
ps[2] = (new_portfolio_value);
|
||||
@@ -2003,6 +2010,10 @@ extern "C" __global__ void experience_env_step(
|
||||
ps[17] = 0.0f;
|
||||
ps[18] = 0.0f;
|
||||
ps[19] = 0.0f;
|
||||
ps[20] = 0.0f; /* intra_trade_max_dd */
|
||||
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 */
|
||||
current_timesteps[i] = 0;
|
||||
} else {
|
||||
/* Soft reset (trade_complete): keep equity, clear trade state only.
|
||||
@@ -2013,6 +2024,9 @@ 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[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 */
|
||||
current_timesteps[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -2393,7 +2407,7 @@ extern "C" __global__ void expert_action_override(
|
||||
/* Check if current position already matches expert signal — skip if redundant.
|
||||
* portfolio_states[i * PORTFOLIO_STRIDE + 0] = current position.
|
||||
* If expert says Long and we're already Long (position > 0.5), skip. */
|
||||
float current_pos = (portfolio_states[i * 23 + 0]); /* PORTFOLIO_STRIDE=23, pos at idx 0 */
|
||||
float current_pos = (portfolio_states[i * PORTFOLIO_STRIDE + 0]);
|
||||
if (expert_dir == 2 && current_pos > 0.5f) return; /* Already Long */
|
||||
if (expert_dir == 0 && current_pos < -0.5f) return; /* Already Short */
|
||||
|
||||
|
||||
@@ -41,10 +41,10 @@ const MAX_EPISODES_LIMIT: usize = 0x8000;
|
||||
/// Absolute upper bound for validation — reject configs above this.
|
||||
const MAX_TIMESTEPS_LIMIT: usize = 1000;
|
||||
const PORTFOLIO_STATE_SIZE: usize = 8;
|
||||
/// Portfolio stride for DQN experience kernels (23 floats per episode).
|
||||
/// Portfolio stride for DQN experience kernels (30 floats per episode).
|
||||
/// Matches PORTFOLIO_STRIDE in experience_kernels.cu.
|
||||
/// Do NOT change PORTFOLIO_STATE_SIZE above — it's for the PPO/legacy path.
|
||||
const PORTFOLIO_STRIDE: usize = 23;
|
||||
const PORTFOLIO_STRIDE: usize = 30;
|
||||
|
||||
/// Number of floats in the trade_stats_reduce output buffer.
|
||||
/// Layout: [win_count, loss_count, sum_wins, sum_losses, sum_returns, sum_sq_returns]
|
||||
@@ -567,7 +567,7 @@ pub struct GpuExperienceCollector {
|
||||
trade_stats_buf: CudaSlice<f32>,
|
||||
|
||||
// Per-episode state buffers [alloc_episodes, ...]
|
||||
portfolio_states: CudaSlice<f32>, // [alloc_episodes * PORTFOLIO_STRIDE] (20 floats per episode)
|
||||
portfolio_states: CudaSlice<f32>, // [alloc_episodes * PORTFOLIO_STRIDE] (30 floats per episode)
|
||||
episode_starts_buf: CudaSlice<i32>,// [alloc_episodes]
|
||||
|
||||
// Output buffers [alloc_episodes * alloc_timesteps, ...]
|
||||
@@ -861,7 +861,7 @@ impl GpuExperienceCollector {
|
||||
}
|
||||
|
||||
// ── Step 6: Allocate per-episode buffers ────────────────────────
|
||||
// Portfolio states for experience kernels: [N, PORTFOLIO_STRIDE=20]
|
||||
// Portfolio states for experience kernels: [N, PORTFOLIO_STRIDE=30]
|
||||
let mut portfolio_states = stream
|
||||
.alloc_zeros::<f32>(alloc_episodes * PORTFOLIO_STRIDE)
|
||||
.map_err(|e| MLError::ModelError(format!("alloc portfolio_states: {e}")))?;
|
||||
@@ -2428,7 +2428,7 @@ impl GpuExperienceCollector {
|
||||
_avg_spread: f32,
|
||||
_cash_reserve_pct: f32,
|
||||
) -> Result<(), MLError> {
|
||||
// Reset portfolio states [N, PORTFOLIO_STRIDE=20]
|
||||
// Reset portfolio states [N, PORTFOLIO_STRIDE=30]
|
||||
let mut portfolio_init = vec![0.0_f32; self.alloc_episodes * PORTFOLIO_STRIDE];
|
||||
for i in 0..self.alloc_episodes {
|
||||
let off = i * PORTFOLIO_STRIDE;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Trade stats reduction kernel.
|
||||
*
|
||||
* Reads portfolio_states[N, PORTFOLIO_STRIDE=23] and sums fields [14:19]
|
||||
* Reads portfolio_states[N, PORTFOLIO_STRIDE=30] and sums fields [14:19]
|
||||
* (win_count, loss_count, sum_wins, sum_losses, sum_returns, sum_sq_returns)
|
||||
* across all N episodes into a 6-float output buffer.
|
||||
* Uses shared-memory warp reduction (same pattern as monitoring_reduce).
|
||||
@@ -9,7 +9,7 @@
|
||||
* Launch config: grid=(1, 1, 1), block=(256, 1, 1).
|
||||
*/
|
||||
|
||||
#define PORTFOLIO_STRIDE 23
|
||||
#define PORTFOLIO_STRIDE 30
|
||||
|
||||
extern "C" __global__ void trade_stats_reduce(
|
||||
const float* __restrict__ portfolio_states, // [N * PORTFOLIO_STRIDE]
|
||||
|
||||
Reference in New Issue
Block a user