{"metadata":{"orig_nbformat":4,"language_info":{"name":"python","version":"3.7.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kernelspec":{"name":"python3","display_name":"Python 3 (ipykernel)","language":"python"}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"code","source":"# IMPORTING PACKAGES\n\nimport numpy as np\nimport requests\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom math import floor\nfrom termcolor import colored as cl\nimport yfinance as yf\n\nplt.style.use('fivethirtyeight')\nplt.rcParams['figure.figsize'] = (20,10)\n\n# EXTRACTING STOCK DATA\n\ndef get_historical_data(symbol, start_date):\n    api_key = 'YOUR API KEY'\n    api_url = f'https://api.twelvedata.com/time_series?symbol={symbol}&interval=1day&outputsize=5000&apikey={api_key}'\n    raw_df = requests.get(api_url).json()\n    df = pd.DataFrame(raw_df['values']).iloc[::-1].set_index('datetime').astype(float)\n    df = df[df.index >= start_date]\n    df.index = pd.to_datetime(df.index)\n    return df\n\n# aapl = get_historical_data('AAPL', '2010-01-01')\n\naapl = yf.download(tickers='AAPL', period='9d', interval='2m')\naapl.tail()\n\n# BOLLINGER BANDS CALCULATION\n\ndef sma(data, lookback):\n    sma = data.rolling(lookback).mean()\n    return sma\n\ndef get_bb(data, lookback):\n    std = data.rolling(lookback).std()\n    upper_bb = sma(data, lookback) + std * 2\n    lower_bb = sma(data, lookback) - std * 2\n    middle_bb = sma(data, lookback)\n    return upper_bb, middle_bb, lower_bb\n\naapl['upper_bb'], aapl['middle_bb'], aapl['lower_bb'] = get_bb(aapl['Close'], 20)\naapl.tail()\n\n# BOLLINGER BANDS PLOT\n\nplot_data = aapl[aapl.index >= '2020-01-01']\n\nplt.plot(plot_data['Close'], linewidth = 2.5)\nplt.plot(plot_data['upper_bb'], label = 'UPPER BB 20', linewidth = 2, color = 'violet')\nplt.plot(plot_data['middle_bb'], label = 'MIDDLE BB 20', linewidth = 1.5, color = 'grey')\nplt.plot(plot_data['lower_bb'], label = 'LOWER BB 20', linewidth = 2, color = 'violet')\nplt.title('AAPL BB 20')\nplt.legend(fontsize = 15)\nplt.show()\n\n# KELTNER CHANNEL CALCULATION\n\ndef get_kc(high, low, close, kc_lookback, multiplier, atr_lookback):\n    tr1 = pd.DataFrame(high - low)\n    tr2 = pd.DataFrame(abs(high - close.shift()))\n    tr3 = pd.DataFrame(abs(low - close.shift()))\n    frames = [tr1, tr2, tr3]\n    tr = pd.concat(frames, axis = 1, join = 'inner').max(axis = 1)\n    atr = tr.ewm(alpha = 1/atr_lookback).mean()\n    \n    kc_middle = close.ewm(kc_lookback).mean()\n    kc_upper = close.ewm(kc_lookback).mean() + multiplier * atr\n    kc_lower = close.ewm(kc_lookback).mean() - multiplier * atr\n    \n    return kc_middle, kc_upper, kc_lower\n    \naapl['kc_middle'], aapl['kc_upper'], aapl['kc_lower'] = get_kc(aapl['High'], aapl['Low'], aapl['Close'], 20, 2, 10)\naapl.tail()\n\n# KELTNER CHANNEL PLOT\n\nplot_data = aapl[aapl.index >= '2020-01-01']\n\nplt.plot(plot_data['Close'], linewidth = 2, label = 'AAPL')\nplt.plot(plot_data['kc_upper'], linewidth = 2, color = 'orange', label = 'KC UPPER 20')\nplt.plot(plot_data['kc_middle'], linewidth = 1.5, color = 'grey', label = 'KC MIDDLE 20')\nplt.plot(plot_data['kc_lower'], linewidth = 2, color = 'orange', label = 'KC LOWER 20')\nplt.legend(fontsize = 15)\nplt.title('AAPL KELTNER CHANNEL 20')\nplt.show()\n\nplot_data = aapl[aapl.index >= '2020-01-01']\n\nplt.plot(plot_data['Close'], linewidth = 2.5, label = 'AAPL')\nplt.plot(plot_data['upper_bb'], label = 'UPPER BB 20', linewidth = 2, color = 'violet')\nplt.plot(plot_data['lower_bb'], label = 'LOWER BB 20', linewidth = 2, color = 'violet')\nplt.plot(plot_data['kc_upper'], linewidth = 2, color = 'orange', label = 'KC UPPER 20')\nplt.plot(plot_data['kc_lower'], linewidth = 2, color = 'orange', label = 'KC LOWER 20')\nplt.legend(fontsize = 15)\nplt.show()\n\n# RSI CALCULATION\n\ndef get_rsi(close, lookback):\n    ret = close.diff()\n    up = []\n    down = []\n    for i in range(len(ret)):\n        if ret[i] < 0:\n            up.append(0)\n            down.append(ret[i])\n        else:\n            up.append(ret[i])\n            down.append(0)\n    up_series = pd.Series(up)\n    down_series = pd.Series(down).abs()\n    up_ewm = up_series.ewm(com = lookback - 1, adjust = False).mean()\n    down_ewm = down_series.ewm(com = lookback - 1, adjust = False).mean()\n    rs = up_ewm/down_ewm\n    rsi = 100 - (100 / (1 + rs))\n    rsi_df = pd.DataFrame(rsi).rename(columns = {0:'rsi'}).set_index(close.index)\n    rsi_df = rsi_df.dropna()\n    return rsi_df[3:]\n\naapl['rsi_14'] = get_rsi(aapl['Close'], 14)\naapl = aapl.dropna()\naapl.tail()\n\n# RSI PLOT\n\nax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1)\nax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1)\nax1.plot(plot_data['Close'])\nax1.set_title('AAPL STOCK PRICE')\nax2.plot(aapl['rsi_14'], color = 'orange', linewidth = 1.5)\nax2.axhline(30, color = 'grey', linestyle = '--', linewidth = 1.5)\nax2.axhline(70, color = 'grey', linestyle = '--', linewidth = 1.5)\nax2.set_title('AAPL RSI 14')\nplt.show()\n\n# TRADING STRATEGY\n\ndef bb_kc_rsi_strategy(prices, upper_bb, lower_bb, kc_upper, kc_lower, rsi):\n    buy_price = []\n    sell_price = []\n    bb_kc_rsi_signal = []\n    signal = 0\n    \n    for i in range(len(prices)):\n        if lower_bb[i] < kc_lower[i] and upper_bb[i] > kc_upper[i] and rsi[i] < 30:\n            if signal != 1:\n                buy_price.append(prices[i])\n                sell_price.append(np.nan)\n                signal = 1\n                bb_kc_rsi_signal.append(signal)\n            else:\n                buy_price.append(np.nan)\n                sell_price.append(np.nan)\n                bb_kc_rsi_signal.append(0)\n                \n        elif lower_bb[i] < kc_lower[i] and upper_bb[i] > kc_upper[i] and rsi[i] > 70:\n            if signal != -1:\n                buy_price.append(np.nan)\n                sell_price.append(prices[i])\n                signal = -1\n                bb_kc_rsi_signal.append(signal)\n            else:\n                buy_price.append(np.nan)\n                sell_price.append(np.nan)\n                bb_kc_rsi_signal.append(0)\n        else:\n            buy_price.append(np.nan)\n            sell_price.append(np.nan)\n            bb_kc_rsi_signal.append(0)\n                        \n    return buy_price, sell_price, bb_kc_rsi_signal\n\nbuy_price, sell_price, bb_kc_rsi_signal = bb_kc_rsi_strategy(aapl['Close'], aapl['upper_bb'], aapl['lower_bb'],\n                                                           aapl['kc_upper'], aapl['kc_lower'], aapl['rsi_14'])\n\nax1 = plt.subplot2grid((11,1), (0,0), rowspan = 5, colspan = 1)\nax2 = plt.subplot2grid((11,1), (6,0), rowspan = 5, colspan = 1)\nax1.plot(aapl['Close'])\nax1.plot(aapl.index, buy_price, marker = '^', markersize = 10, linewidth = 0, color = 'green', label = 'BUY SIGNAL')\nax1.plot(aapl.index, sell_price, marker = 'v', markersize = 10, linewidth = 0, color = 'r', label = 'SELL SIGNAL')\nax1.set_title('AAPL STOCK PRICE')\nax2.plot(aapl['rsi_14'], color = 'purple', linewidth = 2)\nax2.axhline(30, color = 'grey', linestyle = '--', linewidth = 1.5)\nax2.axhline(70, color = 'grey', linestyle = '--', linewidth = 1.5)\nax2.set_title('AAPL RSI 10')\nplt.show()\n\n# POSITION\n\nposition = []\nfor i in range(len(bb_kc_rsi_signal)):\n    if bb_kc_rsi_signal[i] > 1:\n        position.append(0)\n    else:\n        position.append(1)\n        \nfor i in range(len(aapl['Close'])):\n    if bb_kc_rsi_signal[i] == 1:\n        position[i] = 1\n    elif bb_kc_rsi_signal[i] == -1:\n        position[i] = 0\n    else:\n        position[i] = position[i-1]\n        \nkc_upper = aapl['kc_upper']\nkc_lower = aapl['kc_lower']\nupper_bb = aapl['upper_bb'] \nlower_bb = aapl['lower_bb']\nrsi = aapl['rsi_14']\nclose_price = aapl['Close']\nbb_kc_rsi_signal = pd.DataFrame(bb_kc_rsi_signal).rename(columns = {0:'bb_kc_rsi_signal'}).set_index(aapl.index)\nposition = pd.DataFrame(position).rename(columns = {0:'bb_kc_rsi_position'}).set_index(aapl.index)\n\nframes = [close_price, kc_upper, kc_lower, upper_bb, lower_bb, rsi, bb_kc_rsi_signal, position]\nstrategy = pd.concat(frames, join = 'inner', axis = 1)\n\nstrategy.tail()\n\n# BACKTESTING\n\naapl_ret = pd.DataFrame(np.diff(aapl['Close'])).rename(columns = {0:'returns'})\nbb_kc_rsi_strategy_ret = []\n\nfor i in range(len(aapl_ret)):\n    returns = aapl_ret['returns'][i]*strategy['bb_kc_rsi_position'][i]\n    bb_kc_rsi_strategy_ret.append(returns)\n    \nbb_kc_rsi_strategy_ret_df = pd.DataFrame(bb_kc_rsi_strategy_ret).rename(columns = {0:'bb_kc_rsi_returns'})\ninvestment_value = 100000\nnumber_of_stocks = floor(investment_value/aapl['Close'][0])\nbb_kc_rsi_investment_ret = []\n\nfor i in range(len(bb_kc_rsi_strategy_ret_df['bb_kc_rsi_returns'])):\n    returns = number_of_stocks*bb_kc_rsi_strategy_ret_df['bb_kc_rsi_returns'][i]\n    bb_kc_rsi_investment_ret.append(returns)\n\nbb_kc_rsi_investment_ret_df = pd.DataFrame(bb_kc_rsi_investment_ret).rename(columns = {0:'investment_returns'})\ntotal_investment_ret = round(sum(bb_kc_rsi_investment_ret_df['investment_returns']), 2)\nprofit_percentage = floor((total_investment_ret/investment_value)*100)\nprint(cl('Profit gained from the BB KC RSI strategy by investing $100k in AAPL : {}'.format(total_investment_ret), attrs = ['bold']))\nprint(cl('Profit percentage of the BB KC RSI strategy : {}%'.format(profit_percentage), attrs = ['bold']))\n\n","metadata":{"trusted":true},"execution_count":null,"outputs":[],"id":"42795293-5286-49d8-977a-fb7fe5964b7f"},{"cell_type":"code","source":"# SPY ETF COMPARISON\n\ndef get_benchmark(start_date, investment_value):\n    spy = get_historical_data('SPY', start_date)['Close']\n    benchmark = pd.DataFrame(np.diff(spy)).rename(columns = {0:'benchmark_returns'})\n    \n    investment_value = investment_value\n    number_of_stocks = floor(investment_value/spy[0])\n    benchmark_investment_ret = []\n    \n    for i in range(len(benchmark['benchmark_returns'])):\n        returns = number_of_stocks*benchmark['benchmark_returns'][i]\n        benchmark_investment_ret.append(returns)\n\n    benchmark_investment_ret_df = pd.DataFrame(benchmark_investment_ret).rename(columns = {0:'investment_returns'})\n    return benchmark_investment_ret_df\n\nbenchmark = get_benchmark('2010-01-01', 100000)\ninvestment_value = 100000\ntotal_benchmark_investment_ret = round(sum(benchmark['investment_returns']), 2)\nbenchmark_profit_percentage = floor((total_benchmark_investment_ret/investment_value)*100)\nprint(cl('Benchmark profit by investing $100k : {}'.format(total_benchmark_investment_ret), attrs = ['bold']))\nprint(cl('Benchmark Profit percentage : {}%'.format(benchmark_profit_percentage), attrs = ['bold']))\nprint(cl('BB KC RSI Strategy profit is {}% higher than the Benchmark Profit'.format(profit_percentage - benchmark_profit_percentage), attrs = ['bold']))","metadata":{},"execution_count":null,"outputs":[],"id":"7eeb9dbc-d12f-4888-a436-2dae11a2f539"}]}