feat(0074): source real-path pip from the geometry sidecar; drop the authored floor
The data-server now ships per-symbol geometry sidecars, so aura no longer hard-codes instrument geometry. A consumption grep showed production reads exactly one `InstrumentSpec` field — `pip_size` — at the real-data path; the other eight (incl. `instrument_id`) were constructed but never read. - aura-cli resolves the real-path pip from the recorded sidecar (`instrument_geometry` -> `InstrumentGeometry.pip_size`), refusing (exit 2) on absent geometry. The authored table no longer gates: any symbol with a sidecar + bars now runs (new test: USDJPY, never vetted, resolves its JPY pip 0.01 from the sidecar). - Removed the redundant authored floor: `InstrumentSpec`, `instrument_spec`, `VETTED_SYMBOLS`, and the table-only tests. The `InstrumentGeometry` seam (the surviving pip source) and its nameability guard are kept. - `instrument_id` (the "find out"): no production consumer. The position-event table's `instrument_id` is a decoupled caller parameter; the engine never imports an instrument spec. Dropped with the struct. - The example `pip_size_of` is re-sourced to the sidecar; the pure-structural blueprint tests use a literal pip to stay archive-independent. Speculative deploy-grade fields and the #124 override/floor tiers are deferred to the Stage-2 broker that will consume them, read from the sidecar geometry then. Ledger (C8/C15/#22/#106) updated; #124 collapses to "recorded sidecar geometry -> refuse" in the meantime. Verified: cargo test --workspace (all green), clippy -D warnings clean, cargo doc clean, with the local archive present so the sidecar paths run. refs #124
This commit is contained in:
+28
-22
@@ -38,10 +38,10 @@ use std::collections::HashSet;
|
||||
|
||||
/// The pip size the built-in *synthetic* harnesses run at: a 5-decimal FX major
|
||||
/// (`EURUSD`-shaped). The synthetic streams carry no instrument, so there is no
|
||||
/// `instrument_spec` to thread; a single named source keeps the broker's divisor
|
||||
/// (`sample_harness` / `SimBroker::builder`) and the recorded broker label
|
||||
/// recorded geometry sidecar to thread; a single named source keeps the broker's
|
||||
/// divisor (`sample_harness` / `SimBroker::builder`) and the recorded broker label
|
||||
/// (`sim_optimal_manifest`) in lockstep, so they cannot silently drift apart.
|
||||
/// The real path threads the looked-up `spec.pip_size` instead.
|
||||
/// The real path threads the sidecar's looked-up `pip_size` instead.
|
||||
const SYNTHETIC_PIP_SIZE: f64 = 0.0001;
|
||||
|
||||
/// Real walk-forward roller sizes (Fork D/F). `WindowRoller` takes sizes in the
|
||||
@@ -723,15 +723,21 @@ fn no_real_data(symbol: &str) -> ! {
|
||||
std::process::exit(2)
|
||||
}
|
||||
|
||||
/// Look up the vetted per-instrument pip/spec, or refuse (stderr + exit 2) on an
|
||||
/// un-specced symbol — the single home of the guessed-pip refusal message, shared
|
||||
/// by `run_sample_real` and `DataSource::from_choice`. Refusing BEFORE any data
|
||||
/// access keeps the pip honest by construction (never guessed).
|
||||
fn instrument_spec_or_refuse(symbol: &str) -> aura_ingest::InstrumentSpec {
|
||||
match aura_ingest::instrument_spec(symbol) {
|
||||
Some(s) => s,
|
||||
/// Resolve the per-instrument pip from the recorded geometry sidecar, or refuse
|
||||
/// (stderr + exit 2) when the symbol has no recorded geometry — the single home of
|
||||
/// the guessed-pip refusal, shared by `open_real_source` and `from_choice`. Reads
|
||||
/// the symbol's geometry metadata (not bar data) before the run source opens, so an
|
||||
/// instrument with no recorded geometry refuses without a guessed pip; the pip is
|
||||
/// the provider's recorded value, honest by construction.
|
||||
fn pip_or_refuse(server: &std::sync::Arc<data_server::DataServer>, symbol: &str) -> f64 {
|
||||
match aura_ingest::instrument_geometry(server, symbol) {
|
||||
Some(geo) => geo.pip_size,
|
||||
None => {
|
||||
eprintln!("aura: no vetted pip/instrument spec for symbol '{symbol}' — refusing to run a real instrument with a guessed pip (add it to the instrument table)");
|
||||
eprintln!(
|
||||
"aura: no recorded geometry for symbol '{symbol}' at {} — \
|
||||
refusing to run a real instrument with a guessed pip",
|
||||
data_server::DEFAULT_DATA_PATH
|
||||
);
|
||||
std::process::exit(2);
|
||||
}
|
||||
}
|
||||
@@ -758,10 +764,10 @@ fn probe_window(
|
||||
(first, last)
|
||||
}
|
||||
|
||||
/// Open a real M1-close source for a vetted symbol over an optional window, returning
|
||||
/// Open a real M1-close source for a recorded symbol over an optional window, returning
|
||||
/// the run source paired with its manifest `window` and per-instrument `pip_size`.
|
||||
/// Single home of the real-source construction the single-run handlers share — the
|
||||
/// vetted-pip lookup, the `DataServer` `has_symbol` refusal, the probe-window pass, and
|
||||
/// sidecar-pip lookup, the `DataServer` `has_symbol` refusal, the probe-window pass, and
|
||||
/// the run-source `open` (each refusal an stderr + exit 2). Pre-data refusals keep the
|
||||
/// pip honest by construction. Shared by `run_sample_real` and `run_stage1_r`.
|
||||
fn open_real_source(
|
||||
@@ -769,10 +775,10 @@ fn open_real_source(
|
||||
from_ms: Option<i64>,
|
||||
to_ms: Option<i64>,
|
||||
) -> (Box<dyn aura_engine::Source>, (Timestamp, Timestamp), f64) {
|
||||
// Per-instrument pip: look up BEFORE any data access, so an un-specced symbol
|
||||
// refuses without touching local data. Honest by construction.
|
||||
let spec = instrument_spec_or_refuse(symbol);
|
||||
// Per-instrument pip from the recorded sidecar; resolved BEFORE bar-data access
|
||||
// so an instrument with no geometry refuses without touching the archive.
|
||||
let server = std::sync::Arc::new(data_server::DataServer::new(data_server::DEFAULT_DATA_PATH));
|
||||
let pip = pip_or_refuse(&server, symbol);
|
||||
if !server.has_symbol(symbol) {
|
||||
no_real_data(symbol);
|
||||
}
|
||||
@@ -783,24 +789,24 @@ fn open_real_source(
|
||||
Some(s) => Box::new(s),
|
||||
None => no_real_data(symbol),
|
||||
};
|
||||
(source, window, spec.pip_size)
|
||||
(source, window, pip)
|
||||
}
|
||||
|
||||
impl DataSource {
|
||||
/// Build a provider from a parsed choice, or refuse (stderr + exit 2) on an
|
||||
/// un-vetted symbol / absent data — both BEFORE any member runs (Fork C/G),
|
||||
/// via the same `instrument_spec_or_refuse` / `no_real_data` helpers as
|
||||
/// Build a provider from a parsed choice, or refuse (stderr + exit 2) on a symbol
|
||||
/// with no recorded geometry / absent data — both BEFORE any member runs (Fork C/G),
|
||||
/// via the same `pip_or_refuse` / `no_real_data` helpers as
|
||||
/// `run_sample_real`.
|
||||
fn from_choice(choice: DataChoice) -> DataSource {
|
||||
match choice {
|
||||
DataChoice::Synthetic => DataSource::Synthetic,
|
||||
DataChoice::Real { symbol, from_ms, to_ms } => {
|
||||
let spec = instrument_spec_or_refuse(&symbol);
|
||||
let server = std::sync::Arc::new(data_server::DataServer::new(data_server::DEFAULT_DATA_PATH));
|
||||
let pip = pip_or_refuse(&server, &symbol);
|
||||
if !server.has_symbol(&symbol) {
|
||||
no_real_data(&symbol);
|
||||
}
|
||||
DataSource::Real { server, symbol, from_ms, to_ms, pip: spec.pip_size }
|
||||
DataSource::Real { server, symbol, from_ms, to_ms, pip }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user