Instrument-reference & cost resolution hierarchy: recorded dataset-metadata tier (DataServer seam); authored override always wins #124
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The authored layer for instrument reference data and cost models (
instrument_spec()+ the realistic broker's spread/commission models) is permanent and authoritative-by-choice, not a provider stand-in. This issue adds the recorded dataset-metadata tier as the MIDDLE tier of the resolution hierarchy — never above the explicit authored override.Resolution hierarchy (precedence high → low)
Why a tier, not a replacement
Mechanics
M1Columns: OHLC + per-bar spread + volume); no instrument-structural metadata is carried. "Provider-sourced" means: at dataset curate time, record the symbol's structural spec (from the provider's symbol info) into the dataset metadata, which theDataServerthen surfaces at the ingestion edge.InstrumentSpec/ cost model to the broker + derivation (which already consume an injected spec per #113/#116).depends on: #71 (DataServer/Source seam — its home), #113 (authored layer), #120 (cost models)
context: surfaced refining the realistic-broker milestone; the recorded-metadata channel on the source seam is World-II work, separate from the broker milestone.
Design input from cycle 0063 (broker-foundation) — quote_currency representation
The authored vetted floor landed in 0063 (#113) types
quote_currencyas&'static str(crates/aura-ingest/src/lib.rs), keepingInstrumentSpec: Copyand fitting the static Rust-authored table.
An adversarial review of 0063 flagged that this field cannot hold a
runtime-sourced currency (a recorded dataset-metadata value or an Aura.toml
override — exactly this issue's tier). When #124 lands the resolver, it must pick
one of:
InstrumentSpecas the&'static strauthored floor and have the resolver produce a separate
ResolvedInstrumentSpec(ownedString/Cowcurrency). No break to theauthored table; the broker/derivation consume the resolved type.
InstrumentSpec.quote_currencytoCow<'static, str>(orString), droppingCopy. One type throughout; theauthored literals become
Cow::Borrowed.This is a #124 design decision, deliberately not pre-empted in 0063. Recording it
here so the resolver design weighs it rather than discovering the
&'static strfloor by surprise. The C15 "extensible without a signature break" promise is about
additive fields (honored in 0063); the currency type transition is this tier's
concern.
Provider metadata now physically exists — supersedes the bars-only premise
The Mechanics section above states "the Pepperstone NFS files today are bars-only
(M1Columns: OHLC + per-bar spread + volume); no instrument-structural metadata is
carried". That is now superseded: the export pipeline writes one per-symbol
geometry sidecar
<SYMBOL>.meta.jsonbeside the bars. Verified: 30 files in/mnt/tickdata/Pepperstone, allschemaVersion2, carryingdigits,pipSize,tickSize,lotSize,baseAsset,quoteAsset— exactly the "symbol'sstructural spec recorded at curate time" this issue anticipated for tier 2.
The concrete realization of that tier is now filed as two cross-referenced issues,
not folded into this one (which stays the hierarchy/precedence design):
http://192.168.178.103:3000/Brummel/data-server/issues/3— the upstreamreader: parse the sidecars into neutral
InstrumentGeometryso the provider'sfilename/schema/quirks (
DE40/USTECnaming,1E-05,null-for-NaN) stayinside the broker-facing library.
#143— theaura-ingestconsumer: slot the neutral geometry as tier 2,cross-check it against the vetted floor (
#113), addtick_size/digits, andextend
quote_currencypast FX. It defers to this issue on precedence and onthe
quote_currencytype fork raised in the comment below.Scope note: the sidecar is geometry only. It deliberately excludes the
time-varying / account-dependent fields — including the spread, which is this
issue's canonical "recorded value the authored override supersedes" case. So the
sidecars satisfy tier 2 for structural geometry (pip/lot/tick/digits/currency),
not for cost models; the spread/commission tier-2 channel remains open here.
Tier-2 source now reachable at the ingestion edge (via #143)
#143 (closed, cycle 0073) landed the recorded dataset-metadata tier-2 source:
aura_ingest::instrument_geometry(server, symbol) -> Option<InstrumentGeometry>overdata-server's
symbol_meta, returning neutral broker-agnostic geometry(
digits, pip_size, tick_size, lot_size, base, quote). The raw provider JSON staysinside the broker-facing library; aura consumes only the neutral type.
What it deliberately left to this issue:
floor > refuse) — #143 surfaced the tier-2 data, not the precedence engine;
quote_currencytype-fork (distinctResolvedInstrumentSpecvs. wideningto
Cow) — the floor'squote_currencyis still&'static str; the runtime-sourcedString currency lives only in
InstrumentGeometryfor now;the time-varying/account-dependent fields, the spread among them), so cost-model
tier-2 remains open here.
Design reconciliation (specify) — minimal, provider-sourced reframe
User directive (this run): aura takes over and defines only what is
currently needed; the data-server now supplies symbol geometry, so geometry
must no longer be hard-coded in aura. Find out whether an
instrument_idisneeded. This resolves the shape of this issue's resolver. The forks below are
listed open here; this records their resolution before the spec is written.
Consumption investigation (the empirical basis)
Grep of every
InstrumentSpecfield read acrosscrates/(reads, notconstruction):
pip_size— the only field read in production:aura-cli(
open_real_source/DataSource::from_choicethreadspec.pip_sizeinto thereal source / SimBroker) and the
aura-ingestexamplepip_size_of.instrument_id— no production reader. The position-event table carries aninstrument_id, but as a caller-supplied parameterderive_position_events(record, instrument_id)(report.rs:231); the enginenever imports
InstrumentSpec(report.rs:226), andstage1_r_e2e.rsassertsid == 7, an id the floor never registers (it only has 1–5). The field isdecoupled and unused.
contract_size,pip_value_per_lot,min_lot,lot_step,quote_currency,tick_size,digits— constructed only; read only in thetable's own unit tests. Speculative, anticipating the unbuilt Stage-2 broker.
Forks resolved
sidecar geometry → refuse. The four-tier
override > metadata > floor > refusehierarchy is deferred, not deleted: tier 1 (authored override) andtier 3 (authored floor) are built when a consumer needs them (the Stage-2
broker overriding the spread). Tier 2 (provider-sourced) becomes the primary
and only currently-built source; tier 4 (refuse-don't-guess) survives.
Basis: derived — user directive (YAGNI) + the floor's values were
byte-identical duplication of the provider (the #143 cross-check proved it).
InstrumentSpecstruct → drop the struct,instrument_spec(),and
VETTED_SYMBOLS. Pip is sourced fromInstrumentGeometry.pip_size(the#143
instrument_geometryaccessor, which survives). Basis: derived — onlypip_sizeis read in production.instrument_id(the directive's "find out") → not needed; droppedwith the struct. The position-event table keeps its caller-supplied
instrument_id(a separate, real, engine-side concept). No production code mapssymbol → id today; when such a registry is needed it is built then. Basis:
derived — grep shows no production reader.
quote_currencytype (the 0063&'static strvs owned fork raisedabove) → moot now (field dropped). Revived from
InstrumentGeometry.quote(owned
String) when Stage 2 needs currency — noCopyconcern, since it isread off the sidecar, never a static table. Basis: derived — the fork only
existed because of the authored floor that is now gone.
Scope of this run vs. what stays open here
This run implements the currently-needed slice: pip resolved from the
provider sidecar at the aura-ingest/CLI edge, and the dead authored floor removed.
#124 stays open for the deferred tiers — the authored override and the
cost-model / spread tier-2 channel — which the Stage-2 realistic-broker milestone
will need. #140 (hand-register four more symbols into the floor) is obsolete
and closed: pip now comes from whichever symbols ship a sidecar (30 present).
#143's
tick_size/digitsfields, added last cycle and never consumed, areremoved forward as part of this rework (no history rewrite).
Note: the 2026-06-28 C10 rework (
29cdc8c) retires the realistic broker, so this hierarchy's eventual consumer is now the cost-model graph's currency→R normalization at ingestion (#148) and the live/deploy edge (#149), not a Stage-2 realistic broker. The authored-override-wins resolution itself stands. Keeping open.This issue's resolution hierarchy was scoped around two consumers, both retired or removed since filing.
instrument_spec()/InstrumentSpec— the authored tier-1/tier-3 floor this issue names — was deleted in cycle 0074 (commit7e4b91a, "source real-path pip from the geometry sidecar; drop the authored floor"): a consumption grep showed production code read only thepip_sizefield, so the six-field deploy-grade struct,instrument_spec(), andVETTED_SYMBOLSwere removed as dead code. Only the tier-2 source survives:instrument_geometry()(definedcrates/aura-ingest/src/lib.rs:411, re-exported asInstrumentGeometry), which returnsOption<InstrumentGeometry>and refuses (exit 2) onNone— no override tier above it, no authored floor below it. After the #295 shell-boundary extraction, the caller lives incrates/aura-runner/src/member.rs(moved out ofaura-cli, logic unchanged)."The realistic broker's spread/commission models" — the issue's other named consumer — no longer exist. Design commit
29cdc8c("design(C10): retire the realistic broker…", 2026-06-28) reworked C10 indocs/design/INDEX.md: an authored-friction historical broker is now explicitly forbidden ("modelling an authored-friction 'realistic broker' over historical data" — current Forbids clause). NoRealisticBrokertype exists anywhere undercrates/. Cost is now a composable C9 graph of cost nodes in R (crates/aura-strategy/src/constant_cost.rs,carry_cost.rs,vol_slippage_cost.rs,cost_sum.rs), none of which currently reads instrument geometry.The ledger already records this collapse (
docs/design/INDEX.md:1275-1293, "Realization (instrument specs, 2026-06, #22 -> #124)"): the override/floor tiers of the #124 hierarchy "are deferred until a consumer … needs them", and "#124 collapses to recorded sidecar geometry -> refuse in the meantime" — i.e. the design this issue asked for has no live consumer today, and the consumer it was written against is gone, not merely pending.Closing as superseded. If a future cost-model node needs currency/pip normalization from instrument reference data, that resolution design belongs to the C9 cost-graph consumer that actually needs it (e.g. a currency-cost node under
crates/aura-strategy/), scoped against the cost model's real requirements rather than a revival of this issue's authored-override/broker-cost framing.