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.
This commit is contained in:
@@ -908,14 +908,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn walkforward_report_is_deterministic() {
|
fn walkforward_report_is_deterministic() {
|
||||||
// spec §Testing 10: the built-in WFO render is byte-identical across two
|
// The built-in WFO render is byte-identical across two
|
||||||
// calls (C1).
|
// calls (C1).
|
||||||
assert_eq!(walkforward_report(), walkforward_report());
|
assert_eq!(walkforward_report(), walkforward_report());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn walkforward_report_has_one_oos_line_per_window_plus_summary() {
|
fn walkforward_report_has_one_oos_line_per_window_plus_summary() {
|
||||||
// spec §Testing 11: N per-window OOS RunReport lines + one summary line.
|
// N per-window OOS RunReport lines + one summary line.
|
||||||
let out = walkforward_report();
|
let out = walkforward_report();
|
||||||
let lines: Vec<&str> = out.lines().collect();
|
let lines: Vec<&str> = out.lines().collect();
|
||||||
assert_eq!(lines.len(), 4); // built-in roll = 3 windows + 1 summary
|
assert_eq!(lines.len(), 4); // built-in roll = 3 windows + 1 summary
|
||||||
@@ -1116,7 +1116,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// E2E acceptance (#41 / spec 0019, the worked example): the real MACD strategy
|
/// E2E acceptance (#41, the worked example): the real MACD strategy
|
||||||
/// blueprint's swept param surface qualifies the three otherwise-indistinguishable
|
/// blueprint's swept param surface qualifies the three otherwise-indistinguishable
|
||||||
/// EMA `length` slots by node name to `macd.fast.length` / `macd.slow.length` /
|
/// EMA `length` slots by node name to `macd.fast.length` / `macd.slow.length` /
|
||||||
/// `macd.signal.length` — the named composite boundary visible end-to-end through
|
/// `macd.signal.length` — the named composite boundary visible end-to-end through
|
||||||
@@ -1149,7 +1149,7 @@ mod tests {
|
|||||||
/// C1-deterministic — two runs of the same window are bit-identical JSON.
|
/// C1-deterministic — two runs of the same window are bit-identical JSON.
|
||||||
///
|
///
|
||||||
/// Gated like the ingest `streaming_seam` test: skip (early return) when the
|
/// Gated like the ingest `streaming_seam` test: skip (early return) when the
|
||||||
/// local Pepperstone archive is absent, so the spec never fails on a machine
|
/// local Pepperstone archive is absent, so the test never fails on a machine
|
||||||
/// without the data. Uses the verified bounded 2006-08 `AAPL.US` window (the
|
/// without the data. Uses the verified bounded 2006-08 `AAPL.US` window (the
|
||||||
/// same FROM_MS/TO_MS the ingest seam test drives) so the two-run determinism
|
/// same FROM_MS/TO_MS the ingest seam test drives) so the two-run determinism
|
||||||
/// check stays fast.
|
/// check stays fast.
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ mod tests {
|
|||||||
/// deterministic model as the viewer's data source, carries the Graphviz-WASM
|
/// deterministic model as the viewer's data source, carries the Graphviz-WASM
|
||||||
/// bootstrap, and keeps the C4 four-colour palette. Structural, not pixel:
|
/// bootstrap, and keeps the C4 four-colour palette. Structural, not pixel:
|
||||||
/// the DOT/SVG are Graphviz-version-dependent and are exercised by hand
|
/// the DOT/SVG are Graphviz-version-dependent and are exercised by hand
|
||||||
/// against the prototype (spec Testing strategy).
|
/// against the prototype.
|
||||||
#[test]
|
#[test]
|
||||||
fn render_html_is_self_contained_and_embeds_the_model() {
|
fn render_html_is_self_contained_and_embeds_the_model() {
|
||||||
let html = render_html(&sample_blueprint());
|
let html = render_html(&sample_blueprint());
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//! `GraphBuilder` — name-based blueprint authoring (spec 0039).
|
//! `GraphBuilder` — name-based blueprint authoring.
|
||||||
//!
|
//!
|
||||||
//! A fluent, additive authoring surface that wires a blueprint by typed node
|
//! A fluent, additive authoring surface that wires a blueprint by typed node
|
||||||
//! handles and port/field *names*, resolving them to the raw-index `Composite`
|
//! handles and port/field *names*, resolving them to the raw-index `Composite`
|
||||||
@@ -65,7 +65,7 @@ pub enum BuildError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A fluent, additive accumulator that authors a [`Composite`] by typed handles
|
/// A fluent, additive accumulator that authors a [`Composite`] by typed handles
|
||||||
/// and port/field names. See the module docs and spec 0039.
|
/// and port/field names. See the module docs.
|
||||||
pub struct GraphBuilder {
|
pub struct GraphBuilder {
|
||||||
name: String,
|
name: String,
|
||||||
nodes: Vec<BlueprintNode>,
|
nodes: Vec<BlueprintNode>,
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn monte_carlo_runs_one_draw_per_seed_in_input_order() {
|
fn monte_carlo_runs_one_draw_per_seed_in_input_order() {
|
||||||
// spec §Testing 1: N seeds -> N draws, seeds carried in INPUT order.
|
// N seeds -> N draws, seeds carried in INPUT order.
|
||||||
let family = monte_carlo(&base_point(), &[1, 2, 3], run_draw);
|
let family = monte_carlo(&base_point(), &[1, 2, 3], run_draw);
|
||||||
assert_eq!(family.draws.len(), 3);
|
assert_eq!(family.draws.len(), 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -228,7 +228,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn family_is_deterministic_across_thread_counts() {
|
fn family_is_deterministic_across_thread_counts() {
|
||||||
// spec §Testing 2: order = seed input, not completion (C1).
|
// order = seed input, not completion (C1).
|
||||||
let point = base_point();
|
let point = base_point();
|
||||||
let seeds: Vec<u64> = (1..=8).collect();
|
let seeds: Vec<u64> = (1..=8).collect();
|
||||||
let one = monte_carlo_with_threads(&point, &seeds, 1, run_draw);
|
let one = monte_carlo_with_threads(&point, &seeds, 1, run_draw);
|
||||||
@@ -239,7 +239,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn draw_equals_independent_seeded_run() {
|
fn draw_equals_independent_seeded_run() {
|
||||||
// spec §Testing 3: each draw == an independent run of that (seed, point)
|
// each draw == an independent run of that (seed, point)
|
||||||
// — MC adds enumeration + execution, never a metrics change (C1).
|
// — MC adds enumeration + execution, never a metrics change (C1).
|
||||||
let point = base_point();
|
let point = base_point();
|
||||||
let family = monte_carlo(&point, &[10, 11, 12], run_draw);
|
let family = monte_carlo(&point, &[10, 11, 12], run_draw);
|
||||||
@@ -251,7 +251,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn distinct_seeds_produce_distinct_draws() {
|
fn distinct_seeds_produce_distinct_draws() {
|
||||||
// spec §Testing 4: the seed actually perturbs each run — the family does
|
// the seed actually perturbs each run — the family does
|
||||||
// not collapse to one metric.
|
// not collapse to one metric.
|
||||||
let family = monte_carlo(&base_point(), &[1, 2, 3, 4, 5], run_draw);
|
let family = monte_carlo(&base_point(), &[1, 2, 3, 4, 5], run_draw);
|
||||||
let first = family.draws[0].report.metrics.total_pips;
|
let first = family.draws[0].report.metrics.total_pips;
|
||||||
@@ -263,14 +263,14 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aggregate_is_a_pure_reduction() {
|
fn aggregate_is_a_pure_reduction() {
|
||||||
// spec §Testing 5: the stored aggregate is recomputable from the draws.
|
// the stored aggregate is recomputable from the draws.
|
||||||
let family = monte_carlo(&base_point(), &[1, 2, 3, 4], run_draw);
|
let family = monte_carlo(&base_point(), &[1, 2, 3, 4], run_draw);
|
||||||
assert_eq!(McAggregate::from_draws(&family.draws), family.aggregate);
|
assert_eq!(McAggregate::from_draws(&family.draws), family.aggregate);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn aggregate_stats_on_known_fixture() {
|
fn aggregate_stats_on_known_fixture() {
|
||||||
// spec §Testing 6: type-7 quantile + mean over known metric values
|
// type-7 quantile + mean over known metric values
|
||||||
// [0,1,2,3,4]: mean=2.0, p50=2.0, p5≈0.2, p95≈3.8.
|
// [0,1,2,3,4]: mean=2.0, p50=2.0, p5≈0.2, p95≈3.8.
|
||||||
let agg = McAggregate::from_draws(&draws_with_metrics(&[0.0, 1.0, 2.0, 3.0, 4.0]));
|
let agg = McAggregate::from_draws(&draws_with_metrics(&[0.0, 1.0, 2.0, 3.0, 4.0]));
|
||||||
assert_eq!(agg.total_pips.mean, 2.0);
|
assert_eq!(agg.total_pips.mean, 2.0);
|
||||||
@@ -281,7 +281,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn quantile_endpoints_and_singleton() {
|
fn quantile_endpoints_and_singleton() {
|
||||||
// spec §Testing 7: singleton returns the sole value; p=0 -> min, p=1 -> max.
|
// singleton returns the sole value; p=0 -> min, p=1 -> max.
|
||||||
assert_eq!(quantile(&[42.0], 0.0), 42.0);
|
assert_eq!(quantile(&[42.0], 0.0), 42.0);
|
||||||
assert_eq!(quantile(&[42.0], 0.5), 42.0);
|
assert_eq!(quantile(&[42.0], 0.5), 42.0);
|
||||||
assert_eq!(quantile(&[42.0], 1.0), 42.0);
|
assert_eq!(quantile(&[42.0], 1.0), 42.0);
|
||||||
@@ -292,7 +292,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn metric_stats_from_values_matches_known_fixture() {
|
fn metric_stats_from_values_matches_known_fixture() {
|
||||||
// spec §Testing 9: type-7 quantile + mean over [0,1,2,3,4], directly on the
|
// type-7 quantile + mean over [0,1,2,3,4], directly on the
|
||||||
// extracted reduction: mean=2.0, p50=2.0, p5≈0.2, p95≈3.8 (same numbers the
|
// extracted reduction: mean=2.0, p50=2.0, p5≈0.2, p95≈3.8 (same numbers the
|
||||||
// aggregate fixture pins, now on from_values).
|
// aggregate fixture pins, now on from_values).
|
||||||
let s = MetricStats::from_values(&[0.0, 1.0, 2.0, 3.0, 4.0]);
|
let s = MetricStats::from_values(&[0.0, 1.0, 2.0, 3.0, 4.0]);
|
||||||
@@ -304,7 +304,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn metric_stats_serde_round_trips() {
|
fn metric_stats_serde_round_trips() {
|
||||||
// spec §Concrete code shapes: MetricStats gains serde (consistent with the
|
// MetricStats gains serde (consistent with the
|
||||||
// report types) so the CLI summary renders it and #70 lineage can persist.
|
// report types) so the CLI summary renders it and #70 lineage can persist.
|
||||||
let s = MetricStats::from_values(&[1.0, 2.0, 3.0]);
|
let s = MetricStats::from_values(&[1.0, 2.0, 3.0]);
|
||||||
let json = serde_json::to_string(&s).expect("serialize MetricStats");
|
let json = serde_json::to_string(&s).expect("serialize MetricStats");
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ impl Space for RandomSpace {
|
|||||||
// inclusive [lo, hi]; span via i128 then u64 handles a negative lo.
|
// inclusive [lo, hi]; span via i128 then u64 handles a negative lo.
|
||||||
// (Modulo bias for spans not dividing 2^64 is an accepted,
|
// (Modulo bias for spans not dividing 2^64 is an accepted,
|
||||||
// documented simplification — param search needs no crypto
|
// documented simplification — param search needs no crypto
|
||||||
// uniformity, spec §"Error handling".)
|
// uniformity.)
|
||||||
ScalarKind::I64 => {
|
ScalarKind::I64 => {
|
||||||
let (lo, hi) = (r.lo.as_i64(), r.hi.as_i64());
|
let (lo, hi) = (r.lo.as_i64(), r.hi.as_i64());
|
||||||
// span is 1..=2^64; the full-width span [i64::MIN, i64::MAX]
|
// span is 1..=2^64; the full-width span [i64::MIN, i64::MAX]
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn walk_forward_runs_one_window_per_split_in_roll_order() {
|
fn walk_forward_runs_one_window_per_split_in_roll_order() {
|
||||||
// spec §Testing 5: N bounds -> N outcomes, bounds in roll order.
|
// N bounds -> N outcomes, bounds in roll order.
|
||||||
let roller =
|
let roller =
|
||||||
WindowRoller::new((Timestamp(0), Timestamp(24)), 10, 5, 5, RollMode::Rolling)
|
WindowRoller::new((Timestamp(0), Timestamp(24)), 10, 5, 5, RollMode::Rolling)
|
||||||
.expect("valid");
|
.expect("valid");
|
||||||
@@ -349,7 +349,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn walk_forward_is_deterministic_across_thread_counts() {
|
fn walk_forward_is_deterministic_across_thread_counts() {
|
||||||
// spec §Testing 6: order is roll order, not completion (C1).
|
// order is roll order, not completion (C1).
|
||||||
let cfg = || {
|
let cfg = || {
|
||||||
WindowRoller::new((Timestamp(0), Timestamp(100)), 20, 5, 5, RollMode::Rolling)
|
WindowRoller::new((Timestamp(0), Timestamp(100)), 20, 5, 5, RollMode::Rolling)
|
||||||
.expect("valid")
|
.expect("valid")
|
||||||
@@ -362,7 +362,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stitched_curve_carries_equity_forward() {
|
fn stitched_curve_carries_equity_forward() {
|
||||||
// spec §Testing 7: segs [(t0,2),(t1,5)] then [(t2,1),(t3,3)] ->
|
// segs [(t0,2),(t1,5)] then [(t2,1),(t3,3)] ->
|
||||||
// [(t0,2),(t1,5),(t2,6),(t3,8)] (offset by prior segment's final value 5).
|
// [(t0,2),(t1,5),(t2,6),(t3,8)] (offset by prior segment's final value 5).
|
||||||
let windows = vec![
|
let windows = vec![
|
||||||
outcome(vec![(Timestamp(0), 2.0), (Timestamp(1), 5.0)], vec![]),
|
outcome(vec![(Timestamp(0), 2.0), (Timestamp(1), 5.0)], vec![]),
|
||||||
@@ -381,7 +381,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stitched_curve_passes_through_empty_segment() {
|
fn stitched_curve_passes_through_empty_segment() {
|
||||||
// spec §Testing 7b: an empty OOS segment adds 0.0 to the offset and no
|
// an empty OOS segment adds 0.0 to the offset and no
|
||||||
// points: [(t0,2),(t1,5)], [], [(t2,1)] -> [(t0,2),(t1,5),(t2,6)].
|
// points: [(t0,2),(t1,5)], [], [(t2,1)] -> [(t0,2),(t1,5),(t2,6)].
|
||||||
let windows = vec![
|
let windows = vec![
|
||||||
outcome(vec![(Timestamp(0), 2.0), (Timestamp(1), 5.0)], vec![]),
|
outcome(vec![(Timestamp(0), 2.0), (Timestamp(1), 5.0)], vec![]),
|
||||||
@@ -396,7 +396,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn param_stability_reduces_chosen_params_per_slot() {
|
fn param_stability_reduces_chosen_params_per_slot() {
|
||||||
// spec §Testing 8: on-demand reduction over chosen params across windows.
|
// on-demand reduction over chosen params across windows.
|
||||||
// slot 0 [2,2,3,3] -> mean 2.5, p50 2.5; slot 1 [1,1,2,2] -> mean 1.5.
|
// slot 0 [2,2,3,3] -> mean 2.5, p50 2.5; slot 1 [1,1,2,2] -> mean 1.5.
|
||||||
let mk = |a: i64, b: f64| WindowOutcome {
|
let mk = |a: i64, b: f64| WindowOutcome {
|
||||||
bounds: WindowBounds {
|
bounds: WindowBounds {
|
||||||
@@ -423,7 +423,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn param_stability_reduces_bool_slot_to_fraction_true() {
|
fn param_stability_reduces_bool_slot_to_fraction_true() {
|
||||||
// spec §Testing: a Bool param slot coerces 0/1, so mean = fraction of
|
// a Bool param slot coerces 0/1, so mean = fraction of
|
||||||
// windows that chose `true`. 3 of 4 true -> 0.75.
|
// windows that chose `true`. 3 of 4 true -> 0.75.
|
||||||
let mk = |flag: bool| WindowOutcome {
|
let mk = |flag: bool| WindowOutcome {
|
||||||
bounds: WindowBounds {
|
bounds: WindowBounds {
|
||||||
@@ -490,7 +490,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roller_rolling_emits_consecutive_oos_windows() {
|
fn roller_rolling_emits_consecutive_oos_windows() {
|
||||||
// spec §Testing 1: rolling, origin=0, is_len=10, oos_len=5, step=5, end=24.
|
// rolling, origin=0, is_len=10, oos_len=5, step=5, end=24.
|
||||||
// w0 is(0,9) oos(10,14); w1 is(5,14) oos(15,19); w2 is(10,19) oos(20,24);
|
// w0 is(0,9) oos(10,14); w1 is(5,14) oos(15,19); w2 is(10,19) oos(20,24);
|
||||||
// w3 would need oos(25,29) > 24 -> stop. 3 windows; OOS tiles (step==oos_len).
|
// w3 would need oos(25,29) > 24 -> stop. 3 windows; OOS tiles (step==oos_len).
|
||||||
let roller =
|
let roller =
|
||||||
@@ -514,7 +514,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roller_anchored_fixes_is_start_grows_is_end() {
|
fn roller_anchored_fixes_is_start_grows_is_end() {
|
||||||
// spec §Testing 2: anchored, same config — IS always starts at origin (0)
|
// anchored, same config — IS always starts at origin (0)
|
||||||
// and grows; OOS positions identical to rolling.
|
// and grows; OOS positions identical to rolling.
|
||||||
let roller =
|
let roller =
|
||||||
WindowRoller::new((Timestamp(0), Timestamp(24)), 10, 5, 5, RollMode::Anchored)
|
WindowRoller::new((Timestamp(0), Timestamp(24)), 10, 5, 5, RollMode::Anchored)
|
||||||
@@ -538,7 +538,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roller_every_split_has_no_lookahead() {
|
fn roller_every_split_has_no_lookahead() {
|
||||||
// spec §Testing 3 (C2): every emitted split has oos.0 > is.1, zero ticks.
|
// (C2): every emitted split has oos.0 > is.1, zero ticks.
|
||||||
for mode in [RollMode::Rolling, RollMode::Anchored] {
|
for mode in [RollMode::Rolling, RollMode::Anchored] {
|
||||||
let roller = WindowRoller::new((Timestamp(0), Timestamp(100)), 20, 7, 3, mode)
|
let roller = WindowRoller::new((Timestamp(0), Timestamp(100)), 20, 7, 3, mode)
|
||||||
.expect("valid config");
|
.expect("valid config");
|
||||||
@@ -550,7 +550,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roller_rejects_nonpositive_lengths_and_short_span() {
|
fn roller_rejects_nonpositive_lengths_and_short_span() {
|
||||||
// spec §Testing 4: typed config faults before any run.
|
// typed config faults before any run.
|
||||||
let span = (Timestamp(0), Timestamp(100));
|
let span = (Timestamp(0), Timestamp(100));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
WindowRoller::new(span, 0, 5, 5, RollMode::Rolling).unwrap_err(),
|
WindowRoller::new(span, 0, 5, 5, RollMode::Rolling).unwrap_err(),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! End-to-end verification of the GER40 / DAX 15-minute session-breakout
|
//! End-to-end verification of the GER40 / DAX 15-minute session-breakout
|
||||||
//! strategy (spec 0050 §6, build-step 8 — the milestone capstone), hand-wired
|
//! strategy (the milestone capstone), hand-wired
|
||||||
//! from the seven new `aura-std` nodes into a raw-index [`FlatGraph`] and run
|
//! from the seven new `aura-std` nodes into a raw-index [`FlatGraph`] and run
|
||||||
//! over one synthetic Frankfurt session.
|
//! over one synthetic Frankfurt session.
|
||||||
//!
|
//!
|
||||||
@@ -178,7 +178,7 @@ fn build_harness(
|
|||||||
/// bar1 high=100; bar2 high=110, close=108; bar3 close=112 (> bar2 high → the
|
/// bar1 high=100; bar2 high=110, close=108; bar3 close=112 (> bar2 high → the
|
||||||
/// strict breakout, and bars_since_open==3 → ENTRY); bar4 close=115; bar5
|
/// strict breakout, and bars_since_open==3 → ENTRY); bar4 close=115; bar5
|
||||||
/// close=120; then a single 10:15 rollover tick (bar6) that CLOSES bar5 (else the
|
/// close=120; then a single 10:15 rollover tick (bar6) that CLOSES bar5 (else the
|
||||||
/// partial last bar is dropped and exposure leaks to EOF — the spec's trap (a)).
|
/// partial last bar is dropped and exposure leaks to EOF — trap (a)).
|
||||||
/// bars 1 and 2 precede the bar3 entry so `Delay[1]` is warm (trap (b)).
|
/// bars 1 and 2 precede the bar3 entry so `Delay[1]` is warm (trap (b)).
|
||||||
fn entry_session_ticks() -> Vec<M1> {
|
fn entry_session_ticks() -> Vec<M1> {
|
||||||
vec![
|
vec![
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! End-to-end coverage for the random param-sweep axis (spec 0049, C12.1):
|
//! End-to-end coverage for the random param-sweep axis (C12.1):
|
||||||
//! `RandomSpace` + `ParamRange` driven through the **public** `sweep` surface a
|
//! `RandomSpace` + `ParamRange` driven through the **public** `sweep` surface a
|
||||||
//! downstream researcher actually writes (the spec's "Worked author example").
|
//! downstream researcher actually writes (the worked author example).
|
||||||
//!
|
//!
|
||||||
//! The in-module unit tests in `sweep.rs` reach into crate internals
|
//! The in-module unit tests in `sweep.rs` reach into crate internals
|
||||||
//! (`bootstrap_with_cells`, `sweep_with_threads`, `SplitMix64`); these tests use
|
//! (`bootstrap_with_cells`, `sweep_with_threads`, `SplitMix64`); these tests use
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Runnable World-family demo: **`compare`** the session-breakout `Composite`
|
//! Runnable World-family demo: **`compare`** the session-breakout `Composite`
|
||||||
//! blueprint (spec 0051) across two structural axes (C11/C20 experiment matrix),
|
//! blueprint across two structural axes (C11/C20 experiment matrix),
|
||||||
//! on REAL data, with NO re-authoring:
|
//! on REAL data, with NO re-authoring:
|
||||||
//!
|
//!
|
||||||
//! 1. **Instrument** — GER40 vs FRA40 (both `pip_size = 1.0`, index points), the
|
//! 1. **Instrument** — GER40 vs FRA40 (both `pip_size = 1.0`, index points), the
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
//! symbol. The pip honesty is by construction (both quote in index points; the
|
//! symbol. The pip honesty is by construction (both quote in index points; the
|
||||||
//! engine has no pip registry yet — #22, filed).
|
//! engine has no pip registry yet — #22, filed).
|
||||||
//! 2. **Bar period** — a 15m blueprint vs a 30m blueprint. The bar period is a
|
//! 2. **Bar period** — a 15m blueprint vs a 30m blueprint. The bar period is a
|
||||||
//! STRUCTURAL axis (§2 / C34): `ger40_breakout_blueprint` is instantiated TWICE,
|
//! STRUCTURAL axis (C34): `ger40_breakout_blueprint` is instantiated TWICE,
|
||||||
//! at 15 and at 30, each a *different strategy* (the period is bound at
|
//! at 15 and at 30, each a *different strategy* (the period is bound at
|
||||||
//! construction, locking Resample and Session equal — it is NOT a sweep param).
|
//! construction, locking Resample and Session equal — it is NOT a sweep param).
|
||||||
//!
|
//!
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//! This is a *pure composition* of SHIPPED `aura-std` nodes: no project-specific
|
//! This is a *pure composition* of SHIPPED `aura-std` nodes: no project-specific
|
||||||
//! signal code, so it lives in the engine repo's `examples/` carveout (C9), not
|
//! signal code, so it lives in the engine repo's `examples/` carveout (C9), not
|
||||||
//! a separate project crate. The strategy is authored as a World-consumable
|
//! a separate project crate. The strategy is authored as a World-consumable
|
||||||
//! `Composite` blueprint (`ger40_breakout_blueprint`, spec 0051) and bootstrapped
|
//! `Composite` blueprint (`ger40_breakout_blueprint`) and bootstrapped
|
||||||
//! here by name (`entry_bar=3`, `exit_bar=5`); the four real `M1FieldSource`s
|
//! here by name (`entry_bar=3`, `exit_bar=5`); the four real `M1FieldSource`s
|
||||||
//! feed its four OHLC source roles. The blueprint reproduces the shipped
|
//! feed its four OHLC source roles. The blueprint reproduces the shipped
|
||||||
//! hand-wired `FlatGraph` EXACTLY (C23), so this prints the same report + trace.
|
//! hand-wired `FlatGraph` EXACTLY (C23), so this prints the same report + trace.
|
||||||
@@ -59,7 +59,7 @@ fn main() {
|
|||||||
// Author the breakout as a Composite blueprint and bootstrap it by name with
|
// Author the breakout as a Composite blueprint and bootstrap it by name with
|
||||||
// the two genuine tuning knobs (entry bar 3, exit bar 5). The bar-period (15m),
|
// the two genuine tuning knobs (entry bar 3, exit bar 5). The bar-period (15m),
|
||||||
// session open (09:00 Berlin) and delay.lag are structural — bound at
|
// session open (09:00 Berlin) and delay.lag are structural — bound at
|
||||||
// construction, not exposed as params (spec 0051 §2).
|
// construction, not exposed as params.
|
||||||
let (bp, taps) = ger40_breakout_blueprint(BAR_MINUTES, SESSION_HOUR, SESSION_MINUTE, Berlin);
|
let (bp, taps) = ger40_breakout_blueprint(BAR_MINUTES, SESSION_HOUR, SESSION_MINUTE, Berlin);
|
||||||
let mut h = bp
|
let mut h = bp
|
||||||
.with("entry_bar.target", aura_core::Scalar::i64(3))
|
.with("entry_bar.target", aura_core::Scalar::i64(3))
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Runnable World-family demo: **`sweep`** the GER40 session-breakout `Composite`
|
//! Runnable World-family demo: **`sweep`** the GER40 session-breakout `Composite`
|
||||||
//! blueprint (spec 0051) over its two genuine tuning knobs — `entry_bar.target` ×
|
//! blueprint over its two genuine tuning knobs — `entry_bar.target` ×
|
||||||
//! `exit_bar.target` — on REAL GER40 M1 bars, ranked by `total_pips`. This is the
|
//! `exit_bar.target` — on REAL GER40 M1 bars, ranked by `total_pips`. This is the
|
||||||
//! core proof that the shipped strategy is World-consumable: the SAME
|
//! core proof that the shipped strategy is World-consumable: the SAME
|
||||||
//! `ger40_breakout_blueprint` the single backtest bootstraps is driven through the
|
//! `ger40_breakout_blueprint` the single backtest bootstraps is driven through the
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Runnable World-family demo: **`walk_forward`** the GER40 session-breakout
|
//! Runnable World-family demo: **`walk_forward`** the GER40 session-breakout
|
||||||
//! `Composite` blueprint (spec 0051) across multi-year real GER40 history, with a
|
//! `Composite` blueprint across multi-year real GER40 history, with a
|
||||||
//! per-window in-sample optimize of its two genuine tuning knobs
|
//! per-window in-sample optimize of its two genuine tuning knobs
|
||||||
//! (`entry_bar.target` × `exit_bar.target`). This is the executable #97
|
//! (`entry_bar.target` × `exit_bar.target`). This is the executable #97
|
||||||
//! resolution: the roll is NON-DEGENERATE — a real, non-empty `param_space()` is
|
//! resolution: the roll is NON-DEGENERATE — a real, non-empty `param_space()` is
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ pub fn build_harness() -> (Harness, Taps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Author the GER40 session-breakout as a World-consumable [`Composite`]
|
/// Author the GER40 session-breakout as a World-consumable [`Composite`]
|
||||||
/// blueprint (spec 0051) — the canonical shippable form of the strategy, of which
|
/// blueprint — the canonical shippable form of the strategy, of which
|
||||||
/// [`build_harness`]'s hand-wired `FlatGraph` is the compiled substrate (C11/C23).
|
/// [`build_harness`]'s hand-wired `FlatGraph` is the compiled substrate (C11/C23).
|
||||||
///
|
///
|
||||||
/// This is the SAME 13-node breakout `build_harness` wires by raw index, authored
|
/// This is the SAME 13-node breakout `build_harness` wires by raw index, authored
|
||||||
@@ -203,7 +203,7 @@ pub fn build_harness() -> (Harness, Taps) {
|
|||||||
/// `param_space()` / the by-name binder / `bootstrap_with_cells`, so `sweep` /
|
/// `param_space()` / the by-name binder / `bootstrap_with_cells`, so `sweep` /
|
||||||
/// `walk_forward` / compare consume it with NO re-authoring (the #94 friction).
|
/// `walk_forward` / compare consume it with NO re-authoring (the #94 friction).
|
||||||
///
|
///
|
||||||
/// The spec-0051 structural decisions are baked here, not left to the caller:
|
/// The structural decisions are baked here, not left to the caller:
|
||||||
/// - `bar_period_minutes` binds BOTH the period-bearing nodes at construction —
|
/// - `bar_period_minutes` binds BOTH the period-bearing nodes at construction —
|
||||||
/// `Resample`'s `period_minutes` param AND `Session`'s baked period — so the two
|
/// `Resample`'s `period_minutes` param AND `Session`'s baked period — so the two
|
||||||
/// are LOCKED EQUAL and a sweep cannot desync them to 0.0 pips (#96 / C34: a
|
/// are LOCKED EQUAL and a sweep cannot desync them to 0.0 pips (#96 / C34: a
|
||||||
@@ -238,8 +238,8 @@ pub fn ger40_breakout_blueprint(
|
|||||||
|
|
||||||
let mut g = GraphBuilder::new("ger40_breakout");
|
let mut g = GraphBuilder::new("ger40_breakout");
|
||||||
|
|
||||||
// Strategy nodes. The two period-bearing nodes are bound EQUAL by construction
|
// Strategy nodes. The two period-bearing nodes are bound EQUAL by construction:
|
||||||
// (§2): Resample's `period_minutes` param and Session's baked period both take
|
// Resample's `period_minutes` param and Session's baked period both take
|
||||||
// `bar_period_minutes`, so no sweep can desync them. `delay.lag` is bound out.
|
// `bar_period_minutes`, so no sweep can desync them. `delay.lag` is bound out.
|
||||||
let resample = g.add(
|
let resample = g.add(
|
||||||
Resample::builder().bind("period_minutes", Scalar::i64(bar_period_minutes)),
|
Resample::builder().bind("period_minutes", Scalar::i64(bar_period_minutes)),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Gated integration test: the GER40 session-breakout shipped as a
|
//! Gated integration test: the GER40 session-breakout shipped as a
|
||||||
//! World-consumable `Composite` blueprint (spec 0051). Proves the blueprint
|
//! World-consumable `Composite` blueprint. Proves the blueprint
|
||||||
//! reproduces the shipped hand-wired `FlatGraph` EXACTLY (C23) and that its
|
//! reproduces the shipped hand-wired `FlatGraph` EXACTLY (C23) and that its
|
||||||
//! `param_space()` is the two genuine tuning knobs only — no `delay.lag`, no
|
//! `param_space()` is the two genuine tuning knobs only — no `delay.lag`, no
|
||||||
//! bar-period (the desync trap, #96).
|
//! bar-period (the desync trap, #96).
|
||||||
@@ -44,7 +44,7 @@ fn param_space_is_exactly_entry_and_exit_bar_targets() {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
names,
|
names,
|
||||||
vec!["entry_bar.target", "exit_bar.target"],
|
vec!["entry_bar.target", "exit_bar.target"],
|
||||||
"param_space() must be exactly the two EqConst targets (spec 0051 §2)",
|
"param_space() must be exactly the two EqConst targets",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Belt-and-braces on the two specific leaks #96 named, independent of order.
|
// Belt-and-braces on the two specific leaks #96 named, independent of order.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//! Gated integration test: the GER40 session-breakout `Composite` blueprint
|
//! Gated integration test: the GER40 session-breakout `Composite` blueprint is
|
||||||
//! (spec 0051) is driven by the World *orchestration families* — `sweep` and
|
//! driven by the World *orchestration families* — `sweep` and
|
||||||
//! `walk_forward` — on REAL GER40 M1 bars, with NO re-authoring of the strategy.
|
//! `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
|
//! This is the milestone-completing executable proof that the #94 friction is
|
||||||
//! gone: the same `ger40_breakout_blueprint` the single backtest bootstraps is
|
//! gone: the same `ger40_breakout_blueprint` the single backtest bootstraps is
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ publish.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aura-core = { path = "../aura-core" }
|
aura-core = { path = "../aura-core" }
|
||||||
# DST-correct wall-clock math for the `Session` node (spec 0050 §4.5). A vetted
|
# DST-correct wall-clock math for the `Session` node. A vetted
|
||||||
# standard crate for timezone/DST — never hand-rolled (C16 per-case policy).
|
# standard crate for timezone/DST — never hand-rolled (C16 per-case policy).
|
||||||
# `chrono` is already a transitive workspace dep (0.4 via aura-ingest's
|
# `chrono` is already a transitive workspace dep (0.4 via aura-ingest's
|
||||||
# data-server); aligned to that major. `chrono-tz` brings the IANA `Europe/Berlin`
|
# data-server); aligned to that major. `chrono-tz` brings the IANA `Europe/Berlin`
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
//! no params. **Emits `f64` directly**, not `bool`: a held position *is*
|
//! no params. **Emits `f64` directly**, not `bool`: a held position *is*
|
||||||
//! exposure `+1`, flat *is* `0.0`, so the output feeds [`SimBroker`](crate::SimBroker)'s
|
//! exposure `+1`, flat *is* `0.0`, so the output feeds [`SimBroker`](crate::SimBroker)'s
|
||||||
//! `f64` `exposure` slot with no cast — this is the resolution of the `bool → f64`
|
//! `f64` `exposure` slot with no cast — this is the resolution of the `bool → f64`
|
||||||
//! seam (spec 0050 §4.2; no separate `Exposure`/cast node).
|
//! seam (no separate `Exposure`/cast node).
|
||||||
//!
|
//!
|
||||||
//! **State.** A persisted `held: f64`, initial `0.0`, mutated in `eval` and
|
//! **State.** A persisted `held: f64`, initial `0.0`, mutated in `eval` and
|
||||||
//! carried across cycles in the struct — exactly how [`SimBroker`](crate::SimBroker)
|
//! carried across cycles in the struct — exactly how [`SimBroker`](crate::SimBroker)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
//!
|
//!
|
||||||
//! **Timestamp (C4).** The completed bar carries no timestamp of its own — the
|
//! **Timestamp (C4).** The completed bar carries no timestamp of its own — the
|
||||||
//! engine stamps the emission cycle's `ctx.now()` (the new bucket's first M1
|
//! engine stamps the emission cycle's `ctx.now()` (the new bucket's first M1
|
||||||
//! instant, which is the close instant of the bar just emitted, spec 0050 §4.1).
|
//! instant, which is the close instant of the bar just emitted).
|
||||||
//! The node only returns the 4 OHLC values.
|
//! The node only returns the 4 OHLC values.
|
||||||
//!
|
//!
|
||||||
//! **Partial last bar is DROPPED.** There is no end-of-stream flush: a bucket with
|
//! **Partial last bar is DROPPED.** There is no end-of-stream flush: a bucket with
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
//! build (like `SimBroker::builder(fee)` bakes its fee); a timezone is not a
|
//! build (like `SimBroker::builder(fee)` bakes its fee); a timezone is not a
|
||||||
//! scalar, so it is captured by the closure, not declared as a param.
|
//! scalar, so it is captured by the closure, not declared as a param.
|
||||||
//!
|
//!
|
||||||
//! **Semantics (spec 0050 §4).** Let `local = <ctx.now() epoch-ns UTC> converted
|
//! **Semantics.** Let `local = <ctx.now() epoch-ns UTC> converted
|
||||||
//! to tz` (chrono-tz, DST-correct). Let
|
//! to tz` (chrono-tz, DST-correct). Let
|
||||||
//! `mins = (local.hour()*60 + local.minute()) - (open_hour*60 + open_minute)`.
|
//! `mins = (local.hour()*60 + local.minute()) - (open_hour*60 + open_minute)`.
|
||||||
//! Emit `bars_since_open = mins / period_minutes` (i64 division). The resampler
|
//! Emit `bars_since_open = mins / period_minutes` (i64 division). The resampler
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
//! / `EqConst(==5)` gates simply never match; there is no separate in-session
|
//! / `EqConst(==5)` gates simply never match; there is no separate in-session
|
||||||
//! bool gate, `bars_since_open` alone is the contract).
|
//! bool gate, `bars_since_open` alone is the contract).
|
||||||
//!
|
//!
|
||||||
//! **Off-by-one (close-instant indexing, spec 0050 §4.1).** `ctx.now()` at a
|
//! **Off-by-one (close-instant indexing).** `ctx.now()` at a
|
||||||
//! resampler emission is the **just-closed** bar's *close instant*, so "the bar
|
//! resampler emission is the **just-closed** bar's *close instant*, so "the bar
|
||||||
//! that closed at 09:45" reads `bars_since_open == 3`.
|
//! that closed at 09:45" reads `bars_since_open == 3`.
|
||||||
//!
|
//!
|
||||||
@@ -85,8 +85,8 @@ impl Node for Session {
|
|||||||
if ctx.f64_in(0).is_empty() {
|
if ctx.f64_in(0).is_empty() {
|
||||||
return None; // cold: trigger has not fired yet
|
return None; // cold: trigger has not fired yet
|
||||||
}
|
}
|
||||||
// Convert the engine's epoch-ns UTC instant (close-instant, spec 0050
|
// Convert the engine's epoch-ns UTC instant (close-instant) into
|
||||||
// §4.1) into tz-aware LOCAL wall-clock — chrono-tz applies the correct
|
// tz-aware LOCAL wall-clock — chrono-tz applies the correct
|
||||||
// DST offset for this date, so the same local minute reads the same bar
|
// DST offset for this date, so the same local minute reads the same bar
|
||||||
// index in summer (CEST) and winter (CET).
|
// index in summer (CEST) and winter (CET).
|
||||||
let local = self.tz.timestamp_nanos(ctx.now().0);
|
let local = self.tz.timestamp_nanos(ctx.now().0);
|
||||||
@@ -135,7 +135,7 @@ mod tests {
|
|||||||
fn session_indexes_bars_since_frankfurt_open_in_local_dst_aware_time() {
|
fn session_indexes_bars_since_frankfurt_open_in_local_dst_aware_time() {
|
||||||
// THE HEADLINE PROPERTY: bars_since_open = (local wall-clock minutes past
|
// THE HEADLINE PROPERTY: bars_since_open = (local wall-clock minutes past
|
||||||
// the 09:00 Frankfurt open) / period, in tz-aware LOCAL time. Because the
|
// the 09:00 Frankfurt open) / period, in tz-aware LOCAL time. Because the
|
||||||
// close instant is the bucket boundary (:00/:15/:30/:45, spec 0050 §4.1),
|
// close instant is the bucket boundary (:00/:15/:30/:45),
|
||||||
// in-session bar closes are exact positive multiples of the bar index.
|
// in-session bar closes are exact positive multiples of the bar index.
|
||||||
//
|
//
|
||||||
// Built from Berlin local wall-clock via chrono-tz so the assertion is
|
// Built from Berlin local wall-clock via chrono-tz so the assertion is
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ mod tests {
|
|||||||
// param-carrying single nodes
|
// param-carrying single nodes
|
||||||
assert_eq!(Exposure::new(0.5).label(), "Exposure(0.5)");
|
assert_eq!(Exposure::new(0.5).label(), "Exposure(0.5)");
|
||||||
assert_eq!(SimBroker::new(0.0001).label(), "SimBroker(0.0001)");
|
assert_eq!(SimBroker::new(0.0001).label(), "SimBroker(0.0001)");
|
||||||
// bare-kind nodes (identity is not a mis-wiring axis here, per spec)
|
// bare-kind nodes (identity is not a mis-wiring axis here)
|
||||||
assert_eq!(Sub::new().label(), "Sub");
|
assert_eq!(Sub::new().label(), "Sub");
|
||||||
assert_eq!(Add::new().label(), "Add");
|
assert_eq!(Add::new().label(), "Add");
|
||||||
assert_eq!(LinComb::new(vec![1.0, -1.0]).label(), "LinComb");
|
assert_eq!(LinComb::new(vec![1.0, -1.0]).label(), "LinComb");
|
||||||
|
|||||||
Reference in New Issue
Block a user