Files
Aura/crates/aura-ingest/tests/instrument_spec_deploy_metadata.rs
T
Brummel 5b7cd5eb2d feat(0073): consume DataServer geometry — cross-check vetted floor + tick_size/digits
Make data-server's neutral InstrumentGeometry a first-class, broker-agnostic input at the aura-ingest edge: re-export InstrumentGeometry + a thin instrument_geometry(server, symbol) accessor over symbol_meta (the recorded dataset-metadata tier 2 of #124's hierarchy; the tier-composing resolver stays #124). Add the two deferred deploy-grade InstrumentSpec fields tick_size + digits (additive, struct stays Copy; C15), authored for the 5 vetted symbols from the verified sidecars. A new real-data cross-check asserts the authored floor agrees with provider geometry (pip_size, contract_size==lot_size, the C10 pip_value invariant, tick_size, digits, quote_currency), iterating the vetted set so #140's additions are covered for free; skip-if-archive-absent.

Scope (derived, recorded on #143): no runtime resolver and no quote_currency type change — both remain #124's. 'quote_currency beyond FX' is satisfied at the geometry tier (InstrumentGeometry.quote: String), not by widening the &'static str floor.

Beyond the plan (implementer additions, reviewed and accepted): hoisted the vetted-symbol list to one pub const VETTED_SYMBOLS, collapsing the three drift-prone copies plan-recon flagged (#140 now extends one constant); a tick_size == 10^(-digits) consistency guard (verified to hold across all 30 provider sidecars, so it will not false-trip on #140); a re-export-nameable seam test guarding the InstrumentGeometry re-export from silent removal.

Verification: cargo test --workspace all green; cargo clippy --workspace --all-targets -D warnings clean. The cross-check ran against the live Pepperstone archive (not skipped) — all 5 vetted sidecars match the authored table.

refs #143
2026-06-25 16:25:51 +02:00

94 lines
4.7 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.
//! End-to-end verification of the public instrument-spec resolution seam
//! (#113): a downstream broker resolves deploy-grade metadata by symbol through
//! `aura_ingest::instrument_spec` — the permanent authored floor of the
//! milestone's override hierarchy (#124). These tests pin the *consumer-visible*
//! contract (the public return shape + the refuse-don't-guess arm), distinct
//! from the crate-internal literal-table unit tests.
use aura_ingest::{instrument_spec, InstrumentSpec, VETTED_SYMBOLS};
/// Property: every vetted symbol resolves through the *public* lookup to a fully
/// populated `InstrumentSpec` whose deploy fields are all present and sane
/// (positive sizes/ids, positive tick geometry, a non-empty quote currency).
/// This is the floor a broker
/// reads before sizing a lot; a regression that left any field at a placeholder
/// (0.0 / "") or dropped a symbol from the table would size positions wrong with
/// no error. Asserts only the consumer-visible guarantees, not the exact vetted
/// literals (those are the crate's own unit test's remit).
#[test]
fn every_vetted_symbol_resolves_to_a_complete_spec() {
for sym in VETTED_SYMBOLS {
let s: InstrumentSpec = instrument_spec(sym).unwrap_or_else(|| {
panic!("vetted symbol {sym} must resolve through the public lookup")
});
assert!(s.instrument_id > 0, "{sym}: instrument_id must be a real (>0) id");
assert!(s.pip_size > 0.0, "{sym}: pip_size must be positive");
assert!(s.contract_size > 0.0, "{sym}: contract_size must be positive");
assert!(s.pip_value_per_lot > 0.0, "{sym}: pip_value_per_lot must be positive");
assert!(s.min_lot > 0.0, "{sym}: min_lot must be positive");
assert!(s.lot_step > 0.0, "{sym}: lot_step must be positive");
assert!(!s.quote_currency.is_empty(), "{sym}: quote_currency must be labelled");
assert!(s.tick_size > 0.0, "{sym}: tick_size must be positive");
assert!(s.digits > 0, "{sym}: digits must be positive");
}
}
/// Property: the cross-field deploy invariant `tick_size == 10^(-digits)` holds
/// for every vetted instrument as a downstream broker observes it through the
/// public lookup. `tick_size` and `digits` are two views of the same provider
/// price geometry; a broker may round a price by either. This pins that the two
/// agree, so a consistent typo'd *pair* in one table entry (which the positivity
/// asserts and an equally-typo'd literal unit test would both wave through) is
/// caught — exactly the silent-wrong-rounding regression this file guards.
#[test]
fn tick_size_is_consistent_with_digits_at_the_public_boundary() {
for sym in VETTED_SYMBOLS {
let s = instrument_spec(sym).expect("vetted symbol");
let derived = 10f64.powi(-(s.digits as i32));
assert!(
(s.tick_size - derived).abs() < 1e-12,
"{sym}: tick_size {} must equal 10^(-digits) = 10^(-{}) = {}",
s.tick_size,
s.digits,
derived,
);
}
}
/// Property: the cross-field deploy invariant `pip_value_per_lot ==
/// contract_size * pip_size` holds for every vetted instrument as a downstream
/// broker observes it through the public lookup. A broker computing pip P&L may
/// use either `pip_value_per_lot` directly or derive it from contract_size ×
/// pip_size; this pins that the two paths agree, so the choice is free. A future
/// table edit that broke the identity (e.g. a typo'd pip_value) would silently
/// double or halve every realistic-broker P&L.
#[test]
fn pip_value_is_consistent_with_contract_and_pip_at_the_public_boundary() {
for sym in VETTED_SYMBOLS {
let s = instrument_spec(sym).expect("vetted symbol");
let derived = s.contract_size * s.pip_size;
assert!(
(s.pip_value_per_lot - derived).abs() < 1e-9,
"{sym}: pip_value_per_lot {} must equal contract_size {} * pip_size {} = {}",
s.pip_value_per_lot,
s.contract_size,
s.pip_size,
derived,
);
}
}
/// Property: an un-vetted symbol resolves to `None` — the refuse-don't-guess
/// honesty lever (#113). A broker that asked for a symbol with no authored floor
/// must get nothing back, never a fabricated/defaulted spec, so deploy fails
/// loudly rather than sizing on a guessed pip value. A regression that returned
/// a `Some(default)` for unknown symbols is exactly the silent-guess failure
/// this guards.
#[test]
fn unvetted_symbol_refuses_with_none() {
assert_eq!(instrument_spec("NOT_A_REAL_SYMBOL"), None);
assert_eq!(instrument_spec(""), None);
// case sensitivity is part of the refuse arm: the table is exact-match only.
assert_eq!(instrument_spec("ger40"), None);
}