The parity gate
Frozen golden fixtures compared bit-for-bit, a second oracle in the vectorized kernel, and one rule that outlived the oracle the fixtures came from — a tolerance is never widened to make a test pass.
Vike Trader's pure cores — the fill primitive, the fill triggers, the consolidators, the cost
scalars, the event engine, the vectorized kernel, the sizing math, the account read-model — are
held to bit-identical f64 results against committed fixtures. Not "close enough", not a
relative tolerance: the same IEEE-754 bit pattern. This page is what that means, why it is still
true after the thing the fixtures came from was retired, and the one rule that must survive any
future relaxation.
The fixtures are frozen, and that is why the comparisons stay exact
fixtures/r0..r6/ were exported from an earlier implementation of the platform; each carries a
manifest.source_sha pinning the commit that exported it. Every exporter was later deleted from
the tree, so — as crates/vike-backtest/tests/parity.rs's header puts it — the committed bytes
ARE the oracle: there is no environment to regenerate from, no network, no external process, and
nothing to drift. Floats are stored as hex bit patterns and read back through
vike_model::f64_from_hex_bits; the r1_parity/r3_parity/r4_parity golden gates in that
binary compare them exactly. (Those three described themselves as "parity vs the Python oracle"
until 2026-08-28; the provenance is unchanged, the ongoing-comparison reading was never true after
the exporters went.)
What those gates prove is precise and worth stating precisely: that this code has not changed its arithmetic unnoticed. They do not prove ongoing agreement with anything external, because nothing external is run. The decision record that retired the oracle is explicit about the half that matters most:
What retiring the oracle does NOT license
Every committed golden fixture keeps its exact comparison. The rule that dies is "a new port must reproduce the old implementation bit-for-bit" — new work needs no external twin. The rule that survives is "never widen a tolerance to make a failing test pass; investigate the divergence." It was never really about the old implementation. It is about a number that moved for a reason nobody has named yet, and it applies to every gate in the tree. Relaxing an existing assertion needs its own argument: name the mechanism, keep the comparison exact against a stated function of the reference rather than a tolerance band, bound the raw reference value too, and add a control that fails if the relaxation turns out to be a no-op.
The hardest-won detail: sum() is not a fold
crates/vike-model/src/pysum.rs records the single most instructive divergence the gates ever
caught: CPython 3.12 and later compute the builtin sum() over floats with Neumaier compensated
summation, not a naive left fold. A ported site that the original wrote as sum(...) must
therefore use vike_model::py_sum, while an explicit acc += x loop stays a naive fold — mirrored
per site. Getting it wrong is a guaranteed last-ulp divergence, caught by the bit-gates on
2026-07-03. The lesson generalises: bit parity is a property of operation order.
crates/vike-model/src/fill.rs's compute_fill says it outright — do not reorder operations,
introduce mul_add, or "simplify" — and vike-fills carries the same rule for the cost scalars.
Even container choice is part of it: crates/vike-exec/src/account.rs keeps every map an
IndexMap, never a HashMap, because insertion order is the f64 fold order the gate pins
against fixtures/r0/account_scenarios.json.
Why the exactness is portable
A pinned constant usually survives a platform change by luck — two platform maths libraries
agreeing on the inputs it happened to sample. parity.rs's header argues that hazard does not
reach these gates, by construction: every module they drive reaches no transcendental function and
no integer power, only + - * /, which IEEE 754 requires to be correctly rounded. It tells the
reader to grep those modules for a libm-class call before trusting the paragraph, because
introducing one is what would make the fixtures platform-sensitive and nothing else in the suite
would say so. Elsewhere in the tree, where transcendentals are needed, a separate decision record
routes them through the libm crate rather than the platform — the property bought is
reproducibility, not accuracy; the two platforms are differently wrong at the last bit, and
the change makes them identically wrong everywhere.
The second oracle, and the third
Golden fixtures only pin examples. engine_kernel_parity, in the same binary, runs the event
engine (StrategyEngine) and the vectorized kernel (VectorBacktestEngine) on identical synthetic
bars and requires the same trade count and a bit-identical final equity — both are naive-fold
f64 paths over the same inputs, and its own header says never to widen it to a tolerance. It is
the workspace's second oracle, and it keeps working as strategies are added because it compares two
things that both run rather than one thing against a frozen file. rhai_parity is the third: a
Rhai script and its Rust twin must produce a byte-identical BacktestResult.
Where this connects
The paper exchange carries the next link in the chain: the
backtest engine equals the live paper core, bit-for-bit, under r7_gate. And the
indicator crate holds a parity of its own —
crates/vike-indicators/tests/parity.rs proves every registered indicator's streaming on_bar
fold equals its batch vectorize, bitwise, with both-NaN counted equal; the three batch_only
indicators that read future bars (ichimoku, zigzag, williams_fractal) are skipped by name,
their output shape still gated.
Committing a counterexample
Property tests randomize the pure cores where fixtures only pin examples — property tests lists the suites. When one finds a counterexample in CI, the generated regression seed is committed, so the failure reproduces on every machine rather than depending on the random draw that found it. Adding a fixture, a property suite or a seed is the procedure on adding to the parity suite.
The paper exchange
Paper trading is the backtest fill model running behind the live core's own seam, built from the same primitives — so backtest equals paper by construction, and a gate proves it bit-for-bit rather than asserting it.
The latency gate
The execution core's fold is measured in CI on reserved cores and gated on its tail, not its median — and only three of the harness's variants gate on a derived budget, because an uncalibrated ceiling is worse than no gate at all.