ByteTree API documentation

Regime Transitions

A log of the moments assets changed trend regime — for example, every stock that entered a Leading Trend last year, and when. Each entry records the label before and after, plus a snapshot of the asset’s metrics on the day it changed.

Request

# Assets that entered Leading Trend on the 200w-CAPR window in 2024
curl "https://api.bytetree.io/api/metrics/regime-transitions?window=200w-CAPR&regime=Leading%20Trend&from=2024-01-01&to=2024-12-31"

# Any 30d-CAPR transition in the last 90 days for active stocks
curl "https://api.bytetree.io/api/metrics/regime-transitions?window=30d-CAPR&direction=any&from=2026-02-01&type=stock&status=active"

# Custom metric snapshot at transition
curl "https://api.bytetree.io/api/metrics/regime-transitions?window=200w-CAPR&regime=Leading%20Trend&from=2025-01-01&fields=closeUsd,sharpe52w,returnUsd1M"

Query Parameters

NameTypeRequiredDescription
windowstringYesScore window. One of 200w-CAPR, 200w-Local, 30d-CAPR, 30d-Local
regimestringYes when direction !== 'any'Target regime label — one of Leading Trend, Emerging Trend, Weakening Trend, Bear Trend, Neutral. The label is matched as given: any other value matches nothing and returns an empty data, not an error. May be omitted when direction=any
directionstringNoOne of into, outOf, any (case-insensitive). Default into. any returns every transition regardless of regime
fromstringNoInclusive ISO YYYY-MM-DD lower bound on transitionDate. Omitting it applies a 90-day look-back rather than scanning all history — see Default date window
tostringNoInclusive ISO YYYY-MM-DD upper bound on transitionDate
typestringNoAsset-type filter — stock, crypto, etf, index, commodity. fx is rejected
statusstringNoAsset status — active, pending, inactive
sectorstringNoSector filter (case-insensitive)
qstringNoFree-text symbol/name search
universestringNoUniverse slug (e.g. bytetrend, bytefolio) — see Universes. Membership filter: the population becomes that universe’s members. Unknown slugs and macro return 400 — see Group filters
dimensionstringNoOne of the five global dimensions: region, sector, industry, type, or country. Paired with group; independent of universe
groupstringNoGroup label within dimension, exact match. Paired with dimension
fieldsstringNoComma-separated metric keys included in metricsAtTransition. Default: closeUsd, byteTrendCapr200w, byteTrendCapr30d, returnUsd1M, marketCapUsd, sharpe52w
formatstringNoResponse format: json (default), csv, or toon

Group filters

universe restricts the scanned population to that universe’s members — the assets whose universes[] includes the slug. Without it, the scan covers the whole registry.

dimension + group narrow the scan by the asset’s resolved value in one of the five global dimensions. The pair is independent of universe and both-or-neither: one without the other is a 400, as is an unknown dimension. type, status, sector and q compose with all of these. Both filters genuinely narrow the scan, which matters for the row cap under Bounds.

?universe=macro is a 400 — the macro dataset is at /api/macro, not a universe. Filter by nothing to scan the whole registry.

Response

FieldTypeDescription
generatedAtstringISO timestamp captured when the server ran the aggregation
regimestring or nullEcho of the resolved target regime. null when direction=any
windowstringEcho of the resolved window
directionstringEcho of the resolved direction
appliedRangeobjectThe date window actually queried — see Default date window
appliedRange.fromstringISO YYYY-MM-DD lower bound applied, whether you supplied it or it was defaulted
appliedRange.tostring or nullISO YYYY-MM-DD upper bound applied, or null when you supplied none. Here null is meaningful rather than missing: it means open-ended to the latest available data, not “defaulted to today”
appliedRange.defaultedbooleantrue when from was defaulted, false when you supplied it
countnumberNumber of transition rows in data
dataobject[]One row per transition event
data[].symbolstringAsset ticker symbol
data[].transitionDatestringISO YYYY-MM-DD. For raw windows, this IS the confirmation date; see below
data[].fromRegimestringRegime label immediately before the transition
data[].toRegimestringRegime label after the transition
data[].metricsAtTransitionobjectSnapshot of fields evaluated at transitionDate
data[].trendAgeAtTransitionnumberConfirmed window only. Days the prior regime had been in force at the transition
data[].confirmedTransitionDatestringConfirmed window only. Same value as transitionDate — kept for explicitness
data[].pendingStartDatestringConfirmed window only. Date the pending transition first appeared. Confirmation lag is the trading-day delta to confirmedTransitionDate

Two output shapes

{
  "generatedAt": "2026-05-07T19:42:00.613Z",
  "regime": "Leading Trend",
  "window": "200w-CAPR",
  "direction": "into",
  "appliedRange": { "from": "2024-01-01", "to": "2024-12-31", "defaulted": false },
  "count": 160,
  "data": [
    {
      "symbol": "NVDA",
      "transitionDate": "2024-03-12",
      "fromRegime": "Emerging Trend",
      "toRegime": "Leading Trend",
      "trendAgeAtTransition": 5,
      "confirmedTransitionDate": "2024-03-12",
      "pendingStartDate": "2024-03-07",
      "metricsAtTransition": {
        "closeUsd": 880.21,
        "byteTrendCapr200w": 5,
        "byteTrendCapr30d": 5,
        "returnUsd1M": 0.084,
        "marketCapUsd": 2200000000000,
        "sharpe52w": 1.42
      }
    }
  ]
}

Default date window

A call without from does not scan all history. When from is omitted the server applies a 90-day look-back, anchored on to if you supplied one and on the current date otherwise. An explicit from is always honoured as given — widening the range is opt-in.

Every response reports the window it actually used:

// No dates supplied — 90-day look-back, open-ended at the recent end
"appliedRange": { "from": "2026-04-24", "to": null, "defaulted": true }

// from supplied — honoured as-is
"appliedRange": { "from": "2020-01-01", "to": null, "defaulted": false }

// to supplied without from — look-back anchored on `to`
"appliedRange": { "from": "2023-10-03", "to": "2024-01-01", "defaulted": true }

Two things to read carefully:

This default matches the equivalent ByteTree MCP tool, so both surfaces bound an unqualified query the same way.

Regime transitions accumulate over decades across the whole population, and an unbounded scan was slow enough to exceed upstream timeouts — returning an unhelpful error instead of data. The default keeps a date-less exploratory call fast and useful.

Bounds

Regime labels

Regime labels are the values of confirmedRegime* / pendingRegime* produced by the scoring engine. See the Latest Metrics field reference for the full label set per window. The MCP bytetree://glossary resource holds authoritative wording sourced from engine doc-strings.

Notes