---
title: "Regime-Adaptive Market Maker"
description: "HMM-based regime detection that adjusts quoting behavior for calm, volatile, and crisis markets."
icon: "wave-square"
---

<Note>**Pro Feature.** Requires a Pro or Ultra subscription. [Get started at api.mathematicalcompany.com](https://api.mathematicalcompany.com)</Note>

A market maker that uses a Hidden Markov Model to detect market regimes and adapts its quoting strategy: tight spreads in calm markets, wide spreads in volatile markets, and no quotes during crises.

## Full Code

```python
"""Regime-adaptive market maker using HMM regime detection."""

import horizon as hz
from horizon.context import FeedData


# Markov regime detector: 3 states (calm, volatile, crisis)
regime = hz.markov_regime(
    feed_name="polymarket",
    n_states=3,
    lookback=100,
    labels=["calm", "volatile", "crisis"],
)


def quoter(ctx: hz.Context, fair: float) -> list[hz.Quote]:
    """Adjust spread and size based on detected regime."""
    current_regime = ctx.params.get("regime_label", "calm")
    regime_probs = ctx.params.get("regime_probabilities", [1.0, 0.0, 0.0])

    if current_regime == "calm":
        # Tight spread, large size - capture spread in quiet markets
        spread = 0.02
        size = 15.0
    elif current_regime == "volatile":
        # Wide spread, small size - compensate for adverse selection
        spread = 0.06
        size = 5.0
    else:
        # Crisis: don't quote at all
        print(f"  Crisis regime detected (prob={regime_probs[2]:.2f}), pausing quotes")
        return []

    print(f"  Regime: {current_regime} | probs={[f'{p:.2f}' for p in regime_probs]} | spread={spread}")
    return hz.quotes(fair, spread, size=size)


hz.run(
    name="regime_adaptive_mm",
    markets=["election-winner"],
    feeds={
        "polymarket": hz.PolymarketBook("election-winner"),
    },
    pipeline=[regime, quoter],
    risk=hz.Risk(max_position=100, max_drawdown_pct=5),
    interval=1.0,
    mode="paper",
)
```

## How It Works

1. **`markov_regime()`** fits an HMM to recent price returns from the feed
2. Each cycle, it classifies the market into one of 3 states and stores the label + probabilities in `ctx.params`
3. The **quoter** reads the regime and adjusts:
  - **Calm** - tight 2-cent spread, 15 contracts (maximize fill rate)
  - **Volatile** - wide 6-cent spread, 5 contracts (reduce adverse selection)
  - **Crisis** - no quotes (preserve capital)
4. Regime probabilities provide confidence: if the model is 90% sure it's calm, you can trust the tight spread

## Standalone HMM

You can also use the Rust HMM directly for research:

```python
import horizon as hz

# Convert prices to log returns
prices = [0.50, 0.51, 0.49, 0.52, 0.48, 0.53, 0.47, 0.55, 0.45, 0.50]
returns = hz.prices_to_returns(prices)

# Fit a 3-state HMM
model = hz.MarkovRegimeModel(n_states=3)
model.fit(returns, max_iter=100)

# Predict current regime
state = model.predict(returns)
probs = model.state_probabilities(returns)

print(f"Current state: {state}")
print(f"State probabilities: {[f'{p:.3f}' for p in probs]}")
print(f"Transition matrix:")
for row in model.transition_matrix():
    print(f"  {[f'{x:.3f}' for x in row]}")
```

## Run It

```bash
python examples/regime_adaptive_strategy.py
```

## Extending

Combine regime detection with inventory skew for a more robust strategy:

```python
hz.run(
    name="regime_skew_mm",
    markets=["btc-100k"],
    feeds={
        "polymarket": hz.PolymarketBook("btc-100k"),
    },
    pipeline=[
        regime,
        hz.inventory_skewer(gamma=0.15),
        quoter,
    ],
    risk=hz.Risk(max_position=100, max_drawdown_pct=5),
    interval=1.0,
    mode="paper",
)
```

See [Markov Regime Detection](/markov) for the full HMM reference.
