// RStudio: “Use Knit”

  1. Introduction
  2. Fama-Macbeth X-Sect Method (1973)
  3. Time-Series Method**
  4. Translating Signals Into Investment Strategies
  5. Simulating World
  6. Further Important Aspects (Meta/Taxes/Factors)

NOTE: BJSFF = Black-Jensen-Scholes (1972) = Fama-French (1993)


Fama-MacBeth Vs BJSFF


Alpha


BJSFF Example

# 1 signal, but one for each of 4 stocks, and 7 time periods
sigA <- c( 3,  4,  1, -3,  0,  2,  NA )
retA <- c( NA, -6, 12, -1, -22, 6,  -6 )/100.0

sigB <- c(-2, -2,  1,  1,  2,  4,  NA )
retB <- c( NA, -2,-34,  1,  13, 12, 36 )/100.0

sigC <- c(-1,  3, -4, -1,  4, -2,  NA )
retC <- c( NA, -7, 25,  2, -19, -6, -10)/100.0

sigD <- c( 0,  4, -2,  2, -1,  1,  NA )
retD <- c( NA, -2, 29, 11, -5, -30, 7  )/100.0

d <- data.frame( time=1:length(sigA), retA, retB, retC, retD, sigA, sigB, sigC, sigD )
p(d)

Step 1: Choose Your (Zero-Investment) Strategy

  • Your investment strategy maps your known signals into your investment weights.

  • It is up to you to decide how your signal should map to your portfolio investment weights

  • The only portfolio constraint is that your investment weights must add to zero

    • FF only works with zero-investment portfolios!
    • Typically, such strategies are normalized to $1 long and $1 short.
  • If your strategy is not long-short but long only, you must make it net-zero:

    • make all investments add up to 1.0 for your long leg.
    • for your short leg, use the risk-free rate of return,
    • so subtract the risk-free rate, with weight 1.0.
  • Note that the very same “long-short normalization” is also always done with the market factor and even in the CAPM. In other words, we work with \(E(r_m)-r_f\).

Interpretation

  • You can think of a “standard” long-short strategy in terms of dollars rather than in terms of percent.

  • All portfolio algebra works for this. For example, if your $1 long and $1 short strategy then has a net rate of return of 0.05, it means it earned 5 cents cash.

  • You can now accumulate this over many months. It is not compounded, because you do not have an original $1 investment, where you would use a (1+r) formula.

  • You can assign an interest rate to the cash accumulation.

  • The instant any stock in your portfolio moves, your portfolio is really no longer zero investment. However, your portfolio must only be zero investment at the beginning of the time-period.

  • PS: You can choose the time-period length. If it is short, you have many time units, many requirements to rebalance your portfolio back to zero (and put the cash into a piggy bank), and good measurement control of your exposures to your factors (beta controls). If it is long, you have few time units, do not need to rebalance as often, but lousy measurement control for benchmark factors.

Example Strategy

Map From Your Signal to Your Investment Weights:

  • In each time period

    • invest –$0.75 (short) into the stock with the lowest signal,
    • invest –$0.25 (short) into the 2nd-lowest signal stock,
    • invest +$0.25 (long) into the 2nd-highest signal stock,
    • invest +$0.75 (long) into the highest signal stock.
    • If both signals within leg are the same, invest half-half
  • Call this strategy PSAM (haha)

  • PSAM is a zero-investment portfolio, because the weights add to zero (in every time period).

  • Zero-investment strategies scale in perfect markets.

    • it does not cost more money to scale up the rate of return
    • By convention, it is usually easiest for everyone to understand what you are doing by making it $1 long and $1 short
    • The two parts are called the long leg and the short leg.

Step 2: Calculate Your Actual Portfolio Investment Weights

  • Follow your designed strategy slavishly.

  • Calculate the net-of-risk-free rate of return on your portfolio.

  • For example, in the first period, your worst signal is -2 for B, the best signal is +3 for A, etc. In our example,

stock A B C D
weight +$0.75 -$0.75 -$0.25 +$0.25
  • The following code is R programming magic. Ignore the code details. Just verify that the investment weights are indeed set as the strategy requires:
sigs <- subset(d, TRUE, select=startsWith(names(d),"sig"))
wghts <- matrix( NA, nrow=nrow(sigs), ncol=ncol(sigs) )
for (r in 1:(nrow(d)-1)) wghts[r,] <- (rank(sigs[r,])-2.5)/2
wghts[nrow(d),] <- rep(0.0,4)
colnames(wghts) <- paste0("w", c("A","B","C","D"))
stopifnot( all( rowMeans(wghts) == 0 ))  ## sanity check --- overall zero investment
d <- cbind(d, wghts)
p( subset(d, TRUE, select=c("sigA", "sigB", "sigC", "sigD", "wA", "wB", "wC", "wD")) )
  • We no longer need the signals, so we can remove them:
d <- subset(d, TRUE, select= -c(sigA,sigB,sigC,sigD))

Step 3: Calculate the Portfolio’s Overall Rate of Return

  • Calculate the rate of return on the strategy in each time unit. For example, at time 2 (the first time unit when you can earn a rate of return),

\[ R_{t=2} = \$0.75\cdot(-6\%) + (-\$0.75)\cdot (-2\%) + (-\$0.25)\cdot(-7\%) + (+\$0.25)\cdot (-2\%) = -\$0.0175 \]

Step 3A: Align Timing

  • To calculate portfolio rates of return with code, line up the lagged investment choices correctly with their subsequently earned rates of return.

  • This was already done in the Fama-Macbeth example.

lagseries <- function( x ) c( NA, x[1:(length(x)-1)] )
d <- within(d, {
    lwD <- lagseries(wD)
    lwC <- lagseries(wC)
    lwB <- lagseries(wB)
    lwA <- lagseries(wA)
})
p(d)
  • We no longer need the weights, so we can remove them:
d <- subset(d, TRUE, select= -c(wA,wB,wC,wD))

Step 3B: Add the Benchmark Factors

  • We need a market rate of return net of the risk-free rate. Usually, we would just download this from CRSP.
d <- within(d, retmkt <- round( rowMeans(subset(d, TRUE, select=startsWith(names(d),"ret")), na.rm=T),4))
  • Here, we assume that all returns were quoted net of the risk-free rate already, so that the equal-weighted market portfolio is also net of the risk-free rate of return.

Step 3C: Calculate Your Portfolio’s Rate of Return

  • calculate the
d <- within(d, retpsam <- round(lwA*retA + lwB*retB + lwC*retC + lwD*retD, 4))
p(d)
  • We no longer need the individual rates of returns or lag weights, so we can remove them:
d <- subset(d, TRUE, select= -c(retA,retB,retC,retD,lwA,lwB,lwC,lwD))

Step 4: Merge The Factor(s) For Benchmark Control

  • Just like your own strategy rate of return, these factor returns must be quoted net of the risk-free rate.
    • If the original rates of return were all quoted net of the risk-free rate, this is also true for their weighted average
  • Oops. We had already added the market factor (net of the risk-free rate) above.

Step 5: Run A Single Time-Series Regression

1-Factor Model

  • The rate of return of your own portfolio (rpsam, always net of the risk-free rate of course) is always the dependent variable. If the benchmark model is the CAPM, you run a 1-factor model. This means that the only rate of return on the market MKT is the independent variable.
print(coef(summary(lm( retpsam ~ retmkt, data=d ))))
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept)   0.1736    0.07291  2.3812  0.07589
## retmkt        1.0873    1.18661  0.9163  0.41137
  • This intercept is what is called the alpha of your strategy.
    • because the independent variable is the net-of-riskfree stock market rate of return, here this is with respect to the CAPM.
  • The beta measures how much your portfolio is like the stock market.
    • you may or may not want to short SP500 futures to hedge out this exposure.
  • In the example case, the alpha was almost statistically significant at the 5% level (T=2.37, p=7.7%).
    • surprising with only 7 time periods—ok, I cooked the example.
    • the abnormal performance was 17.31% per time unit, insanely large, except the example was cooked.

0-Factor Model

  • The abnormal performance relative to a “0-factor model” (i.e., if the world were risk-neutral) would have been 17.54%

  • You can do the same procedure controlling for more than just the market factors, e.g., SMB, HML, RMW, UMD, etc.

  • Q: What is this?

print(coef(summary(lm( retpsam ~ 1, data=d ))))
##             Estimate Std. Error t value Pr(>|t|)
## (Intercept)   0.1754     0.0717   2.447  0.05819

Compare the average (net-of-risk-free) rates of return, which are also the abnormal rates of return relative to a 0-factor model:

print(colMeans( d, na.rm=TRUE ))
##     time   retmkt  retpsam 
## 4.000000 0.001667 0.175417
print(t.test(d$retpsam))
## 
##  One Sample t-test
## 
## data:  d$retpsam
## t = 2.4, df = 5, p-value = 0.06
## alternative hypothesis: true mean is not equal to 0
## 95 percent confidence interval:
##  -0.008896  0.359729
## sample estimates:
## mean of x 
##    0.1754

Other Models

  • Q: What would this be?
print(  coef( summary(lm( retpsam ~ retmkt + retsmb + rethml, data=d )) )  )

Reflection

A Bit More Formal

  • Run a single time-series regression. For example, if you want the CAPM or an extended model, use

    \[ (r_{pt} - r_{ft}) = \alpha_p + \beta_p \cdot \left( M_{it} - r_{ft} \right) + ... + \epsilon_{pt} \]

    • Note the subscripts. Make sure you run such a regression once, so you understand their meaning.

    • Make sure that \(r_{pt}\) here is long only, so the LHS is a net (zero investment!) rate of return.

      • If it is already zero investment, do not subtract the risk-free rate on the LHS.
    • Only use investable zero-investment portfolios into the FF time-series regression.

      • Otherwise, alpha becomes meaningless.
    • Zero-investment portfolios are sometimes incorrectly called arbitrage portfolios.

      • They are absolutely not arbitrage, because they carry risk.
  • The interesting regression output is \(\alpha_p\). You can use its OLS T-stats, etc. (They are often Newey-West adjusted.)

  • BJSFF time-series regressions are not obsolete.

    • Every quant fund in the world runs these
    • When they talk about alpha, this is exactly what they mean.

Alpha or Beta?

  • Note that other investment regularities can be interesting, even if they have on average a true alpha of zero.

  • For example, consider your strategy relative to a CAPM. In any subperiod, the market may have gone up all the time or gone down all the time.

  • Even if the CAPM holds perfectly, and thus there is no alpha to be had on average, in your subperiod, this may not be true.

  • In the extreme, consider a case in which the (net-of-rf) stock market would randomly return +10% or -10%.

    • the average net-of-rf market rate of return is truly 0.
    • but you only test 1 period.
    • for example, in this period, the excess market return was 10%, your portfolio beta was 1, and your portfolio had a rate of return of 10%.
    • Ergo, your strategy had zero alpha, even though it had a great market-rate of return.

Conclusion

BJSFF time-series regressions can explain/decompose your investment portfolio performance into terms of other known investment strategies’ performances (each beta times the factor realization) plus your strategy’s idiosyncratic performance, i.e., its alpha.


Is Performance Deserved or Not?