Algorithmic Trading with SMA in Python

Updated: Apr 21

Creating and backtesting an SMA trading strategy in python



Disclaimer: This article is strictly for educational purposes and should not be taken as an investment tip.


Introduction


With the increasing number of technological innovations, many industries deprecated their traditional methods and hoped-in to the latest tech ones to keep themselves updated. And so is the financial industry! In the past few years, there has been a lot going with the financial industry. An enormous amount of technological solutions for finance are invented and enhanced. In this article, we are going to see one of the notable technological innovations in finance which became a quantum leap to the stock trading space and that is nothing but Algorithmic Trading! Let’s dig deeper into this topic.


Algorithmic Trading


In most cases, a stock trade is influenced by humans’ emotions or irrational thinking (sometimes). As a result, it reflected bad results in most of the trades done by the trader. People were thinking of a trading method where they could keep their emotions aside and it was this time the concept of Algorithmic trading was invented. Algorithmic trading is the process of enabling computers to trade stocks under certain conditions or rules. A trade will be performed by the computer automatically when the given condition gets satisfied. Also, these conditions are given to the computers by human traders. The conditions or nothing but trading strategies defined by human traders.


In this article, we will be creating a trading strategy using a technical indicator called Simple Moving Average (SMA)


Simple Moving Average


Simple Moving Average (SMA) is nothing but the average price of a specified period of time. It is a technical indicator and widely used in creating trading strategies. Usually, two SMAs are calculated to build a trading strategy, one with a short period of time and the other with longer than the first one. Now, let's get an intuition on the trading strategy we will be building in this article.


About the trading strategy: Our trading strategy is going to be a simple crossover strategy where the computer shoots a trade when the SMA calculated with a shorter period crosses above the SMA calculated with a longer period. Likewise, the computer sells the stock when the SMA calculated with a longer period crosses above the SMA calculates with a shorter period. This is how our condition for the trading strategy looks like:



IF SMA(SHORT PERIOD) > SMA(LONG PERIOD) => BUY
IF SMA(LONG PERIOD) > SMA(SHORT PERIOD) => SELL


With that, we have finished our theory part. Now let’s implement the trading strategy in python and see it in action.


Implementation in Python


Now, we are going to code our trading strategy in python and see how well it works.


Importing Packages


In this step, we are going to import the required packages into our python environment. The primary packages are going to be Pandas to work with dataframes, Matplotlib to create plots, Requests to make API calls, NumPy to work with arrays. The additional packages are Math to perform mathematical calculations and Termcolor to customize fonts in python.


Python Implementation:



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)


We have imported all the required packages into our python environment. Now let’s extract the historical data of Microsoft (MSFT) from IEX Cloud. Before moving on, if you don’t know what is IEX Cloud and how to pull data from it, I highly recommend you to view my article on it (click here to view the article). Let’s pull some data!


Extracting data from IEX Cloud


In this step, we are going to pull the historic data of Microsoft using an API provided by IEX Cloud.


Python Implementation:



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')
msft = pd.read_csv('msft.csv').set_index('date')
msft.index = pd.to_datetime(msft.index)
msft.tail()


Output:



Code Explanation: First we are defining a function named ‘get_historic_data’ that takes a stock’s ticker as the parameter. Inside the function, we are storing the API key and the URL into their respective variables, and then using the ‘GET’ method provided by the Request package, we are extracting the data in a JSON format. Next, we are doing some data manipulation tasks to clean and make the data usable. Finally, we are returning the dataframe. After finished defining the function, we are calling it and stored the data into the ‘msft’ variable. Let’s calculate the SMA values out of the extracted data.


SMA Calculation


In this step, we are going to calculate two SMA values (SMA 20, 50) and append those values to our dataframe.


Python Implementation:



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)
    
msft.tail()
    

Output:



Code Explanation: Firstly, we are defining a function named ‘sma’ that takes data and the number of periods as the parameters. Inside the function, we are using the ‘rolling’ function provided by the Pandas package to calculate the SMA for the given number of periods. We are storing the calculated values into the ‘sma’ variable and returned it. Next, we are calling the function and calculated two SMA values, the shorter one with 20 as the number of periods, and the longer one with 50 as the number of periods. Now, let’s make a plot out of the calculated SMA values.


Plotting the SMA Values


In this step, we are going to plot the calculated SMA values to make more sense out of them.


Python Implementation:



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()


Output:



Code Explanation: Using the ‘plot’ function provided by the Matplotlib package, we have plotted the SMA values along with the ‘close’ prices of Microsoft. Now let’s observe the graph. The light blue line represents the ‘close’ prices of Microsoft, and the red and gold line represents SMA 20 & SMA 50 respectively. It is observed that the golden line (SMA 50) is way smoother than the red line (SMA 20) because the specified period of time for the golden line’s values is considerably higher than the red line’s values.


Now that we have our SMA values. So let’s proceed in creating the trading strategy.


Creating a Trading Strategy


In this step, we are going to implement the discussed trading strategy in python.


Python Implementation:



def implement_sma_strategy(data, short_window, long_window):
    sma1 = short_window
    sma2 = long_window
    buy_price = []
    sell_price = []
    sma_signal = []
    signal = 0
    
    for i in range(len(data)):
        if sma1[i] > sma2[i]:
            if signal != 1:
                buy_price.append(data[i])
                sell_price.append(np.nan)
                signal = 1
                sma_signal.append(signal)
            else:
                buy_price.append(np.nan)
                sell_price.append(np.nan)
                sma_signal.append(0)
        elif sma2[i] > sma1[i]:
            if signal != -1:
                buy_price.append(np.nan)
                sell_price.append(data[i])
                signal = -1
                sma_signal.append(-1)
            else:
                buy_price.append(np.nan)
                sell_price.append(np.nan)
                sma_signal.append(0)
        else:
            buy_price.append(np.nan)
            sell_price.append(np.nan)
            sma_signal.append(0)
            
    return buy_price, sell_price, sma_signal

sma_20 = msft['sma_20']
sma_50 = msft['sma_50']

buy_price, sell_price, signal = implement_sma_strategy(msft['close'], sma_20, sma_50)


Code Explanation: First, we are defining a function named ‘implement_sma_strategy’ which takes data, and the period of time for both short and long SMA as the parameters.


Inside the function, we are first storing the specified period of time into the ‘sma1’ and the ‘sma2’ variable. Next, we are storing three empty lists in which the values will be appended while creating the trading strategy.


After that, we are implementing the trading strategy through a for-loop. Inside the for-loop, we are passing certain conditions, and if the conditions are satisfied, the respective values will be appended to the empty lists. If the condition to buy the stock gets satisfied, the buying price will be appended to the ‘buy_price’ list, and the signal value will be appended as 1 representing to buy the stock. Similarly, if the condition to sell the stock gets satisfied, the selling price will be appended to the ‘sell_price’ list, and the signal value will be appended as -1 representing to sell the stock.


Finally, we are returning the lists appended with values. Then, we are calling the created function and stored the values into the respective variables. The list doesn't make any sense unless we plot the values. So, let’s plot the values of the created trading lists.


Plotting the Trading lists


In this step, we are going to plot the created trading lists to make sense out of them.


Python Implementation:



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()


Output:



Code Explanation: We are plotting the SMA values along with the buy and sell signals generated by the trading strategy. We can observe that whenever the red line (SMA 20) crosses above the golden line (SMA 50), a buy signal is plotted in blue color, similarly, whenever the golden line crosses above the red line, a sell signal is plotted in red color.


Now, using the trading signals, let’s create our position on the stock.


Creating our Position


In this step, we are going to create a list that indicates 1 if we hold the stock or 0 if we don’t own or hold the stock.


Python Implementation:



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]

sma_20 = pd.DataFrame(sma_20).rename(columns = {0:'sma_20'})
sma_50 = pd.DataFrame(sma_50).rename(columns = {0:'sma_50'}) 
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, signal, position]
strategy = pd.concat(frames,