├── Advanced Strategies ├── ADX_RSI.py ├── BollingerBands_KeltnerChannel_RSI.py ├── BollingerBands_Stochastic.py ├── Stochastics_MACD.py └── Williams%R_MACD.py ├── LICENSE ├── Momentum ├── Awesome_Oscillator.py ├── Commodity_Channel_Index.py ├── Coppock_Curve.py ├── Disparity_Index.py ├── Know_Sure_Thing.py ├── MACD.py ├── RSI.py ├── Relative_Vigor_Index.py ├── Stochastic_Oscillator.py ├── True_Strength_Index.py └── Williams_%R.py ├── Overlap ├── Simple_Moving_Average.py └── SuperTrend.py ├── README.md ├── Trend ├── ADX.py ├── Aroon.py └── Choppiness_Index.py └── Volatility ├── Bollinger_Bands.py └── Keltner_Channel.py /Advanced Strategies/ADX_RSI.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import numpy as np 4 | import pandas as pd 5 | import matplotlib.pyplot as plt 6 | import requests 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2010-01-01') 25 | aapl.tail() 26 | 27 | # ADX CALCULATION 28 | 29 | def get_adx(high, low, close, lookback): 30 | plus_dm = high.diff() 31 | minus_dm = low.diff() 32 | plus_dm[plus_dm < 0] = 0 33 | minus_dm[minus_dm > 0] = 0 34 | 35 | tr1 = pd.DataFrame(high - low) 36 | tr2 = pd.DataFrame(abs(high - close.shift(1))) 37 | tr3 = pd.DataFrame(abs(low - close.shift(1))) 38 | frames = [tr1, tr2, tr3] 39 | tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1) 40 | atr = tr.rolling(lookback).mean() 41 | 42 | plus_di = 100 * (plus_dm.ewm(alpha = 1/lookback).mean() / atr) 43 | minus_di = abs(100 * (minus_dm.ewm(alpha = 1/lookback).mean() / atr)) 44 | dx = (abs(plus_di - minus_di) / abs(plus_di + minus_di)) * 100 45 | adx = ((dx.shift(1) * (lookback - 1)) + dx) / lookback 46 | adx_smooth = adx.ewm(alpha = 1/lookback).mean() 47 | return plus_di, minus_di, adx_smooth 48 | 49 | aapl['plus_di'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[0]).rename(columns = {0:'plus_di'}) 50 | aapl['minus_di'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[1]).rename(columns = {0:'minus_di'}) 51 | aapl['adx'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[2]).rename(columns = {0:'adx'}) 52 | aapl = aapl.dropna() 53 | aapl.tail() 54 | 55 | # ADX PLOT 56 | 57 | plot_data = aapl[aapl.index >= '2020-01-01'] 58 | 59 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 60 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 61 | ax1.plot(plot_data['close'], linewidth = 2, color = '#ff9800') 62 | ax1.set_title('AAPL CLOSING PRICE') 63 | ax2.plot(plot_data['plus_di'], color = '#26a69a', label = '+ DI 14', linewidth = 3, alpha = 0.3) 64 | ax2.plot(plot_data['minus_di'], color = '#f44336', label = '- DI 14', linewidth = 3, alpha = 0.3) 65 | ax2.plot(plot_data['adx'], color = '#2196f3', label = 'ADX 14', linewidth = 3) 66 | ax2.axhline(35, color = 'grey', linewidth = 2, linestyle = '--') 67 | ax2.legend() 68 | ax2.set_title('AAPL ADX 14') 69 | plt.show() 70 | 71 | # RSI CALCULATION 72 | 73 | def get_rsi(close, lookback): 74 | ret = close.diff() 75 | up = [] 76 | down = [] 77 | 78 | for i in range(len(ret)): 79 | if ret[i] < 0: 80 | up.append(0) 81 | down.append(ret[i]) 82 | else: 83 | up.append(ret[i]) 84 | down.append(0) 85 | 86 | up_series = pd.Series(up) 87 | down_series = pd.Series(down).abs() 88 | 89 | up_ewm = up_series.ewm(com = lookback - 1, adjust = False).mean() 90 | down_ewm = down_series.ewm(com = lookback - 1, adjust = False).mean() 91 | 92 | rs = up_ewm/down_ewm 93 | rsi = 100 - (100 / (1 + rs)) 94 | rsi_df = pd.DataFrame(rsi).rename(columns = {0:'rsi'}).set_index(close.index) 95 | rsi_df = rsi_df.dropna() 96 | 97 | return rsi_df[3:] 98 | 99 | aapl['rsi_14'] = get_rsi(aapl['close'], 14) 100 | aapl = aapl.dropna() 101 | aapl.tail() 102 | 103 | # RSI PLOT 104 | 105 | plot_data = aapl[aapl.index >= '2020-01-01'] 106 | 107 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 108 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 109 | ax1.plot(plot_data['close'], linewidth = 2.5) 110 | ax1.set_title('AAPL STOCK PRICES') 111 | ax2.plot(plot_data['rsi_14'], color = 'orange', linewidth = 2.5) 112 | ax2.axhline(30, linestyle = '--', linewidth = 1.5, color = 'grey') 113 | ax2.axhline(70, linestyle = '--', linewidth = 1.5, color = 'grey') 114 | ax2.set_title('AAPL RSI 14') 115 | plt.show() 116 | 117 | # RSI ADX PLOT 118 | 119 | plot_data = aapl[aapl.index >= '2020-01-01'] 120 | 121 | ax1 = plt.subplot2grid((19,1), (0,0), rowspan = 5, colspan = 1) 122 | ax2 = plt.subplot2grid((19,1), (7,0), rowspan = 5, colspan = 1) 123 | ax3 = plt.subplot2grid((19,1), (14,0), rowspan = 5, colspan = 1) 124 | 125 | ax1.plot(plot_data['close'], linewidth = 2.5) 126 | ax1.set_title('AAPL STOCK PRICES') 127 | 128 | ax2.plot(plot_data['rsi_14'], color = 'orange', linewidth = 2.5) 129 | ax2.axhline(30, linestyle = '--', linewidth = 1.5, color = 'grey') 130 | ax2.axhline(70, linestyle = '--', linewidth = 1.5, color = 'grey') 131 | ax2.set_title('AAPL RSI 14') 132 | 133 | ax3.plot(plot_data['plus_di'], color = '#26a69a', label = '+ DI 14', linewidth = 3, alpha = 0.3) 134 | ax3.plot(plot_data['minus_di'], color = '#f44336', label = '- DI 14', linewidth = 3, alpha = 0.3) 135 | ax3.plot(plot_data['adx'], color = '#2196f3', label = 'ADX 14', linewidth = 3) 136 | ax3.axhline(35, color = 'grey', linewidth = 2, linestyle = '--') 137 | ax3.legend() 138 | ax3.set_title('AAPL ADX 14') 139 | plt.show() 140 | 141 | # TRADING STRATEGY 142 | 143 | def adx_rsi_strategy(prices, adx, pdi, ndi, rsi): 144 | buy_price = [] 145 | sell_price = [] 146 | adx_rsi_signal = [] 147 | signal = 0 148 | 149 | for i in range(len(prices)): 150 | if adx[i] > 35 and pdi[i] < ndi[i] and rsi[i] < 50: 151 | if signal != 1: 152 | buy_price.append(prices[i]) 153 | sell_price.append(np.nan) 154 | signal = 1 155 | adx_rsi_signal.append(signal) 156 | else: 157 | buy_price.append(np.nan) 158 | sell_price.append(np.nan) 159 | adx_rsi_signal.append(0) 160 | 161 | elif adx[i] > 35 and pdi[i] > ndi[i] and rsi[i] > 50: 162 | if signal != -1: 163 | buy_price.append(np.nan) 164 | sell_price.append(prices[i]) 165 | signal = -1 166 | adx_rsi_signal.append(signal) 167 | else: 168 | buy_price.append(np.nan) 169 | sell_price.append(np.nan) 170 | adx_rsi_signal.append(0) 171 | else: 172 | buy_price.append(np.nan) 173 | sell_price.append(np.nan) 174 | adx_rsi_signal.append(0) 175 | 176 | return buy_price, sell_price, adx_rsi_signal 177 | 178 | buy_price, sell_price, adx_rsi_signal = adx_rsi_strategy(aapl['close'], aapl['adx'], aapl['plus_di'], aapl['minus_di'], aapl['rsi_14']) 179 | 180 | # POSITION 181 | 182 | position = [] 183 | for i in range(len(adx_rsi_signal)): 184 | if adx_rsi_signal[i] > 1: 185 | position.append(1) 186 | else: 187 | position.append(0) 188 | 189 | for i in range(len(aapl['close'])): 190 | if adx_rsi_signal[i] == 1: 191 | position[i] = 1 192 | elif adx_rsi_signal[i] == -1: 193 | position[i] = 0 194 | else: 195 | position[i] = position[i-1] 196 | 197 | 198 | adx = aapl['adx'] 199 | pdi = aapl['plus_di'] 200 | ndi = aapl['minus_di'] 201 | rsi = aapl['rsi_14'] 202 | close_price = aapl['close'] 203 | adx_rsi_signal = pd.DataFrame(adx_rsi_signal).rename(columns = {0:'adx_rsi_signal'}).set_index(aapl.index) 204 | position = pd.DataFrame(position).rename(columns = {0:'adx_rsi_position'}).set_index(aapl.index) 205 | 206 | frames = [close_price, adx, pdi, ndi, rsi, adx_rsi_signal, position] 207 | strategy = pd.concat(frames, join = 'inner', axis = 1) 208 | 209 | strategy 210 | 211 | rets = aapl.close.pct_change().dropna() 212 | strat_rets = strategy.adx_rsi_position[1:]*rets 213 | 214 | plt.title('Daily Returns') 215 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 216 | strat_rets.plot(color = 'r', linewidth = 1) 217 | plt.show() 218 | -------------------------------------------------------------------------------- /Advanced Strategies/BollingerBands_KeltnerChannel_RSI.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import numpy as np 4 | import requests 5 | import pandas as pd 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2010-01-01') 25 | aapl.tail() 26 | 27 | # BOLLINGER BANDS CALCULATION 28 | 29 | def sma(data, lookback): 30 | sma = data.rolling(lookback).mean() 31 | return sma 32 | 33 | def get_bb(data, lookback): 34 | std = data.rolling(lookback).std() 35 | upper_bb = sma(data, lookback) + std * 2 36 | lower_bb = sma(data, lookback) - std * 2 37 | middle_bb = sma(data, lookback) 38 | return upper_bb, middle_bb, lower_bb 39 | 40 | aapl['upper_bb'], aapl['middle_bb'], aapl['lower_bb'] = get_bb(aapl['close'], 20) 41 | aapl.tail() 42 | 43 | # BOLLINGER BANDS PLOT 44 | 45 | plot_data = aapl[aapl.index >= '2020-01-01'] 46 | 47 | plt.plot(plot_data['close'], linewidth = 2.5) 48 | plt.plot(plot_data['upper_bb'], label = 'UPPER BB 20', linewidth = 2, color = 'violet') 49 | plt.plot(plot_data['middle_bb'], label = 'MIDDLE BB 20', linewidth = 1.5, color = 'grey') 50 | plt.plot(plot_data['lower_bb'], label = 'LOWER BB 20', linewidth = 2, color = 'violet') 51 | plt.title('AAPL BB 20') 52 | plt.legend(fontsize = 15) 53 | plt.show() 54 | 55 | # KELTNER CHANNEL CALCULATION 56 | 57 | def get_kc(high, low, close, kc_lookback, multiplier, atr_lookback): 58 | tr1 = pd.DataFrame(high - low) 59 | tr2 = pd.DataFrame(abs(high - close.shift())) 60 | tr3 = pd.DataFrame(abs(low - close.shift())) 61 | frames = [tr1, tr2, tr3] 62 | tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1) 63 | atr = tr.ewm(alpha = 1/atr_lookback).mean() 64 | 65 | kc_middle = close.ewm(kc_lookback).mean() 66 | kc_upper = close.ewm(kc_lookback).mean() + multiplier * atr 67 | kc_lower = close.ewm(kc_lookback).mean() - multiplier * atr 68 | 69 | return kc_middle, kc_upper, kc_lower 70 | 71 | aapl['kc_middle'], aapl['kc_upper'], aapl['kc_lower'] = get_kc(aapl['high'], aapl['low'], aapl['close'], 20, 2, 10) 72 | aapl.tail() 73 | 74 | # KELTNER CHANNEL PLOT 75 | 76 | plot_data = aapl[aapl.index >= '2020-01-01'] 77 | 78 | plt.plot(plot_data['close'], linewidth = 2, label = 'AAPL') 79 | plt.plot(plot_data['kc_upper'], linewidth = 2, color = 'orange', label = 'KC UPPER 20') 80 | plt.plot(plot_data['kc_middle'], linewidth = 1.5, color = 'grey', label = 'KC MIDDLE 20') 81 | plt.plot(plot_data['kc_lower'], linewidth = 2, color = 'orange', label = 'KC LOWER 20') 82 | plt.legend(fontsize = 15) 83 | plt.title('AAPL KELTNER CHANNEL 20') 84 | plt.show() 85 | 86 | plot_data = aapl[aapl.index >= '2020-01-01'] 87 | 88 | plt.plot(plot_data['close'], linewidth = 2.5, label = 'AAPL') 89 | plt.plot(plot_data['upper_bb'], label = 'UPPER BB 20', linewidth = 2, color = 'violet') 90 | plt.plot(plot_data['lower_bb'], label = 'LOWER BB 20', linewidth = 2, color = 'violet') 91 | plt.plot(plot_data['kc_upper'], linewidth = 2, color = 'orange', label = 'KC UPPER 20') 92 | plt.plot(plot_data['kc_lower'], linewidth = 2, color = 'orange', label = 'KC LOWER 20') 93 | plt.legend(fontsize = 15) 94 | plt.show() 95 | 96 | # RSI CALCULATION 97 | 98 | def get_rsi(close, lookback): 99 | ret = close.diff() 100 | up = [] 101 | down = [] 102 | for i in range(len(ret)): 103 | if ret[i] < 0: 104 | up.append(0) 105 | down.append(ret[i]) 106 | else: 107 | up.append(ret[i]) 108 | down.append(0) 109 | up_series = pd.Series(up) 110 | down_series = pd.Series(down).abs() 111 | up_ewm = up_series.ewm(com = lookback - 1, adjust = False).mean() 112 | down_ewm = down_series.ewm(com = lookback - 1, adjust = False).mean() 113 | rs = up_ewm/down_ewm 114 | rsi = 100 - (100 / (1 + rs)) 115 | rsi_df = pd.DataFrame(rsi).rename(columns = {0:'rsi'}).set_index(close.index) 116 | rsi_df = rsi_df.dropna() 117 | return rsi_df[3:] 118 | 119 | aapl['rsi_14'] = get_rsi(aapl['close'], 14) 120 | aapl = aapl.dropna() 121 | aapl.tail() 122 | 123 | # RSI PLOT 124 | 125 | plot_data = aapl[aapl.index >= '2020-01-01'] 126 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 127 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 128 | ax1.plot(plot_data['close']) 129 | ax1.set_title('AAPL STOCK PRICE') 130 | ax2.plot(plot_data['rsi_14'], color = 'orange', linewidth = 2) 131 | ax2.axhline(30, color = 'grey', linestyle = '--', linewidth = 1.5) 132 | ax2.axhline(70, color = 'grey', linestyle = '--', linewidth = 1.5) 133 | ax2.set_title('AAPL RSI 14') 134 | plt.show() 135 | 136 | # TRADING STRATEGY 137 | 138 | def bb_kc_rsi_strategy(prices, upper_bb, lower_bb, kc_upper, kc_lower, rsi): 139 | buy_price = [] 140 | sell_price = [] 141 | bb_kc_rsi_signal = [] 142 | signal = 0 143 | 144 | for i in range(len(prices)): 145 | if lower_bb[i] < kc_lower[i] and upper_bb[i] > kc_upper[i] and rsi[i] < 30: 146 | if signal != 1: 147 | buy_price.append(prices[i]) 148 | sell_price.append(np.nan) 149 | signal = 1 150 | bb_kc_rsi_signal.append(signal) 151 | else: 152 | buy_price.append(np.nan) 153 | sell_price.append(np.nan) 154 | bb_kc_rsi_signal.append(0) 155 | 156 | elif lower_bb[i] < kc_lower[i] and upper_bb[i] > kc_upper[i] and rsi[i] > 70: 157 | if signal != -1: 158 | buy_price.append(np.nan) 159 | sell_price.append(prices[i]) 160 | signal = -1 161 | bb_kc_rsi_signal.append(signal) 162 | else: 163 | buy_price.append(np.nan) 164 | sell_price.append(np.nan) 165 | bb_kc_rsi_signal.append(0) 166 | else: 167 | buy_price.append(np.nan) 168 | sell_price.append(np.nan) 169 | bb_kc_rsi_signal.append(0) 170 | 171 | return buy_price, sell_price, bb_kc_rsi_signal 172 | 173 | buy_price, sell_price, bb_kc_rsi_signal = bb_kc_rsi_strategy(aapl['close'], aapl['upper_bb'], aapl['lower_bb'], 174 | aapl['kc_upper'], aapl['kc_lower'], aapl['rsi_14']) 175 | 176 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 177 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 178 | ax1.plot(aapl['close']) 179 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 10, linewidth = 0, color = 'green', label = 'BUY SIGNAL') 180 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 10, linewidth = 0, color = 'r', label = 'SELL SIGNAL') 181 | ax1.set_title('AAPL STOCK PRICE') 182 | ax2.plot(aapl['rsi_14'], color = 'purple', linewidth = 2) 183 | ax2.axhline(30, color = 'grey', linestyle = '--', linewidth = 1.5) 184 | ax2.axhline(70, color = 'grey', linestyle = '--', linewidth = 1.5) 185 | ax2.set_title('AAPL RSI 10') 186 | plt.show() 187 | 188 | # POSITION 189 | 190 | position = [] 191 | for i in range(len(bb_kc_rsi_signal)): 192 | if bb_kc_rsi_signal[i] > 1: 193 | position.append(0) 194 | else: 195 | position.append(1) 196 | 197 | for i in range(len(aapl['close'])): 198 | if bb_kc_rsi_signal[i] == 1: 199 | position[i] = 1 200 | elif bb_kc_rsi_signal[i] == -1: 201 | position[i] = 0 202 | else: 203 | position[i] = position[i-1] 204 | 205 | kc_upper = aapl['kc_upper'] 206 | kc_lower = aapl['kc_lower'] 207 | upper_bb = aapl['upper_bb'] 208 | lower_bb = aapl['lower_bb'] 209 | rsi = aapl['rsi_14'] 210 | close_price = aapl['close'] 211 | bb_kc_rsi_signal = pd.DataFrame(bb_kc_rsi_signal).rename(columns = {0:'bb_kc_rsi_signal'}).set_index(aapl.index) 212 | position = pd.DataFrame(position).rename(columns = {0:'bb_kc_rsi_position'}).set_index(aapl.index) 213 | 214 | frames = [close_price, kc_upper, kc_lower, upper_bb, lower_bb, rsi, bb_kc_rsi_signal, position] 215 | strategy = pd.concat(frames, join = 'inner', axis = 1) 216 | 217 | strategy.tail() 218 | 219 | rets = aapl.close.pct_change().dropna() 220 | strat_rets = strategy.bb_kc_rsi_position[1:]*rets 221 | 222 | plt.title('Daily Returns') 223 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 224 | strat_rets.plot(color = 'r', linewidth = 1) 225 | plt.show() 226 | -------------------------------------------------------------------------------- /Advanced Strategies/BollingerBands_Stochastic.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import pandas as pd 4 | import requests 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.rcParams['figure.figsize'] = (20, 10) 11 | plt.style.use('fivethirtyeight') 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2010-01-01') 25 | aapl.tail() 26 | 27 | # BOLLINGER BANDS CALCULATION 28 | 29 | def sma(data, lookback): 30 | sma = data.rolling(lookback).mean() 31 | return sma 32 | 33 | def get_bb(data, lookback): 34 | std = data.rolling(lookback).std() 35 | upper_bb = sma(data, lookback) + std * 2 36 | lower_bb = sma(data, lookback) - std * 2 37 | middle_bb = sma(data, lookback) 38 | return upper_bb, lower_bb, middle_bb 39 | 40 | aapl['upper_bb'], aapl['middle_bb'], aapl['lower_bb'] = get_bb(aapl['close'], 20) 41 | aapl = aapl.dropna() 42 | aapl.tail() 43 | 44 | # STOCHASTIC OSCILLATOR CALCULATION 45 | 46 | def get_stoch_osc(high, low, close, k_lookback, d_lookback): 47 | lowest_low = low.rolling(k_lookback).min() 48 | highest_high = high.rolling(k_lookback).max() 49 | k_line = ((close - lowest_low) / (highest_high - lowest_low)) * 100 50 | d_line = k_line.rolling(d_lookback).mean() 51 | return k_line, d_line 52 | 53 | aapl['%k'], aapl['%d'] = get_stoch_osc(aapl['high'], aapl['low'], aapl['close'], 14, 3) 54 | aapl.tail() 55 | 56 | # PLOTTING THE DATA 57 | 58 | plot_data = aapl[aapl.index >= '2020-01-01'] 59 | 60 | plt.plot(plot_data['close'], linewidth = 2.5) 61 | plt.plot(plot_data['upper_bb'], label = 'UPPER BB 20', linestyle = '--', linewidth = 1, color = 'black') 62 | plt.plot(plot_data['middle_bb'], label = 'MIDDLE BB 20', linestyle = '--', linewidth = 1.2, color = 'grey') 63 | plt.plot(plot_data['lower_bb'], label = 'LOWER BB 20', linestyle = '--', linewidth = 1, color = 'black') 64 | plt.title('AAPL BB 20') 65 | plt.legend(loc = 'upper left') 66 | plt.show() 67 | 68 | ax1 = plt.subplot2grid((14,1), (0,0), rowspan = 7, colspan = 1) 69 | ax2 = plt.subplot2grid((15,1), (9,0), rowspan = 6, colspan = 1) 70 | ax1.plot(plot_data['close'], linewidth = 2.5) 71 | ax1.set_title('AAPL STOCK PRICES') 72 | ax2.plot(plot_data['%k'], color = 'deepskyblue', linewidth = 1.5, label = '%K') 73 | ax2.plot(plot_data['%d'], color = 'orange', linewidth = 1.5, label = '%D') 74 | ax2.axhline(70, color = 'black', linewidth = 1, linestyle = '--') 75 | ax2.axhline(30, color = 'black', linewidth = 1, linestyle = '--') 76 | ax2.set_title(f'AAPL STOCH 14,3') 77 | ax2.legend(loc = 'right') 78 | plt.show() 79 | 80 | # TRADING STRATEGY 81 | 82 | def bb_stoch_strategy(prices, k, d, upper_bb, lower_bb): 83 | buy_price = [] 84 | sell_price = [] 85 | bb_stoch_signal = [] 86 | signal = 0 87 | 88 | for i in range(len(prices)): 89 | if k[i-1] > 30 and d[i-1] > 30 and k[i] < 30 and d[i] < 30 and prices[i] < lower_bb[i]: 90 | if signal != 1: 91 | buy_price.append(prices[i]) 92 | sell_price.append(np.nan) 93 | signal = 1 94 | bb_stoch_signal.append(signal) 95 | else: 96 | buy_price.append(np.nan) 97 | sell_price.append(np.nan) 98 | bb_stoch_signal.append(0) 99 | elif k[i-1] < 70 and d[i-1] < 70 and k[i] > 70 and d[i] > 70 and prices[i] > upper_bb[i]: 100 | if signal != -1: 101 | buy_price.append(np.nan) 102 | sell_price.append(prices[i]) 103 | signal = -1 104 | bb_stoch_signal.append(signal) 105 | else: 106 | buy_price.append(np.nan) 107 | sell_price.append(np.nan) 108 | bb_stoch_signal.append(0) 109 | else: 110 | buy_price.append(np.nan) 111 | sell_price.append(np.nan) 112 | bb_stoch_signal.append(0) 113 | 114 | sell_price[-1] = prices[-1] 115 | bb_stoch_signal[-1] = -1 116 | return buy_price, sell_price, bb_stoch_signal 117 | 118 | buy_price, sell_price, bb_stoch_signal = bb_stoch_strategy(aapl['close'], aapl['%k'], aapl['%d'], 119 | aapl['upper_bb'], aapl['lower_bb']) 120 | 121 | # PLOTTING TRADING SIGNALS 122 | 123 | ax1 = plt.subplot2grid((14,1), (0,0), rowspan = 7, colspan = 1) 124 | ax2 = plt.subplot2grid((15,1), (9,0), rowspan = 6, colspan = 1) 125 | ax1.plot(aapl['close'], linewidth = 2.5) 126 | ax1.plot(aapl['upper_bb'], label = 'UPPER BB 20', linestyle = '--', linewidth = 1, color = 'black') 127 | ax1.plot(aapl['middle_bb'], label = 'MIDDLE BB 20', linestyle = '--', linewidth = 1.2, color = 'grey') 128 | ax1.plot(aapl['lower_bb'], label = 'LOWER BB 20', linestyle = '--', linewidth = 1, color = 'black') 129 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 10, color = 'green', label = 'BUY SIGNAL') 130 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 10, color = 'r', label = 'SELL SIGNAL') 131 | ax1.set_title('AAPL BB 20') 132 | ax1.legend(loc = 'right') 133 | ax2.plot(aapl['%k'], color = 'deepskyblue', linewidth = 1.5, label = '%K') 134 | ax2.plot(aapl['%d'], color = 'orange', linewidth = 1.5, label = '%D') 135 | ax2.axhline(70, color = 'black', linewidth = 1, linestyle = '--') 136 | ax2.axhline(30, color = 'black', linewidth = 1, linestyle = '--') 137 | ax2.set_title(f'AAPL STOCH 14,3') 138 | ax2.legend() 139 | plt.show() 140 | 141 | # POSITION 142 | 143 | position = [] 144 | for i in range(len(bb_stoch_signal)): 145 | if bb_stoch_signal[i] > 1: 146 | position.append(0) 147 | else: 148 | position.append(1) 149 | 150 | for i in range(len(aapl['close'])): 151 | if bb_stoch_signal[i] == 1: 152 | position[i] = 1 153 | elif bb_stoch_signal[i] == -1: 154 | position[i] = 0 155 | else: 156 | position[i] = position[i-1] 157 | 158 | k = aapl['%k'] 159 | d = aapl['%d'] 160 | upper_bb = aapl['upper_bb'] 161 | lower_bb = aapl['lower_bb'] 162 | close_price = aapl['close'] 163 | bb_stoch_signal = pd.DataFrame(bb_stoch_signal).rename(columns = {0:'bb_stoch_signal'}).set_index(aapl.index) 164 | position = pd.DataFrame(position).rename(columns = {0:'bb_stoch_position'}).set_index(aapl.index) 165 | 166 | frames = [close_price, k, d, upper_bb, lower_bb, bb_stoch_signal, position] 167 | strategy = pd.concat(frames, join = 'inner', axis = 1) 168 | 169 | strategy.tail() 170 | 171 | rets = aapl.close.pct_change().dropna() 172 | strat_rets = strategy.bb_stoch_position[1:]*rets 173 | 174 | plt.title('Daily Returns') 175 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 176 | strat_rets.plot(color = 'r', linewidth = 1) 177 | plt.show() 178 | 179 | rets_cum = (1 + rets).cumprod() - 1 180 | strat_cum = (1 + strat_rets).cumprod() - 1 181 | 182 | plt.title('Cumulative Returns') 183 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 184 | strat_cum.plot(color = 'r', linewidth = 2) 185 | plt.show() 186 | 187 | 188 | -------------------------------------------------------------------------------- /Advanced Strategies/Stochastics_MACD.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import pandas as pd 4 | import numpy as np 5 | import requests 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2010-01-01') 25 | aapl.tail() 26 | 27 | # STOCHASTIC OSCILLATOR CALCULATION 28 | 29 | def get_stoch_osc(high, low, close, k_lookback, d_lookback): 30 | lowest_low = low.rolling(k_lookback).min() 31 | highest_high = high.rolling(k_lookback).max() 32 | k_line = ((close - lowest_low) / (highest_high - lowest_low)) * 100 33 | d_line = k_line.rolling(d_lookback).mean() 34 | return k_line, d_line 35 | 36 | aapl['%k'], aapl['%d'] = get_stoch_osc(aapl['high'], aapl['low'], aapl['close'], 14, 3) 37 | aapl.tail() 38 | 39 | # STOCHASTIC OSCILLATOR PLOT 40 | 41 | plot_data = aapl[aapl.index >= '2020-01-01'] 42 | 43 | ax1 = plt.subplot2grid((14,1), (0,0), rowspan = 7, colspan = 1) 44 | ax2 = plt.subplot2grid((15,1), (9,0), rowspan = 6, colspan = 1) 45 | ax1.plot(plot_data['close'], linewidth = 2.5) 46 | ax1.set_title('AAPL STOCK PRICES') 47 | ax2.plot(plot_data['%k'], color = 'deepskyblue', linewidth = 1.5, label = '%K') 48 | ax2.plot(plot_data['%d'], color = 'orange', linewidth = 1.5, label = '%D') 49 | ax2.axhline(70, color = 'black', linewidth = 1, linestyle = '--') 50 | ax2.axhline(30, color = 'black', linewidth = 1, linestyle = '--') 51 | ax2.set_title(f'AAPL STOCH 14,3') 52 | ax2.legend(loc = 'right') 53 | plt.show() 54 | 55 | # MACD CALCULATION 56 | 57 | def get_macd(price, slow, fast, smooth): 58 | exp1 = price.ewm(span = fast, adjust = False).mean() 59 | exp2 = price.ewm(span = slow, adjust = False).mean() 60 | macd = pd.DataFrame(exp1 - exp2).rename(columns = {'close':'macd'}) 61 | signal = pd.DataFrame(macd.ewm(span = smooth, adjust = False).mean()).rename(columns = {'macd':'signal'}) 62 | hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'}) 63 | return macd, signal, hist 64 | 65 | aapl['macd'] = get_macd(aapl['close'], 26, 12, 9)[0] 66 | aapl['macd_signal'] = get_macd(aapl['close'], 26, 12, 9)[1] 67 | aapl['macd_hist'] = get_macd(aapl['close'], 26, 12, 9)[2] 68 | aapl = aapl.dropna() 69 | aapl.tail() 70 | 71 | # MACD PLOT 72 | 73 | plot_data = aapl[aapl.index >= '2020-01-01'] 74 | 75 | def plot_macd(prices, macd, signal, hist): 76 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 77 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 78 | 79 | ax1.plot(prices, linewidth = 2.5) 80 | ax1.set_title('AAPL STOCK PRICES') 81 | ax2.plot(macd, color = 'grey', linewidth = 1.5, label = 'MACD') 82 | ax2.plot(signal, color = 'skyblue', linewidth = 1.5, label = 'SIGNAL') 83 | ax2.set_title('AAPL MACD 26,12,9') 84 | 85 | for i in range(len(prices)): 86 | if str(hist[i])[0] == '-': 87 | ax2.bar(prices.index[i], hist[i], color = '#ef5350') 88 | else: 89 | ax2.bar(prices.index[i], hist[i], color = '#26a69a') 90 | 91 | plt.legend(loc = 'lower right') 92 | 93 | plot_macd(plot_data['close'], plot_data['macd'], plot_data['macd_signal'], plot_data['macd_hist']) 94 | 95 | # TRADING STRATEGY 96 | 97 | def implement_stoch_macd_strategy(prices, k, d, macd, macd_signal): 98 | buy_price = [] 99 | sell_price = [] 100 | stoch_macd_signal = [] 101 | signal = 0 102 | 103 | for i in range(len(prices)): 104 | if k[i] < 30 and d[i] < 30 and macd[i] < -2 and macd_signal[i] < -2: 105 | if signal != 1: 106 | buy_price.append(prices[i]) 107 | sell_price.append(np.nan) 108 | signal = 1 109 | stoch_macd_signal.append(signal) 110 | else: 111 | buy_price.append(np.nan) 112 | sell_price.append(np.nan) 113 | stoch_macd_signal.append(0) 114 | 115 | elif k[i] > 70 and d[i] > 70 and macd[i] > 2 and macd_signal[i] > 2: 116 | if signal != -1 and signal != 0: 117 | buy_price.append(np.nan) 118 | sell_price.append(prices[i]) 119 | signal = -1 120 | stoch_macd_signal.append(signal) 121 | else: 122 | buy_price.append(np.nan) 123 | sell_price.append(np.nan) 124 | stoch_macd_signal.append(0) 125 | 126 | else: 127 | buy_price.append(np.nan) 128 | sell_price.append(np.nan) 129 | stoch_macd_signal.append(0) 130 | 131 | return buy_price, sell_price, stoch_macd_signal 132 | 133 | buy_price, sell_price, stoch_macd_signal = implement_stoch_macd_strategy(aapl['close'], aapl['%k'], aapl['%d'], aapl['macd'], aapl['macd_signal']) 134 | 135 | # POSITION 136 | 137 | position = [] 138 | for i in range(len(stoch_macd_signal)): 139 | if stoch_macd_signal[i] > 1: 140 | position.append(0) 141 | else: 142 | position.append(1) 143 | 144 | for i in range(len(aapl['close'])): 145 | if stoch_macd_signal[i] == 1: 146 | position[i] = 1 147 | elif stoch_macd_signal[i] == -1: 148 | position[i] = 0 149 | else: 150 | position[i] = position[i-1] 151 | 152 | close_price = aapl['close'] 153 | k_line = aapl['%k'] 154 | d_line = aapl['%d'] 155 | macd_line = aapl['macd'] 156 | signal_line = aapl['macd_signal'] 157 | stoch_macd_signal = pd.DataFrame(stoch_macd_signal).rename(columns = {0:'stoch_macd_signal'}).set_index(aapl.index) 158 | position = pd.DataFrame(position).rename(columns = {0:'stoch_macd_position'}).set_index(aapl.index) 159 | 160 | frames = [close_price, k_line, d_line, macd_line, signal_line, stoch_macd_signal, position] 161 | strategy = pd.concat(frames, join = 'inner', axis = 1) 162 | 163 | strategy.head() 164 | 165 | rets = aapl.close.pct_change().dropna() 166 | strat_rets = strategy.stoch_macd_position[1:]*rets 167 | 168 | plt.title('Daily Returns') 169 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 170 | strat_rets.plot(color = 'r', linewidth = 1) 171 | plt.show() 172 | 173 | rets_cum = (1 + rets).cumprod() - 1 174 | strat_cum = (1 + strat_rets).cumprod() - 1 175 | 176 | plt.title('Cumulative Returns') 177 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 178 | strat_cum.plot(color = 'r', linewidth = 2) 179 | plt.show() 180 | -------------------------------------------------------------------------------- /Advanced Strategies/Williams%R_MACD.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import numpy as np 4 | import pandas as pd 5 | import matplotlib.pyplot as plt 6 | import requests 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2010-01-01') 25 | aapl.tail() 26 | 27 | # WILLIAMS %R CALCULATION 28 | 29 | def get_wr(high, low, close, lookback): 30 | highh = high.rolling(lookback).max() 31 | lowl = low.rolling(lookback).min() 32 | wr = -100 * ((highh - close) / (highh - lowl)) 33 | return wr 34 | 35 | aapl['wr_14'] = get_wr(aapl['high'], aapl['low'], aapl['close'], 14) 36 | aapl.tail() 37 | 38 | # WILLIAMS %R PLOT 39 | 40 | plot_data = aapl[aapl.index >= '2020-01-01'] 41 | 42 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 43 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 44 | ax1.plot(plot_data['close'], linewidth = 2) 45 | ax1.set_title('AAPL CLOSING PRICE') 46 | ax2.plot(plot_data['wr_14'], color = 'orange', linewidth = 2) 47 | ax2.axhline(-20, linewidth = 1.5, linestyle = '--', color = 'grey') 48 | ax2.axhline(-80, linewidth = 1.5, linestyle = '--', color = 'grey') 49 | ax2.set_title('AAPL WILLIAMS %R 14') 50 | plt.show() 51 | 52 | # MACD CALCULATION 53 | 54 | def get_macd(price, slow, fast, smooth): 55 | exp1 = price.ewm(span = fast, adjust = False).mean() 56 | exp2 = price.ewm(span = slow, adjust = False).mean() 57 | macd = pd.DataFrame(exp1 - exp2).rename(columns = {'close':'macd'}) 58 | signal = pd.DataFrame(macd.ewm(span = smooth, adjust = False).mean()).rename(columns = {'macd':'signal'}) 59 | hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'}) 60 | return macd, signal, hist 61 | 62 | aapl['macd'] = get_macd(aapl['close'], 26, 12, 9)[0] 63 | aapl['macd_signal'] = get_macd(aapl['close'], 26, 12, 9)[1] 64 | aapl['macd_hist'] = get_macd(aapl['close'], 26, 12, 9)[2] 65 | aapl = aapl.dropna() 66 | aapl.tail() 67 | 68 | # MACD PLOT 69 | 70 | plot_data = aapl[aapl.index >= '2020-01-01'] 71 | 72 | def plot_macd(prices, macd, signal, hist): 73 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 74 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 75 | 76 | ax1.plot(prices) 77 | ax1.set_title('AAPL STOCK PRICES') 78 | ax2.plot(macd, color = 'grey', linewidth = 1.5, label = 'MACD') 79 | ax2.plot(signal, color = 'skyblue', linewidth = 1.5, label = 'SIGNAL') 80 | ax2.set_title('AAPL MACD 26,12,9') 81 | 82 | for i in range(len(prices)): 83 | if str(hist[i])[0] == '-': 84 | ax2.bar(prices.index[i], hist[i], color = '#ef5350') 85 | else: 86 | ax2.bar(prices.index[i], hist[i], color = '#26a69a') 87 | 88 | plt.legend(loc = 'lower right') 89 | 90 | plot_macd(plot_data['close'], plot_data['macd'], plot_data['macd_signal'], plot_data['macd_hist']) 91 | 92 | # TRADING STRATEGY 93 | 94 | def implement_wr_macd_strategy(prices, wr, macd, macd_signal): 95 | buy_price = [] 96 | sell_price = [] 97 | wr_macd_signal = [] 98 | signal = 0 99 | 100 | for i in range(len(wr)): 101 | if wr[i-1] > -50 and wr[i] < -50 and macd[i] > macd_signal[i]: 102 | if signal != 1: 103 | buy_price.append(prices[i]) 104 | sell_price.append(np.nan) 105 | signal = 1 106 | wr_macd_signal.append(signal) 107 | else: 108 | buy_price.append(np.nan) 109 | sell_price.append(np.nan) 110 | wr_macd_signal.append(0) 111 | 112 | elif wr[i-1] < -50 and wr[i] > -50 and macd[i] < macd_signal[i]: 113 | if signal != -1: 114 | buy_price.append(np.nan) 115 | sell_price.append(prices[i]) 116 | signal = -1 117 | wr_macd_signal.append(signal) 118 | else: 119 | buy_price.append(np.nan) 120 | sell_price.append(np.nan) 121 | wr_macd_signal.append(0) 122 | 123 | else: 124 | buy_price.append(np.nan) 125 | sell_price.append(np.nan) 126 | wr_macd_signal.append(0) 127 | 128 | return buy_price, sell_price, wr_macd_signal 129 | 130 | buy_price, sell_price, wr_macd_signal = implement_wr_macd_strategy(aapl['close'], aapl['wr_14'], aapl['macd'], aapl['macd_signal']) 131 | 132 | # POSITION 133 | 134 | position = [] 135 | for i in range(len(wr_macd_signal)): 136 | if wr_macd_signal[i] > 1: 137 | position.append(0) 138 | else: 139 | position.append(1) 140 | 141 | for i in range(len(aapl['close'])): 142 | if wr_macd_signal[i] == 1: 143 | position[i] = 1 144 | elif wr_macd_signal[i] == -1: 145 | position[i] = 0 146 | else: 147 | position[i] = position[i-1] 148 | 149 | close_price = aapl['close'] 150 | wr = aapl['wr_14'] 151 | macd_line = aapl['macd'] 152 | signal_line = aapl['macd_signal'] 153 | wr_macd_signal = pd.DataFrame(wr_macd_signal).rename(columns = {0:'wr_macd_signal'}).set_index(aapl.index) 154 | position = pd.DataFrame(position).rename(columns = {0:'wr_macd_position'}).set_index(aapl.index) 155 | 156 | frames = [close_price, wr, macd_line, signal_line, wr_macd_signal, position] 157 | strategy = pd.concat(frames, join = 'inner', axis = 1) 158 | 159 | strategy.head() 160 | 161 | rets = aapl.close.pct_change().dropna() 162 | strat_rets = strategy.wr_macd_position[1:]*rets 163 | 164 | plt.title('Daily Returns') 165 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 166 | strat_rets.plot(color = 'r', linewidth = 1) 167 | plt.show() 168 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Nikhil Adithyan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Momentum/Awesome_Oscillator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import requests 3 | import numpy as np 4 | import matplotlib.pyplot as plt 5 | from math import floor 6 | from termcolor import colored as cl 7 | 8 | plt.rcParams['figure.figsize'] = (20, 10) 9 | plt.style.use('fivethirtyeight') 10 | 11 | # EXTRACTING STOCK DATA 12 | 13 | def get_historical_data(symbol, start_date): 14 | api_key = 'YOUR API KEY' 15 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 16 | raw_df = requests.get(api_url).json() 17 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 18 | df = df[df.index >= start_date] 19 | df.index = pd.to_datetime(df.index) 20 | return df 21 | 22 | aapl = get_historical_data('AAPL', '2020-01-01') 23 | aapl 24 | 25 | def sma(price, period): 26 | sma = price.rolling(period).mean() 27 | return sma 28 | 29 | def ao(price, period1, period2): 30 | median = price.rolling(2).median() 31 | short = sma(median, period1) 32 | long = sma(median, period2) 33 | ao = short - long 34 | ao_df = pd.DataFrame(ao).rename(columns = {'close':'ao'}) 35 | return ao_df 36 | 37 | aapl['ao'] = ao(aapl['close'], 5, 34) 38 | aapl = aapl.dropna() 39 | aapl.tail() 40 | 41 | ax1 = plt.subplot2grid((10,1), (0,0), rowspan = 5, colspan = 1) 42 | ax2 = plt.subplot2grid((10,1), (6,0), rowspan = 4, colspan = 1) 43 | ax1.plot(aapl['close']) 44 | ax1.set_title('BITCOIN CLOSING PRICE') 45 | for i in range(len(aapl)): 46 | if aapl['ao'][i-1] > aapl['ao'][i]: 47 | ax2.bar(aapl.index[i], aapl['ao'][i], color = '#f44336') 48 | else: 49 | ax2.bar(aapl.index[i], aapl['ao'][i], color = '#26a69a') 50 | ax2.set_title('BITCOIN AWESOME OSCILLATOR 5,34') 51 | plt.show() 52 | 53 | def implement_ao_crossover(price, ao): 54 | buy_price = [] 55 | sell_price = [] 56 | ao_signal = [] 57 | signal = 0 58 | 59 | for i in range(len(ao)): 60 | if ao[i] > 0 and ao[i-1] < 0: 61 | if signal != 1: 62 | buy_price.append(price[i]) 63 | sell_price.append(np.nan) 64 | signal = 1 65 | ao_signal.append(signal) 66 | else: 67 | buy_price.append(np.nan) 68 | sell_price.append(np.nan) 69 | ao_signal.append(0) 70 | elif ao[i] < 0 and ao[i-1] > 0: 71 | if signal != -1: 72 | buy_price.append(np.nan) 73 | sell_price.append(price[i]) 74 | signal = -1 75 | ao_signal.append(signal) 76 | else: 77 | buy_price.append(np.nan) 78 | sell_price.append(np.nan) 79 | ao_signal.append(0) 80 | else: 81 | buy_price.append(np.nan) 82 | sell_price.append(np.nan) 83 | ao_signal.append(0) 84 | return buy_price, sell_price, ao_signal 85 | 86 | buy_price, sell_price, ao_signal = implement_ao_crossover(aapl['close'], aapl['ao']) 87 | 88 | ax1 = plt.subplot2grid((10,1), (0,0), rowspan = 5, colspan = 1) 89 | ax2 = plt.subplot2grid((10,1), (6,0), rowspan = 4, colspan = 1) 90 | ax1.plot(aapl['close'], label = 'aapl', color = 'skyblue') 91 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, color = '#26a69a', linewidth = 0, label = 'BUY SIGNAL') 92 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, color = '#f44336', linewidth = 0, label = 'SELL SIGNAL') 93 | ax1.legend() 94 | ax1.set_title('BITCOIN CLOSING PRICE') 95 | for i in range(len(aapl)): 96 | if aapl['ao'][i-1] > aapl['ao'][i]: 97 | ax2.bar(aapl.index[i], aapl['ao'][i], color = '#f44336') 98 | else: 99 | ax2.bar(aapl.index[i], aapl['ao'][i], color = '#26a69a') 100 | ax2.set_title('BITCOIN AWESOME OSCILLATOR 5,34') 101 | plt.show() 102 | 103 | position = [] 104 | for i in range(len(ao_signal)): 105 | if ao_signal[i] > 1: 106 | position.append(0) 107 | else: 108 | position.append(1) 109 | 110 | for i in range(len(aapl['close'])): 111 | if ao_signal[i] == 1: 112 | position[i] = 1 113 | elif ao_signal[i] == -1: 114 | position[i] = 0 115 | else: 116 | position[i] = position[i-1] 117 | 118 | ao = aapl['ao'] 119 | close_price = aapl['close'] 120 | ao_signal = pd.DataFrame(ao_signal).rename(columns = {0:'ao_signal'}).set_index(aapl.index) 121 | position = pd.DataFrame(position).rename(columns = {0:'ao_position'}).set_index(aapl.index) 122 | 123 | frames = [close_price, ao, ao_signal, position] 124 | strategy = pd.concat(frames, join = 'inner', axis = 1) 125 | 126 | strategy 127 | 128 | rets = aapl.close.pct_change().dropna() 129 | strat_rets = strategy.ao_position[1:]*rets 130 | 131 | plt.title('Daily Returns') 132 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 133 | strat_rets.plot(color = 'r', linewidth = 1) 134 | plt.show() 135 | 136 | rets_cum = (1 + rets).cumprod() - 1 137 | strat_cum = (1 + strat_rets).cumprod() - 1 138 | 139 | plt.title('Cumulative Returns') 140 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 141 | strat_cum.plot(color = 'r', linewidth = 2) 142 | plt.show() 143 | -------------------------------------------------------------------------------- /Momentum/Commodity_Channel_Index.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import requests 3 | import pandas_datareader as web 4 | import datetime as dt 5 | import numpy as np 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.rcParams['figure.figsize'] = (20, 10) 11 | plt.style.use('fivethirtyeight') 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2020-01-01') 25 | aapl 26 | 27 | def get_cci(symbol, n, start_date): 28 | api_key = open(r'api_key.txt') 29 | url = f'https://www.alphavantage.co/query?function=CCI&symbol={symbol}&interval=daily&time_period={n}&apikey={api_key}' 30 | raw = requests.get(url).json() 31 | df = pd.DataFrame(raw['Technical Analysis: CCI']).T.iloc[::-1] 32 | df = df[df.index >= start_date] 33 | df.index = pd.to_datetime(df.index) 34 | df = df.astype(float) 35 | return df 36 | 37 | aapl['cci'] = get_cci('aapl', 20, '2020-01-01') 38 | aapl = aapl.dropna() 39 | aapl.tail() 40 | 41 | ax1 = plt.subplot2grid((10,1), (0,0), rowspan = 5, colspan = 1) 42 | ax2 = plt.subplot2grid((10,1), (6,0), rowspan = 4, colspan = 1) 43 | ax1.plot(aapl['close']) 44 | ax1.set_title('FACEBOOK SHARE PRICE') 45 | ax2.plot(aapl['cci'], color = 'orange') 46 | ax2.set_title('FACEBOOK CCI 20') 47 | ax2.axhline(150, linestyle = '--', linewidth = 1, color = 'black') 48 | ax2.axhline(-150, linestyle = '--', linewidth = 1, color = 'black') 49 | plt.show() 50 | 51 | def implement_cci_strategy(prices, cci): 52 | buy_price = [] 53 | sell_price = [] 54 | cci_signal = [] 55 | signal = 0 56 | 57 | lower_band = (-150) 58 | upper_band = 150 59 | 60 | for i in range(len(prices)): 61 | if cci[i-1] > lower_band and cci[i] < lower_band: 62 | if signal != 1: 63 | buy_price.append(prices[i]) 64 | sell_price.append(np.nan) 65 | signal = 1 66 | cci_signal.append(signal) 67 | else: 68 | buy_price.append(np.nan) 69 | sell_price.append(np.nan) 70 | cci_signal.append(0) 71 | 72 | elif cci[i-1] < upper_band and cci[i] > upper_band: 73 | if signal != -1: 74 | buy_price.append(np.nan) 75 | sell_price.append(prices[i]) 76 | signal = -1 77 | cci_signal.append(signal) 78 | else: 79 | buy_price.append(np.nan) 80 | sell_price.append(np.nan) 81 | cci_signal.append(0) 82 | 83 | else: 84 | buy_price.append(np.nan) 85 | sell_price.append(np.nan) 86 | cci_signal.append(0) 87 | 88 | return buy_price, sell_price, cci_signal 89 | 90 | buy_price, sell_price, cci_signal = implement_cci_strategy(aapl['close'], aapl['cci']) 91 | 92 | ax1 = plt.subplot2grid((10,1), (0,0), rowspan = 5, colspan = 1) 93 | ax2 = plt.subplot2grid((10,1), (6,0), rowspan = 4, colspan = 1) 94 | ax1.plot(aapl['close'], color = 'skyblue', label = 'aapl') 95 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, linewidth = 0, label = 'BUY SIGNAL', color = 'green') 96 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, linewidth = 0, label = 'SELL SIGNAL', color = 'r') 97 | ax1.set_title('FACEBOOK SHARE PRICE') 98 | ax1.legend() 99 | ax2.plot(aapl['cci'], color = 'orange') 100 | ax2.set_title('FACEBOOK CCI 20') 101 | ax2.axhline(150, linestyle = '--', linewidth = 1, color = 'black') 102 | ax2.axhline(-150, linestyle = '--', linewidth = 1, color = 'black') 103 | plt.show() 104 | 105 | position = [] 106 | for i in range(len(cci_signal)): 107 | if cci_signal[i] > 1: 108 | position.append(0) 109 | else: 110 | position.append(1) 111 | 112 | for i in range(len(aapl['close'])): 113 | if cci_signal[i] == 1: 114 | position[i] = 1 115 | elif cci_signal[i] == -1: 116 | position[i] = 0 117 | else: 118 | position[i] = position[i-1] 119 | 120 | cci = aapl['cci'] 121 | close_price = aapl['close'] 122 | cci_signal = pd.DataFrame(cci_signal).rename(columns = {0:'cci_signal'}).set_index(aapl.index) 123 | position = pd.DataFrame(position).rename(columns = {0:'cci_position'}).set_index(aapl.index) 124 | 125 | frames = [close_price, cci, cci_signal, position] 126 | strategy = pd.concat(frames, join = 'inner', axis = 1) 127 | 128 | strategy.head() 129 | 130 | rets = aapl.close.pct_change().dropna() 131 | strat_rets = strategy.cci_position[1:]*rets 132 | 133 | plt.title('Daily Returns') 134 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 135 | strat_rets.plot(color = 'r', linewidth = 1) 136 | plt.show() 137 | -------------------------------------------------------------------------------- /Momentum/Coppock_Curve.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import requests 4 | import numpy as np 5 | import pandas as pd 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2020-01-01') 25 | aapl.tail() 26 | 27 | # COPPOCK CURVE CALCULATION 28 | 29 | def wma(data, lookback): 30 | weights = np.arange(1, lookback + 1) 31 | val = data.rolling(lookback) 32 | wma = val.apply(lambda prices: np.dot(prices, weights) / weights.sum(), raw = True) 33 | return wma 34 | 35 | def get_roc(close, n): 36 | difference = close.diff(n) 37 | nprev_values = close.shift(n) 38 | roc = (difference / nprev_values) * 100 39 | return roc 40 | 41 | def get_cc(data, roc1_n, roc2_n, wma_lookback): 42 | longROC = get_roc(data, roc1_n) 43 | shortROC = get_roc(data, roc2_n) 44 | ROC = longROC + shortROC 45 | cc = wma(ROC, wma_lookback) 46 | return cc 47 | 48 | aapl['cc'] = get_cc(aapl['close'], 14, 11, 10) 49 | aapl = aapl.dropna() 50 | aapl.tail() 51 | 52 | # COPPOCK CURVE PLOT 53 | 54 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 55 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 6, colspan = 1) 56 | ax1.plot(aapl['close'], linewidth = 2.5) 57 | ax1.set_title('AAPL CLOSING PRICES') 58 | for i in range(len(aapl)): 59 | if aapl.iloc[i, 5] >= 0: 60 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#009688') 61 | else: 62 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#f44336') 63 | ax2.set_title('AAPL COPPOCK CURVE') 64 | plt.show() 65 | 66 | # COPPOCK CURVE STRATEGY 67 | 68 | def implement_cc_strategy(prices, cc): 69 | buy_price = [] 70 | sell_price = [] 71 | cc_signal = [] 72 | signal = 0 73 | 74 | for i in range(len(prices)): 75 | if cc[i-4] < 0 and cc[i-3] < 0 and cc[i-2] < 0 and cc[i-1] < 0 and cc[i] > 0: 76 | if signal != 1: 77 | buy_price.append(prices[i]) 78 | sell_price.append(np.nan) 79 | signal = 1 80 | cc_signal.append(signal) 81 | else: 82 | buy_price.append(np.nan) 83 | sell_price.append(np.nan) 84 | cc_signal.append(0) 85 | elif cc[i-4] > 0 and cc[i-3] > 0 and cc[i-2] > 0 and cc[i-1] > 0 and cc[i] < 0: 86 | if signal != -1: 87 | buy_price.append(np.nan) 88 | sell_price.append(prices[i]) 89 | signal = -1 90 | cc_signal.append(signal) 91 | else: 92 | buy_price.append(np.nan) 93 | sell_price.append(np.nan) 94 | cc_signal.append(0) 95 | else: 96 | buy_price.append(np.nan) 97 | sell_price.append(np.nan) 98 | cc_signal.append(0) 99 | 100 | return buy_price, sell_price, cc_signal 101 | 102 | buy_price, sell_price, cc_signal = implement_cc_strategy(aapl['close'], aapl['cc']) 103 | 104 | # COPPOCK CURVE TRADING SIGNAL PLOT 105 | 106 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 107 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 6, colspan = 1) 108 | ax1.plot(aapl['close'], linewidth = 2, label = 'AAPL') 109 | ax1.plot(aapl.index, buy_price, marker = '^', color = 'green', markersize = 12, linewidth = 0, label = 'BUY SIGNAL') 110 | ax1.plot(aapl.index, sell_price, marker = 'v', color = 'r', markersize = 12, linewidth = 0, label = 'SELL SIGNAL') 111 | ax1.legend() 112 | ax1.set_title('AAPL CC TRADING SIGNALS') 113 | for i in range(len(aapl)): 114 | if aapl.iloc[i, 5] >= 0: 115 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#009688') 116 | else: 117 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#f44336') 118 | ax2.set_title('AAPL COPPOCK CURVE') 119 | plt.show() 120 | 121 | # STOCK POSITION 122 | 123 | position = [] 124 | for i in range(len(cc_signal)): 125 | if cc_signal[i] > 1: 126 | position.append(0) 127 | else: 128 | position.append(1) 129 | 130 | for i in range(len(aapl['close'])): 131 | if cc_signal[i] == 1: 132 | position[i] = 1 133 | elif cc_signal[i] == -1: 134 | position[i] = 0 135 | else: 136 | position[i] = position[i-1] 137 | 138 | close_price = aapl['close'] 139 | cc = aapl['cc'] 140 | cc_signal = pd.DataFrame(cc_signal).rename(columns = {0:'cc_signal'}).set_index(aapl.index) 141 | position = pd.DataFrame(position).rename(columns = {0:'cc_position'}).set_index(aapl.index) 142 | 143 | frames = [close_price, cc, cc_signal, position] 144 | strategy = pd.concat(frames, join = 'inner', axis = 1) 145 | 146 | strategy 147 | 148 | rets = aapl.close.pct_change().dropna() 149 | strat_rets = strategy.cc_position[1:]*rets 150 | 151 | plt.title('Daily Returns') 152 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 153 | strat_rets.plot(color = 'r', linewidth = 1) 154 | plt.show() 155 | 156 | rets_cum = (1 + rets).cumprod() - 1 157 | strat_cum = (1 + strat_rets).cumprod() - 1 158 | 159 | plt.title('Cumulative Returns') 160 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 161 | strat_cum.plot(color = 'r', linewidth = 2) 162 | plt.show() 163 | -------------------------------------------------------------------------------- /Momentum/Disparity_Index.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import numpy as np 4 | import requests 5 | import pandas as pd 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('aapl', '2020-01-01') 25 | aapl.tail() 26 | 27 | # DISPARITY INDEX CALCULATION 28 | 29 | def get_di(data, lookback): 30 | ma = data.rolling(lookback).mean() 31 | di = ((data - ma) / ma) * 100 32 | return di 33 | 34 | aapl['di_14'] = get_di(aapl['close'], 14) 35 | aapl = aapl.dropna() 36 | aapl.tail() 37 | 38 | # DISPARITY INDEX PLOT 39 | 40 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 41 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 42 | ax1.plot(aapl['close'], linewidth = 2, color = '#1976d2') 43 | ax1.set_title('AAPL CLOSING PRICES') 44 | for i in range(len(aapl)): 45 | if aapl.iloc[i, 5] >= 0: 46 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#26a69a') 47 | else: 48 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#ef5350') 49 | ax2.set_title('AAPL DISPARITY INDEX 14') 50 | plt.show() 51 | 52 | # DISPARITY INDEX STRATEGY 53 | 54 | def implement_di_strategy(prices, di): 55 | buy_price = [] 56 | sell_price = [] 57 | di_signal = [] 58 | signal = 0 59 | 60 | for i in range(len(prices)): 61 | if di[i-4] < 0 and di[i-3] < 0 and di[i-2] < 0 and di[i-1] < 0 and di[i] > 0: 62 | if signal != 1: 63 | buy_price.append(prices[i]) 64 | sell_price.append(np.nan) 65 | signal = 1 66 | di_signal.append(signal) 67 | else: 68 | buy_price.append(np.nan) 69 | sell_price.append(np.nan) 70 | di_signal.append(0) 71 | elif di[i-4] > 0 and di[i-3] > 0 and di[i-2] > 0 and di[i-1] > 0 and di[i] < 0: 72 | if signal != -1: 73 | buy_price.append(np.nan) 74 | sell_price.append(prices[i]) 75 | signal = -1 76 | di_signal.append(signal) 77 | else: 78 | buy_price.append(np.nan) 79 | sell_price.append(np.nan) 80 | di_signal.append(0) 81 | else: 82 | buy_price.append(np.nan) 83 | sell_price.append(np.nan) 84 | di_signal.append(0) 85 | 86 | return buy_price, sell_price, di_signal 87 | 88 | buy_price, sell_price, di_signal = implement_di_strategy(aapl['close'], aapl['di_14']) 89 | 90 | # DISPARITY INDEX TRADING SIGNALS PLOT 91 | 92 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 93 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 94 | ax1.plot(aapl['close'], linewidth = 2, color = '#1976d2') 95 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, linewidth = 0, label = 'BUY SIGNAL', color = 'green') 96 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, linewidth = 0, label = 'SELL SIGNAL', color = 'r') 97 | ax1.legend() 98 | ax1.set_title('AAPL CLOSING PRICES') 99 | for i in range(len(aapl)): 100 | if aapl.iloc[i, 5] >= 0: 101 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#26a69a') 102 | else: 103 | ax2.bar(aapl.iloc[i].name, aapl.iloc[i, 5], color = '#ef5350') 104 | ax2.set_title('AAPL DISPARITY INDEX 14') 105 | plt.show() 106 | 107 | # STOCK POSITION 108 | 109 | position = [] 110 | for i in range(len(di_signal)): 111 | if di_signal[i] > 1: 112 | position.append(0) 113 | else: 114 | position.append(1) 115 | 116 | for i in range(len(aapl['close'])): 117 | if di_signal[i] == 1: 118 | position[i] = 1 119 | elif di_signal[i] == -1: 120 | position[i] = 0 121 | else: 122 | position[i] = position[i-1] 123 | 124 | close_price = aapl['close'] 125 | di = aapl['di_14'] 126 | di_signal = pd.DataFrame(di_signal).rename(columns = {0:'di_signal'}).set_index(aapl.index) 127 | position = pd.DataFrame(position).rename(columns = {0:'di_position'}).set_index(aapl.index) 128 | 129 | frames = [close_price, di, di_signal, position] 130 | strategy = pd.concat(frames, join = 'inner', axis = 1) 131 | 132 | strategy.head() 133 | 134 | rets = aapl.close.pct_change().dropna() 135 | strat_rets = strategy.di_position[1:]*rets 136 | 137 | plt.title('Daily Returns') 138 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 139 | strat_rets.plot(color = 'r', linewidth = 1) 140 | plt.show() 141 | 142 | rets_cum = (1 + rets).cumprod() - 1 143 | strat_cum = (1 + strat_rets).cumprod() - 1 144 | 145 | plt.title('Cumulative Returns') 146 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 147 | strat_cum.plot(color = 'r', linewidth = 2) 148 | plt.show() 149 | -------------------------------------------------------------------------------- /Momentum/Know_Sure_Thing.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import pandas as pd 4 | import numpy as np 5 | import requests 6 | import matplotlib.pyplot as plt 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2019-01-01') 25 | aapl 26 | 27 | # ROC CALCULATION 28 | 29 | def get_roc(close, n): 30 | difference = close.diff(n) 31 | nprev_values = close.shift(n) 32 | roc = (difference / nprev_values) * 100 33 | return roc 34 | 35 | # KST CALCULATION 36 | 37 | def get_kst(close, sma1, sma2, sma3, sma4, roc1, roc2, roc3, roc4, signal): 38 | rcma1 = get_roc(close, roc1).rolling(sma1).mean() 39 | rcma2 = get_roc(close, roc2).rolling(sma2).mean() 40 | rcma3 = get_roc(close, roc3).rolling(sma3).mean() 41 | rcma4 = get_roc(close, roc4).rolling(sma4).mean() 42 | kst = (rcma1 * 1) + (rcma2 * 2) + (rcma3 * 3) + (rcma4 * 4) 43 | signal = kst.rolling(signal).mean() 44 | return kst, signal 45 | 46 | aapl['kst'], aapl['signal_line'] = get_kst(aapl['close'], 10, 10, 10, 15, 10, 15, 20, 30, 9) 47 | aapl = aapl[aapl.index >= '2020-01-01'] 48 | aapl.tail() 49 | 50 | # KST INDICATOR PLOT 51 | 52 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 53 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 54 | ax1.plot(aapl['close'], linewidth = 2.5) 55 | ax1.set_title('aapl CLOSING PRICES') 56 | ax2.plot(aapl['kst'], linewidth = 2, label = 'KST', color = 'orange') 57 | ax2.plot(aapl['signal_line'], linewidth = 2, label = 'SIGNAL', color = 'mediumorchid') 58 | ax2.legend() 59 | ax2.set_title('aapl KST') 60 | plt.show() 61 | 62 | # KST CROSSOVER TRADING STRATEGY 63 | 64 | def implement_kst_strategy(prices, kst_line, signal_line): 65 | buy_price = [] 66 | sell_price = [] 67 | kst_signal = [] 68 | signal = 0 69 | 70 | for i in range(len(kst_line)): 71 | 72 | if kst_line[i-1] < signal_line[i-1] and kst_line[i] > signal_line[i]: 73 | if signal != 1: 74 | buy_price.append(prices[i]) 75 | sell_price.append(np.nan) 76 | signal = 1 77 | kst_signal.append(signal) 78 | else: 79 | buy_price.append(np.nan) 80 | sell_price.append(np.nan) 81 | kst_signal.append(0) 82 | 83 | elif kst_line[i-1] > signal_line[i-1] and kst_line[i] < signal_line[i]: 84 | if signal != -1: 85 | buy_price.append(np.nan) 86 | sell_price.append(prices[i]) 87 | signal = -1 88 | kst_signal.append(signal) 89 | else: 90 | buy_price.append(np.nan) 91 | sell_price.append(np.nan) 92 | kst_signal.append(0) 93 | 94 | else: 95 | buy_price.append(np.nan) 96 | sell_price.append(np.nan) 97 | kst_signal.append(0) 98 | 99 | return buy_price, sell_price, kst_signal 100 | 101 | buy_price, sell_price, kst_signal = implement_kst_strategy(aapl['close'], aapl['kst'], aapl['signal_line']) 102 | 103 | # TRADING SIGNALS PLOT 104 | 105 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 106 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 107 | ax1.plot(aapl['close'], linewidth = 2, label = 'aapl') 108 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, linewidth = 0, color = 'green', label = 'BUY SIGNAL') 109 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, linewidth = 0, color = 'r', label = 'SELL SIGNAL') 110 | ax1.legend() 111 | ax1.set_title('aapl KST TRADING SIGNALS') 112 | ax2.plot(aapl['kst'], linewidth = 2, label = 'KST', color = 'orange') 113 | ax2.plot(aapl['signal_line'], linewidth = 2, label = 'SIGNAL', color = 'mediumorchid') 114 | ax2.legend() 115 | ax2.set_title('aapl KST') 116 | plt.show() 117 | 118 | # STOCK POSITION 119 | 120 | position = [] 121 | for i in range(len(kst_signal)): 122 | if kst_signal[i] > 1: 123 | position.append(0) 124 | else: 125 | position.append(1) 126 | 127 | for i in range(len(aapl['close'])): 128 | if kst_signal[i] == 1: 129 | position[i] = 1 130 | elif kst_signal[i] == -1: 131 | position[i] = 0 132 | else: 133 | position[i] = position[i-1] 134 | 135 | close_price = aapl['close'] 136 | kst = aapl['kst'] 137 | signal_line = aapl['signal_line'] 138 | kst_signal = pd.DataFrame(kst_signal).rename(columns = {0:'kst_signal'}).set_index(aapl.index) 139 | position = pd.DataFrame(position).rename(columns = {0:'kst_position'}).set_index(aapl.index) 140 | 141 | frames = [close_price, kst, signal_line, kst_signal, position] 142 | strategy = pd.concat(frames, join = 'inner', axis = 1) 143 | 144 | strategy 145 | 146 | rets = aapl.close.pct_change().dropna() 147 | strat_rets = strategy.kst_position[1:]*rets 148 | 149 | plt.title('Daily Returns') 150 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 151 | strat_rets.plot(color = 'r', linewidth = 1) 152 | plt.show() 153 | 154 | rets_cum = (1 + rets).cumprod() - 1 155 | strat_cum = (1 + strat_rets).cumprod() - 1 156 | 157 | plt.title('Cumulative Returns') 158 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 159 | strat_cum.plot(color = 'r', linewidth = 2) 160 | plt.show() 161 | -------------------------------------------------------------------------------- /Momentum/MACD.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import pandas as pd 3 | import numpy as np 4 | from math import floor 5 | from termcolor import colored as cl 6 | import matplotlib.pyplot as plt 7 | 8 | plt.rcParams['figure.figsize'] = (20, 10) 9 | plt.style.use('fivethirtyeight') 10 | 11 | # EXTRACTING STOCK DATA 12 | 13 | def get_historical_data(symbol, start_date): 14 | api_key = 'YOUR API KEY' 15 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 16 | raw_df = requests.get(api_url).json() 17 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 18 | df = df[df.index >= start_date] 19 | df.index = pd.to_datetime(df.index) 20 | return df 21 | 22 | aapl = get_historical_data('AAPL', '2020-01-01') 23 | aapl = aapl[aapl.index <= '2021-04-29'] 24 | 25 | # MACD CALCULATION 26 | 27 | def get_macd(price, slow, fast, smooth): 28 | exp1 = price.ewm(span = fast, adjust = False).mean() 29 | exp2 = price.ewm(span = slow, adjust = False).mean() 30 | macd = pd.DataFrame(exp1 - exp2).rename(columns = {'close':'macd'}) 31 | signal = pd.DataFrame(macd.ewm(span = smooth, adjust = False).mean()).rename(columns = {'macd':'signal'}) 32 | hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'}) 33 | frames = [macd, signal, hist] 34 | df = pd.concat(frames, join = 'inner', axis = 1) 35 | return df 36 | 37 | aapl_macd = get_macd(aapl['close'], 26, 12, 9) 38 | aapl_macd.tail() 39 | 40 | # MACD PLOT 41 | 42 | def plot_macd(prices, macd, signal, hist): 43 | ax1 = plt.subplot2grid((8,1), (0,0), rowspan = 5, colspan = 1) 44 | ax2 = plt.subplot2grid((8,1), (5,0), rowspan = 3, colspan = 1) 45 | 46 | ax1.plot(prices) 47 | ax2.plot(macd, color = 'grey', linewidth = 1.5, label = 'MACD') 48 | ax2.plot(signal, color = 'skyblue', linewidth = 1.5, label = 'SIGNAL') 49 | 50 | for i in range(len(prices)): 51 | if str(hist[i])[0] == '-': 52 | ax2.bar(prices.index[i], hist[i], color = '#ef5350') 53 | else: 54 | ax2.bar(prices.index[i], hist[i], color = '#26a69a') 55 | 56 | plt.legend(loc = 'lower right') 57 | 58 | plot_macd(aapl['close'], aapl_macd['macd'], aapl_macd['signal'], aapl_macd['hist']) 59 | 60 | # CREATING THE TRADING STRATEGY 61 | 62 | def implement_macd_strategy(prices, data): 63 | buy_price = [] 64 | sell_price = [] 65 | macd_signal = [] 66 | signal = 0 67 | 68 | for i in range(len(data)): 69 | if data['macd'][i] > data['signal'][i]: 70 | if signal != 1: 71 | buy_price.append(prices[i]) 72 | sell_price.append(np.nan) 73 | signal = 1 74 | macd_signal.append(signal) 75 | else: 76 | buy_price.append(np.nan) 77 | sell_price.append(np.nan) 78 | macd_signal.append(0) 79 | elif data['macd'][i] < data['signal'][i]: 80 | if signal != -1: 81 | buy_price.append(np.nan) 82 | sell_price.append(prices[i]) 83 | signal = -1 84 | macd_signal.append(signal) 85 | else: 86 | buy_price.append(np.nan) 87 | sell_price.append(np.nan) 88 | macd_signal.append(0) 89 | else: 90 | buy_price.append(np.nan) 91 | sell_price.append(np.nan) 92 | macd_signal.append(0) 93 | 94 | return buy_price, sell_price, macd_signal 95 | 96 | buy_price, sell_price, macd_signal = implement_macd_strategy(aapl['close'], aapl_macd) 97 | 98 | # PLOTTING THE TRADING SIGNALS 99 | 100 | ax1 = plt.subplot2grid((8,1), (0,0), rowspan = 5, colspan = 1) 101 | ax2 = plt.subplot2grid((8,1), (5,0), rowspan = 3, colspan = 1) 102 | 103 | ax1.plot(aapl['close'], color = 'skyblue', linewidth = 2, label = 'aapl') 104 | ax1.plot(aapl.index, buy_price, marker = '^', color = 'green', markersize = 10, label = 'BUY SIGNAL', linewidth = 0) 105 | ax1.plot(aapl.index, sell_price, marker = 'v', color = 'r', markersize = 10, label = 'SELL SIGNAL', linewidth = 0) 106 | ax1.legend() 107 | ax1.set_title('aapl MACD SIGNALS') 108 | ax2.plot(aapl_macd['macd'], color = 'grey', linewidth = 1.5, label = 'MACD') 109 | ax2.plot(aapl_macd['signal'], color = 'skyblue', linewidth = 1.5, label = 'SIGNAL') 110 | 111 | for i in range(len(aapl_macd)): 112 | if str(aapl_macd['hist'][i])[0] == '-': 113 | ax2.bar(aapl_macd.index[i], aapl_macd['hist'][i], color = '#ef5350') 114 | else: 115 | ax2.bar(aapl_macd.index[i], aapl_macd['hist'][i], color = '#26a69a') 116 | 117 | plt.legend(loc = 'lower right') 118 | plt.show() 119 | 120 | # CREATING STOCK POSITION 121 | 122 | position = [] 123 | for i in range(len(macd_signal)): 124 | if macd_signal[i] > 1: 125 | position.append(0) 126 | else: 127 | position.append(1) 128 | 129 | for i in range(len(aapl['close'])): 130 | if macd_signal[i] == 1: 131 | position[i] = 1 132 | elif macd_signal[i] == -1: 133 | position[i] = 0 134 | else: 135 | position[i] = position[i-1] 136 | 137 | macd = aapl_macd['macd'] 138 | signal = aapl_macd['signal'] 139 | close_price = aapl['close'] 140 | macd_signal = pd.DataFrame(macd_signal).rename(columns = {0:'macd_signal'}).set_index(aapl.index) 141 | position = pd.DataFrame(position).rename(columns = {0:'macd_position'}).set_index(aapl.index) 142 | 143 | frames = [close_price, macd, signal, macd_signal, position] 144 | strategy = pd.concat(frames, join = 'inner', axis = 1) 145 | 146 | strategy.tail() 147 | 148 | rets = aapl.close.pct_change().dropna() 149 | strat_rets = strategy.macd_position[1:]*rets 150 | 151 | plt.title('Daily Returns') 152 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 153 | strat_rets.plot(color = 'r', linewidth = 1) 154 | plt.show() 155 | 156 | rets_cum = (1 + rets).cumprod() - 1 157 | strat_cum = (1 + strat_rets).cumprod() - 1 158 | 159 | plt.title('Cumulative Returns') 160 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 161 | strat_cum.plot(color = 'r', linewidth = 2) 162 | plt.show() 163 | -------------------------------------------------------------------------------- /Momentum/RSI.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import matplotlib.pyplot as plt 3 | import requests 4 | import numpy as np 5 | from math import floor 6 | from termcolor import colored as cl 7 | 8 | plt.style.use('fivethirtyeight') 9 | plt.rcParams['figure.figsize'] = (20, 10) 10 | 11 | # EXTRACTING STOCK DATA 12 | 13 | def get_historical_data(symbol, start_date): 14 | api_key = 'YOUR API KEY' 15 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 16 | raw_df = requests.get(api_url).json() 17 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 18 | df = df[df.index >= start_date] 19 | df.index = pd.to_datetime(df.index) 20 | return df 21 | 22 | aapl = get_historical_data('AAPL', '2020-01-01') 23 | aapl 24 | 25 | def get_rsi(close, lookback): 26 | ret = close.diff() 27 | up = [] 28 | down = [] 29 | for i in range(len(ret)): 30 | if ret[i] < 0: 31 | up.append(0) 32 | down.append(ret[i]) 33 | else: 34 | up.append(ret[i]) 35 | down.append(0) 36 | up_series = pd.Series(up) 37 | down_series = pd.Series(down).abs() 38 | up_ewm = up_series.ewm(com = lookback - 1, adjust = False).mean() 39 | down_ewm = down_series.ewm(com = lookback - 1, adjust = False).mean() 40 | rs = up_ewm/down_ewm 41 | rsi = 100 - (100 / (1 + rs)) 42 | rsi_df = pd.DataFrame(rsi).rename(columns = {0:'rsi'}).set_index(close.index) 43 | rsi_df = rsi_df.dropna() 44 | return rsi_df[3:] 45 | 46 | aapl['rsi_14'] = get_rsi(aapl['close'], 14) 47 | aapl = aapl.dropna() 48 | aapl 49 | 50 | ax1 = plt.subplot2grid((10,1), (0,0), rowspan = 4, colspan = 1) 51 | ax2 = plt.subplot2grid((10,1), (5,0), rowspan = 4, colspan = 1) 52 | ax1.plot(aapl['close'], linewidth = 2.5) 53 | ax1.set_title('aapl CLOSE PRICE') 54 | ax2.plot(aapl['rsi_14'], color = 'orange', linewidth = 2.5) 55 | ax2.axhline(30, linestyle = '--', linewidth = 1.5, color = 'grey') 56 | ax2.axhline(70, linestyle = '--', linewidth = 1.5, color = 'grey') 57 | ax2.set_title('aapl RELATIVE STRENGTH INDEX') 58 | plt.show() 59 | 60 | def implement_rsi_strategy(prices, rsi): 61 | buy_price = [] 62 | sell_price = [] 63 | rsi_signal = [] 64 | signal = 0 65 | 66 | for i in range(len(rsi)): 67 | if rsi[i-1] > 30 and rsi[i] < 30: 68 | if signal != 1: 69 | buy_price.append(prices[i]) 70 | sell_price.append(np.nan) 71 | signal = 1 72 | rsi_signal.append(signal) 73 | else: 74 | buy_price.append(np.nan) 75 | sell_price.append(np.nan) 76 | rsi_signal.append(0) 77 | elif rsi[i-1] < 70 and rsi[i] > 70: 78 | if signal != -1: 79 | buy_price.append(np.nan) 80 | sell_price.append(prices[i]) 81 | signal = -1 82 | rsi_signal.append(signal) 83 | else: 84 | buy_price.append(np.nan) 85 | sell_price.append(np.nan) 86 | rsi_signal.append(0) 87 | else: 88 | buy_price.append(np.nan) 89 | sell_price.append(np.nan) 90 | rsi_signal.append(0) 91 | 92 | return buy_price, sell_price, rsi_signal 93 | 94 | 95 | buy_price, sell_price, rsi_signal = implement_rsi_strategy(aapl['close'], aapl['rsi_14']) 96 | 97 | ax1 = plt.subplot2grid((10,1), (0,0), rowspan = 4, colspan = 1) 98 | ax2 = plt.subplot2grid((10,1), (5,0), rowspan = 4, colspan = 1) 99 | ax1.plot(aapl['close'], linewidth = 2.5, color = 'skyblue', label = 'aapl') 100 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 10, color = 'green', label = 'BUY SIGNAL') 101 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 10, color = 'r', label = 'SELL SIGNAL') 102 | ax1.set_title('aapl RSI TRADE SIGNALS') 103 | ax2.plot(aapl['rsi_14'], color = 'orange', linewidth = 2.5) 104 | ax2.axhline(30, linestyle = '--', linewidth = 1.5, color = 'grey') 105 | ax2.axhline(70, linestyle = '--', linewidth = 1.5, color = 'grey') 106 | plt.show() 107 | 108 | position = [] 109 | for i in range(len(rsi_signal)): 110 | if rsi_signal[i] > 1: 111 | position.append(0) 112 | else: 113 | position.append(1) 114 | 115 | for i in range(len(aapl['close'])): 116 | if rsi_signal[i] == 1: 117 | position[i] = 1 118 | elif rsi_signal[i] == -1: 119 | position[i] = 0 120 | else: 121 | position[i] = position[i-1] 122 | 123 | rsi = aapl['rsi_14'] 124 | close_price = aapl['close'] 125 | rsi_signal = pd.DataFrame(rsi_signal).rename(columns = {0:'rsi_signal'}).set_index(aapl.index) 126 | position = pd.DataFrame(position).rename(columns = {0:'rsi_position'}).set_index(aapl.index) 127 | 128 | frames = [close_price, rsi, rsi_signal, position] 129 | strategy = pd.concat(frames, join = 'inner', axis = 1) 130 | 131 | strategy.head() 132 | 133 | rets = aapl.close.pct_change().dropna() 134 | strat_rets = strategy.rsi_position[1:]*rets 135 | 136 | plt.title('Daily Returns') 137 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 138 | strat_rets.plot(color = 'r', linewidth = 1) 139 | plt.show() 140 | -------------------------------------------------------------------------------- /Momentum/Relative_Vigor_Index.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import pandas as pd 4 | import matplotlib.pyplot as plt 5 | import numpy as np 6 | import requests 7 | from termcolor import colored as cl 8 | from math import floor 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2019-01-01') 25 | aapl.tail() 26 | 27 | # RELATIVE VIGOR INDEX CALCULATION 28 | 29 | def get_rvi(open, high, low, close, lookback): 30 | a = close - open 31 | b = 2 * (close.shift(2) - open.shift(2)) 32 | c = 2 * (close.shift(3) - open.shift(3)) 33 | d = close.shift(4) - open.shift(4) 34 | numerator = a + b + c + d 35 | 36 | e = high - low 37 | f = 2 * (high.shift(2) - low.shift(2)) 38 | g = 2 * (high.shift(3) - low.shift(3)) 39 | h = high.shift(4) - low.shift(4) 40 | denominator = e + f + g + h 41 | 42 | numerator_sum = numerator.rolling(4).sum() 43 | denominator_sum = denominator.rolling(4).sum() 44 | rvi = (numerator_sum / denominator_sum).rolling(lookback).mean() 45 | 46 | rvi1 = 2 * rvi.shift(1) 47 | rvi2 = 2 * rvi.shift(2) 48 | rvi3 = rvi.shift(3) 49 | rvi_signal = (rvi + rvi1 + rvi2 + rvi3) / 6 50 | 51 | return rvi, rvi_signal 52 | 53 | aapl['rvi'], aapl['signal_line'] = get_rvi(aapl['open'], aapl['high'], aapl['low'], aapl['close'], 10) 54 | aapl = aapl.dropna() 55 | aapl = aapl[aapl.index >= '2020-01-01'] 56 | aapl.tail() 57 | 58 | # RELATIVE VIGOR INDEX PLOT 59 | 60 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 61 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 62 | ax1.plot(aapl['close'], linewidth = 2.5) 63 | ax1.set_title('AAPL CLOSING PRICES') 64 | ax2.plot(aapl['rvi'], linewidth = 2, color = 'orange', label = 'RVI LINE') 65 | ax2.plot(aapl['signal_line'], linewidth = 2, color = '#BA5FE3', label = 'SIGNAL LINE') 66 | ax2.legend() 67 | ax2.set_title('AAPL RVI 10') 68 | plt.show() 69 | 70 | # RELATIVE VIGOR INDEX STRATEGY 71 | 72 | def implement_rvi_strategy(prices, rvi, signal_line): 73 | buy_price = [] 74 | sell_price = [] 75 | rvi_signal = [] 76 | signal = 0 77 | 78 | for i in range(len(prices)): 79 | if rvi[i-1] < signal_line[i-1] and rvi[i] > signal_line[i]: 80 | if signal != 1: 81 | buy_price.append(prices[i]) 82 | sell_price.append(np.nan) 83 | signal = 1 84 | rvi_signal.append(signal) 85 | else: 86 | buy_price.append(np.nan) 87 | sell_price.append(np.nan) 88 | rvi_signal.append(0) 89 | elif rvi[i-1] > signal_line[i-1] and rvi[i] < signal_line[i]: 90 | if signal != -1: 91 | buy_price.append(np.nan) 92 | sell_price.append(prices[i]) 93 | signal = -1 94 | rvi_signal.append(signal) 95 | else: 96 | buy_price.append(np.nan) 97 | sell_price.append(np.nan) 98 | rvi_signal.append(0) 99 | else: 100 | buy_price.append(np.nan) 101 | sell_price.append(np.nan) 102 | rvi_signal.append(0) 103 | 104 | return buy_price, sell_price, rvi_signal 105 | 106 | buy_price, sell_price, rvi_signal = implement_rvi_strategy(aapl['close'], aapl['rvi'], aapl['signal_line']) 107 | 108 | # RELATIVE VIGOR INDEX TRADING SIGNALS PLOT 109 | 110 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 111 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 112 | ax1.plot(aapl['close'], linewidth = 2) 113 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, color = 'green', linewidth = 0, label = 'BUY SIGNAL') 114 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, color = 'r', linewidth = 0, label = 'SELL SIGNAL') 115 | ax1.legend() 116 | ax1.set_title('AAPL RVI TRADING SIGNALS') 117 | ax2.plot(aapl['rvi'], linewidth = 2, color = 'orange', label = 'RVI LINE') 118 | ax2.plot(aapl['signal_line'], linewidth = 2, color = '#BA5FE3', label = 'SIGNAL LINE') 119 | ax2.set_title('AAPL RVI 10') 120 | ax2.legend() 121 | plt.show() 122 | 123 | # STOCK POSITION 124 | 125 | position = [] 126 | for i in range(len(rvi_signal)): 127 | if rvi_signal[i] > 1: 128 | position.append(0) 129 | else: 130 | position.append(1) 131 | 132 | for i in range(len(aapl['close'])): 133 | if rvi_signal[i] == 1: 134 | position[i] = 1 135 | elif rvi_signal[i] == -1: 136 | position[i] = 0 137 | else: 138 | position[i] = position[i-1] 139 | 140 | close_price = aapl['close'] 141 | rvi = aapl['rvi'] 142 | signal_line = aapl['signal_line'] 143 | rvi_signal = pd.DataFrame(rvi_signal).rename(columns = {0:'rvi_signal'}).set_index(aapl.index) 144 | position = pd.DataFrame(position).rename(columns = {0:'rvi_position'}).set_index(aapl.index) 145 | 146 | frames = [close_price, rvi, signal_line, rvi_signal, position] 147 | strategy = pd.concat(frames, join = 'inner', axis = 1) 148 | 149 | strategy 150 | 151 | rets = aapl.close.pct_change().dropna() 152 | strat_rets = strategy.rvi_position[1:]*rets 153 | 154 | plt.title('Daily Returns') 155 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 156 | strat_rets.plot(color = 'r', linewidth = 1) 157 | plt.show() 158 | 159 | rets_cum = (1 + rets).cumprod() - 1 160 | strat_cum = (1 + strat_rets).cumprod() - 1 161 | 162 | plt.title('Cumulative Returns') 163 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 164 | strat_cum.plot(color = 'r', linewidth = 2) 165 | plt.show() 166 | -------------------------------------------------------------------------------- /Momentum/Stochastic_Oscillator.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import requests 4 | from termcolor import colored as cl 5 | from math import floor 6 | import matplotlib.pyplot as plt 7 | 8 | plt.rcParams['figure.figsize'] = (20, 10) 9 | plt.style.use('fivethirtyeight') 10 | 11 | # EXTRACTING STOCK DATA 12 | 13 | def get_historical_data(symbol, start_date): 14 | api_key = 'YOUR API KEY' 15 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 16 | raw_df = requests.get(api_url).json() 17 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 18 | df = df[df.index >= start_date] 19 | df.index = pd.to_datetime(df.index) 20 | return df 21 | 22 | aapl = get_historical_data('AAPL', '2020-01-01') 23 | aapl 24 | 25 | def get_stoch(symbol, k_period, d_period, start_date): 26 | api_key = open(r'api_key.txt') 27 | url = f'https://www.alphavantage.co/query?function=STOCH&symbol={symbol}&interval=daily&fastkperiod={k_period}&slowdperiod={d_period}&apikey={api_key}' 28 | raw = requests.get(url).json() 29 | df = pd.DataFrame(raw['Technical Analysis: STOCH']).T.iloc[::-1] 30 | df = df[df.index >= start_date] 31 | df.index = pd.to_datetime(df.index) 32 | df = df.astype(float) 33 | return df['SlowK'], df['SlowD'] 34 | 35 | aapl['%k'], aapl['%d'] = get_stoch('aapl', 14, 3, '2020-01-01') 36 | aapl = aapl.dropna() 37 | aapl.head() 38 | 39 | def plot_stoch(symbol, price, k, d): 40 | ax1 = plt.subplot2grid((9, 1), (0,0), rowspan = 5, colspan = 1) 41 | ax2 = plt.subplot2grid((9, 1), (6,0), rowspan = 3, colspan = 1) 42 | ax1.plot(price) 43 | ax1.set_title(f'{symbol} STOCK PRICE') 44 | ax2.plot(k, color = 'deepskyblue', linewidth = 1.5, label = '%K') 45 | ax2.plot(d, color = 'orange', linewidth = 1.5, label = '%D') 46 | ax2.axhline(80, color = 'black', linewidth = 1, linestyle = '--') 47 | ax2.axhline(20, color = 'black', linewidth = 1, linestyle = '--') 48 | ax2.set_title(f'{symbol} STOCH') 49 | ax2.legend() 50 | plt.show() 51 | 52 | plot_stoch('aapl', aapl['close'], aapl['%k'], aapl['%d']) 53 | 54 | def implement_stoch_strategy(prices, k, d): 55 | buy_price = [] 56 | sell_price = [] 57 | stoch_signal = [] 58 | signal = 0 59 | 60 | for i in range(len(prices)): 61 | if k[i] < 20 and d[i] < 20 and k[i] < d[i]: 62 | if signal != 1: 63 | buy_price.append(prices[i]) 64 | sell_price.append(np.nan) 65 | signal = 1 66 | stoch_signal.append(signal) 67 | else: 68 | buy_price.append(np.nan) 69 | sell_price.append(np.nan) 70 | stoch_signal.append(0) 71 | elif k[i] > 80 and d[i] > 80 and k[i] > d[i]: 72 | if signal != -1: 73 | buy_price.append(np.nan) 74 | sell_price.append(prices[i]) 75 | signal = -1 76 | stoch_signal.append(signal) 77 | else: 78 | buy_price.append(np.nan) 79 | sell_price.append(np.nan) 80 | stoch_signal.append(0) 81 | else: 82 | buy_price.append(np.nan) 83 | sell_price.append(np.nan) 84 | stoch_signal.append(0) 85 | 86 | return buy_price, sell_price, stoch_signal 87 | 88 | buy_price, sell_price, stoch_signal = implement_stoch_strategy(aapl['close'], aapl['%k'], aapl['%d']) 89 | 90 | ax1 = plt.subplot2grid((9, 1), (0,0), rowspan = 5, colspan = 1) 91 | ax2 = plt.subplot2grid((9, 1), (6,0), rowspan = 3, colspan = 1) 92 | ax1.plot(aapl['close'], color = 'skyblue', label = 'aapl') 93 | ax1.plot(aapl.index, buy_price, marker = '^', color = 'green', markersize = 10, label = 'BUY SIGNAL', linewidth = 0) 94 | ax1.plot(aapl.index, sell_price, marker = 'v', color = 'r', markersize = 10, label = 'SELL SIGNAL', linewidth = 0) 95 | ax1.legend(loc = 'upper left') 96 | ax1.set_title('aapl STOCK PRICE') 97 | ax2.plot(aapl['%k'], color = 'deepskyblue', linewidth = 1.5, label = '%K') 98 | ax2.plot(aapl['%d'], color = 'orange', linewidth = 1.5, label = '%D') 99 | ax2.axhline(80, color = 'black', linewidth = 1, linestyle = '--') 100 | ax2.axhline(20, color = 'black', linewidth = 1, linestyle = '--') 101 | ax2.set_title('aapl STOCH') 102 | ax2.legend() 103 | plt.show() 104 | 105 | position = [] 106 | for i in range(len(stoch_signal)): 107 | if stoch_signal[i] > 1: 108 | position.append(0) 109 | else: 110 | position.append(1) 111 | 112 | for i in range(len(aapl['close'])): 113 | if stoch_signal[i] == 1: 114 | position[i] = 1 115 | elif stoch_signal[i] == -1: 116 | position[i] = 0 117 | else: 118 | position[i] = position[i-1] 119 | 120 | k = aapl['%k'] 121 | d = aapl['%d'] 122 | close_price = aapl['close'] 123 | stoch_signal = pd.DataFrame(stoch_signal).rename(columns = {0:'stoch_signal'}).set_index(aapl.index) 124 | position = pd.DataFrame(position).rename(columns = {0:'stoch_position'}).set_index(aapl.index) 125 | 126 | frames = [close_price, k, d, stoch_signal, position] 127 | strategy = pd.concat(frames, join = 'inner', axis = 1) 128 | 129 | strategy.tail() 130 | 131 | rets = aapl.close.pct_change().dropna() 132 | strat_rets = strategy.stoch_position[1:]*rets 133 | 134 | plt.title('Daily Returns') 135 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 136 | strat_rets.plot(color = 'r', linewidth = 1) 137 | plt.show() 138 | -------------------------------------------------------------------------------- /Momentum/True_Strength_Index.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import pandas as pd 4 | import requests 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | from math import floor 8 | from termcolor import colored as cl 9 | 10 | plt.style.use('fivethirtyeight') 11 | plt.rcParams['figure.figsize'] = (20,10) 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('AAPL', '2019-01-01') 25 | aapl.tail() 26 | 27 | # TRUE STRENGTH INDEX CALCULATION 28 | 29 | def get_tsi(close, long, short, signal): 30 | diff = close - close.shift(1) 31 | abs_diff = abs(diff) 32 | 33 | diff_smoothed = diff.ewm(span = long, adjust = False).mean() 34 | diff_double_smoothed = diff_smoothed.ewm(span = short, adjust = False).mean() 35 | abs_diff_smoothed = abs_diff.ewm(span = long, adjust = False).mean() 36 | abs_diff_double_smoothed = abs_diff_smoothed.ewm(span = short, adjust = False).mean() 37 | 38 | tsi = (diff_double_smoothed / abs_diff_double_smoothed) * 100 39 | signal = tsi.ewm(span = signal, adjust = False).mean() 40 | tsi = tsi[tsi.index >= '2020-01-01'].dropna() 41 | signal = signal[signal.index >= '2020-01-01'].dropna() 42 | 43 | return tsi, signal 44 | 45 | aapl['tsi'], aapl['signal_line'] = get_tsi(aapl['close'], 25, 13, 12) 46 | aapl = aapl[aapl.index >= '2020-01-01'] 47 | aapl.tail() 48 | 49 | # TRUE STRENGTH INDEX PLOT 50 | 51 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 52 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 53 | ax1.plot(aapl['close'], linewidth = 2.5) 54 | ax1.set_title('AAPL CLOSING PRICE') 55 | ax2.plot(aapl['tsi'], linewidth = 2, color = 'orange', label = 'TSI LINE') 56 | ax2.plot(aapl['signal_line'], linewidth = 2, color = '#FF006E', label = 'SIGNAL LINE') 57 | ax2.set_title('AAPL TSI 25,13,12') 58 | ax2.legend() 59 | plt.show() 60 | 61 | # TRUE STRENGTH INDEX STRATEGY 62 | 63 | def implement_tsi_strategy(prices, tsi, signal_line): 64 | buy_price = [] 65 | sell_price = [] 66 | tsi_signal = [] 67 | signal = 0 68 | 69 | for i in range(len(prices)): 70 | if tsi[i-1] < signal_line[i-1] and tsi[i] > signal_line[i]: 71 | if signal != 1: 72 | buy_price.append(prices[i]) 73 | sell_price.append(np.nan) 74 | signal = 1 75 | tsi_signal.append(signal) 76 | else: 77 | buy_price.append(np.nan) 78 | sell_price.append(np.nan) 79 | tsi_signal.append(0) 80 | elif tsi[i-1] > signal_line[i-1] and tsi[i] < signal_line[i]: 81 | if signal != -1: 82 | buy_price.append(np.nan) 83 | sell_price.append(prices[i]) 84 | signal = -1 85 | tsi_signal.append(signal) 86 | else: 87 | buy_price.append(np.nan) 88 | sell_price.append(np.nan) 89 | tsi_signal.append(0) 90 | else: 91 | buy_price.append(np.nan) 92 | sell_price.append(np.nan) 93 | tsi_signal.append(0) 94 | 95 | return buy_price, sell_price, tsi_signal 96 | 97 | buy_price, sell_price, tsi_signal = implement_tsi_strategy(aapl['close'], aapl['tsi'], aapl['signal_line']) 98 | 99 | # TRUE STRENGTH INDEX TRADING SIGNALS PLOT 100 | 101 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 102 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 103 | ax1.plot(aapl['close'], linewidth = 2) 104 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, color = 'green', linewidth = 0, label = 'BUY SIGNAL') 105 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, color = 'r', linewidth = 0, label = 'SELL SIGNAL') 106 | ax1.legend() 107 | ax1.set_title('AAPL TSI TRADING SIGNALS') 108 | ax2.plot(aapl['tsi'], linewidth = 2, color = 'orange', label = 'TSI LINE') 109 | ax2.plot(aapl['signal_line'], linewidth = 2, color = '#FF006E', label = 'SIGNAL LINE') 110 | ax2.set_title('AAPL TSI 25,13,12') 111 | ax2.legend() 112 | plt.show() 113 | 114 | # STOCK POSITION 115 | 116 | position = [] 117 | for i in range(len(tsi_signal)): 118 | if tsi_signal[i] > 1: 119 | position.append(0) 120 | else: 121 | position.append(1) 122 | 123 | for i in range(len(aapl['close'])): 124 | if tsi_signal[i] == 1: 125 | position[i] = 1 126 | elif tsi_signal[i] == -1: 127 | position[i] = 0 128 | else: 129 | position[i] = position[i-1] 130 | 131 | close_price = aapl['close'] 132 | tsi = aapl['tsi'] 133 | signal_line = aapl['signal_line'] 134 | tsi_signal = pd.DataFrame(tsi_signal).rename(columns = {0:'tsi_signal'}).set_index(aapl.index) 135 | position = pd.DataFrame(position).rename(columns = {0:'tsi_position'}).set_index(aapl.index) 136 | 137 | frames = [close_price, tsi, signal_line, tsi_signal, position] 138 | strategy = pd.concat(frames, join = 'inner', axis = 1) 139 | 140 | strategy 141 | 142 | rets = aapl.close.pct_change().dropna() 143 | strat_rets = strategy.tsi_position[1:]*rets 144 | 145 | plt.title('Daily Returns') 146 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 147 | strat_rets.plot(color = 'r', linewidth = 1) 148 | plt.show() 149 | 150 | rets_cum = (1 + rets).cumprod() - 1 151 | strat_cum = (1 + strat_rets).cumprod() - 1 152 | 153 | plt.title('Cumulative Returns') 154 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 155 | strat_cum.plot(color = 'r', linewidth = 2) 156 | plt.show() 157 | -------------------------------------------------------------------------------- /Momentum/Williams_%R.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import requests 4 | import matplotlib.pyplot as plt 5 | from math import floor 6 | from termcolor import colored as cl 7 | 8 | plt.rcParams['figure.figsize'] = (20,10) 9 | plt.style.use('fivethirtyeight') 10 | 11 | def get_historical_data(symbol, start_date): 12 | api_key = 'YOUR API KEY' 13 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 14 | raw_df = requests.get(api_url).json() 15 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 16 | df = df[df.index >= start_date] 17 | df.index = pd.to_datetime(df.index) 18 | return df 19 | 20 | aapl = get_historical_data('AAPL', '2020-01-01') 21 | aapl 22 | 23 | def get_wr(high, low, close, lookback): 24 | highh = high.rolling(lookback).max() 25 | lowl = low.rolling(lookback).min() 26 | wr = -100 * ((highh - close) / (highh - lowl)) 27 | return wr 28 | 29 | aapl['wr_14'] = get_wr(aapl['high'], aapl['low'], aapl['close'], 14) 30 | aapl = aapl.dropna() 31 | aapl 32 | 33 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 34 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 35 | ax1.plot(aapl['close'], linewidth = 2) 36 | ax1.set_title('aapl CLOSING PRICE') 37 | ax2.plot(aapl['wr_14'], color = 'orange', linewidth = 2) 38 | ax2.axhline(-20, linewidth = 1.5, linestyle = '--', color = 'grey') 39 | ax2.axhline(-80, linewidth = 1.5, linestyle = '--', color = 'grey') 40 | ax2.set_title('aapl WILLIAMS %R 14') 41 | plt.show() 42 | 43 | def implement_wr_strategy(prices, wr): 44 | buy_price = [] 45 | sell_price = [] 46 | wr_signal = [] 47 | signal = 0 48 | 49 | for i in range(len(wr)): 50 | if wr[i-1] > -80 and wr[i] < -80: 51 | if signal != 1: 52 | buy_price.append(prices[i]) 53 | sell_price.append(np.nan) 54 | signal = 1 55 | wr_signal.append(signal) 56 | else: 57 | buy_price.append(np.nan) 58 | sell_price.append(np.nan) 59 | wr_signal.append(0) 60 | elif wr[i-1] < -20 and wr[i] > -20: 61 | if signal != -1: 62 | buy_price.append(np.nan) 63 | sell_price.append(prices[i]) 64 | signal = -1 65 | wr_signal.append(signal) 66 | else: 67 | buy_price.append(np.nan) 68 | sell_price.append(np.nan) 69 | wr_signal.append(0) 70 | else: 71 | buy_price.append(np.nan) 72 | sell_price.append(np.nan) 73 | wr_signal.append(0) 74 | 75 | return buy_price, sell_price, wr_signal 76 | 77 | buy_price, sell_price, wr_signal = implement_wr_strategy(aapl['close'], aapl['wr_14']) 78 | 79 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 80 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 81 | ax1.plot(aapl['close'], linewidth = 2) 82 | ax1.plot(aapl.index, buy_price, marker = '^', markersize = 12, linewidth = 0, color = 'green', label = 'BUY SIGNAL') 83 | ax1.plot(aapl.index, sell_price, marker = 'v', markersize = 12, linewidth = 0, color = 'r', label = 'SELL SIGNAL') 84 | ax1.legend() 85 | ax1.set_title('aapl TRADING SIGNALS') 86 | ax2.plot(aapl['wr_14'], color = 'orange', linewidth = 2) 87 | ax2.axhline(-20, linewidth = 1.5, linestyle = '--', color = 'grey') 88 | ax2.axhline(-80, linewidth = 1.5, linestyle = '--', color = 'grey') 89 | ax2.set_title('aapl WILLIAMS %R 14') 90 | plt.show() 91 | 92 | position = [] 93 | for i in range(len(wr_signal)): 94 | if wr_signal[i] > 1: 95 | position.append(0) 96 | else: 97 | position.append(1) 98 | 99 | for i in range(len(aapl['close'])): 100 | if wr_signal[i] == 1: 101 | position[i] = 1 102 | elif wr_signal[i] == -1: 103 | position[i] = 0 104 | else: 105 | position[i] = position[i-1] 106 | 107 | close_price = aapl['close'] 108 | wr = aapl['wr_14'] 109 | wr_signal = pd.DataFrame(wr_signal).rename(columns = {0:'wr_signal'}).set_index(aapl.index) 110 | position = pd.DataFrame(position).rename(columns = {0:'wr_position'}).set_index(aapl.index) 111 | 112 | frames = [close_price, wr, wr_signal, position] 113 | strategy = pd.concat(frames, join = 'inner', axis = 1) 114 | 115 | strategy.head() 116 | 117 | rets = aapl.close.pct_change().dropna() 118 | strat_rets = strategy.wr_position[1:]*rets 119 | 120 | plt.title('Daily Returns') 121 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 122 | strat_rets.plot(color = 'r', linewidth = 1) 123 | plt.show() 124 | -------------------------------------------------------------------------------- /Overlap/Simple_Moving_Average.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import matplotlib.pyplot as plt 3 | import requests 4 | import math 5 | from termcolor import colored as cl 6 | import numpy as np 7 | 8 | plt.style.use('fivethirtyeight') 9 | plt.rcParams['figure.figsize'] = (20, 10) 10 | 11 | # EXTRACTING STOCK DATA 12 | 13 | def get_historical_data(symbol, start_date): 14 | api_key = 'YOUR API KEY' 15 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 16 | raw_df = requests.get(api_url).json() 17 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 18 | df = df[df.index >= start_date] 19 | df.index = pd.to_datetime(df.index) 20 | return df 21 | 22 | aapl = get_historical_data('AAPL', '2020-01-01') 23 | aapl 24 | 25 | def sma(data, n): 26 | sma = data.rolling(window = n).mean() 27 | return pd.DataFrame(sma) 28 | 29 | n = [20, 50] 30 | for i in n: 31 | aapl[f'sma_{i}'] = sma(aapl['close'], i) 32 | 33 | aapl.tail() 34 | 35 | plt.plot(aapl['close'], label = 'aapl', linewidth = 5, alpha = 0.3) 36 | plt.plot(aapl['sma_20'], label = 'SMA 20') 37 | plt.plot(aapl['sma_50'], label = 'SMA 50') 38 | plt.title('aapl Simple Moving Averages (20, 50)') 39 | plt.legend(loc = 'upper left') 40 | plt.show() 41 | 42 | def implement_sma_strategy(data, short_window, long_window): 43 | sma1 = short_window 44 | sma2 = long_window 45 | buy_price = [] 46 | sell_price = [] 47 | sma_signal = [] 48 | signal = 0 49 | 50 | for i in range(len(data)): 51 | if sma1[i] > sma2[i]: 52 | if signal != 1: 53 | buy_price.append(data[i]) 54 | sell_price.append(np.nan) 55 | signal = 1 56 | sma_signal.append(signal) 57 | else: 58 | buy_price.append(np.nan) 59 | sell_price.append(np.nan) 60 | sma_signal.append(0) 61 | elif sma2[i] > sma1[i]: 62 | if signal != -1: 63 | buy_price.append(np.nan) 64 | sell_price.append(data[i]) 65 | signal = -1 66 | sma_signal.append(-1) 67 | else: 68 | buy_price.append(np.nan) 69 | sell_price.append(np.nan) 70 | sma_signal.append(0) 71 | else: 72 | buy_price.append(np.nan) 73 | sell_price.append(np.nan) 74 | sma_signal.append(0) 75 | 76 | return buy_price, sell_price, sma_signal 77 | 78 | sma_20 = aapl['sma_20'] 79 | sma_50 = aapl['sma_50'] 80 | 81 | buy_price, sell_price, signal = implement_sma_strategy(aapl['close'], sma_20, sma_50) 82 | 83 | plt.plot(aapl['close'], alpha = 0.3, label = 'aapl') 84 | plt.plot(sma_20, alpha = 0.6, label = 'SMA 20') 85 | plt.plot(sma_50, alpha = 0.6, label = 'SMA 50') 86 | plt.scatter(aapl.index, buy_price, marker = '^', s = 200, color = 'darkblue', label = 'BUY SIGNAL') 87 | plt.scatter(aapl.index, sell_price, marker = 'v', s = 200, color = 'crimson', label = 'SELL SIGNAL') 88 | plt.legend(loc = 'upper left') 89 | plt.title('aapl SMA CROSSOVER TRADING SIGNALS') 90 | plt.show() 91 | 92 | position = [] 93 | for i in range(len(signal)): 94 | if signal[i] > 1: 95 | position.append(0) 96 | else: 97 | position.append(1) 98 | 99 | for i in range(len(aapl['close'])): 100 | if signal[i] == 1: 101 | position[i] = 1 102 | elif signal[i] == -1: 103 | position[i] = 0 104 | else: 105 | position[i] = position[i-1] 106 | 107 | sma_20 = pd.DataFrame(sma_20).rename(columns = {0:'sma_20'}) 108 | sma_50 = pd.DataFrame(sma_50).rename(columns = {0:'sma_50'}) 109 | signal = pd.DataFrame(signal).rename(columns = {0:'sma_signal'}).set_index(aapl.index) 110 | position = pd.DataFrame(position).rename(columns = {0:'sma_position'}).set_index(aapl.index) 111 | 112 | frames = [sma_20, sma_50, signal, position] 113 | strategy = pd.concat(frames, join = 'inner', axis = 1) 114 | 115 | strategy 116 | 117 | rets = aapl.close.pct_change().dropna() 118 | strat_rets = strategy.sma_position[1:]*rets 119 | 120 | plt.title('Daily Returns') 121 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 122 | strat_rets.plot(color = 'r', linewidth = 1) 123 | plt.show() 124 | 125 | rets_cum = (1 + rets).cumprod() - 1 126 | strat_cum = (1 + strat_rets).cumprod() - 1 127 | 128 | plt.title('Cumulative Returns') 129 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 130 | strat_cum.plot(color = 'r', linewidth = 2) 131 | plt.show() 132 | -------------------------------------------------------------------------------- /Overlap/SuperTrend.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | import requests 5 | from math import floor 6 | from termcolor import colored as cl 7 | 8 | plt.style.use('fivethirtyeight') 9 | plt.rcParams['figure.figsize'] = (20,10) 10 | 11 | def get_historical_data(symbol, start_date): 12 | api_key = 'YOUR API KEY' 13 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 14 | raw_df = requests.get(api_url).json() 15 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 16 | df = df[df.index >= start_date] 17 | df.index = pd.to_datetime(df.index) 18 | return df 19 | 20 | aapl = get_historical_data('aapl', '2020-01-01') 21 | aapl 22 | 23 | def get_supertrend(high, low, close, lookback, multiplier): 24 | 25 | # ATR 26 | 27 | tr1 = pd.DataFrame(high - low) 28 | tr2 = pd.DataFrame(abs(high - close.shift(1))) 29 | tr3 = pd.DataFrame(abs(low - close.shift(1))) 30 | frames = [tr1, tr2, tr3] 31 | tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1) 32 | atr = tr.ewm(lookback).mean() 33 | 34 | # H/L AVG AND BASIC UPPER & LOWER BAND 35 | 36 | hl_avg = (high + low) / 2 37 | upper_band = (hl_avg + multiplier * atr).dropna() 38 | lower_band = (hl_avg - multiplier * atr).dropna() 39 | 40 | # FINAL UPPER BAND 41 | 42 | final_bands = pd.DataFrame(columns = ['upper', 'lower']) 43 | final_bands.iloc[:,0] = [x for x in upper_band - upper_band] 44 | final_bands.iloc[:,1] = final_bands.iloc[:,0] 45 | 46 | for i in range(len(final_bands)): 47 | if i == 0: 48 | final_bands.iloc[i,0] = 0 49 | else: 50 | if (upper_band[i] < final_bands.iloc[i-1,0]) | (close[i-1] > final_bands.iloc[i-1,0]): 51 | final_bands.iloc[i,0] = upper_band[i] 52 | else: 53 | final_bands.iloc[i,0] = final_bands.iloc[i-1,0] 54 | 55 | # FINAL LOWER BAND 56 | 57 | for i in range(len(final_bands)): 58 | if i == 0: 59 | final_bands.iloc[i, 1] = 0 60 | else: 61 | if (lower_band[i] > final_bands.iloc[i-1,1]) | (close[i-1] < final_bands.iloc[i-1,1]): 62 | final_bands.iloc[i,1] = lower_band[i] 63 | else: 64 | final_bands.iloc[i,1] = final_bands.iloc[i-1,1] 65 | 66 | # SUPERTREND 67 | 68 | supertrend = pd.DataFrame(columns = [f'supertrend_{lookback}']) 69 | supertrend.iloc[:,0] = [x for x in final_bands['upper'] - final_bands['upper']] 70 | 71 | for i in range(len(supertrend)): 72 | if i == 0: 73 | supertrend.iloc[i, 0] = 0 74 | elif supertrend.iloc[i-1, 0] == final_bands.iloc[i-1, 0] and close[i] < final_bands.iloc[i, 0]: 75 | supertrend.iloc[i, 0] = final_bands.iloc[i, 0] 76 | elif supertrend.iloc[i-1, 0] == final_bands.iloc[i-1, 0] and close[i] > final_bands.iloc[i, 0]: 77 | supertrend.iloc[i, 0] = final_bands.iloc[i, 1] 78 | elif supertrend.iloc[i-1, 0] == final_bands.iloc[i-1, 1] and close[i] > final_bands.iloc[i, 1]: 79 | supertrend.iloc[i, 0] = final_bands.iloc[i, 1] 80 | elif supertrend.iloc[i-1, 0] == final_bands.iloc[i-1, 1] and close[i] < final_bands.iloc[i, 1]: 81 | supertrend.iloc[i, 0] = final_bands.iloc[i, 0] 82 | 83 | supertrend = supertrend.set_index(upper_band.index) 84 | supertrend = supertrend.dropna()[1:] 85 | 86 | # ST UPTREND/DOWNTREND 87 | 88 | upt = [] 89 | dt = [] 90 | close = close.iloc[len(close) - len(supertrend):] 91 | 92 | for i in range(len(supertrend)): 93 | if close[i] > supertrend.iloc[i, 0]: 94 | upt.append(supertrend.iloc[i, 0]) 95 | dt.append(np.nan) 96 | elif close[i] < supertrend.iloc[i, 0]: 97 | upt.append(np.nan) 98 | dt.append(supertrend.iloc[i, 0]) 99 | else: 100 | upt.append(np.nan) 101 | dt.append(np.nan) 102 | 103 | st, upt, dt = pd.Series(supertrend.iloc[:, 0]), pd.Series(upt), pd.Series(dt) 104 | upt.index, dt.index = supertrend.index, supertrend.index 105 | 106 | return st, upt, dt 107 | 108 | aapl['st'], aapl['s_upt'], aapl['st_dt'] = get_supertrend(aapl['high'], aapl['low'], aapl['close'], 10, 3) 109 | aapl = aapl[1:] 110 | aapl.head() 111 | 112 | plt.plot(aapl['close'], linewidth = 2, label = 'CLOSING PRICE') 113 | plt.plot(aapl['st'], color = 'green', linewidth = 2, label = 'ST UPTREND 10,3') 114 | plt.plot(aapl['st_dt'], color = 'r', linewidth = 2, label = 'ST DOWNTREND 10,3') 115 | plt.legend(loc = 'upper left') 116 | plt.show() 117 | 118 | def implement_st_strategy(prices, st): 119 | buy_price = [] 120 | sell_price = [] 121 | st_signal = [] 122 | signal = 0 123 | 124 | for i in range(len(st)): 125 | if st[i-1] > prices[i-1] and st[i] < prices[i]: 126 | if signal != 1: 127 | buy_price.append(prices[i]) 128 | sell_price.append(np.nan) 129 | signal = 1 130 | st_signal.append(signal) 131 | else: 132 | buy_price.append(np.nan) 133 | sell_price.append(np.nan) 134 | st_signal.append(0) 135 | elif st[i-1] < prices[i-1] and st[i] > prices[i]: 136 | if signal != -1: 137 | buy_price.append(np.nan) 138 | sell_price.append(prices[i]) 139 | signal = -1 140 | st_signal.append(signal) 141 | else: 142 | buy_price.append(np.nan) 143 | sell_price.append(np.nan) 144 | st_signal.append(0) 145 | else: 146 | buy_price.append(np.nan) 147 | sell_price.append(np.nan) 148 | st_signal.append(0) 149 | 150 | return buy_price, sell_price, st_signal 151 | 152 | buy_price, sell_price, st_signal = implement_st_strategy(aapl['close'], aapl['st']) 153 | 154 | plt.plot(aapl['close'], linewidth = 2) 155 | plt.plot(aapl['st'], color = 'green', linewidth = 2, label = 'ST UPTREND') 156 | plt.plot(aapl['st_dt'], color = 'r', linewidth = 2, label = 'ST DOWNTREND') 157 | plt.plot(aapl.index, buy_price, marker = '^', color = 'green', markersize = 12, linewidth = 0, label = 'BUY SIGNAL') 158 | plt.plot(aapl.index, sell_price, marker = 'v', color = 'r', markersize = 12, linewidth = 0, label = 'SELL SIGNAL') 159 | plt.title('aapl ST TRADING SIGNALS') 160 | plt.legend(loc = 'upper left') 161 | plt.show() 162 | 163 | position = [] 164 | for i in range(len(st_signal)): 165 | if st_signal[i] > 1: 166 | position.append(0) 167 | else: 168 | position.append(1) 169 | 170 | for i in range(len(aapl['close'])): 171 | if st_signal[i] == 1: 172 | position[i] = 1 173 | elif st_signal[i] == -1: 174 | position[i] = 0 175 | else: 176 | position[i] = position[i-1] 177 | 178 | close_price = aapl['close'] 179 | st = aapl['st'] 180 | st_signal = pd.DataFrame(st_signal).rename(columns = {0:'st_signal'}).set_index(aapl.index) 181 | position = pd.DataFrame(position).rename(columns = {0:'st_position'}).set_index(aapl.index) 182 | 183 | frames = [close_price, st, st_signal, position] 184 | strategy = pd.concat(frames, join = 'inner', axis = 1) 185 | 186 | strategy.head() 187 | 188 | rets = aapl.close.pct_change().dropna() 189 | strat_rets = strategy.st_position[1:]*rets 190 | 191 | plt.title('Daily Returns') 192 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 193 | strat_rets.plot(color = 'r', linewidth = 1) 194 | plt.show() 195 | 196 | rets_cum = (1 + rets).cumprod() - 1 197 | strat_cum = (1 + strat_rets).cumprod() - 1 198 | 199 | plt.title('Cumulative Returns') 200 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 201 | strat_cum.plot(color = 'r', linewidth = 2) 202 | plt.show() 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algorithmic Trading with Python 2 | 3 | This repository acts as a library of quantitative algorithms for algorithmic trading implemented in Python. There are currently 23 programs and more will be added with the passage of time. Based on the technical indicator's nature, the algorithms are classified into five directories: Advanced Strategies, Momentum, Overlap, Trend, and Volatility. Use the link here for a detailed explanation of each of the strategies represented: https://nikhiladithyan.medium.com/list/algorithmic-trading-with-python-152fa99c535a 4 | 5 | ## [Advanced Strategies (5)](https://github.com/Nikhil-Adithyan/Algorithmic-Trading-with-Python/tree/main/Advanced%20Strategies) 6 | 7 | This folder contains strategies that use two or more technical indicators. 8 | 9 | 1. **ADX_RSI.py:** A strategy that uses Average Directional Index and RSI 10 | 2. **BB_KC_RSI.py:** A strategy that uses Bollinger Bands, Keltner Channel, and RSI 11 | 3. **BB_STOCH.py:** A strategy that uses Bollinger Bands and Stochastic Oscillator 12 | 4. **STOCH_MACD.py:** A strategy that uses Stochastic Oscillator and MACD 13 | 5. **W%R_MACD.py:** A strategy that uses Williams %R and MACD 14 | 15 | ## [Momentum (11)](https://github.com/Nikhil-Adithyan/Algorithmic-Trading-with-Python/tree/main/Momentum) 16 | 17 | This folder contains strategies that uses Momentum-based technical indicators 18 | 19 | 1. **AO.py:** A strategy based on the Awesome Oscillator 20 | 2. **CCI.py:** A strategy based on the Commodity Channel Index 21 | 3. **CC.py:** A strategy based on the Coppock Curve indicator 22 | 4. **DI.py:** A strategy based on the Disparity Index 23 | 5. **KST.py:** A strategy based on the Know Sure Thing indicator 24 | 6. **MACD.py:** A strategy based on the Moving Average Convergence/Divergence indicator 25 | 7. **RSI.py:** A strategy based on the Relative Strength Index 26 | 8. **RVI.py:** A strategy based on the Relative Vigor Index 27 | 9. **STOCH.py:** A strategy based on the Stochastic Oscillator 28 | 10. **TSI.py:** A strategy based on the True Strength Index 29 | 11. **W%R.py:** A strategy based on the Williams %R indicator 30 | 31 | ## [Overlap (2)](https://github.com/Nikhil-Adithyan/Algorithmic-Trading-with-Python/tree/main/Overlap) 32 | 33 | This folder contains strategies that uses Overlap-based technical indicators 34 | 35 | 1. **ST.py:** A strategy based on the SuperTrend indicator 36 | 2. **SMA.py:** A strategy based on the Simple Moving Average indicator 37 | 38 | ## [Trend (3)](https://github.com/Nikhil-Adithyan/Algorithmic-Trading-with-Python/tree/main/Trend) 39 | 40 | This folder contains strategies that uses Trend-based technical indicators 41 | 42 | 1. **ADX.py:** A strategy based on the Average Directional Index 43 | 2. **AROON.py:** A strategy based on the Aroon indicator 44 | 3. **CI.py:** A strategy based on the Choppiness Index 45 | 46 | ## [Volatility (2)](https://github.com/Nikhil-Adithyan/Algorithmic-Trading-with-Python/tree/main/Volatility) 47 | 48 | This folder contains strategies that uses Volatility-based technical indicators 49 | 50 | 1. **BB.py:** A strategy based on the Bollinger Bands 51 | 2. **KC.py:** A strategy based on the Keltner Channel 52 | -------------------------------------------------------------------------------- /Trend/ADX.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import requests 4 | import matplotlib.pyplot as plt 5 | from math import floor 6 | from termcolor import colored as cl 7 | 8 | plt.style.use('fivethirtyeight') 9 | plt.rcParams['figure.figsize'] = (20,10) 10 | 11 | def get_historical_data(symbol, start_date): 12 | api_key = 'YOUR API KEY' 13 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 14 | raw_df = requests.get(api_url).json() 15 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 16 | df = df[df.index >= start_date] 17 | df.index = pd.to_datetime(df.index) 18 | return df 19 | 20 | aapl = get_historical_data('AAPL', '2020-01-01') 21 | aapl 22 | 23 | def get_adx(high, low, close, lookback): 24 | plus_dm = high.diff() 25 | minus_dm = low.diff() 26 | plus_dm[plus_dm < 0] = 0 27 | minus_dm[minus_dm > 0] = 0 28 | 29 | tr1 = pd.DataFrame(high - low) 30 | tr2 = pd.DataFrame(abs(high - close.shift(1))) 31 | tr3 = pd.DataFrame(abs(low - close.shift(1))) 32 | frames = [tr1, tr2, tr3] 33 | tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1) 34 | atr = tr.rolling(lookback).mean() 35 | 36 | plus_di = 100 * (plus_dm.ewm(alpha = 1/lookback).mean() / atr) 37 | minus_di = abs(100 * (minus_dm.ewm(alpha = 1/lookback).mean() / atr)) 38 | dx = (abs(plus_di - minus_di) / abs(plus_di + minus_di)) * 100 39 | adx = ((dx.shift(1) * (lookback - 1)) + dx) / lookback 40 | adx_smooth = adx.ewm(alpha = 1/lookback).mean() 41 | return plus_di, minus_di, adx_smooth 42 | 43 | aapl['plus_di'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[0]).rename(columns = {0:'plus_di'}) 44 | aapl['minus_di'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[1]).rename(columns = {0:'minus_di'}) 45 | aapl['adx'] = pd.DataFrame(get_adx(aapl['high'], aapl['low'], aapl['close'], 14)[2]).rename(columns = {0:'adx'}) 46 | aapl = aapl.dropna() 47 | aapl.tail() 48 | 49 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 50 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 51 | ax1.plot(aapl['close'], linewidth = 2, color = '#ff9800') 52 | ax1.set_title('AAPL CLOSING PRICE') 53 | ax2.plot(aapl['plus_di'], color = '#26a69a', label = '+ DI 14', linewidth = 3, alpha = 0.3) 54 | ax2.plot(aapl['minus_di'], color = '#f44336', label = '- DI 14', linewidth = 3, alpha = 0.3) 55 | ax2.plot(aapl['adx'], color = '#2196f3', label = 'ADX 14', linewidth = 3) 56 | ax2.axhline(25, color = 'grey', linewidth = 2, linestyle = '--') 57 | ax2.legend() 58 | ax2.set_title('AAPL ADX 14') 59 | plt.show() 60 | 61 | def implement_adx_strategy(prices, pdi, ndi, adx): 62 | buy_price = [] 63 | sell_price = [] 64 | adx_signal = [] 65 | signal = 0 66 | 67 | for i in range(len(prices)): 68 | if adx[i-1] < 25 and adx[i] > 25 and pdi[i] > ndi[i]: 69 | if signal != 1: 70 | buy_price.append(prices[i]) 71 | sell_price.append(np.nan) 72 | signal = 1 73 | adx_signal.append(signal) 74 | else: 75 | buy_price.append(np.nan) 76 | sell_price.append(np.nan) 77 | adx_signal.append(0) 78 | elif adx[i-1] < 25 and adx[i] > 25 and ndi[i] > pdi[i]: 79 | if signal != -1: 80 | buy_price.append(np.nan) 81 | sell_price.append(prices[i]) 82 | signal = -1 83 | adx_signal.append(signal) 84 | else: 85 | buy_price.append(np.nan) 86 | sell_price.append(np.nan) 87 | adx_signal.append(0) 88 | else: 89 | buy_price.append(np.nan) 90 | sell_price.append(np.nan) 91 | adx_signal.append(0) 92 | 93 | return buy_price, sell_price, adx_signal 94 | 95 | buy_price, sell_price, adx_signal = implement_adx_strategy(aapl['close'], aapl['plus_di'], aapl['minus_di'], aapl['adx']) 96 | 97 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 98 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1) 99 | ax1.plot(aapl['close'], linewidth = 3, color = '#ff9800', alpha = 0.6) 100 | ax1.set_title('AAPL CLOSING PRICE') 101 | ax1.plot(aapl.index, buy_price, marker = '^', color = '#26a69a', markersize = 14, linewidth = 0, label = 'BUY SIGNAL') 102 | ax1.plot(aapl.index, sell_price, marker = 'v', color = '#f44336', markersize = 14, linewidth = 0, label = 'SELL SIGNAL') 103 | ax2.plot(aapl['plus_di'], color = '#26a69a', label = '+ DI 14', linewidth = 3, alpha = 0.3) 104 | ax2.plot(aapl['minus_di'], color = '#f44336', label = '- DI 14', linewidth = 3, alpha = 0.3) 105 | ax2.plot(aapl['adx'], color = '#2196f3', label = 'ADX 14', linewidth = 3) 106 | ax2.axhline(25, color = 'grey', linewidth = 2, linestyle = '--') 107 | ax2.legend() 108 | ax2.set_title('AAPL ADX 14') 109 | plt.show() 110 | 111 | position = [] 112 | for i in range(len(adx_signal)): 113 | if adx_signal[i] > 1: 114 | position.append(0) 115 | else: 116 | position.append(1) 117 | 118 | for i in range(len(aapl['close'])): 119 | if adx_signal[i] == 1: 120 | position[i] = 1 121 | elif adx_signal[i] == -1: 122 | position[i] = 0 123 | else: 124 | position[i] = position[i-1] 125 | 126 | close_price = aapl['close'] 127 | plus_di = aapl['plus_di'] 128 | minus_di = aapl['minus_di'] 129 | adx = aapl['adx'] 130 | adx_signal = pd.DataFrame(adx_signal).rename(columns = {0:'adx_signal'}).set_index(aapl.index) 131 | position = pd.DataFrame(position).rename(columns = {0:'adx_position'}).set_index(aapl.index) 132 | 133 | frames = [close_price, plus_di, minus_di, adx, adx_signal, position] 134 | strategy = pd.concat(frames, join = 'inner', axis = 1) 135 | 136 | strategy 137 | 138 | rets = aapl.close.pct_change().dropna() 139 | strat_rets = strategy.adx_position[1:]*rets 140 | 141 | plt.title('Daily Returns') 142 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 143 | strat_rets.plot(color = 'r', linewidth = 1) 144 | plt.show() 145 | 146 | rets_cum = (1 + rets).cumprod() - 1 147 | strat_cum = (1 + strat_rets).cumprod() - 1 148 | 149 | plt.title('Cumulative Returns') 150 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 151 | strat_cum.plot(color = 'r', linewidth = 2) 152 | plt.show() 153 | -------------------------------------------------------------------------------- /Trend/Aroon.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import requests 4 | import matplotlib.pyplot as plt 5 | from math import floor 6 | from termcolor import colored as cl 7 | 8 | plt.style.use('fivethirtyeight') 9 | plt.rcParams['figure.figsize'] = (20, 10) 10 | 11 | def get_historical_data(symbol, start_date): 12 | api_key = 'YOUR API KEY' 13 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 14 | raw_df = requests.get(api_url).json() 15 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 16 | df = df[df.index >= start_date] 17 | df.index = pd.to_datetime(df.index) 18 | return df 19 | 20 | aapl = get_historical_data('AAPL', '2020-01-01') 21 | aapl 22 | 23 | def get_aroon(symbol, lookback, start_date): 24 | api_key = 'YOUR API KEY' 25 | api_url = f'https://api.twelvedata.com/aroon?symbol={symbol}&interval=1day&time_period={lookback}&outputsize=5000&apikey={api_key}' 26 | raw_df = requests.get(api_url).json() 27 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 28 | df = df[df.index >= start_date] 29 | df.index = pd.to_datetime(df.index) 30 | aroon_up = df['aroon_up'] 31 | aroon_down = df['aroon_down'] 32 | return aroon_up, aroon_down 33 | 34 | aapl['aroon_up'], aapl['aroon_down'] = get_aroon('aapl', 25, '2020-01-01') 35 | aapl.tail() 36 | 37 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 38 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 4, colspan = 1) 39 | ax1.plot(aapl['close'], linewidth = 2.5, color = '#2196f3') 40 | ax1.set_title('aapl CLOSE PRICES') 41 | ax2.plot(aapl['aroon_up'], color = '#26a69a', linewidth = 2, label = 'AROON UP') 42 | ax2.plot(aapl['aroon_down'], color = '#ef5350', linewidth = 2, label = 'AROON DOWN') 43 | ax2.legend() 44 | ax2.set_title('aapl AROON 25') 45 | plt.show() 46 | 47 | def implement_aroon_strategy(prices, up, down): 48 | buy_price = [] 49 | sell_price = [] 50 | aroon_signal = [] 51 | signal = 0 52 | 53 | for i in range(len(prices)): 54 | if up[i] >= 70 and down[i] <= 30: 55 | if signal != 1: 56 | buy_price.append(prices[i]) 57 | sell_price.append(np.nan) 58 | signal = 1 59 | aroon_signal.append(signal) 60 | else: 61 | buy_price.append(np.nan) 62 | sell_price.append(np.nan) 63 | aroon_signal.append(0) 64 | elif up[i] <= 30 and down[i] >= 70: 65 | if signal != -1: 66 | buy_price.append(np.nan) 67 | sell_price.append(prices[i]) 68 | signal = -1 69 | aroon_signal.append(signal) 70 | else: 71 | buy_price.append(np.nan) 72 | sell_price.append(np.nan) 73 | aroon_signal.append(0) 74 | else: 75 | buy_price.append(np.nan) 76 | sell_price.append(np.nan) 77 | aroon_signal.append(0) 78 | 79 | return buy_price, sell_price, aroon_signal 80 | 81 | buy_price, sell_price, aroon_signal = implement_aroon_strategy(aapl['close'], aapl['aroon_up'], aapl['aroon_down']) 82 | 83 | ax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1) 84 | ax2 = plt.subplot2grid((11,1), (6,0), rowspan = 4, colspan = 1) 85 | ax1.plot(aapl['close'], linewidth = 2.5, color = '#2196f3') 86 | ax1.plot(aapl.index, buy_price, marker = '^', color = '#26a69a', markersize = 12) 87 | ax1.plot(aapl.index, sell_price, marker = 'v', color = '#ef5350', markersize = 12) 88 | ax1.set_title('aapl CLOSE PRICES') 89 | ax2.plot(aapl['aroon_up'], color = '#26a69a', linewidth = 2, label = 'AROON UP') 90 | ax2.plot(aapl['aroon_down'], color = '#ef5350', linewidth = 2, label = 'AROON DOWN') 91 | ax2.legend() 92 | ax2.set_title('aapl AROON 25') 93 | plt.show() 94 | 95 | position = [] 96 | for i in range(len(aroon_signal)): 97 | if aroon_signal[i] > 1: 98 | position.append(0) 99 | else: 100 | position.append(1) 101 | 102 | for i in range(len(aapl['close'])): 103 | if aroon_signal[i] == 1: 104 | position[i] = 1 105 | elif aroon_signal[i] == -1: 106 | position[i] = 0 107 | else: 108 | position[i] = position[i-1] 109 | 110 | aroon_up = aapl['aroon_up'] 111 | aroon_down = aapl['aroon_down'] 112 | close_price = aapl['close'] 113 | aroon_signal = pd.DataFrame(aroon_signal).rename(columns = {0:'aroon_signal'}).set_index(aapl.index) 114 | position = pd.DataFrame(position).rename(columns = {0:'aroon_position'}).set_index(aapl.index) 115 | 116 | frames = [close_price, aroon_up, aroon_down, aroon_signal, position] 117 | strategy = pd.concat(frames, join = 'inner', axis = 1) 118 | 119 | strategy.head() 120 | 121 | rets = aapl.close.pct_change().dropna() 122 | strat_rets = strategy.aroon_position[1:]*rets 123 | 124 | plt.title('Daily Returns') 125 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 126 | strat_rets.plot(color = 'r', linewidth = 1) 127 | plt.show() 128 | 129 | rets_cum = (1 + rets).cumprod() - 1 130 | strat_cum = (1 + strat_rets).cumprod() - 1 131 | 132 | plt.title('Cumulative Returns') 133 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 134 | strat_cum.plot(color = 'r', linewidth = 2) 135 | plt.show() 136 | -------------------------------------------------------------------------------- /Trend/Choppiness_Index.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import requests 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | 6 | plt.style.use('fivethirtyeight') 7 | plt.rcParams['figure.figsize'] = (20, 10) 8 | 9 | def get_historical_data(symbol, start_date): 10 | api_key = 'YOUR API KEY' 11 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 12 | raw_df = requests.get(api_url).json() 13 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 14 | df = df[df.index >= start_date] 15 | df.index = pd.to_datetime(df.index) 16 | return df 17 | 18 | tsla = get_historical_data('TSLA', '2020-01-01') 19 | tsla 20 | 21 | def get_ci(high, low, close, lookback): 22 | tr1 = pd.DataFrame(high - low).rename(columns = {0:'tr1'}) 23 | tr2 = pd.DataFrame(abs(high - close.shift(1))).rename(columns = {0:'tr2'}) 24 | tr3 = pd.DataFrame(abs(low - close.shift(1))).rename(columns = {0:'tr3'}) 25 | frames = [tr1, tr2, tr3] 26 | tr = pd.concat(frames, axis = 1, join = 'inner').dropna().max(axis = 1) 27 | atr = tr.rolling(1).mean() 28 | highh = high.rolling(lookback).max() 29 | lowl = low.rolling(lookback).min() 30 | ci = 100 * np.log10((atr.rolling(lookback).sum()) / (highh - lowl)) / np.log10(lookback) 31 | return ci 32 | 33 | tsla['ci_14'] = get_ci(tsla['high'], tsla['low'], tsla['close'], 14) 34 | tsla = tsla.dropna() 35 | tsla 36 | 37 | ax1 = plt.subplot2grid((11,1,), (0,0), rowspan = 5, colspan = 1) 38 | ax2 = plt.subplot2grid((11,1,), (6,0), rowspan = 4, colspan = 1) 39 | ax1.plot(tsla['close'], linewidth = 2.5, color = '#2196f3') 40 | ax1.set_title('TSLA CLOSING PRICES') 41 | ax2.plot(tsla['ci_14'], linewidth = 2.5, color = '#fb8c00') 42 | ax2.axhline(38.2, linestyle = '--', linewidth = 1.5, color = 'grey') 43 | ax2.axhline(61.8, linestyle = '--', linewidth = 1.5, color = 'grey') 44 | ax2.set_title('TSLA CHOPPINESS INDEX 14') 45 | plt.show() 46 | 47 | def get_macd(price, slow, fast, smooth): 48 | exp1 = price.ewm(span = fast, adjust = False).mean() 49 | exp2 = price.ewm(span = slow, adjust = False).mean() 50 | macd = pd.DataFrame(exp1 - exp2).rename(columns = {'close':'macd'}) 51 | signal = pd.DataFrame(macd.ewm(span = smooth, adjust = False).mean()).rename(columns = {'macd':'signal'}) 52 | hist = pd.DataFrame(macd['macd'] - signal['signal']).rename(columns = {0:'hist'}) 53 | frames = [macd, signal, hist] 54 | df = pd.concat(frames, join = 'inner', axis = 1) 55 | return df 56 | 57 | tsla_macd = get_macd(tsla['close'], 26, 12, 9) 58 | tsla_macd.tail() 59 | 60 | def implement_ci_macd_strategy(prices, data, ci): 61 | buy_price = [] 62 | sell_price = [] 63 | ci_macd_signal = [] 64 | signal = 0 65 | 66 | for i in range(len(prices)): 67 | if data['macd'][i] > data['signal'][i] and ci[i] < 38.2: 68 | if signal != 1: 69 | buy_price.append(prices[i]) 70 | sell_price.append(np.nan) 71 | signal = 1 72 | ci_macd_signal.append(signal) 73 | else: 74 | buy_price.append(np.nan) 75 | sell_price.append(np.nan) 76 | ci_macd_signal.append(0) 77 | elif data['macd'][i] < data['signal'][i] and ci[i] < 38.2: 78 | if signal != -1: 79 | buy_price.append(np.nan) 80 | sell_price.append(prices[i]) 81 | signal = -1 82 | ci_macd_signal.append(signal) 83 | else: 84 | buy_price.append(np.nan) 85 | sell_price.append(np.nan) 86 | ci_macd_signal.append(0) 87 | else: 88 | buy_price.append(np.nan) 89 | sell_price.append(np.nan) 90 | ci_macd_signal.append(0) 91 | 92 | return buy_price, sell_price, ci_macd_signal 93 | 94 | buy_price, sell_price, ci_macd_signal = implement_ci_macd_strategy(tsla['close'], tsla_macd, tsla['ci_14']) 95 | 96 | ax1 = plt.subplot2grid((19,1,), (0,0), rowspan = 5, colspan = 1) 97 | ax2 = plt.subplot2grid((19,1), (7,0), rowspan = 5, colspan = 1) 98 | ax3 = plt.subplot2grid((19,1), (14,0), rowspan = 5, colspan = 1) 99 | ax1.plot(tsla['close'], linewidth = 2.5, color = '#2196f3') 100 | ax1.plot(tsla.index, buy_price, marker = '^', color = 'green', markersize = 12, label = 'BUY SIGNAL', linewidth = 0) 101 | ax1.plot(tsla.index, sell_price, marker = 'v', color = 'r', markersize = 12, label = 'SELL SIGNAL', linewidth = 0) 102 | ax1.legend() 103 | ax1.set_title('tsla TRADING SIGNALS') 104 | ax2.plot(tsla['ci_14'], linewidth = 2.5, color = '#fb8c00') 105 | ax2.axhline(38.2, linestyle = '--', linewidth = 1.5, color = 'grey') 106 | ax2.axhline(61.8, linestyle = '--', linewidth = 1.5, color = 'grey') 107 | ax2.set_title('tsla CHOPPINESS INDEX 14') 108 | ax3.plot(tsla_macd['macd'], color = 'grey', linewidth = 1.5, label = 'MACD') 109 | ax3.plot(tsla_macd['signal'], color = 'skyblue', linewidth = 1.5, label = 'SIGNAL') 110 | for i in range(len(tsla_macd)): 111 | if str(tsla_macd['hist'][i])[0] == '-': 112 | ax3.bar(tsla_macd.index[i], tsla_macd['hist'][i], color = '#ef5350') 113 | else: 114 | ax3.bar(tsla_macd.index[i], tsla_macd['hist'][i], color = '#26a69a') 115 | ax3.legend() 116 | ax3.set_title('TSLA MACD 26,12,9') 117 | plt.show() 118 | 119 | position = [] 120 | for i in range(len(ci_macd_signal)): 121 | if ci_macd_signal[i] > 1: 122 | position.append(0) 123 | else: 124 | position.append(1) 125 | 126 | for i in range(len(tsla['close'])): 127 | if ci_macd_signal[i] == 1: 128 | position[i] = 1 129 | elif ci_macd_signal[i] == -1: 130 | position[i] = 0 131 | else: 132 | position[i] = position[i-1] 133 | 134 | ci = tsla['ci_14'] 135 | close_price = tsla['close'] 136 | ci_macd_signal = pd.DataFrame(ci_macd_signal).rename(columns = {0:'ci_macd_signal'}).set_index(tsla.index) 137 | position = pd.DataFrame(position).rename(columns = {0:'ci_macd_position'}).set_index(tsla.index) 138 | 139 | frames = [close_price, ci, ci_macd_signal, position] 140 | strategy = pd.concat(frames, join = 'inner', axis = 1) 141 | 142 | strategy.head() 143 | 144 | rets = tsla.close.pct_change()[1:] 145 | strat_rets = strategy.ci_macd_position[1:] * rets 146 | 147 | plt.title('Daily Returns') 148 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 149 | strat_rets.plot(color = 'r', linewidth = 1) 150 | plt.show() 151 | 152 | rets_cum = (1 + rets).cumprod() - 1 153 | strat_cum = (1 + strat_rets).cumprod() - 1 154 | 155 | plt.title('Cumulative Returns') 156 | rets_cum.plot(color = 'blue', alpha = 0.3, linewidth = 7) 157 | strat_cum.plot(color = 'r', linewidth = 2) 158 | plt.show() 159 | -------------------------------------------------------------------------------- /Volatility/Bollinger_Bands.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import matplotlib.pyplot as plt 3 | import requests 4 | import math 5 | from termcolor import colored as cl 6 | import numpy as np 7 | 8 | plt.style.use('fivethirtyeight') 9 | plt.rcParams['figure.figsize'] = (20, 10) 10 | 11 | # EXTRACTING STOCK DATA 12 | 13 | def get_historical_data(symbol, start_date): 14 | api_key = 'YOUR API KEY' 15 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 16 | raw_df = requests.get(api_url).json() 17 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 18 | df = df[df.index >= start_date] 19 | df.index = pd.to_datetime(df.index) 20 | return df 21 | 22 | aapl = get_historical_data('AAPL', '2020-01-01') 23 | aapl 24 | 25 | plt.plot(aapl.index, aapl['close']) 26 | plt.xlabel('Date') 27 | plt.ylabel('Closing Prices') 28 | plt.title('aapl Stock Prices 2020-2021') 29 | plt.show() 30 | 31 | def sma(data, window): 32 | sma = data.rolling(window = window).mean() 33 | return sma 34 | 35 | aapl['sma_20'] = sma(aapl['close'], 20) 36 | aapl.tail(3) 37 | 38 | aapl['close'].plot(label = 'CLOSE', alpha = 0.6) 39 | aapl['sma_20'].plot(label = 'SMA 20', linewidth = 2) 40 | plt.xlabel('Date') 41 | plt.ylabel('Closing Prices') 42 | plt.legend(loc = 'upper left') 43 | plt.show() 44 | 45 | def bb(data, sma, window): 46 | std = data.rolling(window = window).std() 47 | upper_bb = sma + std * 2 48 | lower_bb = sma - std * 2 49 | return upper_bb, lower_bb 50 | 51 | aapl['upper_bb'], aapl['lower_bb'] = bb(aapl['close'], aapl['sma_20'], 20) 52 | aapl.tail() 53 | 54 | aapl['close'].plot(label = 'CLOSE PRICES', color = 'skyblue') 55 | aapl['upper_bb'].plot(label = 'UPPER BB 20', linestyle = '--', linewidth = 1, color = 'black') 56 | aapl['sma_20'].plot(label = 'MIDDLE BB 20', linestyle = '--', linewidth = 1.2, color = 'grey') 57 | aapl['lower_bb'].plot(label = 'LOWER BB 20', linestyle = '--', linewidth = 1, color = 'black') 58 | plt.legend(loc = 'upper left') 59 | plt.title('aapl BOLLINGER BANDS') 60 | plt.show() 61 | 62 | def implement_bb_strategy(data, lower_bb, upper_bb): 63 | buy_price = [] 64 | sell_price = [] 65 | bb_signal = [] 66 | signal = 0 67 | 68 | for i in range(len(data)): 69 | if data[i-1] > lower_bb[i-1] and data[i] < lower_bb[i]: 70 | if signal != 1: 71 | buy_price.append(data[i]) 72 | sell_price.append(np.nan) 73 | signal = 1 74 | bb_signal.append(signal) 75 | else: 76 | buy_price.append(np.nan) 77 | sell_price.append(np.nan) 78 | bb_signal.append(0) 79 | elif data[i-1] < upper_bb[i-1] and data[i] > upper_bb[i]: 80 | if signal != -1: 81 | buy_price.append(np.nan) 82 | sell_price.append(data[i]) 83 | signal = -1 84 | bb_signal.append(signal) 85 | else: 86 | buy_price.append(np.nan) 87 | sell_price.append(np.nan) 88 | bb_signal.append(0) 89 | else: 90 | buy_price.append(np.nan) 91 | sell_price.append(np.nan) 92 | bb_signal.append(0) 93 | 94 | return buy_price, sell_price, bb_signal 95 | 96 | buy_price, sell_price, bb_signal = implement_bb_strategy(aapl['close'], aapl['lower_bb'], aapl['upper_bb']) 97 | 98 | aapl['close'].plot(label = 'CLOSE PRICES', alpha = 0.3) 99 | aapl['upper_bb'].plot(label = 'UPPER BB', linestyle = '--', linewidth = 1, color = 'black') 100 | aapl['sma_20'].plot(label = 'MIDDLE BB', linestyle = '--', linewidth = 1.2, color = 'grey') 101 | aapl['lower_bb'].plot(label = 'LOWER BB', linestyle = '--', linewidth = 1, color = 'black') 102 | plt.scatter(aapl.index, buy_price, marker = '^', color = 'green', label = 'BUY', s = 200) 103 | plt.scatter(aapl.index, sell_price, marker = 'v', color = 'red', label = 'SELL', s = 200) 104 | plt.title('aapl BB STRATEGY TRADING SIGNALS') 105 | plt.legend(loc = 'upper left') 106 | plt.show() 107 | 108 | position = [] 109 | for i in range(len(bb_signal)): 110 | if bb_signal[i] > 1: 111 | position.append(0) 112 | else: 113 | position.append(1) 114 | 115 | for i in range(len(aapl['close'])): 116 | if bb_signal[i] == 1: 117 | position[i] = 1 118 | elif bb_signal[i] == -1: 119 | position[i] = 0 120 | else: 121 | position[i] = position[i-1] 122 | 123 | upper_bb = aapl['upper_bb'] 124 | lower_bb = aapl['lower_bb'] 125 | close_price = aapl['close'] 126 | bb_signal = pd.DataFrame(bb_signal).rename(columns = {0:'bb_signal'}).set_index(aapl.index) 127 | position = pd.DataFrame(position).rename(columns = {0:'bb_position'}).set_index(aapl.index) 128 | 129 | frames = [close_price, upper_bb, lower_bb, bb_signal, position] 130 | strategy = pd.concat(frames, join = 'inner', axis = 1) 131 | 132 | strategy.tail(10) 133 | 134 | rets = aapl.close.pct_change().dropna() 135 | strat_rets = strategy.bb_position[1:]*rets 136 | 137 | plt.title('Daily Returns') 138 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 139 | strat_rets.plot(color = 'r', linewidth = 1) 140 | plt.show() 141 | -------------------------------------------------------------------------------- /Volatility/Keltner_Channel.py: -------------------------------------------------------------------------------- 1 | # IMPORTING PACKAGES 2 | 3 | import requests 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | import pandas as pd 7 | from termcolor import colored as cl 8 | from math import floor 9 | 10 | plt.rcParams['figure.figsize'] = (20,10) 11 | plt.style.use('fivethirtyeight') 12 | 13 | # EXTRACTING STOCK DATA 14 | 15 | def get_historical_data(symbol, start_date): 16 | api_key = 'YOUR API KEY' 17 | api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}' 18 | raw_df = requests.get(api_url).json() 19 | df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float) 20 | df = df[df.index >= start_date] 21 | df.index = pd.to_datetime(df.index) 22 | return df 23 | 24 | aapl = get_historical_data('aapl', '2020-01-01') 25 | aapl.tail() 26 | 27 | # KELTNER CHANNEL CALCULATION 28 | 29 | def get_kc(high, low, close, kc_lookback, multiplier, atr_lookback): 30 | tr1 = pd.DataFrame(high - low) 31 | tr2 = pd.DataFrame(abs(high - close.shift())) 32 | tr3 = pd.DataFrame(abs(low - close.shift())) 33 | frames = [tr1, tr2, tr3] 34 | tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1) 35 | atr = tr.ewm(alpha = 1/atr_lookback).mean() 36 | 37 | kc_middle = close.ewm(kc_lookback).mean() 38 | kc_upper = close.ewm(kc_lookback).mean() + multiplier * atr 39 | kc_lower = close.ewm(kc_lookback).mean() - multiplier * atr 40 | 41 | return kc_middle, kc_upper, kc_lower 42 | 43 | aapl = aapl.iloc[:,:4] 44 | aapl['kc_middle'], aapl['kc_upper'], aapl['kc_lower'] = get_kc(aapl['high'], aapl['low'], aapl['close'], 20, 2, 10) 45 | aapl.tail() 46 | 47 | # KELTNER CHANNEL PLOT 48 | 49 | plt.plot(aapl['close'], linewidth = 2, label = 'aapl') 50 | plt.plot(aapl['kc_upper'], linewidth = 2, color = 'orange', linestyle = '--', label = 'KC UPPER 20') 51 | plt.plot(aapl['kc_middle'], linewidth = 1.5, color = 'grey', label = 'KC MIDDLE 20') 52 | plt.plot(aapl['kc_lower'], linewidth = 2, color = 'orange', linestyle = '--', label = 'KC LOWER 20') 53 | plt.legend(loc = 'lower right', fontsize = 15) 54 | plt.title('aapl KELTNER CHANNEL 20') 55 | plt.show() 56 | 57 | # KELTNER CHANNEL STRATEGY 58 | 59 | def implement_kc_strategy(prices, kc_upper, kc_lower): 60 | buy_price = [] 61 | sell_price = [] 62 | kc_signal = [] 63 | signal = 0 64 | 65 | for i in range(len(prices)): 66 | if prices[i] < kc_lower[i] and prices[i+1] > prices[i]: 67 | if signal != 1: 68 | buy_price.append(prices[i]) 69 | sell_price.append(np.nan) 70 | signal = 1 71 | kc_signal.append(signal) 72 | else: 73 | buy_price.append(np.nan) 74 | sell_price.append(np.nan) 75 | kc_signal.append(0) 76 | elif prices[i] > kc_upper[i] and prices[i+1] < prices[i]: 77 | if signal != -1: 78 | buy_price.append(np.nan) 79 | sell_price.append(prices[i]) 80 | signal = -1 81 | kc_signal.append(signal) 82 | else: 83 | buy_price.append(np.nan) 84 | sell_price.append(np.nan) 85 | kc_signal.append(0) 86 | else: 87 | buy_price.append(np.nan) 88 | sell_price.append(np.nan) 89 | kc_signal.append(0) 90 | 91 | return buy_price, sell_price, kc_signal 92 | 93 | buy_price, sell_price, kc_signal = implement_kc_strategy(aapl['close'], aapl['kc_upper'], aapl['kc_lower']) 94 | 95 | # TRADING SIGNALS PLOT 96 | 97 | plt.plot(aapl['close'], linewidth = 2, label = 'aapl') 98 | plt.plot(aapl['kc_upper'], linewidth = 2, color = 'orange', linestyle = '--', label = 'KC UPPER 20') 99 | plt.plot(aapl['kc_middle'], linewidth = 1.5, color = 'grey', label = 'KC MIDDLE 20') 100 | plt.plot(aapl['kc_lower'], linewidth = 2, color = 'orange', linestyle = '--', label = 'KC LOWER 20') 101 | plt.plot(aapl.index, buy_price, marker = '^', color = 'green', markersize = 15, linewidth = 0, label = 'BUY SIGNAL') 102 | plt.plot(aapl.index, sell_price, marker = 'v', color= 'r', markersize = 15, linewidth = 0, label = 'SELL SIGNAL') 103 | plt.legend(loc = 'lower right') 104 | plt.title('AAPL KELTNER CHANNEL 20 TRADING SIGNALS') 105 | plt.show() 106 | 107 | # STOCK POSITION 108 | 109 | position = [] 110 | for i in range(len(kc_signal)): 111 | if kc_signal[i] > 1: 112 | position.append(0) 113 | else: 114 | position.append(1) 115 | 116 | for i in range(len(aapl['close'])): 117 | if kc_signal[i] == 1: 118 | position[i] = 1 119 | elif kc_signal[i] == -1: 120 | position[i] = 0 121 | else: 122 | position[i] = position[i-1] 123 | 124 | close_price = aapl['close'] 125 | kc_upper = aapl['kc_upper'] 126 | kc_lower = aapl['kc_lower'] 127 | kc_signal = pd.DataFrame(kc_signal).rename(columns = {0:'kc_signal'}).set_index(aapl.index) 128 | position = pd.DataFrame(position).rename(columns = {0:'kc_position'}).set_index(aapl.index) 129 | 130 | frames = [close_price, kc_upper, kc_lower, kc_signal, position] 131 | strategy = pd.concat(frames, join = 'inner', axis = 1) 132 | 133 | strategy 134 | 135 | rets = aapl.close.pct_change().dropna() 136 | strat_rets = strategy.kc_position[1:]*rets 137 | 138 | plt.title('Daily Returns') 139 | rets.plot(color = 'blue', alpha = 0.3, linewidth = 7) 140 | strat_rets.plot(color = 'r', linewidth = 1) 141 | plt.show() 142 | --------------------------------------------------------------------------------