docs(aura-ingest): precise None contract for load_m1_window
The rustdoc claimed 'None if the symbol has no data in [from_ms, to_ms]', implying a bar-level None. Empirically (cycle-0011 fieldtest) None is file-level: it propagates data-server's own None, returned only when no archived file overlaps the window (far-future window or unknown symbol). A window that overlaps a loaded file but holds zero bars returns Some(M1Columns) with empty columns, not None. Document the distinction precisely (chosen over collapsing in-coverage- empty into None): None propagates data-server's one file-level meaning unchanged -- 'no data source to read from' -- rather than overloading it with a second aura-level 'source present but empty here' meaning. So Some/None means 'data source present' vs 'nothing to read from', not 'has bars' vs 'has none'; a consumer testing for an empty window must check cols.close.is_empty(). Doc-only, no behaviour change; ledger untouched (the contract is not referenced there). closes #18
This commit is contained in:
@@ -87,16 +87,25 @@ pub fn transpose_m1(bars: &[M1Parsed]) -> M1Columns {
|
||||
/// Drain a data-server M1 window into transposed SoA columns. Reads the
|
||||
/// chronological chunk iterator to exhaustion into one AoS buffer, then
|
||||
/// transposes once at the boundary (C3 — one merge point, not per chunk).
|
||||
/// `None` if the symbol has no data in the window (data-server's own `None`);
|
||||
/// the inclusive Unix-ms window bounds are data-server's contract.
|
||||
///
|
||||
/// Each bound is an `Option<i64>`: `None` means unbounded on that side
|
||||
/// (data-server skips the coarse `unix_ms_to_year_month` file filter rather
|
||||
/// than reaching for a sentinel). `from_ms = None` reads from the start of
|
||||
/// history; `to_ms = None` reads to the end. This threads data-server's own
|
||||
/// per-bound `Option` contract through unchanged, so "to the end of history"
|
||||
/// is expressible without an `i64::MAX` sentinel (which panics upstream in
|
||||
/// chrono's `from_timestamp_millis`).
|
||||
/// Each bound is an `Option<i64>` of inclusive Unix-ms (data-server's window
|
||||
/// contract): `None` means unbounded on that side (data-server skips the
|
||||
/// coarse `unix_ms_to_year_month` file filter rather than reaching for a
|
||||
/// sentinel). `from_ms = None` reads from the start of history; `to_ms = None`
|
||||
/// reads to the end. This threads data-server's own per-bound `Option`
|
||||
/// contract through unchanged, so "to the end of history" is expressible
|
||||
/// without an `i64::MAX` sentinel (which panics upstream in chrono's
|
||||
/// `from_timestamp_millis`).
|
||||
///
|
||||
/// The returned `Option` is **file-level**, propagating data-server's own
|
||||
/// `None`: it is `None` only when no archived file overlaps the window (e.g. a
|
||||
/// far-future window, or an unknown symbol) — i.e. there is no data source to
|
||||
/// read from. A window that *does* overlap a loaded file but happens to hold
|
||||
/// zero bars (a narrow gap inside coverage) returns `Some(M1Columns)` with
|
||||
/// empty columns, **not** `None`. So `Some`/`None` distinguishes "data source
|
||||
/// present" from "nothing to read from", not "has bars" from "has none": a
|
||||
/// consumer testing for "no bars in this window" must check
|
||||
/// `cols.close.is_empty()`, not the `Option` alone.
|
||||
pub fn load_m1_window(
|
||||
server: &Arc<DataServer>,
|
||||
symbol: &str,
|
||||
|
||||
Reference in New Issue
Block a user