Functions

File name

The function ftp.QuantFactor.name() was created to automatically generate the name of the file corresponding to the stock factor being backtested, along with the file’s location within the users EPFR ftp connection.

ftp.QuantFactor.name <- function(x, w = F, u = "Aggregate") {
  # -----------------------------------------------------------------
  # Name        : ftp.QuantFactor.path
  # Author  : OB
  # Date        : 5/24/23
  # Args        : x = the name of a quant factor being backtested
  #         : w = Custom ftp path before StockFlows folder
  #         : u = the name of a filter (Active, Aggregate, ETF, Mutual, Passive)
  # Output  : outputs full ftp file path for quant factor
  # -----------------------------------------------------------------
  
  if(w != F){
    if(x %in% c("AllocMo", "AllocTrend", "AllocDiff", "Herfindahl", "AllocSkew")){
      w <- paste0(w, "/StockFlows5.0/QuantitativeFactors/Monthly/", x, "/", u, "/") 
    } else {
      w <- paste0(w, "/StockFlows5.0/QuantitativeFactors/Daily/", x, "/", u, "/") 
    }
    
    if(grepl("C:", w)){
      w <- txt.replace(w, "/", "\\")
    }
    
  } else {
     w <- ""
  }
  
  if(x == "FloMo"){ w <- paste0(w, "FlowMomentum")
  } else if(x == "FloTrend"){   w <- paste0(w, "StockFlowTrend-")
  } else if(x == "FloDiff"){    w <- paste0(w, "FlowDiff")
  } else if(x == "FloDiff2"){   w <- paste0(w, "FlowDiff2")
  } else if(x == "ActWtTrend"){ w <- paste0(w, "ActiveWeightTrend")
  } else if(x == "ActWtDiff"){  w <- paste0(w, "ActiveWeightDif")
  } else if(x == "ActWtDiff2"){ w <- paste0(w, "ActiveWeightDiff2")
  } else if(x == "AllocMo"){    w <- paste0(w, "AllocationMomentum")
  } else if(x == "AllocTrend"){ w <- paste0(w, "AllocationTrend")
  } else if(x == "AllocDiff"){  w <- paste0(w, "AllocationDiff")
  } else if(x == "Herfindahl"){ w <- paste0(w, "Herfindahl")
  } else if(x == "AllocSkew"){  w <- paste0(w, "AllocationSkew")
  } else {  w <- paste0(w, x) }
  
  if(u != "Aggregate"){
    if(u == "Mutual"){ u <- "MF" } 
    w <- paste0(w, "All", u)
  }
  w
}

Format file

The function ftp.QuantFactor.format() was built for backtesting purposes to automatically format the stock factor files hosted on EPFRs ftp connection, to easily have unique Ids as rownames and each date as a column.

ftp.QuantFactor.format <- function(z, n = -2) {
  # -----------------------------------------------------------------
  # Name        : ftp.QuantFactor.path
  # Author  : OB
  # Date        : 5/24/23
  # Args        : z = single quant factor file from ftp
  #         : n = delay in getting data
  # Output  : outputs formatted data frame - ID as rows, date as header 
  # -----------------------------------------------------------------
  
  z[yyyymmdd.exists(z$ReportDate) == F, "ReportDate"] <- yyyymmdd.ex.txt(z[yyyymmdd.exists(z$ReportDate) == F, "ReportDate"])
  z$ReportDate <- yyyymmdd.lag(z$ReportDate, -2)
  z <- reshape(z, idvar = "HSecurityId", timevar = "ReportDate", direction = "wide", drop = "SecurityName")
  rownames(z) <- as.numeric(z$HSecurityId)
  z <- z[,-1]
}

Fetchs file

The function fetch.ftp.QuantFactor() was created to automatically fetch the desired stock factor data for a designated period of time, via the users EPFR ftp connection.

fetch.ftp.QuantFactor <- function(x, y, n, w = F, h, u = "Aggregate") {
  # -----------------------------------------------------------------
  # Name        : ftp.1y.QuantFactor
  # Author  : OB
  # Date        : 5/24/23
  # Args        : x = either a single variable or a vector of variable names
  #     : y = the YYYYMM or YYYYMMDD for which you want data
  #     : n = number of daily/monthly trailing periods
  #   : w = Custom ftp path before StockFlows folder
  #     : h = classif file
  #   : u = the name of a filter (Active, Aggregate, ETF, Mutual, Passive)
  # Output  : fetches <x> for the trailing <n> periods ending at <y>
  # -----------------------------------------------------------------
  
  daily <- nchar(y) == 8
  
  # PARAMETERS
  if (daily) {
    yyyy <- yyyymmdd.to.yyyymm(y)
    mm <- txt.right(y, 2)
  } else {
    yyyy <- yyyymm.to.yyyy(y)
    mm <- as.numeric(txt.right(y, 2))
  }
  
  if(n > 1) {
    w <- ftp.QuantFactor.name(x, w, u)
    z <- paste0(w, yyyy, ".txt") 
    lCol <- paste(x, y, sep = ".")
    if(grepl("C:", w)){ z <- mat.read(z, "\t", NULL)
    } else { z <- qa.mat.read(z, "C:\\temp\\crap", v = T) }
    z <- ftp.QuantFactor.format(z)
    m <- 1:dim(z)[2]
    m <- m[dimnames(z)[[2]] == lCol]
    
    while (m < n) {
       if (daily) yyyy <- yyyymm.lag(yyyy, 1) else yyyy <- yyyy - 1
       df <- paste0(w, yyyy, ".txt") 
       if(grepl("C:", w)){ df <- mat.read(df, "\t", NULL)
       } else { df <- qa.mat.read(df, "C:\\temp\\crap", v = T) }
       df <- ftp.QuantFactor.format(df)
       z <- data.frame(df, z)
       m <- m + dim(df)[2]
    }
    
    z <- z[, seq(m - n + 1, m)]
  }
  z
}