Goshawk_Hedge_Pro / regime.py
GoshawkVortexAI's picture
Create regime.py
ff98dba verified
raw
history blame
2.78 kB
import pandas as pd
import numpy as np
from typing import Dict, Any
from config import ATR_PERIOD, STRUCTURE_LOOKBACK, VOLATILITY_EXPANSION_MULTIPLIER
def compute_atr(df: pd.DataFrame, period: int = ATR_PERIOD) -> pd.Series:
high = df["high"]
low = df["low"]
close = df["close"]
prev_close = close.shift(1)
tr = pd.concat(
[
high - low,
(high - prev_close).abs(),
(low - prev_close).abs(),
],
axis=1,
).max(axis=1)
atr = tr.ewm(span=period, adjust=False).mean()
return atr
def detect_structure(df: pd.DataFrame, lookback: int = STRUCTURE_LOOKBACK) -> pd.Series:
highs = df["high"].rolling(lookback).max()
lows = df["low"].rolling(lookback).min()
prev_highs = highs.shift(lookback // 2)
prev_lows = lows.shift(lookback // 2)
hh = highs > prev_highs
hl = lows > prev_lows
lh = highs < prev_highs
ll = lows < prev_lows
structure = pd.Series(0, index=df.index)
structure[hh & hl] = 1
structure[lh & ll] = -1
return structure
def compute_volatility_regime(df: pd.DataFrame, period: int = ATR_PERIOD) -> pd.Series:
atr = compute_atr(df, period)
atr_ma = atr.rolling(period * 2).mean()
ratio = atr / atr_ma.replace(0, np.nan)
return ratio
def detect_regime(df: pd.DataFrame) -> Dict[str, Any]:
atr = compute_atr(df, ATR_PERIOD)
structure = detect_structure(df, STRUCTURE_LOOKBACK)
vol_ratio = compute_volatility_regime(df, ATR_PERIOD)
last_atr = atr.iloc[-1]
last_structure = structure.iloc[-1]
last_vol_ratio = vol_ratio.iloc[-1]
recent_structure = structure.iloc[-5:]
bullish_count = (recent_structure == 1).sum()
bearish_count = (recent_structure == -1).sum()
if bullish_count >= 3:
trend = "bullish"
elif bearish_count >= 3:
trend = "bearish"
else:
trend = "ranging"
volatility_expanding = last_vol_ratio > VOLATILITY_EXPANSION_MULTIPLIER
if trend == "bullish" and not volatility_expanding:
regime_score = 1.0
elif trend == "bullish" and volatility_expanding:
regime_score = 0.6
elif trend == "ranging":
regime_score = 0.3
elif trend == "bearish" and not volatility_expanding:
regime_score = 0.2
else:
regime_score = 0.1
close = df["close"].iloc[-1]
atr_pct = last_atr / close if close > 0 else 0.0
return {
"atr": last_atr,
"atr_pct": atr_pct,
"structure": last_structure,
"trend": trend,
"vol_ratio": last_vol_ratio,
"volatility_expanding": volatility_expanding,
"regime_score": regime_score,
"atr_series": atr,
"structure_series": structure,
"vol_ratio_series": vol_ratio,
}