Skip to content
All library documents

Why the GRS Test May Not Reject an Unrelated Factor

Article Quant Q&A · Author: Richard Hardy

Summary

The document examines a simulation in which the Gibbons–Ross–Shanken test is applied to portfolio returns generated under the CAPM. With the true market factor, the test does not reject when portfolio alphas are zero and rejects after nonzero alphas are added. Surprisingly, replacing the market return with an unrelated random factor can still produce a nonrejection when the alphas are zero; adding alphas again leads to rejection.

The accepted explanation is low power in this setup. The random factor produces estimated betas near zero, so the test effectively checks whether portfolio mean returns are zero. Those means may be too small relative to return volatility to reject that null. A nonrejection therefore does not show that the random factor explains returns: near-zero betas indicate that it is not useful for that purpose. The example is a simulation based on a particular sample and factor choice, so its outcome should not be treated as a general property of the GRS test.

Key ideas

  • A GRS nonrejection does not establish that a proposed factor explains portfolio returns.
  • An unrelated factor can yield betas near zero and leave the test effectively assessing whether mean returns are zero.
  • Low power relative to return volatility can help explain why the test fails to reject.
  • Adding nonzero portfolio alphas can make the test reject even when the factor is unrelated.

Tags

Full text
# GRS test does not reject a nonsense factor in place of the market factor


# GRS test does not reject a nonsense factor in place of the market factor












I have been playing with the GRS test (see my R script below) in relation to Why not use a time series regression when the factor is not a return?. I generated a $630\times 26$ matrix of returns on 25 "portfolios" and the market portfolio according to the CAPM. I used the function `GRS.test::GRS.test` in R to test the CAPM, and I could not reject the $H_0$. Then I added idiosyncratic $\alpha$s to each "portfolio", tested the CAPM again and now could easily reject the $H_0$. So far so good.

Then I generated data according to the CAPM again and ran the GRS test with the market's excess return replaced by an unrelated random variable (a random factor). To my surprise, the test could not reject the $H_0$! I have tried a few different random variables instead of the market's excess return, and while the $p$-values varied from case to case, I got the same nonrejection for several more of them. For completeness, I added idiosyncratic $\alpha$s to each "portfolio" and tested the CAPM again with the random factor. As in the case with the true factor, I could again easily reject the $H_0$.

Question: What is going on? Should the GRS test not reject a model with an unrelated, random factor in place of the market's excess return?

(You can run the script online and see the results for yourself at https://rdrr.io/snippets/. Just paste the script there, delete/comment the irrelevant lines following `!!!` and click "Run".)

```
library(MASS)
library(GRS.test)
data("data")  # Fama-French data: market's excess return and 25 portfolios (5x5, sorted on SMB and HML) 
data=data/100 # because original data was in percent

N=25
T=nrow(data)  # 630

Sigma=cov(data[,c(8:32,2)])    # empirical covariance matrix; the last column is the market, the other 25 columns are the portfolios

# !!! Choose one of the two following lines for H0 vs. H1:
alpha =rep(0,N+1)                                   # Jensen's alpha, in this case zero    for all assets
set.seed(-1); alpha=runif(n=N+1,min=-0.01,max=0.01) # Jensen's alpha, in this case nonzero for all assets

beta_m=rep(NA,N+1); for(i in 1:(N+1)) beta_m[i]=Sigma[i,N+1]/Sigma[N+1,N+1] # actual betas from Fama-French data
mu_mte=rep(mean(data[,2]),T)   # expected value of market excess return, in this case time-constant and in line with Fama-French data
# Generate a matrix of returns according to the CAPM (normality is mainly for convenience):
set.seed(1); r_matrix=mvrnorm(n=T, mu=alpha+beta_m*mean(mu_mte), Sigma=Sigma)

# !!! Factor return matrix for the function GRS.test():
# choose one of the two following lines for the true underlying factor vs. a random, unrelated factor:
f_matrix=cbind(r_matrix[,N+1])                 # true underlying   factor returns
set.seed(999); f_matrix=cbind(rnorm(T,mean=5)) # random, unrelated factor returns

# GRS test
result=GRS.test(r_matrix[,1:N],f_matrix); print(round(c(result$GRS.stat,result$GRS.pval),3)) 

# Individual t-tests and individual estimates of alphas and betas 
# (full dots ~ true, hollow circles ~ estimated):
par(mfrow=c(5,5),mar=c(2,2,0.5,0.5))
for(i in 1:N){ 
 m1=lm(r_matrix[,i]~f_matrix); print(summary(m1))
 true=c(alpha[i],beta_m[i]); estimated=as.numeric(m1$coef); ylim1=c(-0.05,2)
 plot(estimated,ylim=ylim1,xlab="",ylab=""); points(true,pch=19)
}; par(mfrow=c(1,1),mar=c(5.1,4.1,4.1,2.1))
```

P.S. A related question is "GRS test does not reject a scalar multiple of the market factor". Increasing the sample size that was helpful here does not seem to fix that problem.

## Answer by fes (score 3, accepted)

https://quant.stackexchange.com/a/75973

As discussed in the comments, the issue is likely that the test has low power in this particular case. Explaining portfolio returns with a randomly generated factor yields close to zero betas. The test is then effectively testing whether the mean returns of the 25 portfolios are zero. Despite the fact that the data begins in the 1970s, the mean returns seem too small, relative to the return volatility, to reject the null that these mean returns are zero.

However, the fact that the betas are close to zero suggest that this factor is not useful for explaining returns.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.