> ## Documentation Index
> Fetch the complete documentation index at: https://mathematicalcompany.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Volatility Suite

> Multiple volatility estimators for prediction markets: close-to-close, Parkinson, Garman-Klass, Yang-Zhang, EWMA, and rolling. Rust-native with Python pipeline integration.

# Volatility Suite

Horizon provides six volatility estimators implemented in Rust, plus a `hz.volatility()` pipeline function that computes all of them per cycle and injects a `VolatilitySnapshot` into your strategy context.

<Note>
  Prediction markets trade 24/7 on a 365-day calendar. All estimators use `sqrt(365)` for annualization by default, which differs from the `sqrt(252)` convention used in equity markets.
</Note>

## Overview

<CardGroup cols={2}>
  <Card title="Close-to-Close" icon="chart-simple">
    `hz.estimate_volatility()` - standard deviation of log returns. Simple, widely used.
  </Card>

  <Card title="Parkinson" icon="arrows-up-down">
    `hz.parkinson_vol()` - high/low range estimator. \~5x more efficient than close-to-close.
  </Card>

  <Card title="Garman-Klass" icon="chart-bar">
    `hz.garman_klass_vol()` - OHLC estimator. Most efficient standard estimator.
  </Card>

  <Card title="Yang-Zhang" icon="layer-group">
    `hz.yang_zhang_vol()` - combines overnight jump + Rogers-Satchell. Handles opening gaps.
  </Card>

  <Card title="EWMA" icon="bolt">
    `hz.ewma_vol()` - exponentially weighted, reactive to recent changes.
  </Card>

  <Card title="Rolling" icon="wave-pulse">
    `hz.rolling_vol()` - windowed realized vol series for time-varying analysis.
  </Card>
</CardGroup>

***

## Rust Functions

All functions return `0.0` on insufficient or invalid data. All accept an `annualize` parameter.

### hz.estimate\_volatility

Standard deviation of log returns (close-to-close).

```python theme={null}
import horizon as hz

vol = hz.estimate_volatility(
    prices=[0.50, 0.52, 0.48, 0.51, 0.49],
    annualize=True,  # default: False (backward compatible)
)
```

### hz.parkinson\_vol

Parkinson high/low range estimator. More efficient than close-to-close because it uses intra-period range information.

```python theme={null}
vol = hz.parkinson_vol(
    highs=[0.55, 0.56, 0.54],
    lows=[0.45, 0.44, 0.46],
    annualize=True,  # default: True
)
```

### hz.garman\_klass\_vol

Garman-Klass OHLC estimator. The most statistically efficient standard estimator using open, high, low, close data.

```python theme={null}
vol = hz.garman_klass_vol(
    opens=[0.50, 0.52, 0.48],
    highs=[0.55, 0.56, 0.54],
    lows=[0.45, 0.44, 0.46],
    closes=[0.52, 0.48, 0.51],
    annualize=True,  # default: True
)
```

### hz.yang\_zhang\_vol

Yang-Zhang estimator combining overnight jump variance, open-to-close variance, and Rogers-Satchell range variance. The most robust OHLC estimator, especially when opening gaps are present.

```python theme={null}
vol = hz.yang_zhang_vol(
    opens=[0.50, 0.52, 0.48, 0.51],
    highs=[0.55, 0.56, 0.54, 0.57],
    lows=[0.45, 0.44, 0.46, 0.43],
    closes=[0.52, 0.48, 0.51, 0.53],
    annualize=True,  # default: True
)
```

<Note>
  Yang-Zhang requires at least 2 bars (for overnight returns). Returns 0.0 with fewer.
</Note>

### hz.ewma\_vol

Exponentially weighted moving average volatility. More reactive to recent price changes than equal-weighted estimators.

```python theme={null}
vol = hz.ewma_vol(
    prices=[0.50, 0.52, 0.48, 0.51, 0.49, 0.53],
    span=20,          # EWMA span (default: 20)
    annualize=True,   # default: True
)
```

### hz.rolling\_vol

Rolling windowed realized volatility series. Returns a list of vol values, one per window position.

```python theme={null}
vols = hz.rolling_vol(
    prices=[0.50, 0.52, 0.48, 0.51, 0.49, 0.53, 0.47],
    window=3,          # rolling window size (default: 20)
    annualize=True,    # default: True
)
# vols is a list of floats, one per window position
```

***

## Pipeline Function

The `hz.volatility()` pipeline function computes all estimators per cycle from a feed and injects a `VolatilitySnapshot` into `ctx.params["vol"]`.

```python theme={null}
import horizon as hz

def model(ctx):
    vol = ctx.params.get("vol")
    if vol and vol.best > 0:
        spread = vol.best * 2  # scale spread by vol
        return hz.quotes(fair=ctx.feeds["poly"].price, spread=spread)
    return []

hz.run(
    pipeline=[
        hz.volatility("poly", lookback=100, ewma_span=20),
        model,
    ],
    feeds={"poly": hz.PolymarketBook(token_id="0x123...")},
    markets=[hz.Market(id="0x123...", name="Example")],
)
```

### Parameters

| Parameter        | Type   | Default  | Description                             |
| ---------------- | ------ | -------- | --------------------------------------- |
| `feed`           | `str`  | required | Feed name to read prices from           |
| `lookback`       | `int`  | `100`    | Maximum price history length per market |
| `ewma_span`      | `int`  | `20`     | EWMA span parameter                     |
| `rolling_window` | `int`  | `20`     | Rolling vol window size                 |
| `annualize`      | `bool` | `True`   | Multiply by sqrt(365)                   |

### VolatilitySnapshot

The snapshot injected into `ctx.params["vol"]` is a frozen dataclass:

```python theme={null}
from horizon import VolatilitySnapshot

snap = VolatilitySnapshot(
    realized=0.15,
    parkinson=0.12,
    garman_klass=0.11,
    yang_zhang=0.13,
    ewma=0.14,
    rolling=0.12,
)

snap.best       # 0.13 (yang_zhang - highest priority non-zero)
snap.as_dict()  # dict with all fields + "best"
```

**Best priority order:** yang\_zhang > garman\_klass > parkinson > ewma > realized

***

## Choosing an Estimator

| Estimator      | Data Needed | Efficiency | Best For                       |
| -------------- | ----------- | ---------- | ------------------------------ |
| Close-to-close | Prices only | 1x         | Tick data, simple strategies   |
| Parkinson      | High/Low    | \~5x       | Range-based analysis           |
| Garman-Klass   | OHLC        | \~8x       | When you have proper OHLC bars |
| Yang-Zhang     | OHLC        | \~14x      | Markets with opening gaps      |
| EWMA           | Prices      | Adaptive   | Reactive volatility tracking   |
| Rolling        | Prices      | 1x/window  | Time-varying vol analysis      |

The pipeline's `best` property automatically selects the highest-quality available estimate.
