Ghost Alpha

← Methodology

The classifier, explained

The Read’s state line comes from a single, versioned, deterministic classifier - regime.py’s classify() function. Given the same inputs, it always produces the same output: no wall-clock reads, no external calls, nothing that could make the same historical day classify differently on a re-run.

Version

The currently pinned version is v1.1. v1 shipped first and its thresholds are frozen permanently once shipped - a rule change is never an edit to v1’s numbers, only a new version (v2, or a dotted follow-up like v1.1). v1.1 is exactly that: an additive follow-up, not a replacement. It changed exactly one thing - see “v1 versus v1.1” below - and everything else about the classifier’s scope, inputs, and vocabulary carries over from v1 unchanged.

Input set: core versus modifier versus adjacent

The classifier reads four input families, and only four: valuation (MVRV, confirmed by Puell Multiple), flows (net exchange flow, exchange reserve change), leverage (realized volatility), and halving position (calendar, always available). These are the core inputs - the only things that can move state_id, the six-way valuation-band × flow-direction label the Read shows.

Two other kinds of input exist and are deliberately kept out of state_id:

Sentiment is adjacent, not core

Fear & Greed is computed and shown next to the state line as a divergence signal - useful context for whether the market’s mood agrees or disagrees with the fundamentals the classifier actually reads - but it never feeds state_id or the core inputs above, in any version. A market that turns euphoric or panicked purely on sentiment, with valuation and flows unchanged, reads as an unchanged state here. That’s the intended design: this classifier describes valuation, flows, leverage, and cycle position, not the full scope of market psychology, and sentiment is kept visibly separate rather than quietly blended in.

The hysteresis rule

A raw daily classification only becomes a confirmed state change after it holds for 3 consecutive days. If today’s raw reading differs from the currently confirmed state, that’s a candidate - not yet a transition. Only once the same differing reading has held for three days running does the classifier record a transition, backdated to the first of those three days. A candidate streak that breaks early - reverting to the already-confirmed state, or switching to a third state before reaching three days - never becomes a transition at all; those in-between days end up attributed to whichever state the streak eventually resolves to. This rule exists specifically to keep a single noisy day from flipping the headline state and flipping it back.

v1 versus v1.1: the neutral-band fix

v1’s flow-direction signal draws on a 30-day rolling sum of net exchange flow, recomputed daily. Because it’s a rolling sum, a single volatile day entering or leaving that 30-day window can cross zero on its own, flipping the accumulating/distributing label with no real change in the underlying trend - a flicker, not a real regime shift. v1.1 addresses this with one addition: a neutral dead-zone of ±5,000 BTC around zero on the 30-day flow signal specifically. A value inside that band abstains from casting a vote rather than forcing a fresh accumulating/distributing reading off a borderline number; the 90-day exchange-reserve-change signal, a slower window and not the diagnosed source of the flicker, is left unbanded and can still decide the direction on its own. Nothing else changed - same six-state vocabulary, same core/modifier/adjacent split, same 3-day hysteresis rule, same institutional-era comparison window. v1 itself remains frozen and unedited; v1.1 is purely additive.