#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jun  5 12:25:25 2021

@author: wupeipei
"""

import pandas as pd 
import matplotlib.pyplot as plt 
import requests
import math
from termcolor import colored as cl 
import numpy as np

plt.style.use('fivethirtyeight')
plt.rcParams['figure.figsize'] = (15, 8)

# EXTRACTING DATA

def get_historic_data(symbol):
    ticker = symbol
    iex_api_key = 'Tsk_30a2677082d54c7b8697675d84baf94b'
    api_url = f'https://sandbox.iexapis.com/stable/stock/{ticker}/chart/max?token={iex_api_key}'
    df = requests.get(api_url).json()
    
    date = []
    open = []
    high = []
    low = []
    close = []
    
    for i in range(len(df)):
        date.append(df[i]['date'])
        open.append(df[i]['open'])
        high.append(df[i]['high'])
        low.append(df[i]['low'])
        close.append(df[i]['close'])
    
    date_df = pd.DataFrame(date).rename(columns = {0:'date'})
    open_df = pd.DataFrame(open).rename(columns = {0:'open'})
    high_df = pd.DataFrame(high).rename(columns = {0:'high'})
    low_df = pd.DataFrame(low).rename(columns = {0:'low'})
    close_df = pd.DataFrame(close).rename(columns = {0:'close'})
    frames = [date_df, open_df, high_df, low_df, close_df]
    df = pd.concat(frames, axis = 1, join = 'inner')
    return df

msft = get_historic_data('MSFT')
msft = msft.set_index('date')
msft = msft[msft.index >= '2020-01-01']
msft.index = pd.to_datetime(msft.index)
msft.to_csv('msft.csv')

# IMPORTING DATA

msft = pd.read_csv('msft.csv').set_index('date')
msft.index = pd.to_datetime(msft.index)

# DEFINING SMA FUNCTION

def sma(data, n):
    sma = data.rolling(window = n).mean()
    return pd.DataFrame(sma)

n = [20, 50]
for i in n:
    msft[f'sma_{i}'] = sma(msft['close'], i)

# PLOTTING SMA VALUES

plt.plot(msft['close'], label = 'MSFT', linewidth = 5, alpha = 0.3)
plt.plot(msft['sma_20'], label = 'SMA 20')
plt.plot(msft['sma_50'], label = 'SMA 50')
plt.title('MSFT Simple Moving Averages (20, 50)')
plt.legend(loc = 'upper left')
plt.show()

# CREATING SMA TRADING STRATEGY
msft = data.copy()
msft['close' ]= msft['Close']
data1 
data1 = msft.iloc[55:,:] 
def implement_sma_strategy(data, short_window, long_window):
    sma1 =  data1['ema_21']
    sma2 = data1['ema_55']
    buy_price = []
    buy_price1= []
    sell_price = []
    sell_price1= []
    sma_signal = []
    signal = 0
    for i in range(1,len(data1)):
        i=3
        if signal ==0:
            if sma1[i] >= sma2[i]:
                buy_price.append(data1['Close'][i])
                buy_price1.append(np.nan)
                sell_price1.append(np.nan)
                sell_price.append(np.nan)
                signal = 1
                sma_signal.append(1)
                
                
            elif sma1[i] < sma2[i]:
                sell_price.append(-data1['Close'][i])
                sell_price1.append(np.nan)
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                signal = -1
                sma_signal.append(-1)
                
            else:
                sell_price.append(np.nan)
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                sell_price1.append(np.nan)
                signal = 0
                sma_signal.append(0)
                

        elif signal == 1:
            mul = 3
            if data1['Low'][i] < (data1['Close'][i-1] - (mul * data1['ATR'][i-1])):
                   buy_price1.append((data1['Close'][i-1] - (mul * data1['ATR'][i-1])))
                   buy_price.append(np.nan)
                   sell_price1.append(np.nan)
                   sell_price.append(np.nan)
                   signal = 0
                   sma_signal.append(0)
    
            elif sma1[i] < sma2[i]:
                sell_price.append(data1['Close'][i])
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                sell_price1.append(np.nan)
                signal = -1
                sma_signal.append(-1)
                
            else:
                signal = 1
                sma_signal.append(1)
                buy_price.append(data1['Close'][i])
                buy_price1.append(np.nan)
                sell_price1.append(np.nan)
                sell_price.append(np.nan)
                
        elif signal == -1:
            if data1['High'][i] > (data1['Close'][i-1] + (mul * data1['ATR'][i-1])):
                sell_price1.append((data1['Close'][i-1] + (mul * data1['ATR'][i-1])))
                sell_price.append(np.nan)
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                signal = 0
                sma_signal.append(0)
                
            elif sma1[i] > sma2[i]:
                buy_price.append(data1['Close'][i])
                buy_price1.append(np.nan)
                sell_price1.append(np.nan)
                sell_price.append(np.nan)
                signal = 1
                sma_signal.append(1)
data2 = data1.iloc[:10, :]                
                
data2 = data2[['Close','Low','ema_21',"ema_55",'ATR']]
    return buy_price, sell_price, sma_signal
def implement_sma_strategy(data, short_window, long_window):
    sma1 =  data1['ema_21']
    sma2 = data1['ema_55']
    sma2 = data1['ema_55']
    buy_price = []
    buy_price1= []
    sell_price = []
    sell_price1= []
    sma_signal = []
    signal = 0
    i=3
    for i in range(1,5):
        if signal != 1:
            if sma1[i] >= sma2[i]:
                buy_price.append(data1['Close'][i])
                buy_price1.append(np.nan)
                signal = 1
                sma_signal.append(1)
                
            else:
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                signal = 0
                sma_signal.append(0)

        elif signal == 1:
            mul = 3
            if data1['Low'][i] <= (data1['Close'][i-1] - (mul * data1['ATR'][i-1])):
                   buy_price1.append((data1['Close'][i-1] - (mul * data1['ATR'][i-1])))
                   buy_price.append(np.nan)
                   signal = -1
                   sma_signal.append(-1)
    
            else :
                signal = 1
                buy_price.append(data1['Close'][i])
                buy_price.append(np.nan)
                sma_signal.append(1)
          
            
    sma1 =  data2['ema_21']
    sma2 = data2['ema_55']
    sma2 = data2['ema_55']
    buy_price = []
    buy_price1= []
    sell_price = []
    sell_price1= []
    sma_signal = []
    signal = 0
    i=3
    for i in range(1,len(data2)):
        if signal != 1:
            if sma1[i] >= sma2[i]:
                buy_price.append(data2['Close'][i])
                buy_price1.append(np.nan)
                signal = 1
                sma_signal.append(1)
                
            else:
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                signal = 0
                sma_signal.append(0)

        elif signal == 1:
            mul = 3
            if data2['Low'][i] <= (data2['Close'][i-1] - (mul * data2['ATR'][i-1])):
                   buy_price1.append((data1['Close'][i-1] - (mul * data1['ATR'][i-1])))
                   buy_price.append(np.nan)
                   signal = -1
                   sma_signal.append(-1)
    
            else :
                signal = 1
                buy_price.append(data2['Close'][i])
                buy_price1.append(np.nan)
                signal = 1
                sma_signal.append(1)          
            
               
            
            
            
            
            
            
        elif signal == -1:
            if data1['High'][i] > (data1['Close'][i-1] + (mul * data1['ATR'][i-1])):
                sell_price1.append((data1['Close'][i-1] + (mul * data1['ATR'][i-1])))
                sell_price.append(np.nan)
                buy_price.append(np.nan)
                buy_price1.append(np.nan)
                signal = 0
                sma_signal.append(0)
                
            elif sma1[i] > sma2[i]:
                buy_price.append(data1['Close'][i])
                buy_price1.append(np.nan)
                sell_price1.append(np.nan)
                sell_price.append(np.nan)
                signal = 1
                sma_signal.append(1)
sma_20 = msft['sma_20']
sma_50 = msft['sma_50']

data = stocks.copy()
h_l = data["High"] - data["Low"]
h_cp = abs(data["High"] - data["Close"].shift(1))
l_cp = abs(data["Low"] - data["Close"].shift(1))
true_range2 = (h_l, h_cp, l_cp)
true_range2
true_range3 = pd.DataFrame(true_range2)
true_range4 = true_range3.T
true_range4.columns = ["h_l", "h_cp", "l_cp"]
data["maximum_value"] = true_range4.max(axis = 1)
length = 21
data['ATR'] = data["maximum_value"].rolling(length).mean()


data['atr_ts1'] = ''
data['atr_ts2'] = ''
df = data
df['crossover'] = ''
mul =3.5
long_short = input("Are you long or short?")
if long_short == 'long':
    df['atr_ts1'] = df['Close'] - (mul * df['ATR'])
    df['atr_ts2'] = df['atr_ts1'].cummax()
    df['crossover'] = df['atr_ts2'] > df['Close']
elif long_short == 'short':
    df['atr_ts1'] = df['Close'] + (mul * df['ATR'])
    df['atr_ts2'] = df['atr_ts1'].cummin()
    df['crossover'] = df['atr_ts2'] < df['Close']
buy_price, sell_price, signal = implement_sma_strategy(msft['close'], sma_20, sma_50)
for i in range(1,len(ohlc_dict)):
        if tickers_signal[ticker] == "":
            tickers_ret[ticker].append(0)
            if sma1[i] > sma2[i]:
                tickers_signal[ticker] = "Buy"
            elif sma1[i] < sma2[i]:
                tickers_signal[ticker] = "Sell"
        
        elif tickers_signal[ticker] == "Buy":
            if ohlc_dict[ticker]["Low"][i]<ohlc_dict[ticker]["Close"][i-1] - ohlc_dict[ticker]["ATR"][i-1]:
                tickers_signal[ticker] = ""
                tickers_ret[ticker].append(((ohlc_dict[ticker]["Close"][i-1] - ohlc_dict[ticker]["ATR"][i-1])/ohlc_dict[ticker]["Close"][i-1])-1)
            elif ohlc_dict[ticker]["Low"][i]<=ohlc_dict[ticker]["roll_min_cp"][i] and \
               ohlc_dict[ticker]["Volume"][i]>1.5*ohlc_dict[ticker]["roll_max_vol"][i-1]:
                tickers_signal[ticker] = "Sell"
                tickers_ret[ticker].append((ohlc_dict[ticker]["Close"][i]/ohlc_dict[ticker]["Close"][i-1])-1)
            else:
                tickers_ret[ticker].append((ohlc_dict[ticker]["Close"][i]/ohlc_dict[ticker]["Close"][i-1])-1)
                
        elif tickers_signal[ticker] == "Sell":
            if ohlc_dict[ticker]["High"][i]>ohlc_dict[ticker]["Close"][i-1] + ohlc_dict[ticker]["ATR"][i-1]:
                tickers_signal[ticker] = ""
                tickers_ret[ticker].append((ohlc_dict[ticker]["Close"][i-1]/(ohlc_dict[ticker]["Close"][i-1] + ohlc_dict[ticker]["ATR"][i-1]))-1)
            elif ohlc_dict[ticker]["High"][i]>=ohlc_dict[ticker]["roll_max_cp"][i] and \
               ohlc_dict[ticker]["Volume"][i]>1.5*ohlc_dict[ticker]["roll_max_vol"][i-1]:
                tickers_signal[ticker] = "Buy"
                tickers_ret[ticker].append((ohlc_dict[ticker]["Close"][i-1]/ohlc_dict[ticker]["Close"][i])-1)
            else:
                tickers_ret[ticker].append((ohlc_dict[ticker]["Close"][i-1]/ohlc_dict[ticker]["Close"][i])-1)
                
    ohlc_dict[ticker]["ret"] = np.array(tickers_ret[ticker])



# PLOTTING SMA TRADE SIGNALS

plt.plot(msft['close'], alpha = 0.3, label = 'MSFT')
plt.plot(sma_20, alpha = 0.6, label = 'SMA 20')
plt.plot(sma_50, alpha = 0.6, label = 'SMA 50')
plt.scatter(msft.index, buy_price, marker = '^', s = 200, color = 'darkblue', label = 'BUY SIGNAL')
plt.scatter(msft.index, sell_price, marker = 'v', s = 200, color = 'crimson', label = 'SELL SIGNAL')
plt.legend(loc = 'upper left')
plt.title('MSFT SMA CROSSOVER TRADING SIGNALS')
plt.show()

# OUR POSITION IN STOCK (HOLD/SOLD)

position = []
for i in range(len(signal)):
    if signal[i] > 1:
        position.append(0)
    else:
        position.append(1)
        
for i in range(len(msft['close'])):
    if signal[i] == 1:
        position[i] = 1
    elif signal[i] == -1:
        position[i] = 0
    else:
        position[i] = position[i-1]
        
# CONSOLIDATING LISTS TO DATAFRAME

sma_20 = pd.DataFrame(sma_20).rename(columns = {0:'sma_20'})
sma_50 = pd.DataFrame(sma_50).rename(columns = {0:'sma_50'})
buy_price = pd.DataFrame(buy_price).rename(columns = {0:'buy_price'}).set_index(msft.index)
sell_price = pd.DataFrame(sell_price).rename(columns = {0:'sell_price'}).set_index(msft.index)
signal = pd.DataFrame(signal).rename(columns = {0:'sma_signal'}).set_index(msft.index)
position = pd.DataFrame(position).rename(columns = {0:'sma_position'}).set_index(msft.index)

frames = [sma_20, sma_50, buy_price, sell_price, signal, position]
strategy = pd.concat(frames, join = 'inner', axis = 1)
strategy = strategy.reset_index().drop('date', axis = 1)

# BACKTESTING THE STRAGEGY

msft_ret = pd.DataFrame(np.diff(msft['close'])).rename(columns = {0:'returns'})
sma_strategy_ret = []

for i in range(len(msft_ret)):
    try:
        returns = msft_ret['returns'][i]*strategy['sma_position'][i]
        sma_strategy_ret.append(returns)
    except:
        pass
    
sma_strategy_ret_df = pd.DataFrame(sma_strategy_ret).rename(columns = {0:'sma_returns'})

investment_value = 100000
number_of_stocks = math.floor(investment_value/msft['close'][1])
sma_investment_ret = []

for i in range(len(sma_strategy_ret_df['sma_returns'])):
    returns = number_of_stocks*sma_strategy_ret_df['sma_returns'][i]
    sma_investment_ret.append(returns)

sma_investment_ret_df = pd.DataFrame(sma_investment_ret).rename(columns = {0:'investment_returns'})
total_investment_ret = round(sum(sma_investment_ret_df['investment_returns']), 2)
print(cl('Profit gained from the strategy by investing $100K in MSFT : ${} in 1 Year'.format(total_investment_ret), attrs = ['bold']))
view rawsma_algo_full_code.py hosted with ❤ by GitHub