Moving Average Crossover for Stocks using Dash
By: Divya Chandran
Tags: Data Visualization, Stock Market, Dashboard, Dash, Data Science

In this post, we discuss the basics of plotting stock data with two moving averages to determine crossovers and compare returns of the chosen strategy using Python and Dash .

Dash is an open source Python based framework for creating reactive, Web-based applications. Dash makes it easier for data scientists to create interactive charts without worrying about the nitty gritty of HTML or Javascript .

If you are new to Dash , I encourage you to go through the Dash user guide. It provides a very good introduction to Dash, its installation, and basics of its working.

Let’s get started.

First, let us ensure that we have all the required dependencies. The output from the requirement.txt file highlighting the dependencies is shown below.

dash == 1.4.1

dash-html-components==1.0.1

dash-renderer==1.1.0

dash-core-components==1.2.0

pandas == 0.25.2

plotly == 4.2.0

Next, let us load the data.

The stock market data for the company Apple(AAPL) and S&P500 (GSPC) are downloaded as a .csv file from YahooFinance. S&P 500 is a market cap weighted index which represents the benchmark for the overall performance for the stock market. We are using S&P 500 in this example to compare the returns for our crossover moving average strategy. Data for the last 5 years is downloaded for this example.

The required libraries are imported and the stock market data for Apple and S&P 500 are loaded into their respective DataFrames using the pandas library.

import dash

import dash_core_components as dcc

import dash_html_components as html

import pandas as pd

import plotly.graph_objs as go

from dash.dependencies import Input, Output # Initialize the app

app = dash.Dash(__name__) df_aapl_raw = pd.read_csv("data/AAPL.csv")

df_spc_raw = pd.read_csv("data/GSPC.csv")

A sample look at the data shows we have five columns: Date, Open, High, Low, Close, Volume and Ad Close.

Date: date the stock was traded

Open: price of the stock at the beginning of the trading day

High: highest price of the stock on that trading day

Low: lowest price of the stock on that trading day

Close: price of the stock at closing time

Volume: indicates how many stocks were traded

Adj Close: price of the stock that is adjusted for corporate actions

For this example, we only consider the “Date” and stock price reflected in the column “Adj Close”.

The date column for the DataFrames is converted to pandas DatetimeIndex object to conveniently extract a new column “Year” from the “Date” column. This step also helps address any mismatches in dates while plotting the two datasets later.

df_aapl_slice = df_aapl_raw[2:].reset_index()

df_spc_slice = df_spc_raw[:-3].reset_index()

df_aapl_slice['Year'] = pd.DatetimeIndex(df_aapl_slice['Date']).year

df_spc_slice['Year'] = pd.DatetimeIndex(df_spc_slice['Date']).year

Dash Web App

Dash apps are composed of two parts: layout and callbacks .

The “layout” of the app defines the visual feel and look of the app, while the “callbacks” enable the apps to be interactive.

App Layout

I will first explain the layout portion of the app.

The app layout contains components from two libraries: dash_html_components and dash_core_components which enables us to use HTML & CSS with Python. It helps us style the webpage with the required HTML components such as Div, Headers, Graphs, Sliders etc. The custom styling for this app is included in the assets folder as a .css file.You can also add an external css stylesheet which generates the styling for the app. This stylesheet can be initialized using the following code:

external_stylesheets =['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

For our example, the app layout is divided into two graph components: one for plotting the AAPL stock data and another for comparing the market returns with S&P 500. The graph component containing the AAPL stock data contains the sliders for changing the date and two moving averages.

App Callback

Interactivity to the graph components are added using the callback function. The callback function outputs whatever we want, based on the input provided. In our case, we want the following updates to graphs:

a) Updates to the AAPL stock price line chart based on the values defined in the date slider.

b) Updates to the moving average line chart based on the chosen moving average input.

c) Updates to the graph component containing the S&P 500 & AAPL line charts based on values defined in the date range slider.

The updates are defined using two callback functions:

update_ma ()

update_returns()

The Inputs and Outputs indicated in the app.callback () are simply the properties of the Dash component through which we want to make updates to the charts. In the code snippet above, the callback function takes in the value property of the sliders as the input arguments and outputs the figure property of the graph component.

The update_ma () defines the code for plotting the stock prices and calculating the simple moving averages (SMA).

The line chart plotting the stock prices uses plotly.graph_objs to plot the charts and style the layout.The line chart for AAPL stock is updated from the value property of the RangeSlider using pandas DataFrame filters.

The simple moving average (SMA) is simply the arithmetic mean over the number of periods, calculated using the pandas .rolling().mean() method.The window parameter within the .rolling() function is defined by the value property of the Slider .

This app callback for the update_returns() is similar to the previous callback, where the input is the value property of RangeSlider (Year) as input and figure of the graph component as output.

The update_returns() function updates the returns for the date range selected in the date slider. The market returns are calculated by comparing percentage returns for AAPL stock and S&P500 stock for the selected time period.

Bring it all together!

Now we bring it all together. All components of the code for the web app graph is combined and shown below

Here is the link to my Github page with the code.

Deployment

Now the code is ready to run. Follow the steps below to run the code locally in your machine

Save the above code as a Python file with the .py extension

file with the extension Run the file from your terminal or any IDE calling Python.

You might get a warning message similar to this.

Copy the link and open the app locally on a web browser.

Dash apps can also be deployed to server for sharing on the web. Rather than configure a server from scratch, you can take advantage of the simple deployment process through the use of hosting platforms like Heroku.

Summarizing the Web App

Moving average crossover trading strategy is a popular strategy used by some traders to identify potential trade opportunities.

The strategy described here is based on two moving averages. Typically one is longer and another one shorter. When the shorter moving average crosses the longer moving average — it is considered a buy signal. This is known as a golden cross.

Alternatively, when the shorter-term moving average crosses below the longer-term moving average, it is considered a sell signal, to indicate that the trend is shifting down. This is known as a “dead/death cross.

The web app allows us to interactively change the moving averages days to identify when we have a “golden cross” or a “death cross”. The returns (%) graph shows by how much the strategy outperforms the S&P 500 index by aligning the dates on the RangeSlider to the employed moving average strategy.

Final App!

Thank you for reading. I hope you found this post interesting. If I missed anything, please let me know, and feel free to leave comments below to share your thoughts.