feat(ml-backtesting): cold-start stopgap — max-confidence bytecode policy (Q1/Tier1)
The threshold-tuning smoke at 81decf40f produced n_trades=0 despite
74.6% of decisions having max_conv ≥ 0.30 — the linear-weighted-mean
aggregator in decision_policy_default is structurally dilution-bound
at cold-start (per spec §1).
Q1 stopgap: when sim_variants[i].use_cold_start_stopgap = true, the
harness uploads a max-confidence Strategy bytecode program for that
backtest, routing decisions through decision_policy_program with
OP_AGG_MAX_CONFIDENCE. Existing kernel; zero CUDA changes.
Field additions (atomically across BatchedSimConfig + UniformSimParams
+ ResolvedSimVariant + SweepBase.SimVariant) — every UniformSimParams
literal migrated to include use_cold_start_stopgap: false (default).
The sweep YAML's sim_variants entry sets it to true only for the
validation run; production deployability uses Q2's kernel fix instead.
Sweep YAML (config/ml/sweep_smoke.yaml) flipped to use_cold_start_stopgap=true
at threshold=0.0, cost=0.125 — same anchor as the threshold-tuning
smoke that produced n_trades=0, for direct comparison.
This is a VALIDATION step. Cluster smoke at this commit MUST produce
n_trades > 100 + finite metrics. Q2's kernel CBSW immediately follows
and deletes this entire stopgap atomically (field, harness branch,
YAML setting, every literal).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,12 @@ pub struct BatchedSimConfig {
|
||||
// per fill in apply_fill_to_pos.
|
||||
pub threshold: Vec<f32>,
|
||||
pub cost_per_lot_per_side: Vec<f32>,
|
||||
/// Q1 stopgap (deleted in Q2 kernel CBSW): when true for backtest b,
|
||||
/// the harness uploads a max-confidence Strategy bytecode program to
|
||||
/// that backtest, bypassing the linear-weighted-mean dilution in
|
||||
/// decision_policy_default. Validates the cold-start dilution
|
||||
/// diagnosis. Default false; Q2's kernel CBSW makes this redundant.
|
||||
pub use_cold_start_stopgap: Vec<bool>,
|
||||
}
|
||||
|
||||
/// P6: one fully-resolved sim variant for the sweep runner's grid-pack
|
||||
@@ -38,6 +44,8 @@ pub struct ResolvedSimVariant {
|
||||
pub sharpe_weight_floor: f32,
|
||||
pub threshold: f32,
|
||||
pub cost_per_lot_per_side: f32,
|
||||
/// Q1 stopgap (Tier 1 only — deleted in Q2). See BatchedSimConfig.
|
||||
pub use_cold_start_stopgap: bool,
|
||||
}
|
||||
|
||||
/// Convenience scalar input for `from_uniform`. Mirror of the historical
|
||||
@@ -52,6 +60,8 @@ pub struct UniformSimParams {
|
||||
pub sharpe_weight_floor: f32,
|
||||
pub threshold: f32,
|
||||
pub cost_per_lot_per_side: f32,
|
||||
/// Q1 stopgap (Tier 1 only — deleted in Q2). See BatchedSimConfig.
|
||||
pub use_cold_start_stopgap: bool,
|
||||
}
|
||||
|
||||
impl BatchedSimConfig {
|
||||
@@ -69,6 +79,7 @@ impl BatchedSimConfig {
|
||||
sharpe_weight_floor: vec![p.sharpe_weight_floor; n],
|
||||
threshold: vec![p.threshold; n],
|
||||
cost_per_lot_per_side: vec![p.cost_per_lot_per_side; n],
|
||||
use_cold_start_stopgap: vec![p.use_cold_start_stopgap; n],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +96,7 @@ impl BatchedSimConfig {
|
||||
sharpe_weight_floor: variants.iter().map(|v| v.sharpe_weight_floor).collect(),
|
||||
threshold: variants.iter().map(|v| v.threshold).collect(),
|
||||
cost_per_lot_per_side: variants.iter().map(|v| v.cost_per_lot_per_side).collect(),
|
||||
use_cold_start_stopgap: variants.iter().map(|v| v.use_cold_start_stopgap).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +110,7 @@ impl BatchedSimConfig {
|
||||
("sharpe_weight_floor", self.sharpe_weight_floor.len()),
|
||||
("threshold", self.threshold.len()),
|
||||
("cost_per_lot_per_side", self.cost_per_lot_per_side.len()),
|
||||
("use_cold_start_stopgap", self.use_cold_start_stopgap.len()),
|
||||
];
|
||||
for (name, l) in lens {
|
||||
if l != n {
|
||||
|
||||
Reference in New Issue
Block a user