Phase 2A scaffolding complete (per spec §7.2): - oracle.rs: OracleAction enum + 3 oracle policies (flat, drift, OU) - harness.rs: BehavioralResult + evaluate_policy_on_market stub. Trainer-side methods (eval_actions_on_features, read_isv_for_test) are documented gap #7; Phase 2B tests add them per-test as needed. - pre-commit hook: cargo test -p ml --test behavioral_suite gates argo-train.sh per spec §4.5 discipline rule. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
54 lines
2.0 KiB
Rust
54 lines
2.0 KiB
Rust
//! SP15 Phase 2A — behavioral evaluator harness.
|
|
//!
|
|
//! Runs a policy on a synthetic market, captures action distribution +
|
|
//! sharpe_net + max_dd. Trainer-side methods (eval_actions_on_features etc)
|
|
//! are not yet implemented — see plan IMPORTANT 7. Each Phase 2B test
|
|
//! adds the specific trainer methods it needs.
|
|
|
|
use ml::cuda_pipeline::lob_bar::LobBar;
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Debug, Default)]
|
|
pub struct BehavioralResult {
|
|
/// Action distribution keys: "hold", "flat", "long_quarter",
|
|
/// "long_half", "long_full", "short_quarter", "short_half", "short_full".
|
|
pub action_dist: HashMap<&'static str, f32>,
|
|
pub sharpe_net: f32,
|
|
pub max_dd: f32,
|
|
pub trade_count: usize,
|
|
}
|
|
|
|
/// Runs the policy on `bars`, captures action distribution + sharpe_net
|
|
/// + max_dd. `n_warm` warmup bars precede action collection.
|
|
///
|
|
/// Phase 2A contract (locked here): trainer-side `eval_actions_on_features`
|
|
/// is added per-test in Phase 2B as each behavioral test needs it (plan
|
|
/// execution-time gap #7). This function returns a default BehavioralResult;
|
|
/// each Phase 2B test rewrites the body to call the trainer methods it
|
|
/// requires. The signature here is the load-bearing piece — keep it stable.
|
|
#[allow(dead_code, unused_variables)]
|
|
pub fn evaluate_policy_on_market(
|
|
// Phase 2B swaps `&mut ()` for `&mut GpuDqnTrainer` once the per-test
|
|
// trainer methods land. Until then the unit param keeps the signature
|
|
// callable in tests that don't yet exercise the trainer path.
|
|
_trainer: &mut (),
|
|
_bars: &[LobBar],
|
|
_n_warm: usize,
|
|
) -> BehavioralResult {
|
|
// Phase 2B wires this to trainer.eval_actions_on_features +
|
|
// launch_sp15_cost_net_sharpe + ISV DD-slot reads.
|
|
BehavioralResult::default()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn behavioral_result_default_is_empty() {
|
|
let r = BehavioralResult::default();
|
|
assert_eq!(r.trade_count, 0);
|
|
assert!(r.action_dist.is_empty());
|
|
}
|
|
}
|