Volatility Signature
Two-scale realized vol, noise variance estimation, and optimal sampling frequency
Realized volatility from high-frequency data is biased upward by microstructure noise (bid-ask bounce, discrete ticks, stale quotes). The volatility signature plot reveals this bias, and the two-scale realized volatility estimator (Zhang-Mykland-Ait-Sahalia) corrects for it.
API
Volatility signature plot
Compute realized vol at multiple sampling frequencies. At high frequencies the estimate is inflated by noise; it stabilizes as frequency decreases.
python
result = hz.volatility_signature(prices, freqs=[1, 2, 5, 10, 30, 60, 300])
# prices: list of (timestamp, price) tuples
# freqs: sampling intervals in seconds
# Returns: list of (frequency, realized_vol) tuples
for freq, vol in result:
print(f"{freq:>4}s: {vol:.4f}")
# Output (typical):
# 1s: 0.2834 <-- inflated by noise
# 2s: 0.2401
# 5s: 0.2012
# 10s: 0.1856
# 30s: 0.1791
# 60s: 0.1782 <-- stabilizes here
# 300s: 0.1775
Two-scale realized volatility
The TSRV estimator combines a fast-scale and slow-scale estimator to cancel out the noise bias. Returns an unbiased vol estimate directly.
python
vol = hz.two_scale_realized_vol(prices)
# prices: list of (timestamp, price) tuples
# Returns: float -- noise-corrected annualized volatility
Optimal sampling frequency
python
freq = hz.optimal_sampling(prices)
# Returns: float -- optimal sampling interval in seconds
Practical usage
Corrected vol for position sizing
python
# Naive RV from 1-second bars is biased upward
naive_vol = hz.volatility_signature(tick_data, freqs=[1])[0][1]
# TSRV gives the corrected estimate
true_vol = hz.two_scale_realized_vol(tick_data)
print(f"Naive: {naive_vol:.4f}, Corrected: {true_vol:.4f}")
# Using naive vol would make you size positions too small (overestimating risk)
Noise-aware signal filtering
python
noise = hz.noise_variance(tick_data)
signal_move = current_price - fair_value
# Only trade if the move exceeds the noise level
if abs(signal_move) > 3 * noise ** 0.5:
# This is a real move, not microstructure noise
pass
When to use
- High-frequency strategies: any strategy sampling prices faster than every 5 minutes needs noise correction.
- Position sizing: using uncorrected vol overestimates risk and undersizes positions.
- Signal filtering: distinguish real price moves from bid-ask bounce before acting on them.
- Sampling rate selection: when designing a data pipeline,
optimal_sampling()tells you the right frequency to avoid both noise contamination and information loss.
For daily or hourly data, microstructure noise is negligible and standard realized vol works fine.