Files
foxhunt/crates/ml-backtesting/cuda/lob_state.cuh
jgrusewski 0c8b4b5608 refactor(per-horizon): N_HORIZONS 5→3 — ml-backtesting full propagation
Source migration:
- crates/ml-backtesting/src/lob/mod.rs:5 + policy/mod.rs:18: local
  const N_HORIZONS 5→3 via re-export from ml_alpha::heads::N_HORIZONS
  (single source of truth across crates)
- crates/ml-backtesting/src/sim/mod.rs:1751,1773,1784: [IsvKellyStateHost; 5]
  array literals → ; N_HORIZONS]
- crates/ml-backtesting/cuda/lob_state.cuh:9: #define N_HORIZONS 5→3
  (this triggers cubin rebuild of decision_policy + 4 other ml-backtesting
  kernels that #include this header)

Test migration (8 test files + 2 JSON fixtures):
- threshold_and_cost.rs, decision_floor_coldstart.rs, parallel_sim_
  correctness.rs, stop_controller.rs (37+10+1 broadcast_alpha calls),
  lob_sim_integrated_fuzz.rs, lob_sim_fixtures.rs: hardcoded [f32; 5]
  alpha-probs and [IsvKellyStateHost; 5] arrays → N_HORIZONS-sized via
  std::array::from_fn or [v; N_HORIZONS] literals
- trainer_parity.rs:34 + ring3_replay.rs:47: horizons literal
  [30,100,300,1000,6000] → ml_alpha::heads::HORIZONS
- fixtures/decision_alpha_buy_close.json + decision_program_h4_only.json:
  5-element warm_start_isv_kelly / alpha_probs / expected_isv_kelly_after
  trimmed to 3 elements; active horizon relocated to N_HORIZONS-1

Library lib-test rewrite (per pearl_tests_must_prove_not_lock_observations):
- crates/ml-backtesting/src/policy/mod.rs:197-233: lib tests
  default_strategy_has_5_horizon_leaves + ..._flattens_to_5_emits...
  renamed to N_HORIZONS-parametric form (observed-value 5 and 7
  were bug-locks).

cargo check -p ml-backtesting --all-targets: clean.
cargo test -p ml-backtesting --lib: 33 passed.
cargo test -p ml-backtesting --tests (non-CUDA, non-fixture-data): 2 passed,
53 ignored (CUDA-gated or FOXHUNT_TEST_DATA-gated).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 01:37:23 +02:00

85 lines
3.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Per-block shared-mem layout for the LOB simulator.
// One block = one parallel backtest. See spec §2 + §5b.
//
// MUST stay in sync with crates/ml-backtesting/src/lob/mod.rs's host mirrors.
#ifndef LOB_STATE_CUH
#define LOB_STATE_CUH
// Must stay in sync with crates/ml-alpha/src/heads.rs::N_HORIZONS and
// crates/ml-backtesting/src/lob/mod.rs::N_HORIZONS.
#define N_HORIZONS 3
#define MAX_LIMITS 32
#define MAX_STOPS 16
struct Book {
float bid_px[10];
float bid_sz[10];
float ask_px[10];
float ask_sz[10];
};
// Per-backtest position + cumulative P&L. See spec §2 (CUDA shared-mem layout).
// Host mirror in crates/ml-backtesting/src/lob/mod.rs::PosFlat — MUST stay in sync.
struct Pos {
int position_lots; // signed (+ long, short)
float vwap_entry; // running entry-price VWAP for current open position
float realized_pnl; // cumulative realized P&L in price-units × lots
float peak_equity; // for drawdown tracking
unsigned int submission_overflow; // diagnostic counter
unsigned int open_horizon_mask; // bit h set if currently open position was authorized by horizon h
};
// Per-horizon adaptive Kelly state. Lives per (backtest, horizon).
// See spec §5 (per-horizon ISV-Kelly).
struct IsvKellyState {
float pnl_ema_win; // Wiener-α blended EMA of winning trade returns (price units)
float pnl_ema_loss; // EMA of losing trade returns (positive magnitude)
float win_rate_ema;
unsigned int n_trades_seen;
float realised_return_var; // Welford running variance over per-trade returns
float recent_sharpe; // composite: (μ × win_rate μ_loss × (1win_rate)) / sqrt(var)
};
// Resting-order slots. See spec §2 (CUDA shared-mem layout) and §3
// (order types). Host mirror in src/lob/mod.rs::{LimitSlotFlat,StopSlotFlat}.
// LimitSlot.kind / StopSlot.kind values mirror OrderEventKind:
// Limit=1, Ioc=2, Fok=3 for LimitSlot
// StopMarket=4, StopLimit=5 for StopSlot
struct LimitSlot {
unsigned char active; // 0=free, 1=resting, 2=in-flight (latency)
unsigned char side; // 0=buy, 1=sell
unsigned char kind; // 1=Limit, 2=Ioc, 3=Fok
unsigned char oco_pair; // 0xFF=no pair, else paired-slot global index
// (limits: 0..31; stops: 32..47)
float price; // limit price in price-units (e.g. 5500.25)
float size_remaining; // contracts left unfilled
float queue_position; // contracts ahead of us at this level (queue decay)
unsigned long long arrival_ts_ns; // when in-flight order becomes resting
unsigned short gen_counter; // bumped on each slot allocation for SlotTag freshness
unsigned char _pad[6]; // pad-to-8 for u64-aligned arrays of this struct
}; // 32 bytes
struct StopSlot {
unsigned char active; // 0=free, 1=armed, 2=in-flight
unsigned char side; // 0=buy, 1=sell
unsigned char kind; // 4=StopMarket, 5=StopLimit
unsigned char oco_pair; // 0xFF=no pair, else paired-slot global index
float trigger_price;
float limit_price; // 0.0 for StopMarket; price for StopLimit
float size;
unsigned long long arrival_ts_ns;
unsigned short gen_counter;
unsigned char _pad[6]; // pad-to-8 for u64-aligned arrays
}; // 32 bytes
#define MAX_LIMITS 32
#define MAX_STOPS 16
struct Orders {
LimitSlot limits[MAX_LIMITS]; // 32 × 32 = 1024 B
StopSlot stops[MAX_STOPS]; // 16 × 32 = 512 B
}; // 1536 B total
#endif // LOB_STATE_CUH