eshan6704 commited on
Commit
91fe931
·
verified ·
1 Parent(s): 3f6ff4d

Create indicators.py

Browse files
Files changed (1) hide show
  1. indicators.py +215 -0
indicators.py ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # indicators.py
2
+ import pandas as pd
3
+ import numpy as np
4
+
5
+ # Try TA-Lib
6
+ try:
7
+ import talib
8
+ TALIB = True
9
+ except:
10
+ TALIB = False
11
+
12
+
13
+ # ============================================================
14
+ # BASIC INDICATORS (SMA, EMA, ATR)
15
+ # ============================================================
16
+
17
+ def sma(series, period):
18
+ return series.rolling(period).mean()
19
+
20
+
21
+ def ema(series, period):
22
+ return series.ewm(span=period, adjust=False).mean()
23
+
24
+
25
+ def atr(high, low, close, period=14):
26
+ if TALIB and hasattr(talib, "ATR"):
27
+ return talib.ATR(high, low, close, timeperiod=period)
28
+ else:
29
+ tr1 = high - low
30
+ tr2 = (high - close.shift()).abs()
31
+ tr3 = (low - close.shift()).abs()
32
+ tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
33
+ return tr.rolling(period).mean()
34
+
35
+
36
+ # ============================================================
37
+ # SUPERTREND — TradingView Perfect Replication
38
+ # ============================================================
39
+
40
+ def supertrend(df, period=10, multiplier=3):
41
+ """
42
+ Returns:
43
+ ST: SuperTrend line
44
+ DIR: Trend direction (True = Uptrend, False = Downtrend)
45
+ """
46
+ high = df['High']
47
+ low = df['Low']
48
+ close = df['Close']
49
+
50
+ # ATR
51
+ atr_val = atr(high, low, close, period)
52
+
53
+ # Basic bands
54
+ hl2 = (high + low) / 2
55
+ upperband = hl2 + multiplier * atr_val
56
+ lowerband = hl2 - multiplier * atr_val
57
+
58
+ final_upper = upperband.copy()
59
+ final_lower = lowerband.copy()
60
+
61
+ for i in range(1, len(df)):
62
+ # Final upper band
63
+ if upperband.iloc[i] < final_upper.iloc[i - 1] or close.iloc[i - 1] > final_upper.iloc[i - 1]:
64
+ final_upper.iloc[i] = upperband.iloc[i]
65
+ else:
66
+ final_upper.iloc[i] = final_upper.iloc[i - 1]
67
+
68
+ # Final lower band
69
+ if lowerband.iloc[i] > final_lower.iloc[i - 1] or close.iloc[i - 1] < final_lower.iloc[i - 1]:
70
+ final_lower.iloc[i] = lowerband.iloc[i]
71
+ else:
72
+ final_lower.iloc[i] = final_lower.iloc[i - 1]
73
+
74
+ # Supertrend
75
+ st = pd.Series(index=df.index)
76
+ dir_up = pd.Series(index=df.index, dtype=bool)
77
+
78
+ for i in range(1, len(df)):
79
+ if close.iloc[i] > final_upper.iloc[i - 1]:
80
+ dir_up.iloc[i] = True
81
+ elif close.iloc[i] < final_lower.iloc[i - 1]:
82
+ dir_up.iloc[i] = False
83
+ else:
84
+ dir_up.iloc[i] = dir_up.iloc[i - 1]
85
+
86
+ st.iloc[i] = final_lower.iloc[i] if dir_up.iloc[i] else final_upper.iloc[i]
87
+
88
+ return st, dir_up
89
+
90
+
91
+ # ============================================================
92
+ # KELTNER CHANNEL — (EMA ± ATR * Mult)
93
+ # ============================================================
94
+
95
+ def keltner_channel(df, ema_period=20, atr_period=10, mult=2):
96
+ close = df['Close']
97
+ upper = ema(close, ema_period) + mult * atr(df['High'], df['Low'], df['Close'], atr_period)
98
+ lower = ema(close, ema_period) - mult * atr(df['High'], df['Low'], df['Close'], atr_period)
99
+ mid = ema(close, ema_period)
100
+ return mid, upper, lower
101
+
102
+
103
+ # ============================================================
104
+ # ZIGZAG — PERCENT BASED
105
+ # ============================================================
106
+
107
+ def zigzag(series, pct=5):
108
+ """
109
+ Returns ZigZag turning points based on percentage move.
110
+ """
111
+ zz = pd.Series(index=series.index, dtype=float)
112
+ last_pivot_price = series.iloc[0]
113
+ last_pivot_idx = series.index[0]
114
+ trend = 0 # +1 up, -1 down
115
+
116
+ for i in range(1, len(series)):
117
+ change = (series.iloc[i] - last_pivot_price) / last_pivot_price * 100
118
+
119
+ if trend >= 0 and change <= -pct:
120
+ zz.iloc[i] = series.iloc[i]
121
+ last_pivot_price = series.iloc[i]
122
+ trend = -1
123
+
124
+ elif trend <= 0 and change >= pct:
125
+ zz.iloc[i] = series.iloc[i]
126
+ last_pivot_price = series.iloc[i]
127
+ trend = +1
128
+
129
+ return zz
130
+
131
+
132
+ # ============================================================
133
+ # SWING HIGH / SWING LOW
134
+ # ============================================================
135
+
136
+ def swing_high_low(df, window=5):
137
+ """
138
+ Identifies swing high/low using window method.
139
+ For window=5, center index is 2 (2 left, 2 right)
140
+ """
141
+ highs = df['High']
142
+ lows = df['Low']
143
+ idx = df.index
144
+
145
+ swing_high = pd.Series(np.nan, index=idx)
146
+ swing_low = pd.Series(np.nan, index=idx)
147
+
148
+ half = window // 2
149
+
150
+ for i in range(half, len(df) - half):
151
+ segment_high = highs[i - half: i + half + 1]
152
+ segment_low = lows[i - half: i + half + 1]
153
+
154
+ if highs.iloc[i] == segment_high.max():
155
+ swing_high.iloc[i] = highs.iloc[i]
156
+
157
+ if lows.iloc[i] == segment_low.min():
158
+ swing_low.iloc[i] = lows.iloc[i]
159
+
160
+ return swing_high, swing_low
161
+
162
+
163
+ # ============================================================
164
+ # RSI FALLBACK
165
+ # ============================================================
166
+
167
+ def rsi(series, period=14):
168
+ if TALIB and hasattr(talib, "RSI"):
169
+ return talib.RSI(series, timeperiod=period)
170
+ else:
171
+ delta = series.diff()
172
+ up = delta.clip(lower=0)
173
+ down = -delta.clip(upper=0)
174
+ ema_up = up.ewm(span=period).mean()
175
+ ema_down = down.ewm(span=period).mean()
176
+ rs = ema_up / ema_down
177
+ return 100 - (100 / (1 + rs))
178
+
179
+
180
+ # ============================================================
181
+ # MACD FALLBACK
182
+ # ============================================================
183
+
184
+ def macd(series, fast=12, slow=26, signal=9):
185
+ if TALIB and hasattr(talib, "MACD"):
186
+ macd_line, macd_signal, macd_hist = talib.MACD(series, fastperiod=fast, slowperiod=slow, signalperiod=signal)
187
+ return macd_line, macd_signal, macd_hist
188
+ else:
189
+ ema_fast = ema(series, fast)
190
+ ema_slow = ema(series, slow)
191
+ macd_line = ema_fast - ema_slow
192
+ macd_signal = ema(macd_line, signal)
193
+ macd_hist = macd_line - macd_signal
194
+ return macd_line, macd_signal, macd_hist
195
+
196
+
197
+ # ============================================================
198
+ # STOCHASTIC FALLBACK
199
+ # ============================================================
200
+
201
+ def stochastic(df, k_period=14, d_period=3):
202
+ if TALIB and hasattr(talib, "STOCH"):
203
+ k, d = talib.STOCH(
204
+ df['High'], df['Low'], df['Close'],
205
+ fastk_period=k_period,
206
+ slowk_period=d_period, slowk_matype=0,
207
+ slowd_period=d_period, slowd_matype=0
208
+ )
209
+ return k, d
210
+ else:
211
+ low_min = df['Low'].rolling(k_period).min()
212
+ high_max = df['High'].rolling(k_period).max()
213
+ k = (df['Close'] - low_min) * 100 / (high_max - low_min)
214
+ d = k.rolling(d_period).mean()
215
+ return k, d