By TickDistill — order-flow microstructure signals. Educational content, not financial advice.
The same signal processor runs on BTC, ETH, SOL, and later on ES/NQ by injecting a different MarketProfile — a per-market configuration object — without touching the signal logic itself. A canonical event schema normalizes raw exchange data into a common representation first, so every processor is permanently market-agnostic. Capability-tags then determine which packages are eligible to run on which markets, preventing nonsensical pairings like an options-gamma signal running on a spot crypto feed.
Without abstraction, every new market requires rewriting every signal. With abstraction, adding a new market means supplying one new adapter and one new MarketProfile — the existing processors require no changes.
Two challenges make cross-market reuse non-trivial:
| Challenge | Without abstraction | With abstraction |
|---|---|---|
| Different raw data formats | Each processor parses exchange-specific fields | Processors see only canonical events |
| Different market characteristics | Hard-coded thresholds per instrument | Per-market profile injected at runtime |
A raw Binance aggTrade record and a CME ES tick carry the same economic information — a trade happened, at a price, with a side — but in completely different formats. The canonical event schema resolves this before processors see any data.
A canonical event schema is a normalized internal data structure that every exchange adapter must produce before the signal engine processes a single trade.
Concretely: every ingestion adapter — whether reading Binance aggTrades, CME tick tape, or a level-2 book feed — converts its source format into one of two internal types:
TradeEvent { ts, price, notional, aggressor_side, … } for trade dataBookEvent { ts, side, level, price, size, action } for order book updatesSignal processors receive only these canonical types. They never parse a raw exchange format. This single design decision makes every processor permanently market-agnostic, because the differences between exchanges are fully absorbed at the adapter boundary.
A MarketProfile is a per-market configuration object that parameterizes a signal processor without changing the processor’s logic. The same BigOrderProcessor function takes BTC trades as input when injected with the BTC profile and takes ES trades as input when injected with the ES profile.
The profile captures the characteristics that differ between markets: the scale of what counts as “large” relative to normal flow for that instrument, the relevant session windows and their timing conventions, and normalization conventions appropriate to that asset class. The exact fields and values are proprietary calibrations — the profile design is the engineering work that makes cross-market signals honest rather than naively ported. Changing the profile changes the processor’s sensitivity; the logic that measures order-flow structure remains identical.
This is the core claim: same code, different profile.
Sigma-normalization is the reason a single threshold can be meaningful on both a very large-cap asset and a much smaller one. Because every signal expresses its output in standard deviations from a causal local baseline — rather than in raw notional or contract count — “2σ” means genuinely unusual on BTC and genuinely unusual on ES, even though the absolute values differ by orders of magnitude.
The mathematical foundation is straightforward: for any scalar measurement x_t, the normalized reading is
z_t = (x_t - μ_t) / σ_t
where μ_t and σ_t are computed from the past only — a rolling causal window that never peeks at future data. The public z-score framework is standard statistics; what the MarketProfile governs is the window structure and the set of sessions excluded from the baseline so that mechanical volume spikes (funding settlements on perpetuals, market-on-close auctions on regulated futures) do not distort what counts as “normal.” For a full treatment of sigma-normalization, see Why Order-Flow Signals Should Be Measured in Standard Deviations, Not Raw Numbers.
A capability-tag is a package-level declaration of what data types a signal requires and which markets it is eligible to run on. Tags prevent a processor from silently running on incompatible data and producing meaningless output.
Every package in the registry declares two tag dimensions:
| Tag dimension | Example values | Effect |
|---|---|---|
needs |
trades, book_l2, options |
Signal only registers when the required event type is available |
markets |
[cross], [btc], [es] |
Signal only registers for markets in the approved list |
Concrete examples illustrate the separation:
cvd and big_order_base declare needs: trades, markets: [cross] — they run on BTC, ETH, SOL, and later on ES/NQ once the CME adapter exists.needs: options, markets: [es] — not because crypto lacks an options tape (it has one — Deribit), but because the high-value use case (0DTE index-options dealer hedging) lives on regulated futures infrastructure: ES/NQ futures-options on the CME GLBX/MDP3 feed.ofi (Order Flow Imbalance; concept originates with Cont, Kukanov & Stoikov, 2014) declares needs: book_l2 — it does not register on trade-only sources such as free Binance Vision dumps, even though those sources produce valid TradeEvent records.The runner enforces this at startup: for each active market and data source, it queries the registry and registers only compatible packages. No signal silently degrades to a meaningless computation.
The layered architecture makes each extension type independent:
signals/ that operates on existing event types. No adapter, no profile, no registry change needed beyond the new entry.TradeEvent (and optionally BookEvent), then write a MarketProfile for that market. Every existing [cross] processor immediately becomes eligible to run — no processor code changes.needs: book_l2 automatically activate on any market where the new adapter exists.This three-way separation is not incidental — it is the explicit design rule. The ES/NQ roadmap currently lists signals like volume_profile_vpoc and trade-imbalance derivatives as candidates for direct reuse precisely because their processors are already written against canonical events with markets: [cross] tags.
No. Order-flow signals are not uniformly portable, and the architecture is honest about the limits.
The [cross] tag applies to markets with a centralized trade tape — a single authoritative record of who was the aggressor on each transaction. Centralized crypto perpetual markets (BTC, ETH, SOL on Binance and peers) satisfy this condition. CME ES and NQ futures satisfy it via the MDP3 tape. Forex spot does not: there is no consolidated tape, no single aggressor field, and no equivalent to isBuyerMaker. Applying trade-imbalance signals to forex spot data is a category error, not a parameterization problem.
The [cross] tag therefore means “cross centralized tape markets” — not “every asset class.” The [es] tag marks signals whose high-value use case lives on regulated futures infrastructure (e.g. ES/NQ futures-options and MBO data on the CME feed), even where a crypto analogue exists elsewhere.
For a broader treatment of what microstructure signals measure and where they apply, see What Is Order-Flow Microstructure?.
The MarketProfile specifies which time windows to exclude from the rolling baseline. This exclusion list is the mechanism by which the causal σ computation remains honest across sessions with mechanical volume patterns.
Without session-aware exclusions, a baseline computed across a full trading day on an equity futures market would absorb the market-on-close (MOC) auction volume — a structural spike unrelated to informational order flow. On crypto perpetuals, funding settlement windows (at 00:00, 08:00, and 16:00 UTC on most major venues) create predictable volume spikes for mechanical rather than informational reasons. Including these windows in the baseline would make genuinely unusual flow appear less rare than it is.
The exact exclusion windows are proprietary per-market calibrations. The public principle — exclude sessions where volume is structurally elevated for non-informational reasons before computing the rarity baseline — is standard practice in microstructure research and is described in the look-ahead bias literature. See What Is Point-in-Time Correctness? for the full treatment.
Q: If the signal logic is identical across markets, where is the differentiation? A: The differentiation is in the MarketProfile calibration and the adapter engineering — two proprietary layers that determine whether a “2σ” reading is an honest measurement or a naively ported threshold that means nothing in the new market context. Same code; different profile; the profile quality is the work.
Q: Why not just use a universal fixed threshold for all markets? A: A fixed notional threshold that is meaningful on a deep, high-volume regulated future is noise on a thin crypto perp. Sigma-normalization makes the threshold dimensionless and market-adaptive; the MarketProfile governs how the baseline is computed for each specific market’s session structure.
Q: Does [cross] mean a signal runs on literally every market?
A: No. [cross] means the signal is eligible for any market that provides the required event type — centralized trade tape for needs: trades, L2 book for needs: book_l2. Markets without a centralized tape (forex spot) are excluded by architecture, not by a special-case check.
Q: How is adding ES different from adding a new crypto asset?
A: Adding a new crypto perpetual on Binance requires only a new MarketProfile (same adapter already exists). Adding ES requires a new CME adapter (different wire format: MDP3, not aggTrades), a new MarketProfile, and gating any options-dependent signals behind the [es] tag. The processor code for [cross] signals is unchanged in both cases.
Q: What happens to a signal package when a new market is added but the package was not designed for it?
A: Nothing — the package simply does not register for that market. The capability-tag check runs at startup: if the market does not satisfy the package’s needs and markets declarations, the package is not loaded for that market. No silent degradation, no runtime error.
TickDistill sells clean, computed order-flow inputs — not trading advice or guaranteed alpha. Backtests are illustrative and not a promise of future results.