Skip to content
All library documents

Constructing and Interpreting a Long-Short Factor Portfolio

Article Quant Q&A · Author: user113156

Summary

The document discusses a long-short portfolio formed by taking equal-weight average monthly returns for two groups of stocks, subtracting the mature group’s returns from the technology group’s returns, and regressing the spread on Fama-French market, size, and value factors. The author expected the market factor to remain significant and viewed its weaker result as evidence that the construction might be wrong. The response says the regression is not necessarily defective: a long-short spread can have lower risk than either leg when their returns are positively correlated, and its factor sensitivities can change as exposures offset.

In the reported regression, the market loading is not statistically significant, while the size and value loadings are negative and significant. The answer interprets the market neutrality as plausible, and notes that limited factor explanatory power may simply mean the portfolio is not well described by those factors. The source assumes positive stock correlation and does not examine weighting, leverage, transaction costs, short-borrow constraints, or whether the two legs are appropriately normalized. Its explanation is therefore an intuition for the regression outcome, not proof that the portfolio is well specified.

Key ideas

  • A long-short return spread can have lower risk than either leg when the legs are positively correlated.
  • Subtracting one portfolio’s returns from another can change the spread’s sensitivity to market and style factors.
  • A statistically insignificant market loading may be consistent with offsetting market exposures.
  • Weak factor explanatory power does not by itself establish that the portfolio construction is incorrect.
  • The discussion assumes positive correlation and does not address portfolio weighting, leverage, or shorting costs.

Tags

Full text
# Finance: Portfolio - Long Short Portfolio construction


# Finance: Portfolio - Long Short Portfolio construction












I am trying to construct a Long / Short portfolio in R. Say I have two portfolios `Tech` and `Mature` and I want to go long on the `Tech` portfolio and short on the `Mature` portfolio.

I collect and download the data using:

```
tickers <- c("GOOG", "MSFT", "GE", "WAL")

library(tidyquant)
library(dplyr)
library(tidyverse)
library(glue)

data <- tq_get(tickers,
               get = "stock.prices",
               from = "2010-01-01",
               to = "2015-01-01") %>%
  group_by(symbol) %>%
  tq_transmute(select = adjusted,
                 mutate_fun = periodReturn,
                 period = "monthly",
                 type = "arithmetic") %>%
  mutate(portfolio = case_when(
    symbol == "GOOG" ~ "Tech",
    symbol == "MSFT" ~ "Tech",
    symbol == "GE"  ~ "Mature",
    symbol == "WAL" ~ "Mature"
    ),
    date = ceiling_date(date, "month") - days(1)) %>% # set the date to the end of the month
  group_by(portfolio, date) %>%
  summarise(
    Port_Monthly_Rets = mean(monthly.returns)
  )
```

Which looks like:

```
# A tibble: 120 x 3
# Groups:   portfolio [2]
   portfolio date       Port_Monthly_Rets
   <chr>     <date>                 <dbl>
 1 Mature    2010-01-31            0.173 
 2 Mature    2010-02-28            0.0639
 3 Mature    2010-03-31            0.0605
 4 Mature    2010-04-30            0.283 
 5 Mature    2010-05-31           -0.104 
 6 Mature    2010-06-30           -0.111 
 7 Mature    2010-07-31            0.0659
 8 Mature    2010-08-31           -0.130 
 9 Mature    2010-09-30            0.113 
10 Mature    2010-10-31           -0.0563
# ... with 110 more rows
```

I also download the Fama French Factors:

```
# Collect Fama French Factors:

temp <- tempfile()
base <- "http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/"
factor <- "North_America_3_Factors"
format<-"_CSV.zip"
full_url <-glue(base,factor,format,sep ="")
download.file(full_url,temp,quiet = TRUE)

FF_Factors <- read_csv(unz(temp, "North_America_3_Factors.csv"), skip = 6) %>%
  rename(date = X1) %>%
  mutate_at(vars(-date), as.numeric) %>%
  mutate(date = rollback(ymd(parse_date_time(date, "%Y%m") + months(1)))) %>%
  drop_na(date) %>%
  rename(Mkt_Rf_3 = `Mkt-RF`,
         SMB_3 = SMB,
         HML_3 = HML,
         RF_3 = RF)
```

I join everything together and compute the excess returns:

```
# Join factors with portfolios

df <- data %>%
  left_join(FF_Factors, by = "date") %>%
  mutate(R_excess = Port_Monthly_Rets - RF_3)
```

Which now looks like:

```
# A tibble: 120 x 8
# Groups:   portfolio [2]
   portfolio date       Port_Monthly_Rets Mkt_Rf_3 SMB_3 HML_3  RF_3 R_excess
   <chr>     <date>                 <dbl>    <dbl> <dbl> <dbl> <dbl>    <dbl>
 1 Mature    2010-01-31            0.173     -3.63  0.45  0.89  0      0.173 
 2 Mature    2010-02-28            0.0639     3.71  0.86  2.35  0      0.0639
 3 Mature    2010-03-31            0.0605     6.27  1.5   1.48  0.01   0.0505
 4 Mature    2010-04-30            0.283      1.92  3.73  1.9   0.01   0.273 
 5 Mature    2010-05-31           -0.104     -7.86  0.74 -2.32  0.01  -0.114 
 6 Mature    2010-06-30           -0.111     -5.5  -1.07 -3.73  0.01  -0.121 
 7 Mature    2010-07-31            0.0659     6.95  0.02  1.03  0.01   0.0559
 8 Mature    2010-08-31           -0.130     -4.44 -1.61 -2.35  0.01  -0.140 
 9 Mature    2010-09-30            0.113      9.47  3.67 -1.85  0.01   0.103 
10 Mature    2010-10-31           -0.0563     3.89  0.98 -1.55  0.01  -0.0663
# ... with 110 more rows
```

I run Fama French regressions on my portfolios:

```
summary(lm(R_excess ~ Mkt_Rf_3 + SMB_3 + HML_3, data = subset(df, portfolio == "Mature")))
summary(lm(R_excess ~ Mkt_Rf_3 + SMB_3 + HML_3, data = subset(df, portfolio == "Tech")))
```

For example, the `Tech` portfolio looks like:

```
Call:
lm(formula = R_excess ~ Mkt_Rf_3 + SMB_3 + HML_3, data = subset(df, 
    portfolio == "Mature"))

Residuals:
     Min       1Q   Median       3Q      Max 
-0.10673 -0.03100 -0.01297  0.02820  0.18958 

Coefficients:
            Estimate Std. Error t value  Pr(>|t|)    
(Intercept) 0.010782   0.007560   1.426   0.15934    
Mkt_Rf_3    0.009913   0.002130   4.654 0.0000204 ***
SMB_3       0.008572   0.004173   2.054   0.04463 *  
HML_3       0.011192   0.004137   2.705   0.00903 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.05491 on 56 degrees of freedom
Multiple R-squared:  0.5271,    Adjusted R-squared:  0.5018 
F-statistic: 20.81 on 3 and 56 DF,  p-value: 0.00000000349
```

I want to go long on the `tech` portfolio and short on the `mature` portfolio. Here is my attempt at creating the Long/Short portfolio.

```
LS_Portfolio <- df %>%
  select(-Port_Monthly_Rets) %>%
  pivot_wider(names_from = portfolio, values_from = c(R_excess)) %>%
  mutate(Long_Short = Tech - Mature)

summary(lm(Long_Short ~ Mkt_Rf_3 + SMB_3 + HML_3, data = LS_Portfolio))
```

Which outputs:

```
Call:
lm(formula = Long_Short ~ Mkt_Rf_3 + SMB_3 + HML_3, data = LS_Portfolio)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.248952 -0.027568  0.003106  0.029772  0.191031 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept) -0.017876   0.009873  -1.810  0.07559 . 
Mkt_Rf_3     0.002387   0.002782   0.858  0.39457   
SMB_3       -0.018172   0.005450  -3.334  0.00152 **
HML_3       -0.012778   0.005404  -2.365  0.02154 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.07171 on 56 degrees of freedom
Multiple R-squared:  0.2307,    Adjusted R-squared:  0.1895 
F-statistic: 5.597 on 3 and 56 DF,  p-value: 0.001983
```

Which appears to me to be wrong, the `Mkt_Rf_3` should be significant. I get very similar regression results when I apply this to a larger portfolio of stocks.

My question is not related to programming it but how should I construct the Long / Short portfolio given that I have a number of stocks in each portfolio.

What I do is:

1) Form a portfolio of stocks based on some criteria

2) Compute the average monthly returns of each portfolio

3) Compute the excess return of the portfolio by taking the average monthly portfolio return and taking away the Risk Free rate from the Fama French data

4) Take the `tech` portfolio returns and subtract the `mature` portfolio returns.

5) Run my regression analysis (which performs poorly).

I just want to know where I am going wrong in my logic.

## Answer by Dhruv Mahajan (score 1)

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

You're not going "wrong" anywhere. When you say the regression runs poorly it is a sign that the returns for your portfolio are not that well explained by the fama french factors (which is a positive thing for your risk factors, idk why you call it poor).

When you long-short the two stocks you create a portfolio that has lesser risk that the individual stocks (I'm assuming the stocks' correlation is positive,which usually is). Lesser risk can be due to change in sensitivity to various parameters or factors if you will. In your case the portfolio returns are neutral to the market (mkt_rf) which makes perfect sense.

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.