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".)

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

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):
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.

  • $\begingroup$ Perhaps the test has low power. Returns are pretty volatile and a randomly generated factor should not be able to explain much of the return variation so standard errors are going to be pretty large. Or then you made a typo somewhere... $\endgroup$
    – fes
    Commented Jun 28, 2023 at 10:38
  • $\begingroup$ How do the betas look wrt. this random factor? $\endgroup$
    – fes
    Commented Jun 28, 2023 at 10:39
  • $\begingroup$ @fes, the estimated betas are all close to zero. The test should have enough power, as it is able to reject smallish alphas in the setup under $H_1$ with the true factor. You can run the script online and see the results for yourself: rdrr.io/snippets. $\endgroup$ Commented Jun 28, 2023 at 11:52
  • $\begingroup$ You are probably correct. But I would expect it to be easier to reject zero alphas if you have a factor that goes a long way in explaining returns than when you have a randomly generated factor. The residual variance will be higher in the latter case; the $R^2$ in the CAPM regression should be relatively high. $\endgroup$
    – fes
    Commented Jun 28, 2023 at 12:00
  • $\begingroup$ If the betas are close to zero, your basically testing whether the mean returns are zero. Finding statistically significant mean returns can require quite a long history of data. The FF portfolios have also not done too well over the last 15 years. $\endgroup$
    – fes
    Commented Jun 28, 2023 at 12:09

1 Answer 1


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.

  • $\begingroup$ Thank you for your answer! I was going to check whether this actually is the case but never found the time, so I will just assume it is. The logic is convincing enough. $\endgroup$ Commented Dec 3, 2023 at 16:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.