vike
Concepts

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.

On this page