The choice of frequency and Annualization of returns
Contents
# load libraries used in this notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# import data
url="https://raw.githubusercontent.com/amoreira2/Lectures/main/assets/data/GlobalFinMonthly.csv"
Data = pd.read_csv(url,na_values=-99)
Data['Date']=pd.to_datetime(Data['Date'])
Data=Data.set_index(['Date'])
6.3. The choice of frequency and Annualization of returns#
Data is always structured at a particular frequency, daily, monthly…
For example, the data set “Data” that we have been working with is at the “monthly” frequency
So the returns there tell us what you would have earned if you bought a particular asset at the closing of the last trading day of the month (say 31 of January) and sold at the last trading day of the next month (28 of Ferbruary).
But this Frequency choice is entirely arbitrary since there are transactions happening at each milisecond
In this course we will work at monthly or daily frequency since that is what most practioners work with (exception of course for High Frequency trading funds)
It also keeps it managable–as you will quickly see that the data set can get very large once you go to higher frequencies
One could argue that monthly is too short. Most people have one year or even multiple year investment plans so maybe it makes sense to look at the data at lower frequecies.
There is merit to this view, but you end up with much less data, so harder to make conclusive statements
What we end up doing in the academic world and in the industry is to make out analaysis at monthly frquency, and we then extrapolate the results to yearly and so on.
Now we will discuss how to do that.
It is much easier to keep the units at the yearly frequency in your head. So we will be almost always annualize our results just to get intuition about what they mean
Standard annualization (the quick and dirty way)
\(\hat{\mu}_A=12\times\hat{\mu}_M\)
\(\hat{\sigma}^2_A=12\times\hat{\sigma}^2_M\)
\(\hat{\sigma}_A=\sqrt{12}\times\hat{\sigma}_M\)
Formulas make sense if monthly returns are i.i.d. and a sum of monthly returns (e.g. log returns)
However, annual return are given by
if returns were i.i.d, averages are
and variances are uglier still,
and this still ignores time-variation in volatility, auto-correlations..
However, we will always use the standard annualization
\(\hat{\mu}_A=12\times\hat{\mu}_M\)
\(\hat{\sigma}^2_A=12\times\hat{\sigma}^2_M\)
\(\hat{\sigma}_A=\sqrt{12}\times\hat{\sigma}_M\)
# simply multiply by number of months in a year
Data.MKT.mean()*12
0.10862132921174653
# for standard deviation you multiply by the square root of number of periods since the varaince grows with T
Data.MKT.var()*12
0.023235325364506825
Data.MKT.std()*12**0.5
0.15243137919899177
If it is wrong, why we will use it?
Because it is the standard
good idea about annual magnitudes
allows you to compare across assets pretty well
easy to get t-stats from monthly data
ok if you don’t compare returns across frequencies, i.e., use annual data for real estate, and monthly for stocks
6.3.1. Changing the dataset frequency#
Suppose that you don’t want to do this approximation. What do you do?
You have to aggregate the monthly data set to the frequence of choice (say yearly)
This makes no assumptions and it is always correct
For that we will have to learn the `groupby’ method
Conceptually, what do we need to do?
For every year we want to compute the cumulative returns
In the end we want a table that looks like
year |
MKT… |
---|---|
1997 |
\(r_{1997}\) |
1998 |
\(r_{1998}\) |
1999 |
\(r_{1999}\) |
We add 1 to the net return to transform it into a gross returns allowing us to compound it
If you invest 1 in start of month 1 and the returns are 0.2 in month 1 and 0.1 in month 2, how many dollars do you have in the end of month 2?
\[ \$(1+r_1)(1+r_2)=1*(1+0.2)(1+0.1) \]What was you net cumulative return between start of month 1 and end of month 2?
\[ (1+r_1)(1+r_2)-1=1*(1+0.2)(1+0.1)-1 \]
We then just need to compount all the mothly returns of a given year to obtain the yearly returns
Let’s do it step by step:
step 1: \((1+r_t)\)
(Data+1)
step 2: group by year
(Data+1).groupby(Data.index.year)
step 3: gross return within each year using function
prod()
(Data+1).groupby(Data.index.year).prod()
step 4: subtract 1 to get the net return
(Data+1).groupby(Data.index.year).prod()-1
The key here is the groupby method. This is a super useful method that we will use more later on
For more on it, please look at https://amoreira2.github.io/quantitativeinvesting/chapters/pandas/groupby.html
Datayear=(Data+1).groupby(Data.index.year).prod()-1
Datayear.head()
RF | MKT | USA30yearGovBond | EmergingMarkets | WorldxUSA | WorldxUSAGovBond | |
---|---|---|---|---|---|---|
Date | ||||||
1963 | 0.028564 | 0.150037 | -0.000649 | -0.030022 | 0.012480 | 0.029684 |
1964 | 0.035257 | 0.160619 | 0.044469 | -0.062168 | -0.034879 | 0.022714 |
1965 | 0.039186 | 0.144355 | 0.011539 | 0.100006 | 0.029518 | 0.030502 |
1966 | 0.047503 | -0.087400 | -0.020147 | -0.033125 | -0.109079 | 0.003024 |
1967 | 0.041986 | 0.286824 | -0.070192 | 0.106930 | 0.134399 | 0.015742 |
# we could want to calculate the standard devition, the mean, the median, the min, the max, or even to apply some customized function
# in our case all we need is the product
[Datayear.MKT.mean(),Data.MKT.mean()*12,Datayear.MKT.std(),Data.MKT.std()*12**0.5]
[0.1155945787163523,
0.10862132921174653,
0.17219331914550604,
0.15243137919899177]
In problem set I will always ask you about annual numbers
You should always go for the quick and dirty annualization unless told otherwise