Market Structure Engine

The Market Structure Engine is the navigator of the RiskState stack. Where RiskState answers how much risk is allowed, the Market Structure Engine answers a different, orthogonal question:

Are we near a structural inflection?

It sits on top of the same risk pipeline and emits structural events — breakouts, breakdowns, regime transitions, local tops and bottoms — as probabilistic, track-recorded signals plotted on a live structural map.

Open the live Market Structure Engine →

The viewer is free and read-only. It holds no funds, requires no wallet, and shows no positions — it is the navigator layer, public by design.

Everything the viewer shows is also available programmatically — see Consuming it via API for POST /v1/market-structure (the same endpoint behind the viewer), built for developers, trading agents, and downstream systems.

What it does

  • Structural map — breakout / breakdown triggers, a 180d structural range, nearest major top (ATH) and support (200W MA) — computed live for both BTC/USD and ETH/USD — and the live price in context.
  • Event feed — local-low / local-high pivots and panic markers (Fear & Greed ≤ 20 clusters), the same pivots the engine records.
  • Regime & transition — the current market structure regime and recent BEAR → NEUTRAL → BULL (and reverse) transitions, each with a hash for audit.
  • On-chain context — MVRV (Coin Metrics CapMVRVCur) and NUPL alongside the structural read.

The two questions, side by side

RiskStateMarket Structure Engine
QuestionHow much risk now?Near an inflection?
NatureGovernor (state → policy)Navigator (events → asymmetry)
Outputpolicy_level, max_size, regimestructural events + map
AxisHOW MUCHWHEN / WHERE

The two are orthogonal — one says how much exposure is allowed, the other whether the terrain is changing — and they combine into something neither gives alone.

Where it sits in the stack

The Market Structure Engine is built on top of RiskState — its event evidence (deep drawdown, seller exhaustion, policy easing) are RiskState signals. It is consumed as its own surface with its own question and output, but the synergy is native.

It is one of three complementary engines, each answering a different question:

  • Navigator — Market Structure Engine — are we near an inflection?
  • StrategistTrading Playbook Engineis there a setup I trade?
  • GovernorRiskStatehow much is allowed?

Each is consumed independently and stands on its own; together they give a fuller read of the market than any one alone.

Consuming it via API

The Market Structure Engine is the same surface a developer, AI agent, or downstream system consumes over HTTP. The viewer is just one client of this endpoint.

View the open-source client on GitHub → — typed TypeScript + Python client, response types, runnable examples, and an offline fixture.

Endpoint

POST https://api.riskstate.ai/v1/market-structure

Authentication

Bearer token, same key as the rest of the RiskState API — any valid key (owner or external rs_live_) may read the feed. Request a key from the home page (email only, free during beta). The endpoint fails closed: missing or invalid credentials return 401; external keys are rate-limited (429 with retry_after_seconds).

Authorization: Bearer <your_api_key>

Request

FieldTypeDefaultDescription
assetstring"BTC"Asset to evaluate. "BTC" or "ETH".
curl -X POST https://api.riskstate.ai/v1/market-structure \
  -H "Authorization: Bearer $RISKSTATE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"asset": "BTC"}'

What it returns

A JSON document with the structural read, the event feed, the map, and an audit trail. Top-level fields:

FieldTypeDescription
assetstringThe evaluated asset.
headline / subhead / watchstringHuman-readable summary of the current structural state and what to watch next.
eventsarrayStructural events the engine is tracking. Each has event, direction (bullish / bearish / null), kind, tier, status (forming / strengthening / confirmed / suppressed), confidence (0–100, or null for pure risk flags), validated (true = backed by a standalone backtest; false = a newer directional event still accruing its prior live, so consumers can choose to treat it as informational), and regime_gate. A shadow calibrated_confidence (also 0–100) is attached when calibration data exists — it does not change the emitted confidence.
structural_mapobjectNear-term breakout / breakdown triggers (40d swing, breakout_window_days), a longer 180d structural range (range_high / range_low, range_window_days), nearest major top (ATH) and support (200W MA) — both computed live from OKX weekly candles for BTC and ETHdrawdown_from_ath_pct, and live price in context.
asymmetryobjectThe combined Structure × RiskState read — a label plus the reasoning behind it.
risk_overlayobjectThe RiskState context: market_regime, macro_state, policy_level, structural_score, sustained_bear + bear_reasons, the bear_gate inputs (macro risk-off, below-falling-200DMA, 7d exchange netflow), and momentum_7d_pct.
data_sourcesobjectProvenance for each input: onchain (Coin Metrics CapMVRVCur or fallback), price_structure (OKX 1D), structural_levels (OKX 1W — ATH + 200W MA), risk_state, calibration.
structure_hashstringSHA-256 per-response integrity hash (includes live price — changes every tick).
state_hashstringSHA-256 of the discrete structural state only — the dedup key for the track record, so it records transitions, not price ticks.
structure_version / api_version / timestampstringEngine version, endpoint version, and ISO timestamp.

On-chain valuation fields (mvrv, nupl, exchange netflow) are BTC-only — for "ETH" they report null / n/a. ETH instead gets its own structural events (from the native ETH structural score) plus live ATH / 200W MA / drawdown, so its structural read leans on price structure, regime, macro, and the ETH structural layer.

Errors

StatusMeaning
400Invalid JSON body, or asset not BTC/ETH.
401Missing or invalid API key.
429Rate limit exceeded (external keys) — retry after retry_after_seconds.
503Upstream risk-state momentarily unavailable (cold start / transient core-data gap) — retry after Retry-After seconds. The engine already retries once internally before surfacing this.

Related