eshan6704 commited on
Commit
7fd28c9
·
verified ·
1 Parent(s): df15986

Update indicator.py

Browse files
Files changed (1) hide show
  1. indicator.py +98 -129
indicator.py CHANGED
@@ -1,139 +1,108 @@
1
  # indicator.py
2
  import pandas as pd
3
  import numpy as np
4
-
5
- # Try TA-Lib
6
- try:
7
- import talib
8
- TALIB_AVAILABLE = True
9
- except:
10
- TALIB_AVAILABLE = False
11
-
12
-
13
- # ==============================
14
- # MACD
15
- # ==============================
16
- def calc_macd(df):
17
- if TALIB_AVAILABLE:
18
- macd, signal, hist = talib.MACD(df["Close"])
19
- else:
20
- ema12 = df["Close"].ewm(span=12).mean()
21
- ema26 = df["Close"].ewm(span=26).mean()
22
- macd = ema12 - ema26
23
- signal = macd.ewm(span=9).mean()
24
- hist = macd - signal
25
-
26
- return pd.DataFrame({
27
- "MACD": macd,
28
- "Signal": signal,
29
- "Histogram": hist
30
- })
31
-
32
-
33
- # ==============================
34
- # RSI
35
- # ==============================
36
- def calc_rsi(df):
37
- if TALIB_AVAILABLE:
38
- rsi = talib.RSI(df["Close"], timeperiod=14)
39
- else:
40
- delta = df["Close"].diff()
41
- gain = (delta.where(delta > 0, 0)).rolling(14).mean()
42
- loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
43
- rs = gain / loss
44
- rsi = 100 - (100 / (1 + rs))
45
-
46
- return pd.DataFrame({"RSI": rsi})
47
-
48
-
49
- # ==============================
50
- # Supertrend (Custom)
51
- # ==============================
52
- def calc_supertrend(df, period=10, multiplier=3):
53
- hl2 = (df["High"] + df["Low"]) / 2
54
- tr1 = df["High"] - df["Low"]
55
- tr2 = abs(df["High"] - df["Close"].shift())
56
- tr3 = abs(df["Low"] - df["Close"].shift())
57
- tr = tr1.combine(tr2, max).combine(tr3, max)
58
-
59
  atr = tr.rolling(period).mean()
 
 
 
60
  upperband = hl2 + multiplier * atr
61
  lowerband = hl2 - multiplier * atr
62
 
63
- st = pd.Series(index=df.index)
64
- direction = pd.Series(index=df.index)
65
-
66
- for i in range(len(df)):
67
- if i == 0:
68
- st.iloc[i] = upperband.iloc[i]
69
- direction.iloc[i] = 1
 
 
70
  else:
71
- if df["Close"].iloc[i] > st.iloc[i - 1]:
72
- st.iloc[i] = lowerband.iloc[i]
73
- direction.iloc[i] = 1
74
  else:
75
- st.iloc[i] = upperband.iloc[i]
76
- direction.iloc[i] = -1
77
-
78
- return pd.DataFrame({
79
- "Supertrend": st,
80
- "Direction": direction
81
- })
82
-
83
-
84
- # ==============================
85
- # Stochastic
86
- # ==============================
87
- def calc_stochastic(df):
88
- if TALIB_AVAILABLE:
89
- slowk, slowd = talib.STOCH(df["High"], df["Low"], df["Close"])
90
- else:
91
- low14 = df["Low"].rolling(14).min()
92
- high14 = df["High"].rolling(14).max()
93
- slowk = (df["Close"] - low14) * 100 / (high14 - low14)
94
- slowd = slowk.rolling(3).mean()
95
-
96
- return pd.DataFrame({"STOCH_K": slowk, "STOCH_D": slowd})
97
-
98
-
99
- # ==============================
100
- # Keltner Channel
101
- # ==============================
102
- def calc_keltner(df):
103
- typical = (df["High"] + df["Low"] + df["Close"]) / 3
104
- ema = typical.ewm(span=20).mean()
105
- atr = (df["High"] - df["Low"]).rolling(20).mean()
106
-
107
- upper = ema + 2 * atr
108
- lower = ema - 2 * atr
109
-
110
- return pd.DataFrame({"KC_UP": upper, "KC_MID": ema, "KC_LOW": lower})
111
-
112
-
113
- # ==============================
114
- # ZigZag (simplified)
115
- # ==============================
116
- def calc_zigzag(df, pct=3):
117
- zigzag = [np.nan] * len(df)
118
- last_pivot = df["Close"].iloc[0]
119
-
120
  for i in range(1, len(df)):
121
- change = (df["Close"].iloc[i] - last_pivot) / last_pivot * 100
122
- if abs(change) >= pct:
123
- zigzag[i] = df["Close"].iloc[i]
124
- last_pivot = df["Close"].iloc[i]
125
-
126
- return pd.DataFrame({"ZIGZAG": zigzag})
127
-
128
-
129
- # ==============================
130
- # Swing High / Low
131
- # ==============================
132
- def calc_swings(df, period=5):
133
- swing_high = df["High"].rolling(period).max()
134
- swing_low = df["Low"].rolling(period).min()
135
-
136
- return pd.DataFrame({
137
- "SWING_HIGH": swing_high,
138
- "SWING_LOW": swing_low
139
- })
 
 
 
 
1
  # indicator.py
2
  import pandas as pd
3
  import numpy as np
4
+ import talib
5
+
6
+ # ============================================================
7
+ # TRENDING INDICATOR HELPERS
8
+ # ============================================================
9
+
10
+ def macd(df, fast=12, slow=26, signal=9):
11
+ """Compute MACD and signal line."""
12
+ try:
13
+ macd_line, signal_line, hist = talib.MACD(df['Close'], fastperiod=fast, slowperiod=slow, signalperiod=signal)
14
+ df['MACD'] = macd_line
15
+ df['MACD_Signal'] = signal_line
16
+ except Exception:
17
+ # fallback
18
+ df['MACD'] = df['Close'].ewm(span=fast).mean() - df['Close'].ewm(span=slow).mean()
19
+ df['MACD_Signal'] = df['MACD'].ewm(span=signal).mean()
20
+ return df
21
+
22
+ def rsi(df, period=14):
23
+ try:
24
+ df['RSI'] = talib.RSI(df['Close'], timeperiod=period)
25
+ except Exception:
26
+ delta = df['Close'].diff()
27
+ gain = delta.where(delta > 0, 0)
28
+ loss = -delta.where(delta < 0, 0)
29
+ avg_gain = gain.rolling(period).mean()
30
+ avg_loss = loss.rolling(period).mean()
31
+ rs = avg_gain / avg_loss
32
+ df['RSI'] = 100 - (100 / (1 + rs))
33
+ return df
34
+
35
+ def supertrend(df, period=10, multiplier=3):
36
+ """Compute SuperTrend indicator"""
37
+ # ATR calculation
38
+ high_low = df['High'] - df['Low']
39
+ high_close = (df['High'] - df['Close'].shift()).abs()
40
+ low_close = (df['Low'] - df['Close'].shift()).abs()
41
+ tr = pd.concat([high_low, high_close, low_close], axis=1).max(axis=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  atr = tr.rolling(period).mean()
43
+
44
+ # Basic Upper and Lower Bands
45
+ hl2 = (df['High'] + df['Low']) / 2
46
  upperband = hl2 + multiplier * atr
47
  lowerband = hl2 - multiplier * atr
48
 
49
+ # SuperTrend calculation
50
+ supertrend = [True] # True = uptrend, False = downtrend
51
+ final_upper = upperband.copy()
52
+ final_lower = lowerband.copy()
53
+ for i in range(1, len(df)):
54
+ if df['Close'][i] > final_upper[i-1]:
55
+ supertrend.append(True)
56
+ elif df['Close'][i] < final_lower[i-1]:
57
+ supertrend.append(False)
58
  else:
59
+ supertrend.append(supertrend[i-1])
60
+ if supertrend[i-1]:
61
+ final_upper[i] = min(upperband[i], final_upper[i-1])
62
  else:
63
+ final_lower[i] = max(lowerband[i], final_lower[i-1])
64
+ df['SuperTrend'] = supertrend
65
+ return df
66
+
67
+ def keltner_channel(df, period=20, atr_mult=2):
68
+ """Compute Keltner Channels"""
69
+ try:
70
+ high_low = df['High'] - df['Low']
71
+ high_close = (df['High'] - df['Close'].shift()).abs()
72
+ low_close = (df['Low'] - df['Close'].shift()).abs()
73
+ tr = pd.concat([high_low, high_close, low_close], axis=1).max(axis=1)
74
+ atr = tr.rolling(period).mean()
75
+ ma = df['Close'].rolling(period).mean()
76
+ df['KC_Upper'] = ma + atr_mult * atr
77
+ df['KC_Lower'] = ma - atr_mult * atr
78
+ except Exception:
79
+ pass
80
+ return df
81
+
82
+ def zigzag(df, change_pct=5):
83
+ """Simple ZigZag based on % change"""
84
+ zz = [df['Close'].iloc[0]]
85
+ last_dir = 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  for i in range(1, len(df)):
87
+ change = (df['Close'].iloc[i] - zz[-1]) / zz[-1] * 100
88
+ if change > change_pct:
89
+ zz.append(df['Close'].iloc[i])
90
+ last_dir = 1
91
+ elif change < -change_pct:
92
+ zz.append(df['Close'].iloc[i])
93
+ last_dir = -1
94
+ else:
95
+ zz.append(np.nan)
96
+ df['ZigZag'] = zz
97
+ return df
98
+
99
+ def swing_high_low(df, period=5):
100
+ """Mark swing highs and lows"""
101
+ df['Swing_High'] = df['High'][(df['High'].rolling(period*2+1, center=True).max() == df['High'])]
102
+ df['Swing_Low'] = df['Low'][(df['Low'].rolling(period*2+1, center=True).min() == df['Low'])]
103
+ return df
104
+
105
+ def stockstick(df):
106
+ """Simple stick colors for up/down"""
107
+ df['StickColor'] = np.where(df['Close'] >= df['Open'], 'green', 'red')
108
+ return df