Files
Aura/crates/aura-ingest/tests/ger40_breakout_world.rs
T
Brummel d858caf67b chore: scrub dangling references to deleted specs/plans from sources
docs/specs and docs/plans were retired (prior commit); the source/test
comments that cited them ("spec 0050 §4.1", "spec §Testing N", "per spec",
"the spec's ...") now point at nothing. Strip every such pointer while
preserving the technical substance, the design-ledger contract refs
(C1/C11/C20/C34/C12.1/...), and the Gitea issue refs (#41).

Comment/doc edits only across 20 files — no logic change; full workspace
suite green, clippy clean.
2026-06-18 11:16:28 +02:00

262 lines
11 KiB
Rust
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.
//! Gated integration test: the GER40 session-breakout `Composite` blueprint is
//! driven by the World *orchestration families* — `sweep` and
//! `walk_forward` — on REAL GER40 M1 bars, with NO re-authoring of the strategy.
//! This is the milestone-completing executable proof that the #94 friction is
//! gone: the same `ger40_breakout_blueprint` the single backtest bootstraps is
//! consumed verbatim by the World machinery.
//!
//! Mirrors `tests/ger40_breakout_real.rs` / `real_bars.rs`: skips with a note
//! where the local Pepperstone archive is absent, so `cargo test --workspace`
//! stays green anywhere; exercises the real path where the files exist.
//!
//! Two properties, both over the shipped blueprint:
//! - `sweep` returns a ranked grid over the two named params
//! (`entry_bar.target` × `exit_bar.target`), each point's `total_pips` finite —
//! the `param_space()` is driven directly.
//! - `walk_forward` returns a NON-EMPTY roll, every window carrying a NON-EMPTY
//! `chosen_params` (the executable #97 non-degenerate proof: a real, non-empty
//! space is optimized per window — contrast the fieldtest's empty-space
//! degenerate roll over the raw FlatGraph).
use std::sync::Arc;
use aura_core::{Cell, Scalar, Timestamp};
use aura_engine::{
sweep, summarize, walk_forward, GridSpace, RollMode, RunManifest, RunReport, WindowBounds,
WindowRoller, WindowRun,
};
use chrono::TimeZone;
use chrono_tz::Europe::Berlin;
use data_server::{DataServer, DEFAULT_DATA_PATH};
#[path = "../examples/shared/breakout_real.rs"]
mod breakout_real;
use breakout_real::*;
/// ns → ms: the shipped `open_ohlc_sources` opens by Unix-ms, but the World
/// `WindowBounds` are epoch-ns. `aura-ingest` exports only the forward direction
/// (`unix_ms_to_epoch_ns`), so the inverse is a local hand-divide (#80, filed).
fn ns_to_ms(ts: Timestamp) -> i64 {
ts.0 / 1_000_000
}
/// Bootstrap the shipped blueprint at one `{entry_bar, exit_bar}` point, run it
/// over `[from_ms, to_ms]` of real GER40 OHLC, and fold the recorded equity/held
/// taps into a `RunReport` (`summarize` over the drained channels — exactly as
/// the SMA-cross sweep fixture and the fieldtest's `run_point` do). A fresh
/// blueprint per call (fresh nodes + channels) keeps the disjoint sweep points
/// independent (C1).
fn run_point(server: &Arc<DataServer>, point: &[Cell], from_ms: i64, to_ms: i64) -> RunReport {
let (bp, taps) = ger40_breakout_blueprint(BAR_MINUTES, SESSION_HOUR, SESSION_MINUTE, Berlin);
let mut h = bp
.bootstrap_with_cells(point)
.expect("sweep point kind-checked against param_space");
let sources = open_ohlc_sources(server, from_ms, to_ms).expect("window overlaps GER40 data");
h.run(sources);
drop(h);
let equity: Vec<(Timestamp, f64)> = taps.equity.try_iter().collect::<Vec<_>>()
.iter()
.map(|(t, r)| (*t, scalar_f64(&r[0])))
.collect();
let exposure: Vec<(Timestamp, f64)> = taps.held.try_iter().collect::<Vec<_>>()
.iter()
.map(|(t, r)| (*t, scalar_f64(&r[0])))
.collect();
RunReport {
manifest: RunManifest {
commit: "ger40-breakout-world".to_string(),
params: vec![],
window: (
aura_ingest::unix_ms_to_epoch_ns(from_ms),
aura_ingest::unix_ms_to_epoch_ns(to_ms),
),
seed: 0,
broker: "sim-optimal(pip_size=1)".to_string(),
},
metrics: summarize(&equity, &exposure),
}
}
fn scalar_f64(s: &Scalar) -> f64 {
match s {
Scalar::F64(v) => *v,
other => panic!("expected f64, got {other:?}"),
}
}
/// Property: the World `sweep` family CONSUMES the shipped breakout blueprint
/// over its two named params on real GER40 — it returns a full ranked grid (no
/// re-authoring), and every grid point's `total_pips` is finite (a backtest
/// actually ran at each point). The grid is built from the blueprint's
/// `param_space()` directly, so the two `EqConst` targets are the swept axes.
#[test]
fn sweep_consumes_blueprint_over_named_params() {
let server = Arc::new(DataServer::new(DEFAULT_DATA_PATH));
if !server.has_symbol(SYMBOL) {
eprintln!("skip: no local data at {DEFAULT_DATA_PATH} (symbol {SYMBOL} absent)");
return;
}
let (from_ms, to_ms) = utc_month_window_ms(2024, 9);
let space = ger40_breakout_blueprint(BAR_MINUTES, SESSION_HOUR, SESSION_MINUTE, Berlin)
.0
.param_space();
// The grid is exactly over `param_space()`: entry ∈ {2,3,4}, exit ∈ {4,5,6}.
let grid = GridSpace::new(
&space,
space
.iter()
.map(|ps| match ps.name.as_str() {
"entry_bar.target" => vec![Scalar::i64(2), Scalar::i64(3), Scalar::i64(4)],
"exit_bar.target" => vec![Scalar::i64(4), Scalar::i64(5), Scalar::i64(6)],
other => panic!("unexpected param slot {other}"),
})
.collect(),
)
.expect("grid well-formed for the breakout param_space");
let server_for_closure = Arc::clone(&server);
let family = sweep(&grid, |pt: &[Cell]| {
run_point(&server_for_closure, pt, from_ms, to_ms)
});
// A full 3×3 grid was enumerated over the two named params (no re-authoring).
assert_eq!(family.points.len(), 9, "the 3×3 entry×exit grid must enumerate 9 points");
assert_eq!(
family.space.iter().map(|p| p.name.as_str()).collect::<Vec<_>>(),
vec!["entry_bar.target", "exit_bar.target"],
"the swept space is exactly the two genuine tuning knobs",
);
// Every point's metrics are finite — a real backtest ran at each grid point.
for (i, p) in family.points.iter().enumerate() {
assert!(
p.report.metrics.total_pips.is_finite(),
"point {i} {:?} produced a non-finite total_pips",
family.named_params(i),
);
}
// The best point (max total_pips) is finite — the ranked grid has a real head.
let best = family
.points
.iter()
.map(|p| p.report.metrics.total_pips)
.fold(f64::NEG_INFINITY, f64::max);
assert!(best.is_finite(), "the best grid point's total_pips must be finite");
}
/// Property: the World `walk_forward` family CONSUMES the shipped breakout
/// blueprint NON-DEGENERATELY (the executable #97 resolution). The roll over
/// multi-year GER40 yields a NON-EMPTY set of windows, and EACH window carries a
/// NON-EMPTY `chosen_params` — a real `{entry_bar, exit_bar}` point was selected
/// by an in-sample sweep per window (contrast the fieldtest's empty-space roll
/// over the raw FlatGraph, where `chosen_params == vec![]` everywhere).
#[test]
fn walk_forward_consumes_blueprint_non_degenerate() {
let server = Arc::new(DataServer::new(DEFAULT_DATA_PATH));
if !server.has_symbol(SYMBOL) {
eprintln!("skip: no local data at {DEFAULT_DATA_PATH} (symbol {SYMBOL} absent)");
return;
}
// A short 2-window roll over 2023..2024 keeps the gated test cheap while still
// exercising the per-window in-sample optimize. is=6mo, oos=3mo, step=3mo.
let day_ns: i64 = 86_400_000 * 1_000_000;
let month_ns: i64 = 30 * day_ns;
let origin = aura_ingest::unix_ms_to_epoch_ns(
chrono::Utc.with_ymd_and_hms(2023, 1, 1, 0, 0, 0).unwrap().timestamp_millis(),
);
let end = aura_ingest::unix_ms_to_epoch_ns(
chrono::Utc.with_ymd_and_hms(2024, 6, 30, 23, 59, 59).unwrap().timestamp_millis(),
);
let roller = WindowRoller::new(
(origin, end),
6 * month_ns,
3 * month_ns,
3 * month_ns,
RollMode::Rolling,
)
.expect("span fits >= 1 window");
// The non-empty space the in-sample sweep optimizes over per window: the two
// genuine tuning knobs. This is the #97 resolution — a real space, so the
// chosen params are populated, never an empty degenerate vec.
let space = ger40_breakout_blueprint(BAR_MINUTES, SESSION_HOUR, SESSION_MINUTE, Berlin)
.0
.param_space();
let server_for_closure = Arc::clone(&server);
let result = walk_forward(roller, space.clone(), move |w: WindowBounds| -> WindowRun {
// In-sample optimize: a tiny entry×exit grid over the IS window, choose the
// point with the best in-sample total_pips. The blueprint is consumed
// directly via its param_space() — no re-authoring.
let is_grid = GridSpace::new(
&space,
space
.iter()
.map(|ps| match ps.name.as_str() {
"entry_bar.target" => vec![Scalar::i64(2), Scalar::i64(3)],
"exit_bar.target" => vec![Scalar::i64(5), Scalar::i64(6)],
other => panic!("unexpected param slot {other}"),
})
.collect(),
)
.expect("IS grid well-formed");
let (is_from, is_to) = (ns_to_ms(w.is.0), ns_to_ms(w.is.1));
let is_family = sweep(&is_grid, |pt: &[Cell]| {
run_point(&server_for_closure, pt, is_from, is_to)
});
let best = is_family
.points
.iter()
.max_by(|a, b| {
a.report
.metrics
.total_pips
.partial_cmp(&b.report.metrics.total_pips)
.unwrap_or(std::cmp::Ordering::Equal)
})
.expect("the IS grid is non-empty");
let chosen = best.params.clone();
// Apply the chosen params on the OOS window.
let (oos_from, oos_to) = (ns_to_ms(w.oos.0), ns_to_ms(w.oos.1));
let oos_report = run_point(&server_for_closure, &chosen, oos_from, oos_to);
// Re-run once on OOS to capture the recorded equity segment for stitching.
let (bp, taps) =
ger40_breakout_blueprint(BAR_MINUTES, SESSION_HOUR, SESSION_MINUTE, Berlin);
let mut h = bp.bootstrap_with_cells(&chosen).expect("chosen point kind-checked");
let sources = open_ohlc_sources(&server_for_closure, oos_from, oos_to)
.expect("OOS window overlaps data");
h.run(sources);
drop(h);
let oos_equity: Vec<(Timestamp, f64)> = taps
.equity
.try_iter()
.collect::<Vec<_>>()
.iter()
.map(|(t, r)| (*t, scalar_f64(&r[0])))
.collect();
WindowRun { chosen_params: chosen, oos_equity, oos_report }
});
// Non-degenerate: a non-empty roll, EACH window carrying a non-empty chosen
// point (the #97 proof — a real space was optimized per window).
assert!(!result.windows.is_empty(), "walk_forward must yield >= 1 window");
for (k, w) in result.windows.iter().enumerate() {
assert!(
!w.run.chosen_params.is_empty(),
"window {k}: chosen_params must be NON-empty (the #97 non-degenerate proof)",
);
assert_eq!(
w.run.chosen_params.len(),
2,
"window {k}: chosen_params spans the two-param space",
);
assert!(
w.run.oos_report.metrics.total_pips.is_finite(),
"window {k}: OOS total_pips must be finite",
);
}
}