---
title: "HMM Dual-scale Direction"
description: "hmm_regime API reference: requests, parameters, response fields and result handling."
---

# HMM Dual-scale Direction

## Example request

Use `POST /api/indicators` to calculate HMM from market data. Set `id: "hmm"` to read the result at `indicators.hmm`.

```bash
curl -X POST 'https://api.mobiusquant.ai/api/indicators?explain=false' \
  -H 'Content-Type: application/json' \
  -d '{
    "exchange": "binance",
    "market": "perp",
    "symbol": "BTCUSDT",
    "interval": "1h",
    "limit": 100,
    "calc": [{"name": "hmm_regime", "id": "hmm"}]
  }'
```

Live support covers connected Binance, Bybit, OKX and Hyperliquid feeds at `5m / 15m / 1h / 4h / 1d`, including [Binance stock perpetuals](/markets#binance-stock-perp), but not stock spot venues. See [integration basics](../agents) for authentication and common request fields.

## Parameters

All parameters are optional and belong in `calc[].params`. Omitted parameters use their defaults.

| Parameter | Type | Default | Values / range | Description |
| --- | --- | --- | --- | --- |
| `horizon` | integer | `20` | 5–100 | Local scale; the context scale is three times this value. |
| `fast_weight` | number | `0.35` | 0–1 | Weight assigned to fast-changing evidence. |
| `stick` | number | `0.97` | 0.80–0.999 | Persistence parameter; higher values favor retaining the current direction. |
| `confirm` | integer | `3` | 1–10 | Consecutive qualifying closed bars needed to establish or switch direction. |
| `dominance` | number | `0.55` | 0.34–0.95 | Minimum model weight for a candidate direction. |
| `margin` | number | `0.15` | 0–0.9 | Minimum weight advantage over the runner-up. |
| `normalization` | string | `auto` | auto, d1, legacy | Calculation mode: select automatically by interval, or specify d1 or legacy. |

`normalization: "auto"` selects d1 for 5m/15m/1h and legacy for 4h/12h/1d.
To specify a mode: `{"name":"hmm_regime","id":"hmm","params":{"normalization":"legacy"}}`.

## Response

Only `indicators.hmm` is shown below. Values illustrate the structure; they are not live market data.
Each row in `data` corresponds to one candle, with values ordered as listed in `columns`.

```json
{
  "columns": [
    "open_time", "hmm_state", "hmm_status",
    "hmm_p_up", "hmm_p_range", "hmm_p_down",
    "hmm_context_state", "hmm_context_status", "hmm_supported"
  ],
  "data": [
    [1735689600000, 1, "confirmed", 0.7, 0.2, 0.1, 1, "confirmed", true]
  ],
  "meta": {
    "schema_version": 3,
    "model_version": "mobius-direction-v2",
    "effective_normalization": "d1",
    "history_start_ms": 1717693200000,
    "history_status": "ready",
    "history_bars": 5000,
    "last_bar_closed": true,
    "last_confirmed_time_ms": 1735689600000
  }
}
```

| Field | Type | Description |
| --- | --- | --- |
| `open_time` | integer | Candle open time in Unix milliseconds. |
| `hmm_state` | integer | Retained local direction. |
| `hmm_status` | string | Local status: unavailable, uncertain or confirmed. |
| `hmm_p_up` | number | Local up model weight, 0–1. |
| `hmm_p_range` | number | Local range model weight, 0–1. |
| `hmm_p_down` | number | Local down model weight, 0–1. |
| `hmm_context_state` | integer | Context direction at horizon×3 on the same candle interval. |
| `hmm_context_status` | string | Context status; uses the same values as hmm_status. |
| `hmm_supported` | boolean / null | Whether closed-bar evidence supports the retained local direction; see below. |

Both direction fields use: `-1` no valid direction yet, `0` range, `1` up, `2` down.
Context is a slower scale on the same candle interval, not data from another timeframe.

The three weights sum to approximately 1. They express relative model support for the current categories,
not future-return probabilities or win rates. When status is unavailable, the initial 1/3 weights do not provide a valid assessment.

If complete history is required, check `meta.history_status === "ready"`; otherwise, results may change.
`ready` does not mean a confirmed direction. Read `hmm_status` and `hmm_context_status` for direction status.

<details>
<summary>meta fields</summary>

| Field | Description |
| --- | --- |
| `history_status` | History availability: warming (preparing), ready (complete), or partial (incomplete). Market-data requests only. |
| `history_bars` | Actual calculation input count, including history before the output window; live requests only. |
| `schema_version` | Response schema version; currently 3. |
| `model_version` | Calculation model identifier; currently mobius-direction-v2. |
| `effective_normalization` | Effective mode: d1 or legacy. |
| `history_start_ms` | Open time of the first calculation input, in milliseconds. |
| `last_bar_closed` | Whether the last returned bar is closed; null for an empty window. |
| `last_confirmed_time_ms` | Open time, in milliseconds, of the last closed input bar up to the returned window end; null if none. Not a direction-switch time. |

</details>

## Read the result

Use column names instead of hard-coded array positions. This converts the latest row to an object,
or returns null if there are no rows.

```js
const result = response.indicators.hmm;
const row = result.data.at(-1);
const latest = row
  ? Object.fromEntries(result.columns.map((field, i) => [field, row[i]]))
  : null;

// latest?.hmm_state
// latest?.hmm_supported
```

| Status | Meaning |
| --- | --- |
| `unavailable` | Insufficient history or gap recovery; do not infer a direction. |
| `uncertain` | The first direction is pending, or current evidence does not support the retained direction. |
| `confirmed` | Direction is confirmed and supported by current evidence. |

| hmm_supported | Meaning |
| --- | --- |
| `true` | Current evidence supports the retained local direction. |
| `false` | A direction is retained, but current evidence does not support it; this does not confirm a reversal. |
| `null` | No valid direction yet. |

For example, `hmm_state=1` with `hmm_supported=false` retains up, but lacks current supporting evidence.
By default results update only on closed bars. A forming final candle carries the latest committed direction, weights and support.
With `signals: true` and `include_forming: true`, the current final OHLCV sample participates once as complete.
Direction, weights, support and features all come from that trial and can change or disappear on updates.
Model requirements such as `confirm` are unchanged; repeated requests do not increase the confirmation count.
In this mode `hmm_status=confirmed` means the model conditions hold, not that the candle actually closed:
its signals have `bar_status=forming` and `confirmed_at_ms=null`.
`meta.last_bar_closed` and `meta.last_confirmed_time_ms` still describe actual input closure; `meta.include_forming=true` identifies the trial mode.

## Bring your own candles

Use `POST /api/indicators/compute`. See [BYO computation](../compute) for the candle format.

- Supply `interval`: 5m/15m/1h/4h/12h/1d. The 12h interval is available only for BYO computation.
- Input is assumed closed. Set top-level `last_bar_closed: false` if only the final candle is forming.
- HMM-only requests accept up to 5000 candles; mixed requests accept 2000. At most eight HMM instances per request.
- Timestamps must be strictly increasing milliseconds, and OHLC values must be positive. Do not fill gaps with duplicates.

At the default horizon=20, d1 needs 20/60 input bars for local/context readiness; legacy needs 153/461.
Consecutive direction confirmation is additional. Changing horizon changes history requirements; check status for availability.
To compare results, use identical data, history start, interval, parameters and closed-bar flags.

## Chart

Change the example endpoint to `POST /api/chart` and keep the same request body.
The HMM subpanel in `panels[]` uses the request ID (hmm in this example).
Its `items` contain Up / Range / Down lines, using the three model weights on a 0–1 scale.
Chart points use `time` in Unix **seconds**; calculation rows use `open_time` in **milliseconds**.
History readiness and input count are available at `indicator_meta.hmm` (keyed by request ID).


## Native features

Set top-level `signals: true` and read `indicators[responseKey].signals`. By default features are evaluated on closed bars: `true` is a positive result, `false` a valid negative result, and `null` unknown. These are not trade instructions.

This indicator supports `include_forming: true`: treat the current final OHLCV sample as complete under the same native rules, returning one set of values, features and objects. The signal table appends `bar_status`: `closed` for closed bars, `forming` for a trial with `confirmed_at_ms=null`. A trial may disappear on later updates or at close. For BYO, still set `last_bar_closed: false`. Close requirements below describe the default mode; trials only admit the final sample without shortening structural windows or model confirmation requirements. See [forming trials](/signals#forming).

History lengths are minimum evaluation requirements, not convergence guarantees. Comparisons use unrounded values and the exact boundaries below. Do not turn `null` into `false` on gaps, invalid dependencies or forming bars in the default mode.

| Feature column | Kind | Rule | Meaning | History / validity |
| --- | --- | --- | --- | --- |
| `hmm_regime.direction_established` | `event` | hmm_state changes from -1 to 0/1/2 with local inputs available. | A qualifying candidate establishes a retained direction after confirm bars; this is not a reversal. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |
| `hmm_regime.direction_changed` | `event` | Both hmm_state values are 0/1/2 and they differ. | The retained local direction switches; read hmm_state for the new direction. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |
| `hmm_regime.context_established` | `event` | hmm_context_state changes from -1 to 0/1/2 with context inputs available. | First confirmation at the longer scale of the same candle interval, not a higher-timeframe confirmation. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |
| `hmm_regime.context_changed` | `event` | Both hmm_context_state values are 0/1/2 and they differ. | The retained longer-scale direction changes; read hmm_context_state. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |
| `hmm_regime.support_lost` | `event` | Retained local direction is unchanged and hmm_supported changes from true to false. | Evidence no longer supports the retained direction, which has not switched. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |
| `hmm_regime.support_restored` | `event` | Retained local direction is unchanged and hmm_supported changes from false to true. | Evidence supports the same direction again, without a new confirm streak or direction switch. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |
| `hmm_regime.evidence_supported` | `state` | Uses hmm_supported; null without a valid retained direction or on a forming bar. | True means supported, false means unsupported; neither is a calibrated price forecast. | Uses readiness of the relevant scale; events need consecutive closed bars. Support changes require the same valid direction on both bars. |

See [feature requests](/compute#native-features) for the format and examples. `/api/chart` also accepts `signals: true`, marking confirmed events by default. With `include_forming`, trial events also produce markers tagged `bar_status=forming`; states are not drawn on every bar. See [feature charts](/compute#feature-chart).
