/mean-reversion
Mean-reversion strategy tools including Hurst exponent, half-life estimation, z-score signals, ADF testing, and Ornstein-Uhlenbeck modeling
$ npx -y skills add agiprolabs/claude-trading-skills --skill mean-reversion --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/mean-reversion
Context preview
The summary Claude sees to decide when to auto-load this skill.
Mean-reversion strategy tools including Hurst exponent, half-life estimation, z-score signals, ADF testing, and Ornstein-Uhlenbeck modeling
SKILL.md
mean-reversion.SKILL.mdname: mean-reversion
description: Mean-reversion strategy tools including Hurst exponent, half-life estimation, z-score signals, ADF testing, and Ornstein-Uhlenbeck modeling
Mean Reversion
Mean reversion is the statistical tendency for prices, spreads, or other financial variables to return toward a long-run average after deviating from it. A mean-reverting series overshoots its mean, then corrects back -- creating predictable oscillations that can be traded.
When Mean Reversion Works
- **Ranging markets**: Sideways price action with clear support/resistance
- **Pairs spreads**: Spread between cointegrated assets reverts to equilibrium
- **Oversold/overbought extremes**: RSI, Bollinger Band, or z-score extremes in stationary series
- **Funding rate arbitrage**: Perpetual funding rates revert to baseline
- **Stablecoin depegs**: Classic mean-reversion opportunity (peg = known mean)
- **Post-dump recovery**: Brief mean-reversion windows after initial PumpFun dumps
When Mean Reversion Fails
- Strong trending markets (most crypto most of the time)
- Regime changes: what was stationary becomes non-stationary
- Structural breaks: token migration, protocol upgrade, delistings
- Low liquidity: wide spreads consume mean-reversion profits
---
Testing for Mean Reversion
Before trading mean reversion, you must statistically confirm the series is mean-reverting. Three complementary tests:
1. Augmented Dickey-Fuller (ADF) Test
Tests the null hypothesis that a series has a unit root (non-stationary).
from scipy import stats
import numpy as np
def adf_test(series: np.ndarray, max_lag: int = 0) -> dict:
"""Run ADF test. Reject null (p < 0.05) → stationary → mean-reverting."""
# See references/statistical_tests.md for full implementation
# Use statsmodels.tsa.stattools.adfuller for production
pass- **p < 0.01**: Strong evidence of stationarity
- **p < 0.05**: Evidence of stationarity
- **p > 0.10**: Cannot reject unit root -- likely non-stationary
2. Hurst Exponent
Measures the long-range dependence of a time series.
| Hurst Value | Interpretation | Trading Implication | |-------------|---------------|---------------------| | H < 0.5 | Mean-reverting | Trade mean reversion | | H = 0.5 | Random walk | No edge | | H > 0.5 | Trending | Trade momentum |
def hurst_exponent(series: np.ndarray) -> float:
"""Compute Hurst exponent via R/S method. H < 0.5 → mean-reverting."""
# See references/statistical_tests.md for full R/S algorithm
pass3. Variance Ratio Test
Compares variance of multi-period returns to single-period variance.
- **VR < 1**: Negative autocorrelation (mean-reverting)
- **VR = 1**: Random walk
- **VR > 1**: Positive autocorrelation (trending)
def variance_ratio(series: np.ndarray, q: int = 5) -> float:
"""Compute variance ratio at horizon q. VR < 1 → mean-reverting."""
returns = np.diff(np.log(series))
var_1 = np.var(returns)
returns_q = np.diff(np.log(series[::q]))
var_q = np.var(returns_q)
return var_q / (q * var_1)See `references/statistical_tests.md` for complete implementations and interpretation guides.
---
Half-Life Estimation
The half-life tells you how many periods it takes for a deviation to decay to half its size. This is the single most important parameter for mean-reversion trading.
AR(1) Regression Method
Fit the autoregressive model: `delta_X_t = alpha + beta * X_{t-1} + epsilon`
def half_life(series: np.ndarray) -> float:
"""Estimate mean-reversion half-life from AR(1) regression.
Returns:
Half-life in periods. Negative means non-mean-reverting.
"""
y = np.diff(series)
x = series[:-1]
x = np.column_stack([np.ones(len(x)), x])
beta = np.linalg.lstsq(x, y, rcond=None)[0][1]
if beta >= 0:
return -1.0 # Not mean-reverting
return -np.log(2) / np.log(1 + beta)Using Half-Life
| Parameter | Rule of Thumb | |-----------|--------------| | Lookback window | 2x half-life | | Holding period | 1x half-life | | Maximum hold | 3x half-life (stop) | | Signal recalc | 0.5x half-life |
---
Z-Score Signal Framework
The z-score normalizes the deviation from the mean, providing standardized entry/exit signals.
z = (price - rolling_mean) / rolling_std
Signal Rules
| Condition | Signal | Action | |-----------|--------|--------| | z < -2.0 | Buy | Enter long (price below mean) | | z > +2.0 | Sell | Enter short (price above mean) | | z crosses 0 | Exit | Close position (returned to mean) | | abs(z) > 3.0 | Stop | Close position (reversion failed) |
Lookback Window
Set the rolling window to approximately **2x the half-life**:
def z_score_signals(
prices: np.ndarray,
lookback: int,
entry_z: float = 2.0,
exit_z: float = 0.0,
stop_z: float = 3.0,
) -> np.ndarray:
"""Generate z-score-based mean-reversion signals.
Returns:
Array of signals: 1 (long), -1 (short), 0 (flat).
"""
rolling_mean = pd.Series(prices).rolling(lookback).mean().values
rolling_std = pd.Series(prices).rolling(lookback).std().values
z = (prices - rolling_mean) / rolling_std
# See scripts/mean_reversion_test.py for full signal generation
...Position Sizing with Z-Score
Scale position size with z-score magnitude for better risk-adjusted returns:
size = base_size * min(abs(z) / entry_threshold, max_scale)
See `references/strategy_design.md` for complete entry/exit framework and sizing.
---
Ornstein-Uhlenbeck (OU) Process
The OU process is the continuous-time model of mean reversion:
dX = theta * (mu - X) * dt + sigma * dW
| Parameter | Meaning | Estimation | |-----------|---------|------------| | theta | Speed of mean reversion | From AR(1) beta: theta = -ln(1+beta)/dt | | mu | Long-run mean | From AR(1) intercept: mu
Read more
name: mean-reversion description: Mean-reversion strategy tools including Hurst exponent, half-life estimation, z-score signals, ADF testing, and Ornstein-Uhlenbeck modeling
Mean Reversion
Mean reversion is the statistical tendency for prices, spreads, or other financial variables to return toward a long-run average after deviating from it. A mean-reverting series overshoots its mean, then corrects back -- creating predictable oscillations that can be traded.
When Mean Reversion Works
- **Ranging markets**: Sideways price action with clear support/resistance
- **Pairs spreads**: Spread between cointegrated assets reverts to equilibrium
- **Oversold/overbought extremes**: RSI, Bollinger Band, or z-score extremes in stationary series
- **Funding rate arbitrage**: Perpetual funding rates revert to baseline
- **Stablecoin depegs**: Classic mean-reversion opportunity (peg = known mean)
- **Post-dump recovery**: Brief mean-reversion windows after initial PumpFun dumps
When Mean Reversion Fails
- Strong trending markets (most crypto most of the time)
- Regime changes: what was stationary becomes non-stationary
- Structural breaks: token migration, protocol upgrade, delistings
- Low liquidity: wide spreads consume mean-reversion profits
---
Testing for Mean Reversion
Before trading mean reversion, you must statistically confirm the series is mean-reverting. Three complementary tests:
1. Augmented Dickey-Fuller (ADF) Test
Tests the null hypothesis that a series has a unit root (non-stationary).
from scipy import stats
import numpy as np
def adf_test(series: np.ndarray, max_lag: int = 0) -> dict:
"""Run ADF test. Reject null (p < 0.05) → stationary → mean-reverting."""
# See references/statistical_tests.md for full implementation
# Use statsmodels.tsa.stattools.adfuller for production
pass- **p < 0.01**: Strong evidence of stationarity
- **p < 0.05**: Evidence of stationarity
- **p > 0.10**: Cannot reject unit root -- likely non-stationary
2. Hurst Exponent
Measures the long-range dependence of a time series.
| Hurst Value | Interpretation | Trading Implication | |-------------|---------------|---------------------| | H < 0.5 | Mean-reverting | Trade mean reversion | | H = 0.5 | Random walk | No edge | | H > 0.5 | Trending | Trade momentum |
def hurst_exponent(series: np.ndarray) -> float:
"""Compute Hurst exponent via R/S method. H < 0.5 → mean-reverting."""
# See references/statistical_tests.md for full R/S algorithm
pass3. Variance Ratio Test
Compares variance of multi-period returns to single-period variance.
- **VR < 1**: Negative autocorrelation (mean-reverting)
- **VR = 1**: Random walk
- **VR > 1**: Positive autocorrelation (trending)
def variance_ratio(series: np.ndarray, q: int = 5) -> float:
"""Compute variance ratio at horizon q. VR < 1 → mean-reverting."""
returns = np.diff(np.log(series))
var_1 = np.var(returns)
returns_q = np.diff(np.log(series[::q]))
var_q = np.var(returns_q)
return var_q / (q * var_1)See `references/statistical_tests.md` for complete implementations and interpretation guides.
---
Half-Life Estimation
The half-life tells you how many periods it takes for a deviation to decay to half its size. This is the single most important parameter for mean-reversion trading.
AR(1) Regression Method
Fit the autoregressive model: `delta_X_t = alpha + beta * X_{t-1} + epsilon`
def half_life(series: np.ndarray) -> float:
"""Estimate mean-reversion half-life from AR(1) regression.
Returns:
Half-life in periods. Negative means non-mean-reverting.
"""
y = np.diff(series)
x = series[:-1]
x = np.column_stack([np.ones(len(x)), x])
beta = np.linalg.lstsq(x, y, rcond=None)[0][1]
if beta >= 0:
return -1.0 # Not mean-reverting
return -np.log(2) / np.log(1 + beta)Using Half-Life
| Parameter | Rule of Thumb | |-----------|--------------| | Lookback window | 2x half-life | | Holding period | 1x half-life | | Maximum hold | 3x half-life (stop) | | Signal recalc | 0.5x half-life |
---
Z-Score Signal Framework
The z-score normalizes the deviation from the mean, providing standardized entry/exit signals.
z = (price - rolling_mean) / rolling_std
Signal Rules
| Condition | Signal | Action | |-----------|--------|--------| | z < -2.0 | Buy | Enter long (price below mean) | | z > +2.0 | Sell | Enter short (price above mean) | | z crosses 0 | Exit | Close position (returned to mean) | | abs(z) > 3.0 | Stop | Close position (reversion failed) |
Lookback Window
Set the rolling window to approximately **2x the half-life**:
def z_score_signals(
prices: np.ndarray,
lookback: int,
entry_z: float = 2.0,
exit_z: float = 0.0,
stop_z: float = 3.0,
) -> np.ndarray:
"""Generate z-score-based mean-reversion signals.
Returns:
Array of signals: 1 (long), -1 (short), 0 (flat).
"""
rolling_mean = pd.Series(prices).rolling(lookback).mean().values
rolling_std = pd.Series(prices).rolling(lookback).std().values
z = (prices - rolling_mean) / rolling_std
# See scripts/mean_reversion_test.py for full signal generation
...Position Sizing with Z-Score
Scale position size with z-score magnitude for better risk-adjusted returns:
size = base_size * min(abs(z) / entry_threshold, max_scale)
See `references/strategy_design.md` for complete entry/exit framework and sizing.
---
Ornstein-Uhlenbeck (OU) Process
The OU process is the continuous-time model of mean reversion:
dX = theta * (mu - X) * dt + sigma * dW
| Parameter | Meaning | Estimation | |-----------|---------|------------| | theta | Speed of mean reversion | From AR(1) beta: theta = -ln(1+beta)/dt | | mu | Long-run mean | From AR(1) intercept: mu
A comprehensive collection of 67 ready-to-use trading, DeFi, and quantitative finance Agent Skills. Works with Claude Code, Cursor, Codex, Gemini CLI, and 30+ other tools.
Repo: agiprolabs/claude-trading-skills
Other skills on trading-skills.
- /backtrader
Event-driven backtesting with bar-by-bar execution, complex order types, multiple analyzers, and custom indicators
Open skill - /birdeye-api
Solana token market data via Birdeye — prices, OHLCV, trades, token metadata, security checks, and trader activity
Open skill - /coingecko-api
Broad crypto market data from CoinGecko covering 13,000+ tokens. Global market stats, historical price data going back years, exchange volumes, trending tokens, and category filters. Best for macro analysis and long-term historical data.
Open skill - /cointegration-analysis
Cointegration testing for pairs trading using Engle-Granger, Johansen, and rolling stability analysis
Open skill - /copy-trading
Wallet evaluation, monitoring, and copy-trade strategy design for Solana DEX trading
Open skill - /correlation-analysis
Cross-asset correlation analysis including rolling correlation, hierarchical clustering, tail dependence, and regime-dependent correlation
Open skill

