Much of technical analysis is staring at charts, not at figures. Few traders can make trading decisions based solely on a table of historical price data - few humans can, in fact. When deciding on a visualisation tool, I recommend opting for something that allows you to interact with the data, minimally through hover-on tooltips. One such Python library which integrates with D3.js and JavaScript is Plotly. (Although I'll be explaining the mechanics of the Python Plotly library, the graphs on this page are generated via the JavaScript Plotly library.)
If you haven't installed Plotly, key in the following command in your terminal for a quick installation:
pip install plotlyOnce installed, load up Plotly together with other relevant libraries in your Python code:
## Loading Libraries
import plotly.express as px
import pandas as pd
import yfinance as yf
To help you see what we're aiming for, I've coded a final product below for you to explore first. A line chart is the most basic of charts used for analysis - however, by plotting the daily high and low prices with time, one minimally obtains a sense of the price band variation of a stock. We'll look at how we can create an interactive line chart with a 1-month and 6-month look-back function for the TSLA stock price via Plotly.
Start off by accessing the stock price data you're interested in from yfinance:
## Accessing stock price data from yfinance
tsla_df=yf.download(
tickers="TSLA",
period="ytd",
interval="1d",
progress=False,
auto_adjust=True
)
## Change the "date" index into a "date" column
tsla_df = tsla_df.reset_index()
Then proceed to create a Plotly chart object and load your data in. We will start by creating only one line that corresponds to the daily low price.
## Creating the Plotly chart object
# Step 1 - Creating the general chart object
fig = px.line( # specify type of chart
tsla_df, # specify dataframe
x="Date", # specify column for x axis
y="Low", # specify column for y axis
title="Tesla Stock Price (Year to Date)"
)
# Step 2 - Creating the traces of the chart (i.e. line)
fig.update_traces(
line_width=2,
line_color="black"
)
# Step 3 - Setting the layout of the chart
fig.update_layout(
xaxis_title="Date",
xaxis_gridcolor="lightgrey",
yaxis_title="Price",
yaxis_gridcolor="lightgrey",
font_color="black",
title_font_size=20,
title_x=0.5,
paper_bgcolor='white',
plot_bgcolor='white'
)
# Step 4 - Generate chart in browser
fig.show()
## Alternatively, write to a HTML file
fig.write_html("tsla-ytd-closing-prices.html")
You should obtain an output like the one below. I recommend always starting with a simple black and white design, with just a single line, so that you can focus on any patterns you may want to highlight in your end product.
This is so important, I've dedicated a single section for it. Once the basic Plotly object is created, you can add traces by using the ".add_trace()" method.
# Step 5 - Create another Plotly object and load in data
fig2 = px.line(
tsla_df,
x="Date",
y="High"
)
# Step 6 - Add the data from fig2 as another
# trace in the original fig
fig.add_trace(fig2.data[0])
This should another line to your plot. And because we pre-empted the default colour blue, we had earlier defined the colour of the first line to be black.
We will now need to format the chart. In simple terms, we will do the following:
From the above list of changes, notice how I've separated the necessary changes into "Layout Changes" and "Trace Changes". I will illustrate two ways to make formatting changes:
# Step 7 - Update trace changes
# Notice how we extract out the datasets individually, and then
# accessing their trace property individually as well
fig.data[0].line.color = "#17BECF"
fig.data[1].line.color = "#7F7F7F"
fig['data'][0]['showlegend']=True
fig['data'][1]['showlegend']=True
fig['data'][0]['name']='Daily Low'
fig['data'][1]['name']='Daily High'
# Step 8a - Actually you can also access layout properties individually
fig.layout.legend.font.color = 'white'
# Step 8b - Update layout through the "update_layout" method
fig.update_layout(
xaxis_title="<b>Date</b>",
xaxis_gridcolor="#272822",
xaxis_title_font_color="white",
yaxis_title="<b>Price</b>t",
yaxis_gridcolor="#272822",
yaxis_title_font_color="white",
title="<b>Tesla Stock Price (YTD, 15 Jun 2022)</b>",
title_font_color="white",
title_x=0.5,
paper_bgcolor="#272822",
plot_bgcolor="#272822"
)
Nicely done! This should have given you the following chart:
Plotly allows us to code for additional chart functions through the use of buttons. Let's try to code a "1-month" and "6-month" lookback, and another button to reset the chart to show all data. We do so using the "update_layout()" method again, and we call in what we call a "rangeselector" (which only works with "date"-type axes):
# Step 9 - Code in a range selector
fig.update_layout(
xaxis=dict(
rangeselector=dict(
buttons=list([
dict(count=1,
label="1m",
step="month",
stepmode="backward"),
dict(count=6,
label="6m",
step="month",
stepmode="backward"),
dict(count=1,
label="YTD",
step="year",
stepmode="todate"),
dict(count=1,
label="1y",
step="year",
stepmode="backward"),
dict(step="all")
])
),
## shows a useful slider at bottom of chart
rangeslider=dict(
visible=True
)
)
)
And this should give you some nice range selection buttons to play with:
Try playing around with the Plotly documentation a bit by yourself, and you'll realise that there are a ton more functions you can code into your chart. We'll explore more of these in posts to come.
Here's the entire Plotly chart coded in Python, for your convenience:
## Loading Libraries
import plotly.express as px
import pandas as pd
import yfinance as yf
## Accessing stock price data from yfinance
tsla_df=yf.download(
tickers="TSLA",
period="ytd",
interval="1d",
progress=False,
auto_adjust=True
)
## Change the "date" index into a "date" column
tsla_df = tsla_df.reset_index()
## Creating the Plotly chart object
# Step 1 - Creating the general chart object
fig = px.line( # specify type of chart
tsla_df, # specify dataframe
x="Date", # specify column for x axis
y="Low", # specify column for y axis
title="Tesla Stock Price (Year to Date)"
)
# Step 2 - Creating the traces of the chart (i.e. line)
fig.update_traces(
line_width=2,
line_color="black"
)
# Step 3 - Setting the layout of the chart
fig.update_layout(
xaxis_title="Date",
xaxis_gridcolor="lightgrey",
yaxis_title="Price",
yaxis_gridcolor="lightgrey",
font_color="black",
title_font_size=20,
title_x=0.5,
paper_bgcolor='white',
plot_bgcolor='white'
)
# Step 4 - Generate chart in browser
fig.show()
# Step 5 - Create another Plotly object and load in data
fig2 = px.line(
tsla_df,
x="Date",
y="High"
)
# Step 6 - Add the data from fig2 as another trace in
# the original fig
fig.add_trace(fig2.data[0])
# Step 7 - Update trace changes
# Notice how we extract out the datasets individually, and then
# accessing their trace property individually as well
fig.data[0].line.color = "#17BECF"
fig.data[1].line.color = "#7F7F7F"
fig['data'][0]['showlegend']=True
fig['data'][1]['showlegend']=True
fig['data'][0]['name']='Daily Low'
fig['data'][1]['name']='Daily High'
# Step 8a - Actually you can also access layout properties individually
fig.layout.legend.font.color = 'white'
# Step 8b - Update layout through the "update_layout" method
fig.update_layout(
xaxis_title="Date",
xaxis_gridcolor="#272822",
xaxis_title_font_color="white",
yaxis_title="Pricet",
yaxis_gridcolor="#272822",
yaxis_title_font_color="white",
title="Tesla Stock Price (YTD, 15 Jun 2022)",
title_font_color="white",
title_x=0.5,
paper_bgcolor="#272822",
plot_bgcolor="#272822"
)
# Step 9 - Code in a range selector
fig.update_layout(
xaxis=dict(
rangeselector=dict(
buttons=list([
dict(count=1,
label="1m",
step="month",
stepmode="backward"),
dict(count=6,
label="6m",
step="month",
stepmode="backward"),
dict(count=1,
label="YTD",
step="year",
stepmode="todate"),
dict(count=1,
label="1y",
step="year",
stepmode="backward"),
dict(step="all")
])
),
## shows a useful slider at bottom of chart
rangeslider=dict(
visible=True
)
)
)
# Step 10 - write to a HTML file
fig.write_html("tsla-ytd-closing-prices.html")
Mhm... how do we compare different stock prices?
Find more Finalytics stories on my blog. Have a suggestion? Contact me at [email protected].