A key element to success in trading is to understand the market and the trend of the stock before you buy it. In this tutorial we will not cover how to read the market, but take a top-down analysis approach to stock prices. We will use what is called Multiple Time Frame Analysis on a stock starting with a 1-month, 1-week, and 1-day perspective. Finally, we will compare that with a Simple Moving Average with a monthly view.
We will use the Pandas-datareader library to collect the time series of stock. The library has an endpoint to read data from Yahoo! Finance, which we will use as it does not require registration and can deliver the data we need.
import pandas_datareader as pdr
import datetime as dt
ticker = "MSFT"
start = dt.datetime(2019, 1, 1)
end = dt.datetime.now()
day = pdr.get_data_yahoo(ticker, start, end, interval='d')
week = pdr.get_data_yahoo(ticker, start, end, interval='wk')
month = pdr.get_data_yahoo(ticker, start, end, interval='mo')
Where the key is to set the interval to ‘d’ (Day), ‘wk’ (Week), and ‘mo’ (Month).
This will give us 3 DataFrames, each indexed with different intervals.
Dayly.
High Low ... Volume Adj Close
Date ...
2019-01-02 101.750000 98.940002 ... 35329300.0 98.860214
2019-01-03 100.190002 97.199997 ... 42579100.0 95.223351
2019-01-04 102.510002 98.930000 ... 44060600.0 99.652115
2019-01-07 103.269997 100.980003 ... 35656100.0 99.779205
2019-01-08 103.970001 101.709999 ... 31514400.0 100.502670
Weekly.
High Low ... Volume Adj Close
Date ...
2019-01-01 103.269997 97.199997 ... 157625100.0 99.779205
2019-01-08 104.879997 101.260002 ... 150614100.0 99.769432
2019-01-15 107.900002 101.879997 ... 127262100.0 105.302940
2019-01-22 107.879997 104.660004 ... 142112700.0 102.731720
2019-01-29 106.379997 102.169998 ... 203449600.0 103.376968
Monthly.
High Low ... Volume Adj Close
Date ...
2019-01-01 107.900002 97.199997 ... 7.142128e+08 102.096245
2019-02-01 113.239998 102.349998 ... 4.690959e+08 109.526405
2019-03-01 120.820000 108.800003 ... 5.890958e+08 115.796768
2019-04-01 131.369995 118.099998 ... 4.331577e+08 128.226700
2019-05-01 130.649994 123.040001 ... 5.472188e+08 121.432449
2019-06-01 138.399994 119.010002 ... 5.083165e+08 132.012497
The challenge to connect the DataFrames is that they have different index entries. If we add the data points from Daily with Weekly, there will be a lot of missing entries that Daily has, but Weekly does not have.
day week
Date
2019-01-02 101.120003 NaN
2019-01-03 97.400002 NaN
2019-01-04 101.930000 NaN
2019-01-07 102.059998 NaN
2019-01-08 102.800003 102.050003
... ... ...
2020-08-13 208.699997 NaN
2020-08-14 208.899994 NaN
2020-08-17 210.279999 NaN
2020-08-18 211.490005 209.699997
2020-08-19 209.699997 209.699997
To deal with that we can choose to interpolate by using the DataFrame interpolate function.
import pandas_datareader as pdr
import datetime as dt
import pandas as pd
ticker = "MSFT"
start = dt.datetime(2019, 1, 1)
end = dt.datetime.now()
day = pdr.get_data_yahoo(ticker, start, end, interval='d')
week = pdr.get_data_yahoo(ticker, start, end, interval='wk')
month = pdr.get_data_yahoo(ticker, start, end, interval='mo')
data = pd.DataFrame()
data['day'] = day['Close']
data['week'] = week['Close']
data['week'] = data['week'].interpolate(method='linear')
print(data)
Which results in the following output.
day week
Date
2019-01-02 101.120003 NaN
2019-01-03 97.400002 NaN
2019-01-04 101.930000 NaN
2019-01-07 102.059998 NaN
2019-01-08 102.800003 102.050003
... ... ...
2020-08-13 208.699997 210.047998
2020-08-14 208.899994 209.931998
2020-08-17 210.279999 209.815997
2020-08-18 211.490005 209.699997
2020-08-19 209.699997 209.699997
Where the missing points (except the first entry) will be linearly put between. This can be done for months as well, but we need to be more careful because of three things. First, some dates (1st of the month) do not exist in the data DataFrame. To solve that we use an outer-join, which will include them. Second, this introduces some extra dates, which are not trading dates. Hence, we need to delete them afterwards, which we can do by deleting the column (drop) and removing rows with NA value (dropna). Thirdly, we also need to understand that the monthly view looks backwards. Hence, the 1st of January is first finalized the last day of January. Therefore we shift it back in the join.
import pandas_datareader as pdr
import datetime as dt
import pandas as pd
ticker = "MSFT"
start = dt.datetime(2019, 1, 1)
end = dt.datetime.now()
day = pdr.get_data_yahoo(ticker, start, end, interval='d')
week = pdr.get_data_yahoo(ticker, start, end, interval='wk')
month = pdr.get_data_yahoo(ticker, start, end, interval='mo')
data = pd.DataFrame()
data['day'] = day['Close']
data['week'] = week['Close']
data['week'] = data['week'].interpolate(method='index')
data = data.join(month['Close'].shift(), how='outer')
data['month'] = data['Close'].interpolate(method='index')
data = data.drop(columns=['Close']).dropna()
data['SMA20'] = data['day'].rolling(20).mean()
To visualize it is straight forward by using matplotlib.
import pandas_datareader as pdr
import datetime as dt
import matplotlib.pyplot as plt
import pandas as pd
ticker = "MSFT"
start = dt.datetime(2019, 1, 1)
end = dt.datetime.now()
day = pdr.get_data_yahoo(ticker, start, end, interval='d')
week = pdr.get_data_yahoo(ticker, start, end, interval='wk')
month = pdr.get_data_yahoo(ticker, start, end, interval='mo')
data = pd.DataFrame()
data['day'] = day['Close']
data['week'] = week['Close']
data['week'] = data['week'].interpolate(method='index')
data = data.join(month['Close'].shift(), how='outer')
data['month'] = data['Close'].interpolate(method='index')
data = data.drop(columns=['Close']).dropna()
data.plot()
plt.show()
Which results in the following graph.
As expected the monthly price is adjusted to be the closing day-price the day before. Hence, it looks like the monthly-curve is crossing the day-curve on the 1st every month (which is almost true).
To really appreciate the Multiple Time Frames Analysis, it is better to keep the graphs separate and interpret them each isolated.
Given the picture it is a good idea to start top down. First look at the monthly picture, which shows the overall trend.
In the case of MSFT it is a clear growing trend, with the exception of two declines. But the overall impression is a company in growth that does not seem to slow down. Even the Dow theory (see this tutorial on it) suggest that there will be secondary movements in a general bull trend.
Secondly, we will look at the weekly view.
Here your impression is a bit more volatile. It shows many smaller ups and downs, with a big one in March, 2020. It could also indicate a small decline in the growth right and the end. Also, the Dow theory could suggest that it will turn. Though it is not certain.
Finally, on the daily view it gives a more volatile picture, which can be used to when to enter the market.
Here you could also be a bit worried. Is this the start of a smaller bull market.
To sum up. In the month-view, we have concluded a growth. The week-view shows signs of possible change. Finally, the day-view is also showing signs of possible decline.
As an investor, and based on the above, I would not enter the market right now. If both the month-view and week-view showed growth, while the day-view decline, that would be a good indicator. You want the top level to show growth, while a day-view might show a small decline.
Finally, remember that you should not just use one way to interpret to enter the market or not.
Good question, I am glad you asked. The Simple Moving Average (SMA) can be calculated easy with DataFrames using rolling and mean function.
Best way is to just try it.
import pandas_datareader as pdr
import datetime as dt
import matplotlib.pyplot as plt
import pandas as pd
ticker = "MSFT"
start = dt.datetime(2019, 1, 1)
end = dt.datetime.now()
day = pdr.get_data_yahoo(ticker, start, end, interval='d')
week = pdr.get_data_yahoo(ticker, start, end, interval='wk')
month = pdr.get_data_yahoo(ticker, start, end, interval='mo')
data = pd.DataFrame()
data['day'] = day['Close']
data['week'] = week['Close']
data['week'] = data['week'].interpolate(method='index')
data = data.join(month['Close'].shift(), how='outer')
data['month'] = data['Close'].interpolate(method='index')
data = data.drop(columns=['Close']).dropna()
data['SMA20'] = data['day'].rolling(20).mean()
data.plot()
plt.show()
As you see, the SMA is not as reactive on the in crisis in March, 2020, as the monthly view is. This shows a difference in them. This does not exclude the one from the other, but shows a difference in how they react.
Please remember, that the monthly view is first updated at the end of a month, while SMA is updated on a daily basis.
Other differences is that SMA is an average of the 20 last days, while the monthly is the actual value of the last day of a month (as we look at Close). This implies that the monthly view can be much more volatile than the SMA.
It is advised to make analysis from bigger time frames and zoom in. This way you first look at overall trends, and get a bigger picture of the market. This should eliminate not to fall into being focused on a small detail in the market, but understand it on a higher level.
Would you like to get 12% in return of your investments?
D. A. Carter promises and shows how his simple investment strategy will deliver that in the book The 12% Solution. The book shows how to test this statement by using backtesting.
Did Carter find a strategy that will consistently beat the market?
Actually, it is not that hard to use Python to validate his calculations. But we can do better than that. If you want to work smarter than traditional investors then continue to read here.
Build and Deploy an AI App with Python Flask, OpenAI API, and Google Cloud: In…
Python REST APIs with gcloud Serverless In the fast-paced world of application development, building robust…
App Development with Python using Docker Are you an aspiring app developer looking to level…
Why Value-driven Data Science is the Key to Your Success In the world of data…
Harnessing the Power of Project-Based Learning and Python for Machine Learning Mastery In today's data-driven…
Is Python the right choice for Machine Learning? Should you learn Python for Machine Learning?…
View Comments
As I assume people are looking at this with the intention to copy ideas, please make sure you point out weaknesses in creating interpolated values. Creating automated strategies (or letting an algorithm learn from these inputs) is very dangerous as your values create a "look ahead bias":
2020-08-13 208.699997 210.047998
2020-08-14 208.899994 209.931998
2020-08-17 210.279999 209.815997 <--- !!
2020-08-18 211.490005 209.699997 <--- !!
2020-08-19 209.699997 209.699997
As an example: your daily view on data does not know about the future, therefore does not know about the 209.699 value yet. When closing at 210 or 211, you are suggesting your machine that it can use the future value of 209 form the 19th Aug. 2020 to estimate the drop of the daily prices.
Hi Shuhari,
Thank you for taking the time to write a comment.
I happy that you share your knowledge.
I am not sure I follow along - that is just me not fully understanding the context. You say there is a forward bias. In the above tutorial we use the Close price. Hence, I do not fully understand how the daily close price can be biased?
Please help me understand, so I can improve this tutorial.
Thank you so much.
Rune
Hello sir, I'm a beginner in programming. I have few questions. Correct me if I'm wrong.
1. Can I use 4 hour, 1 hour and 15 minutes timeframes?
2. I trade using renko charts. Is it possible to build renko charts using yahoo Finance?
Hi Vijay,
Great question.
With the Yahoo! Finance free API you can only get daily, weekly, or monthly data. Unfortunately, the API does not offer 4 hours, 1 hour, 15 minute timeframes.
I am not aware of a free api, which provides that.
Cheers,
Rune
Thanks for clarifying.
You can get 1m, 5m, 15m, 1h, 1D, 3Month etc. from yahoo finance. Contact me if interested.....
txt 7572178884 "Let's Code some Python"
In exchange for some Collaboration on Python coding projects.
I could use some help.
Hi Davis,
Great to connect with you. Feel free to reach me on LearnPythonWithRune@gmail.com.