Skip to main content
added 208 characters in body
Source Link

I follow the method of Fama-French when constructing the MOM factor and then I try to follow the exact same procedure when creating the SUE and CAR3 factors, just like Robert Novy-Marx in his article "Fundamentally, Momentum is Fundamental Momentum" from 2015: http://rnm.simon.rochester.edu/research/FMFM.pdf. My data is collected directly from WRDS to R by following this code: https://drive.google.com/file/d/0BxvBvE2V-dFTVnZuLUFhZWNuazA/view?fbclid=IwAR0-uPDl1-kzRyugIVePTtIFxMiM5jQbbWqE9VxIdMftrs4adJ_zDGuh4Go

Novy-Marx (2015) creates a figure of the factors performance on p. 9 which is the figure I aim to replicate. My results of MOM and CAR3 are very similar to Fama-French and Robert. The figure bellow is my results, where the UMD factor is the one I have constructed and the MOM factor is the one I downloaded from Fama-French. This clearly showed that I have been able to replicate the UMD factor almost 1:1 and CAR3 is also very similar to Novy-Marx (2015).

I follow the method of Fama-French when constructing the MOM factor and then I try to follow the exact same procedure when creating the SUE and CAR3 factors, just like Robert Novy-Marx in his article "Fundamentally, Momentum is Fundamental Momentum" from 2015: http://rnm.simon.rochester.edu/research/FMFM.pdf. Novy-Marx (2015) creates a figure of the factors performance on p. 9 which is the figure I aim to replicate. My results of MOM and CAR3 are very similar to Fama-French and Robert. The figure bellow is my results, where the UMD factor is the one I have constructed and the MOM factor is the one I downloaded from Fama-French. This clearly showed that I have been able to replicate the UMD factor almost 1:1 and CAR3 is also very similar to Novy-Marx (2015).

I follow the method of Fama-French when constructing the MOM factor and then I try to follow the exact same procedure when creating the SUE and CAR3 factors, just like Robert Novy-Marx in his article "Fundamentally, Momentum is Fundamental Momentum" from 2015: http://rnm.simon.rochester.edu/research/FMFM.pdf. My data is collected directly from WRDS to R by following this code: https://drive.google.com/file/d/0BxvBvE2V-dFTVnZuLUFhZWNuazA/view?fbclid=IwAR0-uPDl1-kzRyugIVePTtIFxMiM5jQbbWqE9VxIdMftrs4adJ_zDGuh4Go

Novy-Marx (2015) creates a figure of the factors performance on p. 9 which is the figure I aim to replicate. My results of MOM and CAR3 are very similar to Fama-French and Robert. The figure bellow is my results, where the UMD factor is the one I have constructed and the MOM factor is the one I downloaded from Fama-French. This clearly showed that I have been able to replicate the UMD factor almost 1:1 and CAR3 is also very similar to Novy-Marx (2015).

Source Link

Replicating momentum strategies (UMD/MOM, SUE and CAR3) in R

I am writing my Master Thesis on momentum strategies including price momentum (UMD/MOM) and two fundamental momentum strategies (SUE and CAR3). Right now I'm trying to create the three momentum factors in order to compare their performance from 1975-2012. The UMD/MOM factor is a factor already constructed by Fama-French. The documentation can be seen on French' website: https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/Data_Library/det_mom_factor.html

I follow the method of Fama-French when constructing the MOM factor and then I try to follow the exact same procedure when creating the SUE and CAR3 factors, just like Robert Novy-Marx in his article "Fundamentally, Momentum is Fundamental Momentum" from 2015: http://rnm.simon.rochester.edu/research/FMFM.pdf. Novy-Marx (2015) creates a figure of the factors performance on p. 9 which is the figure I aim to replicate. My results of MOM and CAR3 are very similar to Fama-French and Robert. The figure bellow is my results, where the UMD factor is the one I have constructed and the MOM factor is the one I downloaded from Fama-French. This clearly showed that I have been able to replicate the UMD factor almost 1:1 and CAR3 is also very similar to Novy-Marx (2015).

enter image description here

However, when I include SUE to the graph it results in this:

enter image description here

But as you see SUE is unrealistically high. Since the procedure of constructing the performance of the factors are exactly the same as for UMD and CAR3 it implies that the problem must be in relation to my calculation of SUE itself. I therefore need some help with examining where exactly the problem occurs.

When calculating SUE I follow Novy-Marx (2015). He defines SUE as "the most recent year-over-year change in earnings per share, scaled by the standard deviation of the these earnings innovations over the last eight announcements, subject to a requirement of at least six observed announcements over the two year window.". I'll try to write step by step what exactly I do:

Step 1: I download Quarterly data from Compustat, including the variables DATADATE, GVKEY and EPSPXQ (Earnings Per Share (Basic) / Excluding Extraordinary Items).

res <- dbSendQuery(wrds,"select gvkey, datadate, epspxq from comp.fundq 
           where INDFMT='INDL' and DATAFMT='STD' and CONSOL='C' and POPSRC='D'")  
 
comp.fundq <- dbFetch(res, n = -1) 

Step 2: I arrange the data by datadate and gvkey to make sure the data is arranged in the right order before lagging EPSPXQ by 4 quarters.

comp.data <-  
  comp.data %>% 
  arrange(datadate, gvkey) %>% 
  group_by(gvkey) %>% 
  mutate(lag.eps = dplyr::lag(epspxq, n = 4, default = NA))

Step 3: I calculate Earnings Innovations by

comp.data$ei <- comp.data$epspxq-comp.data$lag.eps

Step 4: I calculate the rolling std. deviation of the earnings innovations calculated in step 3 over the last 8 announcements (width = 8) with a criteria where at least 6 observations of non NAs are required (Partial = 6)

FUN <- function(x) if (length(na.omit(x)) >= 6) sd(x, na.rm = TRUE) else NA 
roll1 <- function(z) rollapplyr(z, width = 8, FUN = FUN, fill = NA, partial = 6)   
comp.data <-  
  comp.data %>% 
  arrange(datadate, gvkey) %>% 
  transform(comp.data, roll1 = ave(ei, gvkey, FUN = roll1))

Step 5: I calculate SUE by

comp.data$sue <- comp.data$ei/comp.data$roll1 

Step 6: I download CCM data from WRDS as a step to merge Compustat Data with CRSP Data:

res <- dbSendQuery(wrds,"select GVKEY, LPERMNO, LINKDT, LINKENDDT, LINKTYPE, LINKPRIM 
                    from crsp.ccmxpf_lnkhist") 
 
ccm <- dbFetch(res, n = -1) 

Step 7: I merge my Compustat dataset comp.data (incl. my new SUE variable) with CCM:

ccm.comp <-   
  ccm %>% 
  filter(linktype %in% c("LU", "LC", "LS")) %>% 
  filter(linkprim %in% c("P", "C", "J")) %>% 
  merge(comp.data, by="gvkey") %>%  
  mutate(datadate = as.Date(datadate),  
         permno = as.factor(lpermno), 
         linkdt = as.Date(linkdt), 
         linkenddt = as.Date(linkenddt), 
         linktype = factor(linktype, levels=c("LC", "LU", "LS")), 
         linkprim = factor(linkprim, levels=c("P", "C", "J"))) %>% 
  filter(datadate >= linkdt & (datadate <= linkenddt | is.na(linkenddt))) %>% 
  arrange(datadate, permno, linktype, linkprim) %>% 
  distinct(datadate, permno, .keep_all = TRUE)

Step 8: I clean my data after the merge:

ccm.comp.cln <-  
  ccm.comp %>% 
  arrange(datadate, permno) %>% 
  select(datadate, permno, sue) %>% 
  mutate_if(is.numeric, funs(ifelse(is.infinite(.), NA, .))) %>%  
  mutate_if(is.numeric, funs(round(., 5)))
 
ccm.comp.cln$datadate <- strptime(as.character(ccm.comp.cln$datadate), "%Y-%m-%d") 
ccm.comp.cln$datadate <- format(ccm.comp.cln$datadate,"%Y%m") 

Step 9: I load in CRSP data and clean it the same way as Fama-French: " "... all CRSP firms incorporated in the US and listed on the NYSE, AMEX, or NASDAQ that have a CRSP share code of 10 or 11 at the beginning of month t, good shares and price data at the beginning of t, and good return data for t". This includes the handling of delist returns as well.

Step 10: I merge my CCM-Compustat data with my CRSP data:

na_locf_until = function(x, n) { 
  l <- cumsum(! is.na(x)) 
  c(NA, x[! is.na(x)])[replace(l, ave(l, l, FUN=seq_along) > (n+1), 0) + 1] 
} 
 
crsp.comp <- merge(x = crsp.data, y = ccm.comp.cln, by.x = c("permno", "date"), by.y = c("permno", "datadate"), all.x = TRUE) 

Can anyone help me identify where a problem could occur?