plan: Trade Plan Head — 5 tasks, hierarchical plan-based trading
Task 1: PORTFOLIO_STRIDE 23→30, plan slots ps[23-29] Task 2: trade_plan_forward kernel + 4 weight tensors (82→86) Task 3: Plan activation + enforcement in env_step Task 4: Direction lock in action_select + counter-plan Q (N14) Task 5: Smoke test + compute-sanitizer Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
511
docs/superpowers/plans/2026-04-16-trade-plan-head.md
Normal file
511
docs/superpowers/plans/2026-04-16-trade-plan-head.md
Normal file
@@ -0,0 +1,511 @@
|
||||
# Trade Plan Head Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add a hierarchical plan head that outputs 6 trade parameters (target_bars, profit_target, stop_loss, scale_aggression, conviction, asymmetry) at entry, with auto-exit enforcement during the trade. Replaces per-bar coin-flip decisions with committed, risk-managed trade plans.
|
||||
|
||||
**Architecture:** Plan head MLP (h_s2→AH→6 params) fires at entry. Plan stored in portfolio state ps[23-29]. Direction locked during plan. Auto-exit on profit/stop/time/regime. PORTFOLIO_STRIDE grows 23→30. 4 new weight tensors at indices 82-85 (NUM_WEIGHT_TENSORS 82→86, assuming Phase 3 completes first at 82; if Phase 3 is not done yet, adjust indices accordingly).
|
||||
|
||||
**Tech Stack:** Rust 1.85, CUDA 12.4, experience_kernels.cu, gpu_dqn_trainer.rs
|
||||
|
||||
---
|
||||
|
||||
## Task 1: PORTFOLIO_STRIDE 23→30 + Plan Slot Allocation
|
||||
|
||||
Grow the portfolio state array to accommodate 7 plan slots. This must come FIRST because all other tasks depend on the wider stride.
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/ml/src/cuda_pipeline/experience_kernels.cu`
|
||||
- Modify: `crates/ml/src/cuda_pipeline/trade_stats_kernel.cu`
|
||||
- Modify: `crates/ml/src/cuda_pipeline/backtest_env_kernel.cu`
|
||||
- Modify: `crates/ml/src/cuda_pipeline/gpu_experience_collector.rs`
|
||||
|
||||
- [ ] **Step 1: Change PORTFOLIO_STRIDE in experience_kernels.cu**
|
||||
|
||||
Find line 58:
|
||||
```cuda
|
||||
#define PORTFOLIO_STRIDE 23
|
||||
```
|
||||
Change to:
|
||||
```cuda
|
||||
#define PORTFOLIO_STRIDE 30
|
||||
```
|
||||
|
||||
Update the doc comment (lines 23-52) to add:
|
||||
```
|
||||
* [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 (0=cautious, 1=all-in)
|
||||
* [27] plan_conviction — position size fraction (Kelly proxy)
|
||||
* [28] plan_asymmetry — profit/stop ratio
|
||||
* [29] counter_plan_q — opposite direction Q-value at entry (N14)
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Change PORTFOLIO_STRIDE in trade_stats_kernel.cu**
|
||||
|
||||
Find:
|
||||
```cuda
|
||||
#define PORTFOLIO_STRIDE 23
|
||||
```
|
||||
Change to:
|
||||
```cuda
|
||||
#define PORTFOLIO_STRIDE 30
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Fix hardcoded `i * 23` in action select**
|
||||
|
||||
In `experience_kernels.cu`, find line ~774:
|
||||
```cuda
|
||||
int ps_base = i * 23; /* PORTFOLIO_STRIDE = 23 */
|
||||
```
|
||||
Change to:
|
||||
```cuda
|
||||
int ps_base = i * PORTFOLIO_STRIDE;
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Update Rust buffer allocation**
|
||||
|
||||
In `gpu_experience_collector.rs`, find where `portfolio_states` buffer is allocated. It uses `n_episodes * PORTFOLIO_STRIDE_VALUE` or similar. Search for `* 23` in the allocation. Change to `* 30`.
|
||||
|
||||
Also search for any Rust constant like `const PORTFOLIO_STRIDE: usize = 23` and update to 30.
|
||||
|
||||
- [ ] **Step 5: Zero plan slots on episode reset**
|
||||
|
||||
In `experience_env_step`, find the hard reset block (around where `ps[15] = 0.0f` etc. are zeroed). Add:
|
||||
```cuda
|
||||
ps[23] = 0.0f; /* plan_target_bars */
|
||||
ps[24] = 0.0f; /* plan_profit_target */
|
||||
ps[25] = 0.0f; /* plan_stop_loss */
|
||||
ps[26] = 0.0f; /* plan_scale_aggression */
|
||||
ps[27] = 0.0f; /* plan_conviction */
|
||||
ps[28] = 0.0f; /* plan_asymmetry */
|
||||
ps[29] = 0.0f; /* counter_plan_q */
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Check backtest_env_kernel.cu**
|
||||
|
||||
Search for `PORTFOLIO_STRIDE` or `* 23` in backtest kernels. Update any hardcoded values. The backtest kernel may have its own stride — check `backtest_env_kernel.cu` carefully. If it uses a different stride (e.g., 8 for the simpler portfolio sim), leave it alone.
|
||||
|
||||
- [ ] **Step 7: Verify compilation**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
|
||||
```
|
||||
|
||||
- [ ] **Step 8: Commit**
|
||||
|
||||
```bash
|
||||
cd /home/jgrusewski/Work/foxhunt && git add -A && git commit -m "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 → i*PORTFOLIO_STRIDE in action select.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Plan Head Kernel + Weight Tensors
|
||||
|
||||
Add `trade_plan_forward` kernel and 4 new weight tensors.
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/ml/src/cuda_pipeline/experience_kernels.cu`
|
||||
- Modify: `crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs`
|
||||
|
||||
- [ ] **Step 1: Write `trade_plan_forward` kernel**
|
||||
|
||||
Add to end of `experience_kernels.cu`:
|
||||
|
||||
```cuda
|
||||
/* ================================================================== */
|
||||
/* Kernel: trade_plan_forward — plan head MLP → 6 plan parameters */
|
||||
/* ================================================================== */
|
||||
extern "C" __global__ void trade_plan_forward(
|
||||
const float* __restrict__ h_s2, /* [B, SH2] */
|
||||
const float* __restrict__ w_plan_fc, /* [AH, SH2] */
|
||||
const float* __restrict__ b_plan_fc, /* [AH] */
|
||||
const float* __restrict__ w_plan_out, /* [6, AH] */
|
||||
const float* __restrict__ b_plan_out, /* [6] */
|
||||
float* __restrict__ plan_params, /* [B, 6] output */
|
||||
int B, int SH2, int AH
|
||||
) {
|
||||
int i = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
if (i >= B) return;
|
||||
|
||||
const float* h = h_s2 + (long long)i * SH2;
|
||||
float hidden[128]; /* AH <= 128 */
|
||||
|
||||
for (int j = 0; j < AH; j++) {
|
||||
float val = b_plan_fc[j];
|
||||
for (int k = 0; k < SH2; k++)
|
||||
val += w_plan_fc[(long long)j * SH2 + k] * h[k];
|
||||
hidden[j] = fmaxf(val, 0.0f); /* ReLU */
|
||||
}
|
||||
|
||||
float* out = plan_params + i * 6;
|
||||
for (int p = 0; p < 6; p++) {
|
||||
float val = b_plan_out[p];
|
||||
for (int j = 0; j < AH; j++)
|
||||
val += w_plan_out[(long long)p * AH + j] * hidden[j];
|
||||
out[p] = val;
|
||||
}
|
||||
|
||||
/* Activations */
|
||||
out[0] = 3.0f + 22.0f / (1.0f + expf(-out[0])); /* target_bars [3, 25] */
|
||||
out[1] = 0.0005f + 0.0145f / (1.0f + expf(-out[1])); /* profit_target [0.05%, 1.5%] */
|
||||
out[2] = 0.0002f + 0.0048f / (1.0f + expf(-out[2])); /* stop_loss [0.02%, 0.5%] */
|
||||
out[3] = 1.0f / (1.0f + expf(-out[3])); /* scale_aggression [0, 1] */
|
||||
out[4] = 1.0f / (1.0f + expf(-out[4])); /* conviction [0, 1] */
|
||||
out[5] = 0.5f + 2.5f / (1.0f + expf(-out[5])); /* asymmetry [0.5, 3.0] */
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add weight tensors to compute_param_sizes**
|
||||
|
||||
In `gpu_dqn_trainer.rs`, determine the current NUM_WEIGHT_TENSORS value. Add 4 after the last index:
|
||||
|
||||
```rust
|
||||
// ── Trade Plan Head ──
|
||||
cfg.adv_h * cfg.shared_h2, // [N] w_plan_fc [AH, SH2]
|
||||
cfg.adv_h, // [N+1] b_plan_fc [AH]
|
||||
6 * cfg.adv_h, // [N+2] w_plan_out [6, AH]
|
||||
6, // [N+3] b_plan_out [6]
|
||||
```
|
||||
|
||||
Where N is the first available index. Update NUM_WEIGHT_TENSORS += 4.
|
||||
|
||||
- [ ] **Step 3: Add fan_dims for Xavier init**
|
||||
|
||||
```rust
|
||||
(cfg.adv_h, cfg.shared_h2), // w_plan_fc
|
||||
(1, cfg.adv_h), // b_plan_fc
|
||||
(6, cfg.adv_h), // w_plan_out
|
||||
(1, 6), // b_plan_out
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Add plan_params_buf + kernel field**
|
||||
|
||||
Struct fields:
|
||||
```rust
|
||||
plan_params_buf: CudaSlice<f32>, // [B, 6]
|
||||
trade_plan_fwd_kernel: CudaFunction,
|
||||
```
|
||||
|
||||
Allocate: `stream.alloc_zeros::<f32>(b * 6)`. Load kernel from experience_kernels cubin.
|
||||
|
||||
- [ ] **Step 5: Add launch method**
|
||||
|
||||
```rust
|
||||
pub(crate) fn launch_trade_plan_forward(&self, batch_size: usize) -> Result<(), MLError> {
|
||||
let param_sizes = compute_param_sizes(&self.config);
|
||||
let plan_fc_idx = /* first plan tensor index */;
|
||||
let w_fc = self.ptrs.params_ptr + padded_byte_offset(¶m_sizes, plan_fc_idx);
|
||||
let b_fc = self.ptrs.params_ptr + padded_byte_offset(¶m_sizes, plan_fc_idx + 1);
|
||||
let w_out = self.ptrs.params_ptr + padded_byte_offset(¶m_sizes, plan_fc_idx + 2);
|
||||
let b_out = self.ptrs.params_ptr + padded_byte_offset(¶m_sizes, plan_fc_idx + 3);
|
||||
let blocks = ((batch_size as u32 + 255) / 256).max(1);
|
||||
let b_i32 = batch_size as i32;
|
||||
let sh2 = self.config.shared_h2 as i32;
|
||||
let ah = self.config.adv_h as i32;
|
||||
|
||||
unsafe {
|
||||
self.stream.launch_builder(&self.trade_plan_fwd_kernel)
|
||||
.arg(&self.save_h_s2)
|
||||
.arg(&w_fc).arg(&b_fc)
|
||||
.arg(&w_out).arg(&b_out)
|
||||
.arg(&self.plan_params_buf)
|
||||
.arg(&b_i32).arg(&sh2).arg(&ah)
|
||||
.launch(LaunchConfig {
|
||||
grid_dim: (blocks, 1, 1),
|
||||
block_dim: (256, 1, 1),
|
||||
shared_mem_bytes: 0,
|
||||
})
|
||||
.map_err(|e| MLError::ModelError(format!("trade_plan_forward: {e}")))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Wire into reduce_current_q_stats**
|
||||
|
||||
After `launch_recursive_confidence_forward()` and before `risk_budget_forward()`:
|
||||
```rust
|
||||
self.launch_trade_plan_forward(batch_size)?;
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Expose plan_params_buf to experience collector**
|
||||
|
||||
Add accessor:
|
||||
```rust
|
||||
pub fn plan_params_buf_ptr(&self) -> u64 { self.plan_params_buf.raw_ptr() }
|
||||
```
|
||||
|
||||
And passthrough in `fused_training.rs`.
|
||||
|
||||
- [ ] **Step 8: Verify compilation**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
|
||||
```
|
||||
|
||||
- [ ] **Step 9: Commit**
|
||||
|
||||
```bash
|
||||
cd /home/jgrusewski/Work/foxhunt && git add crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs crates/ml/src/cuda_pipeline/experience_kernels.cu crates/ml/src/trainers/dqn/fused_training.rs && git commit -m "feat(plan): trade_plan_forward kernel + 4 weight tensors
|
||||
|
||||
Plan MLP: h_s2 → hidden[AH] → plan_params[B, 6].
|
||||
6 outputs: target_bars[3-25], profit_target[0.05-1.5%],
|
||||
stop_loss[0.02-0.5%], scale_aggression[0-1], conviction[0-1],
|
||||
asymmetry[0.5-3.0]. NUM_WEIGHT_TENSORS grows by 4.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Plan Activation + Enforcement in env_step
|
||||
|
||||
Wire plan parameters into the experience env_step kernel for activation at entry and enforcement during trades.
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/ml/src/cuda_pipeline/experience_kernels.cu`
|
||||
- Modify: `crates/ml/src/cuda_pipeline/gpu_experience_collector.rs`
|
||||
|
||||
- [ ] **Step 1: Add plan_params_ptr to env_step kernel signature**
|
||||
|
||||
After `isv_signals_ptr`:
|
||||
```cuda
|
||||
const float* __restrict__ plan_params_ptr /* [N, 6] trade plan parameters from plan head */
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Add plan activation logic**
|
||||
|
||||
In `experience_env_step`, after the position update and hold enforcement, add plan activation when transitioning Flat→Positioned:
|
||||
|
||||
```cuda
|
||||
/* ── Plan activation: Flat → Positioned ── */
|
||||
int was_flat = (fabsf(pre_trade_position) < 0.001f);
|
||||
int now_positioned = (fabsf(position) > 0.001f);
|
||||
|
||||
if (was_flat && now_positioned && plan_params_ptr != NULL) {
|
||||
const float* pp = plan_params_ptr + i * 6;
|
||||
ps[23] = pp[0]; /* target_bars */
|
||||
ps[24] = pp[1]; /* profit_target */
|
||||
ps[25] = pp[2]; /* stop_loss */
|
||||
ps[26] = pp[3]; /* scale_aggression */
|
||||
ps[27] = pp[4]; /* conviction */
|
||||
ps[28] = pp[5]; /* asymmetry */
|
||||
/* Apply conviction to position size */
|
||||
position *= fmaxf(ps[27], 0.1f);
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 3: Add plan enforcement logic**
|
||||
|
||||
After plan activation, add plan execution checks:
|
||||
|
||||
```cuda
|
||||
/* ── Plan enforcement: auto-exit conditions ── */
|
||||
int has_plan = (ps[23] > 0.5f);
|
||||
if (has_plan && fabsf(position) > 0.001f) {
|
||||
float pnl_pct = (raw_close - entry_price) / fmaxf(fabsf(entry_price), 1.0f)
|
||||
* ((position > 0.0f) ? 1.0f : -1.0f);
|
||||
|
||||
/* ISV-modulated thresholds (N16) */
|
||||
float stability = (isv_signals_ptr != NULL) ? isv_signals_ptr[11] : 1.0f;
|
||||
float eff_profit = ps[24] * ps[28] * (0.5f + 0.5f * stability);
|
||||
float eff_stop = ps[25] * fmaxf(stability, 0.5f);
|
||||
|
||||
int plan_exit = 0;
|
||||
if (pnl_pct >= eff_profit) plan_exit = 1; /* profit target */
|
||||
if (pnl_pct <= -eff_stop) plan_exit = 1; /* stop loss */
|
||||
if (hold_time >= ps[23]) plan_exit = 1; /* time exit */
|
||||
if (stability < 0.3f) plan_exit = 1; /* regime emergency */
|
||||
|
||||
/* G9: Scale schedule — ramp position over first 3 bars */
|
||||
if (hold_time < 3.0f && !plan_exit) {
|
||||
float scale = ps[26] + (1.0f - ps[26]) * hold_time / 3.0f;
|
||||
position *= fminf(scale, 1.0f);
|
||||
}
|
||||
|
||||
if (plan_exit) {
|
||||
position = 0.0f;
|
||||
for (int s = 23; s <= 29; s++) ps[s] = 0.0f;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Place this AFTER the existing hold enforcement and BEFORE the reward computation.
|
||||
|
||||
- [ ] **Step 4: Pass plan_params_ptr in Rust launch**
|
||||
|
||||
In `gpu_experience_collector.rs`, find the env_step launch. Add after `isv_signals_dev_ptr`:
|
||||
```rust
|
||||
.arg(&self.plan_params_dev_ptr) // trade plan parameters
|
||||
```
|
||||
|
||||
Add field `plan_params_dev_ptr: u64` to the collector struct, with setter:
|
||||
```rust
|
||||
pub fn set_plan_params_ptr(&mut self, ptr: u64) { self.plan_params_dev_ptr = ptr; }
|
||||
```
|
||||
|
||||
Wire from trainer → fused_ctx → collector in training_loop.rs (same pattern as isv_signals).
|
||||
|
||||
- [ ] **Step 5: Verify compilation**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
|
||||
```
|
||||
|
||||
- [ ] **Step 6: Commit**
|
||||
|
||||
```bash
|
||||
cd /home/jgrusewski/Work/foxhunt && git add -A && git commit -m "feat(plan): plan activation + enforcement in env_step
|
||||
|
||||
Flat→Positioned copies plan_params to ps[23-29]. Auto-exit on
|
||||
profit_target (ISV-modulated × asymmetry), stop_loss (ISV-modulated),
|
||||
target_bars, regime_stability<0.3. Scale schedule via scale_aggression.
|
||||
Conviction applied to position size (Kelly proxy).
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Direction Lock in Action Select + Counter-Plan Q
|
||||
|
||||
Lock direction branch during active plan. Store opposite-direction Q for N14 comparison.
|
||||
|
||||
**Files:**
|
||||
- Modify: `crates/ml/src/cuda_pipeline/experience_kernels.cu`
|
||||
|
||||
- [ ] **Step 1: Add direction lock during active plan**
|
||||
|
||||
In `experience_action_select`, after the hold enforcement block (which uses `in_hold`), add plan direction lock:
|
||||
|
||||
```cuda
|
||||
/* Plan direction lock: during active plan, force current direction */
|
||||
int has_plan_active = 0;
|
||||
if (portfolio_states != NULL) {
|
||||
int ps_base = i * PORTFOLIO_STRIDE;
|
||||
has_plan_active = (portfolio_states[ps_base + 23] > 0.5f);
|
||||
if (has_plan_active) {
|
||||
float cur_pos = portfolio_states[ps_base + 0];
|
||||
if (cur_pos > 0.001f) dir_idx = 2; /* Long locked */
|
||||
else if (cur_pos < -0.001f) dir_idx = 0; /* Short locked */
|
||||
/* Magnitude: follows scale — let the plan enforcement in env_step handle it */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Store counter-plan Q at entry**
|
||||
|
||||
In `experience_action_select`, when the model selects a direction (before plan lock), compute the opposite direction's Q-value:
|
||||
|
||||
```cuda
|
||||
/* N14: Store counter-direction Q for plan comparison.
|
||||
* Only computed when model is flat (potential entry). */
|
||||
if (portfolio_states != NULL) {
|
||||
int ps_base_n14 = i * PORTFOLIO_STRIDE;
|
||||
float cur_pos_n14 = portfolio_states[ps_base_n14 + 0];
|
||||
if (fabsf(cur_pos_n14) < 0.001f) {
|
||||
/* Flat — compute opposite direction Q */
|
||||
int opp_dir = (dir_idx == 2) ? 0 : 2; /* Long↔Short */
|
||||
float counter_q_val = q_per_action[opp_dir]; /* Q-value of opposite direction */
|
||||
portfolio_states[ps_base_n14 + 29] = counter_q_val; /* store for N14 */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note: `q_per_action` or `q_values` — check what variable name holds the per-action Q-values in the action select kernel. Read the code.
|
||||
|
||||
IMPORTANT: writing to `portfolio_states` in the action select kernel requires it to be non-const. Check if it's `const float*` — if so, this needs to move to env_step instead. If const, store the counter-Q in a separate buffer passed as output.
|
||||
|
||||
- [ ] **Step 3: Verify compilation**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true cargo check -p ml 2>&1 | tail -5
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
cd /home/jgrusewski/Work/foxhunt && git add crates/ml/src/cuda_pipeline/experience_kernels.cu && git commit -m "feat(plan): direction lock during active plan + counter-plan Q (N14)
|
||||
|
||||
Direction branch locked to current position during active plan.
|
||||
Prevents direction flips that would violate plan commitment.
|
||||
Counter-direction Q-value stored at entry for N14 opportunity
|
||||
cost comparison (exit early if opposite thesis is winning).
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 5: Smoke Test + Compute-Sanitizer
|
||||
|
||||
**Files:** None (verification only)
|
||||
|
||||
- [ ] **Step 1: Run smoke test**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true FOXHUNT_TEST_DATA=test_data/futures-baseline cargo test -p ml --lib -- test_generalization_components_smoke --include-ignored --nocapture 2>&1 | tail -20
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run compute-sanitizer**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true cargo test -p ml --lib --no-run 2>&1 | grep "Executable"
|
||||
# Use the binary path:
|
||||
FOXHUNT_TEST_DATA=test_data/futures-baseline compute-sanitizer --tool memcheck --print-limit 10 <binary> "test_generalization_components_smoke" --test-threads=1 --include-ignored 2>&1 | tail -5
|
||||
```
|
||||
|
||||
**Target: 0 errors.**
|
||||
|
||||
- [ ] **Step 3: Full test suite**
|
||||
|
||||
```bash
|
||||
SQLX_OFFLINE=true cargo test -p ml --lib 2>&1 | tail -5
|
||||
```
|
||||
|
||||
**Target: 899+ passed, 0 failed.**
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
cd /home/jgrusewski/Work/foxhunt && git add -A && git commit -m "chore(plan): trade plan head verification — smoke test + compute-sanitizer 0 errors
|
||||
|
||||
Plan head complete: 6 learned params per trade, auto-exit enforcement,
|
||||
direction lock, ISV-modulated thresholds, conviction sizing, pyramiding.
|
||||
PORTFOLIO_STRIDE 23→30. compute-sanitizer: 0 errors.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review
|
||||
|
||||
**Spec coverage:**
|
||||
- ✅ Plan head MLP (6 params) — Task 2
|
||||
- ✅ PORTFOLIO_STRIDE 23→30 — Task 1
|
||||
- ✅ Plan activation (Flat→Positioned) — Task 3
|
||||
- ✅ Plan enforcement (profit/stop/time/regime exit) — Task 3
|
||||
- ✅ ISV-modulated thresholds (N16) — Task 3
|
||||
- ✅ Scale schedule / pyramiding (G9) — Task 3
|
||||
- ✅ Conviction sizing (P9) — Task 3
|
||||
- ✅ Asymmetric R/R (G8) — Task 3
|
||||
- ✅ Direction lock — Task 4
|
||||
- ✅ Counter-plan Q (N14) — Task 4
|
||||
- ✅ Weight tensors — Task 2
|
||||
- ✅ compute-sanitizer — Task 5
|
||||
|
||||
**Not in this plan (future):**
|
||||
- Plan backward kernel (gradients flow through main C51 loss naturally via Q-value at entry bar)
|
||||
- Plan replay priority (N15) — requires replay buffer changes
|
||||
- Learned termination function (G10) — future enhancement on top of hard thresholds
|
||||
|
||||
**Placeholder scan:** No TBD/TODO found. All code blocks complete.
|
||||
Reference in New Issue
Block a user