GoshawkVortexAI commited on
Commit
ff98dba
·
verified ·
1 Parent(s): 939baa1

Create regime.py

Browse files
Files changed (1) hide show
  1. regime.py +93 -0
regime.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import numpy as np
3
+ from typing import Dict, Any
4
+ from config import ATR_PERIOD, STRUCTURE_LOOKBACK, VOLATILITY_EXPANSION_MULTIPLIER
5
+
6
+
7
+ def compute_atr(df: pd.DataFrame, period: int = ATR_PERIOD) -> pd.Series:
8
+ high = df["high"]
9
+ low = df["low"]
10
+ close = df["close"]
11
+ prev_close = close.shift(1)
12
+ tr = pd.concat(
13
+ [
14
+ high - low,
15
+ (high - prev_close).abs(),
16
+ (low - prev_close).abs(),
17
+ ],
18
+ axis=1,
19
+ ).max(axis=1)
20
+ atr = tr.ewm(span=period, adjust=False).mean()
21
+ return atr
22
+
23
+
24
+ def detect_structure(df: pd.DataFrame, lookback: int = STRUCTURE_LOOKBACK) -> pd.Series:
25
+ highs = df["high"].rolling(lookback).max()
26
+ lows = df["low"].rolling(lookback).min()
27
+ prev_highs = highs.shift(lookback // 2)
28
+ prev_lows = lows.shift(lookback // 2)
29
+ hh = highs > prev_highs
30
+ hl = lows > prev_lows
31
+ lh = highs < prev_highs
32
+ ll = lows < prev_lows
33
+ structure = pd.Series(0, index=df.index)
34
+ structure[hh & hl] = 1
35
+ structure[lh & ll] = -1
36
+ return structure
37
+
38
+
39
+ def compute_volatility_regime(df: pd.DataFrame, period: int = ATR_PERIOD) -> pd.Series:
40
+ atr = compute_atr(df, period)
41
+ atr_ma = atr.rolling(period * 2).mean()
42
+ ratio = atr / atr_ma.replace(0, np.nan)
43
+ return ratio
44
+
45
+
46
+ def detect_regime(df: pd.DataFrame) -> Dict[str, Any]:
47
+ atr = compute_atr(df, ATR_PERIOD)
48
+ structure = detect_structure(df, STRUCTURE_LOOKBACK)
49
+ vol_ratio = compute_volatility_regime(df, ATR_PERIOD)
50
+
51
+ last_atr = atr.iloc[-1]
52
+ last_structure = structure.iloc[-1]
53
+ last_vol_ratio = vol_ratio.iloc[-1]
54
+
55
+ recent_structure = structure.iloc[-5:]
56
+ bullish_count = (recent_structure == 1).sum()
57
+ bearish_count = (recent_structure == -1).sum()
58
+
59
+ if bullish_count >= 3:
60
+ trend = "bullish"
61
+ elif bearish_count >= 3:
62
+ trend = "bearish"
63
+ else:
64
+ trend = "ranging"
65
+
66
+ volatility_expanding = last_vol_ratio > VOLATILITY_EXPANSION_MULTIPLIER
67
+
68
+ if trend == "bullish" and not volatility_expanding:
69
+ regime_score = 1.0
70
+ elif trend == "bullish" and volatility_expanding:
71
+ regime_score = 0.6
72
+ elif trend == "ranging":
73
+ regime_score = 0.3
74
+ elif trend == "bearish" and not volatility_expanding:
75
+ regime_score = 0.2
76
+ else:
77
+ regime_score = 0.1
78
+
79
+ close = df["close"].iloc[-1]
80
+ atr_pct = last_atr / close if close > 0 else 0.0
81
+
82
+ return {
83
+ "atr": last_atr,
84
+ "atr_pct": atr_pct,
85
+ "structure": last_structure,
86
+ "trend": trend,
87
+ "vol_ratio": last_vol_ratio,
88
+ "volatility_expanding": volatility_expanding,
89
+ "regime_score": regime_score,
90
+ "atr_series": atr,
91
+ "structure_series": structure,
92
+ "vol_ratio_series": vol_ratio,
93
+ }