regime-detection
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRegime Detection
市场状态识别(Regime Detection)
Identify the current market regime so you can pick the right strategy, size positions correctly, and avoid deploying trend-following logic in a ranging market (or vice versa).
识别当前的市场状态(Regime),以便选择合适的策略、正确调整仓位规模,避免在震荡市场中使用趋势跟踪逻辑(反之亦然)。
Why Regime Detection Matters
为何Regime状态识别至关重要
Every strategy has a "home regime." A momentum strategy prints money in a clean uptrend but bleeds in a choppy range. A mean-reversion grid thrives in low-volatility consolidation but gets steamrolled by a trending breakout. Regime detection tells you which playbook to use right now.
Key benefits:
- Strategy selection: Route signals to the right strategy for the current environment
- Position sizing: Reduce exposure in hostile regimes, increase in favorable ones
- Stop adaptation: Wider stops in high-vol regimes, tighter in low-vol trends
- Drawdown control: Sit out "danger zone" regimes (high vol + no trend)
每种策略都有其适配的「目标状态(Regime)」。动量策略在清晰的上涨趋势中盈利丰厚,但在震荡区间会持续亏损。均值回归网格策略在低波动盘整行情中表现出色,但会被趋势性突破碾压。Regime状态识别能告诉你当前应采用哪套策略方案。
核心优势:
- 策略选择:根据当前市场环境将信号导向合适的策略
- 仓位调整:在不利状态下降低仓位,在有利状态下增加仓位
- 止损适配:高波动状态下设置更宽止损,低波动趋势下设置更窄止损
- 回撤控制:避开「危险区域」状态(高波动+无趋势)
Core Regime Dimensions
Regime状态核心维度
Two orthogonal axes define the four-quadrant regime model:
| Low Volatility | High Volatility | |
|---|---|---|
| Trending | Q1: Clean trend — best for trend following | Q2: Volatile trend — momentum with caution |
| Ranging | Q3: Quiet range — mean-reversion paradise | Q4: Choppy chaos — reduce or sit out |
A third dimension — mean-reversion tendency (Hurst exponent) — refines Q3 by telling you how reliably price reverts.
两个正交维度构成了四象限状态模型:
| 低波动(Low Volatility) | 高波动(High Volatility) | |
|---|---|---|
| 趋势行情(Trending) | Q1:清晰趋势——最适合趋势跟踪 | Q2:波动趋势——谨慎使用动量策略 |
| 震荡行情(Ranging) | Q3:平静区间——均值回归策略的理想环境 | Q4:混乱震荡——降低仓位或离场观望 |
第三个维度——均值回归倾向(Hurst指数)——通过告知价格回归的可靠性来优化Q3区间的判断。
Simple Approaches (No ML Required)
简易方法(无需机器学习)
1. ATR Volatility Percentile
1. ATR波动率百分位
Rank the current ATR against its own recent history to get a 0–100 percentile score.
python
import pandas as pd
import numpy as np
def atr_percentile(
high: pd.Series, low: pd.Series, close: pd.Series,
atr_period: int = 14, lookback: int = 100
) -> pd.Series:
"""ATR percentile rank over a rolling window."""
tr = pd.concat([
high - low,
(high - close.shift(1)).abs(),
(low - close.shift(1)).abs()
], axis=1).max(axis=1)
atr = tr.rolling(atr_period).mean()
return atr.rolling(lookback).apply(
lambda x: pd.Series(x).rank(pct=True).iloc[-1], raw=False
)- < 25th percentile → Low volatility regime
- 25th–75th → Normal volatility
- > 75th percentile → High volatility regime
将当前ATR与近期历史数据对比,得出0-100的百分位得分。
python
import pandas as pd
import numpy as np
def atr_percentile(
high: pd.Series, low: pd.Series, close: pd.Series,
atr_period: int = 14, lookback: int = 100
) -> pd.Series:
"""ATR percentile rank over a rolling window."""
tr = pd.concat([
high - low,
(high - close.shift(1)).abs(),
(low - close.shift(1)).abs()
], axis=1).max(axis=1)
atr = tr.rolling(atr_period).mean()
return atr.rolling(lookback).apply(
lambda x: pd.Series(x).rank(pct=True).iloc[-1], raw=False
)- <25百分位 → 低波动状态
- 25-75百分位 → 正常波动
- >75百分位 → 高波动状态
2. ADX Trend Strength
2. ADX趋势强度
ADX above 25 signals a trending market; below 20 signals a range.
python
def compute_adx(
high: pd.Series, low: pd.Series, close: pd.Series,
period: int = 14
) -> pd.Series:
"""Average Directional Index."""
plus_dm = high.diff().clip(lower=0)
minus_dm = (-low.diff()).clip(lower=0)
# Zero out when the other is larger
plus_dm[plus_dm < minus_dm] = 0
minus_dm[minus_dm < plus_dm] = 0
tr = pd.concat([
high - low,
(high - close.shift(1)).abs(),
(low - close.shift(1)).abs()
], axis=1).max(axis=1)
atr = tr.ewm(span=period, adjust=False).mean()
plus_di = 100 * plus_dm.ewm(span=period, adjust=False).mean() / atr
minus_di = 100 * minus_dm.ewm(span=period, adjust=False).mean() / atr
dx = 100 * (plus_di - minus_di).abs() / (plus_di + minus_di)
return dx.ewm(span=period, adjust=False).mean()ADX高于25表示市场处于趋势行情;低于20表示市场处于震荡区间。
python
def compute_adx(
high: pd.Series, low: pd.Series, close: pd.Series,
period: int = 14
) -> pd.Series:
"""Average Directional Index."""
plus_dm = high.diff().clip(lower=0)
minus_dm = (-low.diff()).clip(lower=0)
# Zero out when the other is larger
plus_dm[plus_dm < minus_dm] = 0
minus_dm[minus_dm < plus_dm] = 0
tr = pd.concat([
high - low,
(high - close.shift(1)).abs(),
(low - close.shift(1)).abs()
], axis=1).max(axis=1)
atr = tr.ewm(span=period, adjust=False).mean()
plus_di = 100 * plus_dm.ewm(span=period, adjust=False).mean() / atr
minus_di = 100 * minus_dm.ewm(span=period, adjust=False).mean() / atr
dx = 100 * (plus_di - minus_di).abs() / (plus_di + minus_di)
return dx.ewm(span=period, adjust=False).mean()3. EMA Slope + Price Position
3. EMA斜率+价格位置
python
def trend_direction(close: pd.Series, period: int = 20) -> pd.Series:
"""Returns +1 (uptrend), -1 (downtrend), 0 (neutral)."""
ema = close.ewm(span=period, adjust=False).mean()
slope = ema.diff(5) # 5-bar slope
above = (close > ema).astype(int)
direction = pd.Series(0, index=close.index)
direction[(slope > 0) & (above == 1)] = 1
direction[(slope < 0) & (above == 0)] = -1
return directionpython
def trend_direction(close: pd.Series, period: int = 20) -> pd.Series:
"""Returns +1 (uptrend), -1 (downtrend), 0 (neutral)."""
ema = close.ewm(span=period, adjust=False).mean()
slope = ema.diff(5) # 5-bar slope
above = (close > ema).astype(int)
direction = pd.Series(0, index=close.index)
direction[(slope > 0) & (above == 1)] = 1
direction[(slope < 0) & (above == 0)] = -1
return direction4. Bollinger Band Width Percentile
4. 布林带宽度百分位
BB width (upper - lower) / middle as a volatility proxy. A "squeeze" (low percentile) often precedes a breakout.
python
def bb_width_percentile(
close: pd.Series, period: int = 20,
std_dev: float = 2.0, lookback: int = 100
) -> pd.Series:
"""Bollinger Band width percentile."""
sma = close.rolling(period).mean()
std = close.rolling(period).std()
width = (2 * std_dev * std) / sma
return width.rolling(lookback).apply(
lambda x: pd.Series(x).rank(pct=True).iloc[-1], raw=False
)布林带宽度(上轨-下轨)/中轨作为波动率指标。「收缩」(低百分位)通常预示着突破行情。
python
def bb_width_percentile(
close: pd.Series, period: int = 20,
std_dev: float = 2.0, lookback: int = 100
) -> pd.Series:
"""Bollinger Band width percentile."""
sma = close.rolling(period).mean()
std = close.rolling(period).std()
width = (2 * std_dev * std) / sma
return width.rolling(lookback).apply(
lambda x: pd.Series(x).rank(pct=True).iloc[-1], raw=False
)Statistical Approaches
统计方法
Rolling Hurst Exponent
滚动Hurst指数
The Hurst exponent H classifies time series behavior:
- H < 0.4 → Mean-reverting (anti-persistent)
- 0.4 ≤ H ≤ 0.6 → Random walk (no exploitable structure)
- H > 0.6 → Trending (persistent)
Computed via the Rescaled Range (R/S) method. See for the full derivation.
references/methodology.mdpython
def hurst_exponent(series: pd.Series, max_lag: int = 50) -> float:
"""Estimate Hurst exponent using R/S method."""
lags = range(2, max_lag)
rs_values = []
for lag in lags:
chunks = [series.iloc[i:i+lag] for i in range(0, len(series) - lag, lag)]
rs_list = []
for chunk in chunks:
if len(chunk) < lag:
continue
mean_val = chunk.mean()
devs = chunk - mean_val
cumdev = devs.cumsum()
r = cumdev.max() - cumdev.min()
s = chunk.std(ddof=1)
if s > 0:
rs_list.append(r / s)
if rs_list:
rs_values.append(np.mean(rs_list))
else:
rs_values.append(np.nan)
valid = [(l, r) for l, r in zip(lags, rs_values) if not np.isnan(r)]
if len(valid) < 5:
return 0.5
log_lags = np.log([v[0] for v in valid])
log_rs = np.log([v[1] for v in valid])
coeffs = np.polyfit(log_lags, log_rs, 1)
return coeffs[0]Hurst指数H用于分类时间序列行为:
- H < 0.4 → 均值回归(反持续性)
- 0.4 ≤ H ≤ 0.6 → 随机游走(无可利用结构)
- H > 0.6 → 趋势性(持续性)
通过重标极差(R/S)方法计算。完整推导请参见。
references/methodology.mdpython
def hurst_exponent(series: pd.Series, max_lag: int = 50) -> float:
"""Estimate Hurst exponent using R/S method."""
lags = range(2, max_lag)
rs_values = []
for lag in lags:
chunks = [series.iloc[i:i+lag] for i in range(0, len(series) - lag, lag)]
rs_list = []
for chunk in chunks:
if len(chunk) < lag:
continue
mean_val = chunk.mean()
devs = chunk - mean_val
cumdev = devs.cumsum()
r = cumdev.max() - cumdev.min()
s = chunk.std(ddof=1)
if s > 0:
rs_list.append(r / s)
if rs_list:
rs_values.append(np.mean(rs_list))
else:
rs_values.append(np.nan)
valid = [(l, r) for l, r in zip(lags, rs_values) if not np.isnan(r)]
if len(valid) < 5:
return 0.5
log_lags = np.log([v[0] for v in valid])
log_rs = np.log([v[1] for v in valid])
coeffs = np.polyfit(log_lags, log_rs, 1)
return coeffs[0]Change-Point Detection (CUSUM)
变点检测(CUSUM)
Detects abrupt shifts in mean or variance of a return series.
python
def cusum_test(
returns: pd.Series, threshold: float = 2.0
) -> list[int]:
"""CUSUM change-point detection on returns.
Returns indices where regime changes are detected.
"""
mean_r = returns.mean()
std_r = returns.std()
if std_r == 0:
return []
s_pos, s_neg = 0.0, 0.0
changes = []
for i, r in enumerate(returns):
z = (r - mean_r) / std_r
s_pos = max(0, s_pos + z - 0.5)
s_neg = max(0, s_neg - z - 0.5)
if s_pos > threshold or s_neg > threshold:
changes.append(i)
s_pos, s_neg = 0.0, 0.0
return changes检测收益序列的均值或方差突变。
python
def cusum_test(
returns: pd.Series, threshold: float = 2.0
) -> list[int]:
"""CUSUM change-point detection on returns.
Returns indices where regime changes are detected.
"""
mean_r = returns.mean()
std_r = returns.std()
if std_r == 0:
return []
s_pos, s_neg = 0.0, 0.0
changes = []
for i, r in enumerate(returns):
z = (r - mean_r) / std_r
s_pos = max(0, s_pos + z - 0.5)
s_neg = max(0, s_neg - z - 0.5)
if s_pos > threshold or s_neg > threshold:
changes.append(i)
s_pos, s_neg = 0.0, 0.0
return changesHidden Markov Models
隐马尔可夫模型(Hidden Markov Models)
For 2–3 state regime models using . This is optional — all core functionality works with numpy/pandas only.
hmmlearnpython
undefined使用构建2-3状态的Regime模型。这是可选功能——所有核心功能仅依赖numpy/pandas即可实现。
hmmlearnpython
undefinedOptional: requires uv pip install hmmlearn
uv pip install hmmlearnOptional: requires uv pip install hmmlearn
uv pip install hmmlearnfrom hmmlearn import hmm
def fit_hmm_regimes(
returns: np.ndarray, n_states: int = 2, n_iter: int = 100
) -> tuple[np.ndarray, object]:
"""Fit a Gaussian HMM to return series."""
X = returns.reshape(-1, 1)
model = hmm.GaussianHMM(
n_components=n_states, covariance_type="full", n_iter=n_iter
)
model.fit(X)
states = model.predict(X)
return states, model
See `references/methodology.md` for details on feature selection and state interpretation.from hmmlearn import hmm
def fit_hmm_regimes(
returns: np.ndarray, n_states: int = 2, n_iter: int = 100
) -> tuple[np.ndarray, object]:
"""Fit a Gaussian HMM to return series."""
X = returns.reshape(-1, 1)
model = hmm.GaussianHMM(
n_components=n_states, covariance_type="full", n_iter=n_iter
)
model.fit(X)
states = model.predict(X)
return states, model
特征选择和状态解读的详细信息请参见`references/methodology.md`。Crypto-Specific Considerations
加密货币专属考量
Regime Speed
Regime状态变化速度
Crypto regimes change much faster than equities:
| Parameter | Equities | Crypto (large cap) | Crypto (micro cap / PumpFun) |
|---|---|---|---|
| ATR lookback | 100–200 bars | 50–100 bars | 20–50 bars |
| ADX period | 14–28 | 10–14 | 7–10 |
| Regime persistence | Weeks–months | Days–weeks | Hours–days |
| Hurst window | 200+ bars | 100 bars | 50 bars |
加密货币的Regime状态变化速度远快于股票:
| 参数 | 股票 | 加密货币(大盘) | 加密货币(小盘/PumpFun) |
|---|---|---|---|
| ATR回溯周期 | 100–200K线 | 50–100K线 | 20–50K线 |
| ADX周期 | 14–28 | 10–14 | 7–10 |
| Regime状态持续时间 | 数周–数月 | 数天–数周 | 数小时–数天 |
| Hurst计算窗口 | 200+K线 | 100K线 | 50K线 |
Volume as a Regime Signal
成交量作为Regime状态信号
In crypto, volume confirms regime quality:
- High volume + trend → Strong conviction, ride it
- Low volume + trend → Drift, unreliable, reduce size
- High volume + range → Distribution or accumulation, watch for breakout
- Low volume + range → Dead market, skip
在加密货币市场中,成交量可验证状态质量:
- 高成交量+趋势 → 信念坚定,持有仓位
- 低成交量+趋势 → 行情漂移,不可靠,降低仓位
- 高成交量+震荡 → 派发或吸筹,关注突破
- 低成交量+震荡 → 市场冷清,跳过
PumpFun Micro-Regimes
PumpFun微状态
New token launches follow a stereotyped sequence:
- Launch pump (minutes): Vertical move, extreme vol, no mean-reversion
- First dump (minutes–hours): Profit-taking, high vol, trending down
- Consolidation (hours–days): Low vol range, potential mean-reversion
- Second wave or death: Either breaks out again (new trend) or fades to zero
Each micro-regime lasts minutes to hours. Use 1-minute bars with 20–50 bar windows.
新代币发行遵循典型的流程:
- 首发拉涨(数分钟):垂直拉升,极端波动,无均值回归
- 首次砸盘(数分钟–数小时):获利了结,高波动,下跌趋势
- 盘整(数小时–数天):低波动区间,潜在均值回归
- 第二波行情或消亡:要么再次突破(新趋势),要么逐渐归零
每个微状态持续数分钟至数小时。使用1分钟K线,窗口设置为20-50K线。
Combined Regime Classification
组合Regime状态分类
python
def classify_regime(
vol_percentile: float, adx: float, hurst: float,
trend_dir: int
) -> dict[str, str]:
"""Classify into the 4-quadrant model."""
vol_regime = (
"low" if vol_percentile < 0.30
else "high" if vol_percentile > 0.70
else "normal"
)
trend_regime = (
"trending" if adx > 25
else "ranging" if adx < 20
else "transitional"
)
direction = (
"up" if trend_dir > 0
else "down" if trend_dir < 0
else "neutral"
)
mr_regime = (
"mean_reverting" if hurst < 0.4
else "trending" if hurst > 0.6
else "random"
)
return {
"volatility": vol_regime,
"trend": trend_regime,
"direction": direction,
"mean_reversion": mr_regime,
"quadrant": f"{vol_regime}_vol_{trend_regime}",
}python
def classify_regime(
vol_percentile: float, adx: float, hurst: float,
trend_dir: int
) -> dict[str, str]:
"""Classify into the 4-quadrant model."""
vol_regime = (
"low" if vol_percentile < 0.30
else "high" if vol_percentile > 0.70
else "normal"
)
trend_regime = (
"trending" if adx > 25
else "ranging" if adx < 20
else "transitional"
)
direction = (
"up" if trend_dir > 0
else "down" if trend_dir < 0
else "neutral"
)
mr_regime = (
"mean_reverting" if hurst < 0.4
else "trending" if hurst > 0.6
else "random"
)
return {
"volatility": vol_regime,
"trend": trend_regime,
"direction": direction,
"mean_reversion": mr_regime,
"quadrant": f"{vol_regime}_vol_{trend_regime}",
}Strategy Adaptation
策略适配
See for the full regime-strategy matrix.
references/strategy_adaptation.mdQuick reference:
| Current Regime | Action |
|---|---|
| Low vol + trending up | Full size trend-following, tight stops |
| High vol + trending | Half size momentum, wide stops |
| Low vol + ranging | Mean-reversion / grid strategies |
| High vol + ranging | Reduce to 25% size or sit out |
| Regime transition | Flatten or reduce to minimum size |
完整的状态-策略矩阵请参见。
references/strategy_adaptation.md快速参考:
| 当前状态 | 操作 |
|---|---|
| 低波动+上涨趋势 | 全仓趋势跟踪,窄止损 |
| 高波动+趋势 | 半仓动量策略,宽止损 |
| 低波动+震荡 | 均值回归/网格策略 |
| 高波动+震荡 | 仓位降至25%或离场观望 |
| 状态转换 | 平仓或降至最小仓位 |
Integration with Other Skills
与其他工具集成
- : Compute ATR, ADX, Bollinger Bands, EMAs
pandas-ta - : Advanced vol forecasting (GARCH, realized vol)
volatility-modeling - : Route signals through regime filter before execution
strategy-framework - : Scale position size by regime volatility
position-sizing - : Adjust portfolio risk limits per regime
risk-management
- :计算ATR、ADX、布林带、EMA
pandas-ta - :高级波动率预测(GARCH、已实现波动率)
volatility-modeling - :执行前通过状态过滤器筛选信号
strategy-framework - :根据状态波动率调整仓位规模
position-sizing - :根据状态调整投资组合风险限额
risk-management
Files
文件
References
参考资料
- — Detailed math for Hurst exponent, HMM, change-point detection, and volatility estimation methods
references/methodology.md - — Full regime-strategy matrix with position sizing, stop adaptation, and PumpFun micro-regime playbook
references/strategy_adaptation.md
- — Hurst指数、隐马尔可夫模型、变点检测和波动率估算方法的详细数学推导
references/methodology.md - — 完整的状态-策略矩阵,包含仓位调整、止损适配和PumpFun微状态策略方案
references/strategy_adaptation.md
Scripts
脚本
- — Compute regime indicators on live or demo data, classify into 4-quadrant model
scripts/detect_regime.py - — Compare regime-adaptive vs static strategy on synthetic data with clear regime transitions
scripts/regime_backtest.py
- — 在实时或演示数据上计算状态指标,分类至四象限模型
scripts/detect_regime.py - — 在具有清晰状态转换的合成数据上比较自适应状态策略与静态策略
scripts/regime_backtest.py