Upload technical_indicators.py
Browse files- technical_indicators.py +67 -0
technical_indicators.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Advanced Technical Indicators - Ichimoku, Supertrend, Keltner, VPVR"""
|
| 2 |
+
import numpy as np
|
| 3 |
+
import pandas as pd
|
| 4 |
+
|
| 5 |
+
class AdvancedTechnical:
|
| 6 |
+
"""Advanced technical indicators"""
|
| 7 |
+
|
| 8 |
+
@staticmethod
|
| 9 |
+
def ichimoku(close, high, low, tenkan=9, kijun=26, senkou_b=52):
|
| 10 |
+
features = pd.DataFrame(index=close.index)
|
| 11 |
+
tenkan_s = (high.rolling(tenkan).max() + low.rolling(tenkan).min()) / 2
|
| 12 |
+
kijun_s = (high.rolling(kijun).max() + low.rolling(kijun).min()) / 2
|
| 13 |
+
senkou_a = (tenkan_s + kijun_s) / 2
|
| 14 |
+
senkou_b = (high.rolling(senkou_b).max() + low.rolling(senkou_b).min()) / 2
|
| 15 |
+
features['ichimoku_tk_cross'] = (tenkan_s - kijun_s) / close
|
| 16 |
+
features['ichimoku_price_kumo'] = (close - senkou_a) / close
|
| 17 |
+
features['ichimoku_cloud_width'] = (senkou_a - senkou_b) / close
|
| 18 |
+
return features
|
| 19 |
+
|
| 20 |
+
@staticmethod
|
| 21 |
+
def supertrend(close, high, low, period=10, multiplier=3.0):
|
| 22 |
+
features = pd.DataFrame(index=close.index)
|
| 23 |
+
tr = pd.concat([high - low, (high - close.shift(1)).abs(), (low - close.shift(1)).abs()], axis=1).max(axis=1)
|
| 24 |
+
atr = tr.rolling(period).mean()
|
| 25 |
+
hl2 = (high + low) / 2
|
| 26 |
+
upper = hl2 + multiplier * atr
|
| 27 |
+
lower = hl2 - multiplier * atr
|
| 28 |
+
# Determine trend direction
|
| 29 |
+
supertrend_val = pd.Series(index=close.index, dtype=float)
|
| 30 |
+
direction = pd.Series(1.0, index=close.index)
|
| 31 |
+
supertrend_val.iloc[0] = lower.iloc[0]
|
| 32 |
+
for i in range(1, len(close)):
|
| 33 |
+
if close.iloc[i] > upper.iloc[i-1]:
|
| 34 |
+
supertrend_val.iloc[i] = lower.iloc[i]
|
| 35 |
+
direction.iloc[i] = 1.0
|
| 36 |
+
elif close.iloc[i] < lower.iloc[i-1]:
|
| 37 |
+
supertrend_val.iloc[i] = upper.iloc[i]
|
| 38 |
+
direction.iloc[i] = -1.0
|
| 39 |
+
else:
|
| 40 |
+
supertrend_val.iloc[i] = supertrend_val.iloc[i-1]
|
| 41 |
+
direction.iloc[i] = direction.iloc[i-1]
|
| 42 |
+
features['supertrend_dist'] = (close - supertrend_val) / close
|
| 43 |
+
features['supertrend_signal'] = direction
|
| 44 |
+
return features
|
| 45 |
+
|
| 46 |
+
@staticmethod
|
| 47 |
+
def keltner_channels(close, high, low, ema_period=20, atr_period=10, multiplier=2.0):
|
| 48 |
+
features = pd.DataFrame(index=close.index)
|
| 49 |
+
ema = close.ewm(span=ema_period).mean()
|
| 50 |
+
tr = pd.concat([high - low, (high - close.shift(1)).abs(), (low - close.shift(1)).abs()], axis=1).max(axis=1)
|
| 51 |
+
atr = tr.rolling(atr_period).mean()
|
| 52 |
+
upper = ema + multiplier * atr
|
| 53 |
+
lower = ema - multiplier * atr
|
| 54 |
+
features['keltner_position'] = (close - lower) / (upper - lower).replace(0, np.nan)
|
| 55 |
+
features['keltner_width'] = (upper - lower) / close
|
| 56 |
+
return features
|
| 57 |
+
|
| 58 |
+
@staticmethod
|
| 59 |
+
def volume_profile(close, volume, high, low, window=21):
|
| 60 |
+
features = pd.DataFrame(index=close.index)
|
| 61 |
+
vwp = (close * volume).rolling(window).sum() / volume.rolling(window).sum().replace(0, np.nan)
|
| 62 |
+
features['vwp_deviation'] = (close - vwp) / close
|
| 63 |
+
up_vol = volume.where(close > close.shift(1), 0)
|
| 64 |
+
down_vol = volume.where(close < close.shift(1), 0)
|
| 65 |
+
features['volume_delta'] = (up_vol.rolling(window).sum() - down_vol.rolling(window).sum()) / \
|
| 66 |
+
volume.rolling(window).sum().replace(0, np.nan)
|
| 67 |
+
return features
|