perf(ingest,cli): derive archive bounds from the monthly file index — probe_window drain retired

probe_window drained a source's entire close column just to learn its
first and last bar timestamp; both live callers (open_real_source and
campaign_window_ms on the campaign trunk) now resolve through
aura-ingest's new archive_extent(): list the symbol's SYM_YYYY_MM.m1
files, load only the boundary months via the existing loader seam, and
walk across gap months forward/backward — O(2 file loads) typical
instead of O(archive). Empty-window refusal semantics are unchanged
(pinned). Two characterization tests captured the resolved windows
against the OLD implementation over the synthetic per-test archive and
stay green unchanged after the swap.

Measured: the probe itself drops 366ms -> 13ms (~28x) on the full
2014-2026 GER40 archive; end-to-end command wall-clock moves only
~2-3% because the sim loop dominates — the fix removes an
O(archive-size) term, not the dominant cost.

closes #252
This commit is contained in:
2026-07-13 16:33:18 +02:00
parent 479c6620e2
commit a895891ab1
5 changed files with 456 additions and 10 deletions
+135
View File
@@ -5694,6 +5694,141 @@ fn shipped_r_sma_example_reproduces_the_builtin_grade() {
assert!(stdout.contains("\"n_trades\":3"), "{stdout}");
}
/// Characterization pin (#252, byte-identity anchor before `probe_window`'s
/// internals swap from a full-window drain to `aura_ingest::archive_extent`'s
/// boundary-month derivation). Captured against the PRE-#252 drain-based code
/// over `fresh_project_with_data`'s hermetic two-symbol synthetic archive
/// (SYMA spans 2024-01..08, SYMB 2024-03..06, weekday 08:00-16:00 UTC bars):
/// the resolved `campaign_window_ms(full_window)` span persists verbatim into
/// the generated campaign document's `data.windows[0]`, exactly like the
/// sibling `generalize_without_explicit_window_resolves_the_intersection_of_all_symbols`
/// probe. Three cases: SYMA's and SYMB's full (no-window) spans, and an
/// explicit `--from`/`--to` sub-window straddling three month files
/// (2024-03-15..2024-05-15, so `filter_files` alone would load 3 files under
/// the old drain). The first bar of each captured span carries a known -1ms
/// float round-trip artifact (the synthetic fixture's Delphi-`TDateTime`
/// pack/unpack in `data-server`'s own record format, not a `probe_window` bug)
/// — this test does not explain it, only pins it exactly, since the
/// post-swap code must reproduce the identical bytes (same underlying decoder,
/// only fewer files touched to reach them).
#[test]
fn probe_window_resolves_the_pinned_span_before_the_252_swap() {
let (cwd, _g) = fresh_project_with_data();
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
let window_of = |name: &str| -> (i64, i64) {
let dir = cwd.join("runs").join("campaigns");
let path = std::fs::read_dir(&dir)
.expect("campaigns dir exists after a run")
.filter_map(|e| e.ok())
.map(|e| e.path())
.find(|p| {
let doc: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string(p).expect("read campaign doc"))
.expect("campaign doc parses as JSON");
doc["name"].as_str() == Some(name)
})
.unwrap_or_else(|| panic!("no campaign document named {name:?} in {}", dir.display()));
let doc: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string(&path).expect("read campaign doc"))
.expect("campaign doc parses as JSON");
let w = &doc["data"]["windows"][0];
(
w["from_ms"].as_i64().expect("from_ms is an integer"),
w["to_ms"].as_i64().expect("to_ms is an integer"),
)
};
let sweep = |symbol: &str, name: &str, from: Option<&str>, to: Option<&str>| {
let mut args = vec![
"sweep", fixture.as_str(), "--real", symbol,
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
"--name", name,
];
if let Some(f) = from {
args.push("--from");
args.push(f);
}
if let Some(t) = to {
args.push("--to");
args.push(t);
}
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
.args(&args)
.current_dir(&cwd)
.output()
.expect("spawn aura sweep");
assert_eq!(
out.status.code(), Some(0),
"window-probe sweep {name:?} must run to exit 0: {}",
String::from_utf8_lossy(&out.stderr)
);
};
sweep("SYMA", "probe-252-no-window-syma", None, None);
assert_eq!(
window_of("probe-252-no-window-syma"),
(1_704_095_999_999, 1_725_033_540_000),
"SYMA's full (no-window) resolved span"
);
sweep("SYMB", "probe-252-no-window-symb", None, None);
assert_eq!(
window_of("probe-252-no-window-symb"),
(1_709_279_999_999, 1_719_590_340_000),
"SYMB's full (no-window) resolved span"
);
// 2024-03-15 00:00 UTC .. 2024-05-15 00:00 UTC: straddles the March, April,
// and May files (three boundary months under the old file-range drain).
sweep("SYMA", "probe-252-straddle", Some("1710460800000"), Some("1715731200000"));
assert_eq!(
window_of("probe-252-straddle"),
(1_710_489_599_999, 1_715_702_340_000),
"explicit sub-window straddling month boundaries, clipped to the archive's actual bars"
);
}
/// Characterization pin (#252, hostless zero-bar case): a window that falls
/// entirely on a weekend inside a COVERED month (2024-03-02/03, both inside
/// SYMA's Jan-Aug 2024 span, weekday-only bars) still refuses with the SAME
/// exit-1 "no data ... in the requested window" message `probe_window`'s
/// drain-based emptiness check raises today — `archive_extent` must reach the
/// identical conclusion by finding zero matching months in range, not by
/// draining a stream, and the refusal wording is part of what must not move
/// (mirrors `run_real_empty_window_refusal_names_the_window_not_the_symbol`,
/// hostless here since the property (an empty resolved sub-window still
/// refuses) needs no full archive, only a covered-but-empty range).
#[test]
fn probe_window_still_refuses_a_hostless_zero_bar_window() {
let (cwd, _g) = fresh_project_with_data();
let fixture = format!("{}/examples/r_sma.json", env!("CARGO_MANIFEST_DIR"));
let out = std::process::Command::new(env!("CARGO_BIN_EXE_aura"))
.args([
"sweep", &fixture, "--real", "SYMA",
"--axis", "sma_signal.fast.length=3", "--axis", "sma_signal.slow.length=12",
"--name", "probe-252-zero-bars",
"--from", "1709337600000", // 2024-03-02 00:00 UTC (Saturday)
"--to", "1709424000000", // 2024-03-03 00:00 UTC (Sunday)
])
.current_dir(&cwd)
.output()
.expect("spawn aura sweep");
assert_eq!(
out.status.code(), Some(1),
"a zero-bar window inside covered archive months still refuses with exit 1: stderr={}",
String::from_utf8_lossy(&out.stderr)
);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
stderr.contains("no data") && stderr.contains("window"),
"must name the empty window, not a missing symbol: {stderr}"
);
assert!(
!cwd.join("runs").join("campaigns").exists()
|| std::fs::read_dir(cwd.join("runs").join("campaigns")).unwrap().count() == 0,
"a refused zero-bar window must not register a generated campaign document"
);
}
/// `aura run` on the shipped closed r-meanrev example (#159 cut 3) actually loads
/// and grades through the real, separately-linked `aura` binary — not merely
/// in-process, as `r_meanrev_example_loaded_runs_identically_to_the_carved_signal`