Definition of excess returns, as per {exret}: Excess return for a stock is the difference between the stock return and the return on the risk-free security over the same period. For such risk-free securities, it is common to use a government bond such as a 10-year US Treasury bond.\
Definition of mktcap, as per {mktcap}: The variable ‘mktcap’ is defined as the market capitalization, which refers to the total dollar market value of a company’s outstanding shares of stock. Market capitalization is commonly referred to as “market cap,” and is calculated by multiplying the total number of a company’s outstanding shares by the current market price of one share.
## [1] "There is probably a smarter way to do this, but this method includes creating two seperate summary statistics. One can do the summary statistics across a variable. "
| name | ret_excess | mktcap |
|---|---|---|
| mean | 0.0083 | 1814.65 |
| sd | 0.1523 | 8770.21 |
| min | -0.6906 | 0.71 |
| max | 2.6775 | 242415.02 |
Summary statistics for ret_excess and mktcap shows that the mean return per month is 0.79% although the median is -0.0004%. An important distinction between the variables is that ret_excess is in relative numbers, while mktcap of course is absolute, since the return is a relative change and market cap is a true number.
If crsp_monthly contains implicitly missing values, this will cause a ret_excess_lag to not necessarily represent the value of the previous month, but the previous value in the dataset. An implicitly missing value then makes a ret_excess_lag value represent the second lagged value.
Even without implicitly missing values, the given code returns a variable with missing values for the first cell of every permno. The following code can be used to avoid missing values.
## # A tibble: 6 x 9
## permno month ret rf ret_excess mkt_excess mktcap mktcap_lag
## <dbl> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 10000 1986-02-01 -0.257 0.0053 -0.262 0.0713 12.0 16.1
## 2 10000 1986-03-01 0.365 0.006 0.359 0.0488 16.3 12.0
## 3 10000 1986-04-01 -0.0986 0.0052 -0.104 -0.0131 15.2 16.3
## 4 10000 1986-05-01 -0.223 0.0049 -0.228 0.0462 11.8 15.2
## 5 10000 1986-06-01 -0.00503 0.0052 -0.0102 0.0103 11.7 11.8
## 6 10000 1986-07-01 -0.0808 0.0052 -0.0860 -0.0645 10.8 11.7
## # ... with 1 more variable: ret_excess_lag <dbl>
| ret | ret_lag | |
|---|---|---|
| ret | 1 | -0.01738 |
As the mean of returns is non-constant, it does not fluctuate around a constant value, returns suffer from autocorrelation. Furthermore, there is a negative correlation between \(r_t\) and \(r_{t-1}\).
The PACF plot clearly shows that there is a significant relationship between \(r_t\) and \(r_{t-1}\).
Lagging a variable can be a frustrating task, since the days of a month will differ. The below function will always return a date in the nth month after Date. This allows for 1) not exceeding the end of month and 2) handles NA’s really well.
First we create a variable by lagging the month column without touching the others. Next, we merge our sorting variable with the return data. We use the 12-month lagged marketcap as a sorting variable to ensure that the sorts rely only on information available when we create the portfolios.
\[Mom_{i,t} = 100\frac{(mc_{i,t-1} −mc_{i,t-12})}{mc_{i,t-12}}\]
Create summary statistics for \(Mom_{i,t}\) as follows: Each month, compute the mean, standard deviation, minimum, fifth percentile, 25th percentile, median, 75th percentile, 95th percentile, and maximum values of the cross-sectional distribution of \(Mom_{i,t}\).
| Mean | SD | Min | Q5 | Q25 | Median | Q75 | Q95 | Max |
|---|---|---|---|---|---|---|---|---|
| 18.99 | 95.41 | -89.13 | -48.21 | -16.28 | 5.576 | 32.99 | 117.9 | 3169 |
| momentum | log_mktcap | |
|---|---|---|
| momentum | 1 | 0.06729 |
| log_mktcap | 0.06729 | 1 |
Yes, there is a positive correlation coefficient of 0.067 between the momentum value and log of market capitalization.
We need to create a function that is able to sort stocks into a number of portfolios. We use quantile() to compute breakpoints for n_portfolios. Then, we assign portfolios to stocks using the findInterval() function. The output of the following function is a new column that contains the number of the portfolio to which a stock belongs.
First, we create a function that is able to sort stocks into a number of portfolios based on their momentum score. The output one gets when running the function with a dataframe is a new column that contains the number of the portfolio in which the stock belongs.
## # A tibble: 6 x 6
## # Groups: month [4]
## permno month ret mktcap_lag momentum portfolio
## <dbl> <date> <dbl> <dbl> <dbl> <fct>
## 1 10000 1987-02-01 0 1.58 -86.8 1
## 2 10000 1987-03-01 -0.385 1.58 -90.3 1
## 3 10000 1987-04-01 -0.0625 0.973 -93.6 1
## 4 10000 1987-05-01 -0.0667 0.912 -92.3 1
## 5 10001 1987-02-01 -0.0741 6.69 8.66 6
## 6 10001 1987-03-01 0.0368 6.19 -0.387 5
This shows a snip of the new portfolios sorts that have been created. Portfolio 1 has the lowest momentum and 10 has the highest.
## # A tibble: 10 x 3
## portfolio mom_mean mc_mean
## <fct> <dbl> <dbl>
## 1 1 -53.8 288.
## 2 2 -30.4 899.
## 3 3 -17.6 1578.
## 4 4 -7.69 2092.
## 5 5 1.19 2479.
## 6 6 10.2 2745.
## 7 7 20.7 2813.
## 8 8 34.7 2727.
## 9 9 59.0 2226.
## 10 10 184. 1213.
This summary shows that the lowest portfolio sorts on momentum has the lowest market capitalization as well. Momentum is small for the largest companies. Momentum portfolios ranging from 6 to 8 has the highest market cap. The fact that the highest momentum companies are not the largest makes sense, since the largest companies might not be able to grow their business as much as smaller.
## # A tibble: 10 x 4
## portfolio alpha beta excess_ret
## <fct> <dbl> <dbl> <dbl>
## 1 1 -0.00676 1.67 0.00267
## 2 2 -0.00374 1.35 0.00392
## 3 3 -0.00109 1.17 0.00552
## 4 4 -0.000223 1.06 0.00574
## 5 5 0.000849 0.977 0.00637
## 6 6 -0.000661 0.957 0.00475
## 7 7 0.000668 0.942 0.00599
## 8 8 0.00151 0.939 0.00682
## 9 9 0.00149 1.02 0.00727
## 10 10 0.00312 1.22 0.0100
The plot indicates that the higher the momentum of a portfolio, the higher is the realized alpha. Alpha becomes negative in the bottom four portfolio sorts. The beta of the momentum portfolio is highest in the lowest decile, which might come from the fact that this is also the portfolios with the lowest market capitalization.
## `summarise()` has grouped output by 'month'. You can override using the
## `.groups` argument.
## # A tibble: 2 x 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 0.00988 0.00308 3.21 1.40e- 3
## 2 mkt_excess -0.448 0.0685 -6.54 1.20e-10
The test statistics shows that is it possible to generate 0.1% alpha by having a short position in the lowest decile momentum stocks and a long position in highest decile momentum stocks. The alpha can be implied by the graph above, which shows that alpha is highest within the highest momentum stocks. The strategy is not market neutral as the beta is -0.45.
The momentum strategy delivers the highest risk-adjusted excess return with a 1-month ahead horizon. The 0-month ahead is included as a verification of the method, as this is the same number as earlier reported.
## `summarise()` has grouped output by 'month'. You can override using the `.groups` argument.
## `summarise()` has grouped output by 'month'. You can override using the `.groups` argument.
## `summarise()` has grouped output by 'month'. You can override using the `.groups` argument.
## `summarise()` has grouped output by 'month'. You can override using the `.groups` argument.
## `summarise()` has grouped output by 'month'. You can override using the `.groups` argument.
| k ahead | alpha |
|---|---|
| 0 | 0.00988 |
| 1 | 0.1074 |
| 3 | 0.1048 |
| 6 | 0.106 |
| 12 | 0.01142 |
When a given portfolio selection is based on i.e., past year market cap momentum, then the composition of the portfolio would change frequently as this is based purely on the performance of the stock value. Basically, since the analysis is made purely on activity from the past 12 months the momentum-portfolio composition will change often, since the market value of public companies tend to change frequently. Compared to a beta selection strategy where the analysis is made from i.e., 20 or 30 year historic stock price data, then the estimate would change much less frequently. This dramatically increases the need for trading activity and thus transaction costs of the momentum strategy. For the momentum strategy to be efficient, there will have to be frequent turnover, otherwise the strategy might not be able to catch it if a stock loses momentum after it’s traded.