Navigation

Iteration 09 · 2026-06-09 · driver: native Claude Code /loop (laptop run)

Feature #8 — sign_two_state_entropy_rate (PR #98)

← Dashboard · PR terrylica/mql5#98 · card 83 · cut off bootstrap #90

Done. The eighth ξ-confirmed candidate — the FIRST information-theoretic entropy-rate feature — is a REAL continuous-float production column on fxview_cache.forex_bars: bit-exact Rust verified against a pinned Python SSoT, populated through the wired producer, with batch≡streaming parity and an independent 3-way FOSS corroboration. PR #98 open (base main; diff auto-cleans once #90–#97 land).

What it computes

Shannon entropy rate (bits, in [0,1]) of a first-order 2-state (up/down) Markov chain over the binarized sign sequence of the per-bar mid log-return across the 200-bar strictly-trailing window — an information-theoretic predictability measure (0 = perfectly predictable sign chain, e.g. strict alternation; 1 = maximally unpredictable). Causal: the window is the 200 bars BEFORE bar i (current bar excluded). None on warmup (<16 finite trailing signs) OR a degenerate single-state window (pi[i]==0). H = −Σi statp[i] Σj P[i,j] log2 P[i,j] where the 2×2 transition counts are integer-exact (i64), P (row-stochastic) + statp (empirical from-frequency) are exact rationals, and only the final log2 + products are float (card 83 tier EXACT counts, ε on log2). Substrate = "signs" = np.sign(logret) over the gap-nulled mid log-return (logret = ln(close)−diff, 8 h weekend/Ouroboros gap-null — identical to anderson_darling_a2 / lziv_complexity_signs); (s>0) → bit 1 iff up-bar (flat OR down → 0). No new dep (f64::log2).

The chain — one SSoT, bit-exact to the column

LayerArtifactResult
Python SSoToracle_sign_two_state_entropy_rate.py — bit-faithful reproduction of probe k_sign_entropy_rate over the "signs" 200-bar windowsha-pinned jsonl (12000 rows, 11200 finite) + .sha256 sidecar
Rust kernelorthogonal_extension_kernels::sign_two_state_entropy_rate — integer 2×2 i64 transition counts + row-stochastic P + statp + −Σ statp·P·log2 P; no new depclippy clean; 6 unit tests pin probe behaviour
Differential parityvs the pinned oracle on the frozen fixture11200 == oracle, 12000 bars == rows, max|dev| 1.110e-16
Producer columnBarOrthogonalExtV1 { sign_two_state_entropy_rate } + BarRow + schema.sql Nullable(Float64) CODEC(Gorilla(8),ZSTD(1)) + feature_metadata.yamltest_schema_contract 4/4
Producer populateSignTwoStateEntropyRateRollingState — 200-bar sign ring + prior close/close-time (gap-null like lziv); read-before-push observe(close_mid, open_time_us, close_time_us) @ finalize
batch≡streamingstreaming observe() over the fixture per partition11200 == oracle, max|dev| 1.110e-16 (identical to batch)
3-way FOSSprobe-form vs clean-room conditional-entropy decomposition vs pyitlib H(Xt|Xt−1) (ML)PASS — 0 mismatches, max|dev| 2.220e-16 (clean-room) / 5.551e-16 (pyitlib) / 11200

3-way FOSS finding (the FOSS trap caught)

The 2-state Markov entropy rate is corroborated THREE independent ways: the probe-form (SSoT; statp·P·log2 grouped by transition), a from-scratch clean-room conditional-entropy decomposition H = Σx p(x) H(next|x) via plain dict accumulation (no shared code with the probe; agrees at 2.220e-16), and pyitlib drv.entropy_conditional(b[1:], b[:−1], base=2, estimator='ML') (agrees at 5.551e-16). The FOSS trap: the candidate card lists NPEET, but NPEET is a kNN CONTINUOUS-entropy estimator — the wrong tool for a discrete 2-state chain. The correct discrete FOSS reference is pyitlib (MIT): its empirical (plug-in / ML) conditional entropy H(Xt|Xt−1) is identically the probe's estimator (p(from=i)=pi[i]/(n−1)=statp[i], p(to=j|from=i)=P[i,j]) — i.e. the Markov entropy rate of a first-order chain IS the one-step conditional entropy. The errata is carried through the oracle, kernel, schema COMMENT, metadata + this FOSS leg.

Challenge-and-Held (inline; sub-agent dispatch skipped per the tick-3 signal)

Gates / scope

Next

Feature #9 (final implementable) — spectral_log_slope (card 75, PSD log-spectral slope via rfft + OLS log-log; ε ~1e-6; FFT — match libm primitive).

Presentation only — never the SSoT.