Premchan369 commited on
Commit
02b0456
·
verified ·
1 Parent(s): 12fb8be

Upload regime_features.py

Browse files
Files changed (1) hide show
  1. regime_features.py +54 -0
regime_features.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Regime Detection Features - Volatility and trend regimes"""
2
+ import numpy as np
3
+ import pandas as pd
4
+
5
+ class RegimeFeatures:
6
+ """Market regime detection: bull/bear/high-vol"""
7
+
8
+ @staticmethod
9
+ def volatility_regime(returns, windows=[5, 21, 63]):
10
+ features = pd.DataFrame(index=returns.index)
11
+ for w in windows:
12
+ vol = returns.rolling(w).std() * np.sqrt(252)
13
+ features[f'vol_regime_{w}d'] = pd.cut(vol, bins=[0, 0.10, 0.20, 0.35, 1.0], labels=[0, 1, 2, 3]).astype(float)
14
+ features[f'vol_zscore_{w}d'] = (vol - vol.rolling(252).mean()) / vol.rolling(252).std().replace(0, 1)
15
+ return features
16
+
17
+ @staticmethod
18
+ def trend_regime(close):
19
+ features = pd.DataFrame(index=close.index)
20
+ for w in [21, 63, 126]:
21
+ ret = close.pct_change(w)
22
+ features[f'trend_{w}d'] = np.sign(ret)
23
+ features[f'trend_strength_{w}d'] = ret.abs()
24
+ # Composite regime
25
+ features['regime_composite'] = features['trend_21d'] + features['trend_63d']
26
+ return features
27
+
28
+ @staticmethod
29
+ def liquidity_regime(volume, close):
30
+ features = pd.DataFrame(index=volume.index)
31
+ dollar_vol = volume * close
32
+ features['dollar_vol_rank'] = dollar_vol.rolling(63).rank(pct=True)
33
+ features['volume_trend'] = volume.rolling(21).mean() / volume.rolling(63).mean() - 1
34
+ return features
35
+
36
+ @staticmethod
37
+ def detect_regime(returns, vol_window=21):
38
+ """Simple regime: bull/bear/high-vol/neutral"""
39
+ trend = returns.rolling(63).mean()
40
+ vol = returns.rolling(vol_window).std() * np.sqrt(252)
41
+ vol_median = vol.median()
42
+ regimes = pd.Series(index=returns.index, dtype='object')
43
+ for i, date in enumerate(returns.index):
44
+ if pd.isna(trend.loc[date]) or pd.isna(vol.loc[date]):
45
+ regimes.loc[date] = 'unknown'
46
+ elif vol.loc[date] > vol_median * 1.5:
47
+ regimes.loc[date] = 'high_vol'
48
+ elif trend.loc[date] > 0.001:
49
+ regimes.loc[date] = 'bull'
50
+ elif trend.loc[date] < -0.001:
51
+ regimes.loc[date] = 'bear'
52
+ else:
53
+ regimes.loc[date] = 'neutral'
54
+ return regimes