โ€บNavigation

iteration 06 ยท card 59 S1 oracle ยท batch-6 implementation ยท 2026-07-02

Card 59 started โ€” the "how long until price comes back?" ruler, answer key frozen S1 DONE

← campaign board ยท previous: iter 05 (card 78 shipped, PR #568)

In plain language โ€” what happened this iteration

Feature 2 of 4 began: card 59, the "forward visibility horizon". For every bar it asks a beautifully simple question: from this bar's closing price, how many bars into the future until the price closes at that level or higher again? If the answer over the last 200 bars averages ~2, dips are being bought back almost immediately; if it averages ~15, levels take a long time to be reclaimed. On the frozen reference data the average sits around 6 bars โ€” with excursions from ~2.2 (relentless buying) to ~17.8 (long underwater stretches). Bars whose level is never re-reached before the window ends are honestly dropped, not guessed.

Why "visibility"? The name comes from a physics technique that turns a price series into a network of bars that can "see" each other over intervening bars. This feature's number is exactly a node's forward sight distance in that construction โ€” but the arithmetic needs no network at all: it's a plain "first time the level is re-touched" scan. Simpler arithmetic = fewer places for bugs to hide.

The answer key was double-checked by two very different algorithms: the straightforward scan (look forward bar by bar), and a cleverer one-pass method using a "monotonic stack" โ€” a completely different route to the same integers. Both had to agree exactly โ€” not approximately โ€” on all 19,602 windows, plus known-answer drills (an always-rising market must score exactly 1.0; an always-falling one must honestly say "undefined"; a tiny hand-worked example must give exactly 5/3). All passed.

Good news for effort: unlike feature 1 (which needed a brand-new dataset carrying bar durations), this one reads only closing prices โ€” so it reuses the exact fingerprint-locked datasets every earlier feature trusts. And because the computation is just comparisons plus one division, the upcoming Rust version is expected to match the reference to the last binary digit โ€” zero tolerance headroom needed.

Plan correction (surfaced, not silently absorbed): the campaign scaffold said card 59 would "carry the shared visibility-graph Rust helper". Reading the actually-evaluated kernel disproved that premise: card 59 builds no graph โ€” it's a pure first-passage scan. The graph builder is genuinely needed by card 60 (past-vs-future clustering asymmetry), so the shared helper lands in 60's PR where it's used, not as dead code in 59's. Stack order is unchanged.

Grounded this iteration

Worktree batch6-59-hvg-horizon created, branch STACKED on the card-78 PR branch (fb68842e), not main. S1 (oracle) for bar_hvg_forward_visibility_horizon_mean: scripts/gen_hvghorizon_oracle.py โ€” reuses the committed SHA-pinned close fixtures (close-only substrate); I3 FixedPoint drift guard (drift=0); I4 second leg = independent monotonic-stack next-greater-or-equal pass, exact integer-list equality on all 19,602 windows (no released FOSS implementation exists โ€” card-59 closed-form/property convention); four property anchors green; oracle CSVs written for BTC+ETH, 9,801 rows each, all values โ‰ฅ 1.

featurecard 59
stage1/16 oracle
stack78 โœ… โ†’ 59 โ†’ 60 โ†’ 50
dual-leg xcheck19,602/19,602
anchors4/4 exact
mean horizon BTC5.95 bars
mean horizon ETH6.01 bars

Artifacts + integrity pins

Artifactsha256 (prefix)Note
BTCUSDT-bars-close-sample-10k.csv (reused)08725310896db0a8โ€ฆexisting committed fixture โ€” close-only substrate
ETHUSDT-bars-close-sample-10k.csv (reused)09060aecc9bef0f5โ€ฆโ‰ฅ2-symbol gate
BTCUSDT-hvghorizon-oracle-sample-10k.csvaff5c3a08b5eab81โ€ฆ9,801 rows ยท range [2.24, 15.31]
ETHUSDT-hvghorizon-oracle-sample-10k.csv54acf3c71e300db9โ€ฆ9,801 rows ยท range [2.49, 17.76]

Next fire picks up here

S2/S3 kernel: compute_bar_hvg_forward_visibility_horizon_mean(closes) in bar_close_features.rs โ€” production kernel = monotonic-stack O(n); in-Rust independent leg = naive O(nยฒ) scan; property battery (increasing/constant โ†’ exactly 1.0, decreasing โ†’ NaN, hand-pinned 5/3, never-Inf, determinism). Close-only substrate โ†’ threads through the STANDARD bar_close_feature_walk (12โ†’13-tuple: all 12 existing selectors gain a `_` โ€” unlike card 78's dedicated seam). Then S4 wiring (manifest 14th bar_close entry, tripwires 86โ†’87 / 91โ†’92, compat 66โ†’67 / 13โ†’14), harness lanes, ADR, hvghorizon:* namespace. Expect a BIT-EXACT oracle gate (residual 0). Worktree: ~/eon/odb-worktrees/batch6-59-hvg-horizon (stacked on the #568 branch โ€” rebase onto it if the operator merges and it moves). Ledger is truth.