Simple Moving Average Strategy Using Python

Introduction

Since I began coding, writing my own trading algorithm has been a top priority on my to-do list. I know that it is incredibly hard to make them profitable, as it takes a team of individuals working on and updating the algorithm on a daily basis. As a first-attempt personal project, I do not expect this algorithm to start making me any money. A simple working algorithm is the goal for now.

I initially began with a YouTube video series, hoping that a guided tour of the space would grant me immediate understanding. Unfortunately, there are many added complexities when you want to automate the interaction between code and your online broker, and I was quickly lost. While the video series is something that I will go back to in the future, I will start with a simple time-series analysis and work my way forward.

Simple MA Strategy

Goal:

  • Input: list of stock tickers
  • Output: subset list made from input list made up of stock tickers in which the 30-day moving average has crossed the 200-day moving average in the last 10 days

Visualize Moving Average Strategy

I first downloaded TSLA price data from Yahoo Finance ranging from 2010 to 2020. I wanted to visualize the 30–200 moving average strategy. I first plotted the price:

Next, I plotted the 200 and 30-day moving averages against this price plot:

And, finally, I placed markers on the plot to indicate buy and sell signals:

Now that I had an idea of the strategy implementation, it was time to put it into action.

Returning Subset List of Tickers

As you may have noticed, I am using a 30-day moving average instead of the classical 50-day moving average. This was simply done to ensure that I was not left empty handed with my output. Furthermore, no real-world implementation will be made with the code in this blog. Everything done here was more for curiosity’s sake than anything else.

Anyway, here are the steps I took:

Step 1: Necessary Imports

import pandas_datareader as pdr
import datetime
from datetime import date

Step 2: Writing Function

def ticker_satisfy(list_of_tickers):

# Getting today's date
today = date.today()
# Splitting today's date into day, month, year
end_day = today.day
end_month = today.month
end_year = today.year
# Getting the date 365 days before today
year_ago = date.today() - datetime.timedelta(days=365)
# Splitting year_ago date into day, month, year
start_day = year_ago.day
start_month = year_ago.month
start_year = year_ago.year

buy_list = []

# iterating over list to return satisfying tickers
for ticker in list_of_tickers:

try:
# Grabs daily price data of specified ticker with specified start and end dates
data = pdr.get_data_yahoo(ticker,
start=datetime.datetime(start_year, start_month, start_day),
end=datetime.datetime(end_year, end_month, end_day))
# Creating columns to assess crossover
data['SMA30'] = data['Adj Close'].rolling(window=30).mean()
data['SMA200'] = data['Adj Close'].rolling(window=200).mean()
data['above'] = np.where(data['SMA30'] > data['SMA200'], True, False)

# Dropping null values from dataframe
data = data.dropna()

# Resetting index for simplified slicing
data.reset_index(inplace=True)

# Creating variables for comparison
last_10 = data.iloc[len(data)-10:, :].above.any()
eleventh = data.iloc[len(data)-11].above
except:
continue

# Assessing crossover in last 10 days
if eleventh == False and last_10 == True:
buy_list.append(ticker)
else:
pass

return buy_list

A couple things to point out about the above function:

  1. The try and except statement was used after the function kept running into errors for simplicity’s sake. I did not investigate those errors.
  2. The dates are set up where you can run the function on any given day, and it will return you a list of stocks that satisfy the strategy criteria relative to the current day.
  3. No effort was yet made as to the optimization of the function. With a list of about 3,500 ticker symbols, I killed the kernel after the function was going on an hour of run time. Therefore, as you will see below, I limited the function to an input of only 100 ticker symbols.

Step 3: Getting the output

I downloaded the NYSE ticker symbols as a CSV. I then set variable “tickers” to the first 100 ticker symbols in the CSV. Here are the symbols below:

['DDD','MMM','WBAI','EGHT','AHC','AOS','ATEN','AIR','AAN','ABB','ABT','ABBV','ANF','AGD','AWP','ACP','JEQ','ASGI','AOD','ABM','AKR','ACEL','ACN','ACCO','ATV','AYI','GOLF','ADX','PEO','ADCT','AGRO','ADNT','ADT','ATGE','AAP','WMS','ASIX','AVK','IMPX.U','ACM','AEFC','AEB','AEG','AENZ','AER','AJRD','AMG','MGR','MGRB','AFL','MITT','MITT^A','MITT^B','MITT^C','AGCO','A','AEM','ADC','AL','AL^A','APD','AJAX.U','ALP^Q','ALG','AGI','ALK','AIN','ALB','ACI','AA','ALC','ALEX','ALX','ARE','AQN','AQNA','AQNB','BABA','Y','ATI','ALLE','ALE','ADS','AFB','AWF','AB','AIO','CBH','NCV','NCV^A','NCZ','NCZ^A','ACV','NFJ','NIE','ALSN','ALL','ALL^B','ALL^G','ALL^H']

After running this list of tickers through the function, the output was as follows:

['AIR',
'ABBV',
'AWP',
'ACCO',
'AGRO',
'AFL',
'ADC',
'ALK',
'AIN',
'ALEX',
'Y',
'ATI',
'ALLE',
'ADS']

And, just to make sure the function was properly returning ticker symbols, I plotted the first ticker in the list ‘AIR’:

As you can see from the graph above, the 30-day moving average just passed the 200-day moving average in the last couple days.

Conclusion

Given that the function returned a suitable list, I think we can chalk this exercise up to a success. As we continue to explore python within the field of finance, the goals will get more complex, and the outcomes, hopefully, will incrementally be more useful in real-world applications.

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

LemonSqueezy Vulnhub Walkthrough

MyYut Game Rules

Deploy Microsoft Presidio to AWS

See it here: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html

Hack the Box Shocker

Join Forever Incentivized Beta App Testing

PlayMolecule® CrypticScout: Probing the surface of proteins [TUTORIAL]

A Simple Animation App in Flutter

Kubernetes goes soul (size) searching

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Michael Wirtz

Michael Wirtz

More from Medium

Simple way to visualize financial data. MplFinance

Python Basics, Variables & Data Types

Selecting a Stock Market Data (Web) API: Not So Simple

Top 10 Python tips and tricks that will blow your mind