R/fmCov.R

Defines functions fmCov.ffm fmCov.sfm fmCov.tsfm fmCov

Documented in fmCov fmCov.ffm fmCov.sfm fmCov.tsfm

#' @title Covariance Matrix for assets' returns from fitted factor model.
#'
#' @description Computes the covariance matrix for assets' returns based on a
#' fitted factor model. This is a generic function with methods for classes
#' \code{tsfm}, \code{sfm} and \code{ffm}.
#'
#' @details \code{R(i, t)}, the return on asset \code{i} at time \code{t},
#' is assumed to follow a factor model of the form, \cr \cr
#' \code{R(i,t) = alpha(i) + beta(i)*f(t) + e(i,t)}, \cr \cr
#' where, \code{alpha(i)} is the intercept, \code{f(t)} is a \code{K x 1} vector of
#' factor returns at time \code{t}, \code{beta(i)} is a \code{1 x K} vector of
#' factor exposures and the error terms \code{e(i,t)} are serially
#' uncorrelated across time and contemporaneously uncorrelated across assets
#' so that \code{e(i,t) ~ iid(0,sig(i)^2)}. Thus, the variance of asset
#' \code{i}'s return is given by \cr \cr
#' \code{var(R(i)) = beta(i)*cov(F)*tr(beta(i)) + sig(i)^2}. \cr \cr
#' And, the \code{N x N} covariance matrix of asset returns is \cr \cr
#' \code{var(R) = B*cov(F)*tr(B) + D}, \cr \cr
#' where, B is the \code{N x K} matrix of factor betas and \code{D} is a
#' diagonal matrix with \code{sig(i)^2} along the diagonal.
#'
#' The method for computing covariance can be specified via the \dots
#' argument. Note that the default of \code{use="pairwise.complete.obs"} for
#' handling NAs restricts the method to "pearson".
#'
#' @param object fit object of class \code{tsfm}, \code{sfm} or \code{ffm}.
#' @param factor.cov factor covariance matrix (optional); defaults to the
#' sample covariance matrix.
#' @param use method for computing covariances in the presence of missing
#' values; one of "everything", "all.obs", "complete.obs", "na.or.complete", or
#' "pairwise.complete.obs". Default is "pairwise.complete.obs".
#' @param ... optional arguments passed to \code{\link[stats]{cov}}.
#'
#' @return The computed \code{N x N} covariance matrix for asset returns based
#' on the fitted factor model.
#'
#' @author Eric Zivot, Yi-An Chen and Sangeetha Srinivasan.
#'
#' @references
#' Zivot, E., & Jia-hui, W. A. N. G. (2006). Modeling Financial Time
#' Series with S-Plus Springer-Verlag.
#'
#' @seealso \code{\link{fitTsfm}},\code{\link{fitFfm}}
#'
#' \code{\link[stats]{cov}} for more details on arguments \code{use} and
#' \code{method}.
#'
#' @examples
#' # Time Series Factor model example
#'  # load data
#' data(managers, package = 'PerformanceAnalytics')
#'  # Make syntactically valid column names
#' colnames(managers)
#' colnames(managers) <- make.names( colnames(managers))
#' colnames(managers)
#'
#' fit <- fitTsfm(asset.names = colnames(managers[, (1:6)]),
#'                factor.names = c("EDHEC.LS.EQ","SP500.TR"),
#'                data = managers)
#' fmCov(fit)
#'
#' @rdname fmCov
#' @export

fmCov <- function(object, ...){
  # check input object validity
  if (!inherits(object, c("tsfm", "sfm", "ffm"))) {
    stop("Invalid argument: Object should be of class 'tsfm', 'sfm' or 'ffm'.")
  }
  UseMethod("fmCov")
}

#' @rdname fmCov
#' @method fmCov tsfm
#' @export

fmCov.tsfm <- function(object, factor.cov, use="pairwise.complete.obs", ...) {

  # get parameters and factors from factor model
  beta <- as.matrix(object$beta)
  # convert NAs to 0 to enable matrix multiplication
  beta[is.na(beta)] <- 0
  sig2.e = object$resid.sd^2
  factor <- as.matrix(object$data[, object$factor.names])

  # factor covariance matrix
  if (missing(factor.cov)) {
    factor.cov = cov(factor, use=use, ...)
  } else {
    identical(dim(factor.cov), as.integer(c(ncol(factor), ncol(factor))))
  }

  # residual covariance matrix D
  if (length(sig2.e) > 1) {
    D.e = diag(sig2.e)
  } else {
    D.e =  as.vector(sig2.e)
  }

  cov.fm = beta %*% factor.cov %*% t(beta) + D.e

  if (any(diag(chol(cov.fm))==0)) {
    warning("Covariance matrix is not positive definite!")
  }

  return(cov.fm)
}

#' @rdname fmCov
#' @method fmCov sfm
#' @export

fmCov.sfm <- function(object, use="pairwise.complete.obs", ...) {

  # already computed via fitSfm function
  return(object$Omega)
}

#' @rdname fmCov
#' @method fmCov ffm
#' @export

fmCov.ffm <- function(object, use="pairwise.complete.obs", ...) {

  # already computed via fitFfm function

	# get parameters and factors from factor model
	beta <- as.matrix(object$beta)
	# convert NAs to 0 to enable matrix multiplication
	beta[is.na(beta)] <- 0
	sig2.e = object$resid.var
	factor <- as.matrix(object$data[, object$factor.names])
	factor.cov = object$factor.cov
	# factor covariance matrix
	if (is.null(factor.cov)) {
		factor.cov = cov(factor, use=use, ...)
	} else {
		identical(dim(factor.cov), as.integer(c(ncol(factor), ncol(factor))))
	}

	# residual covariance matrix D
	if (length(sig2.e) > 1) {
		D.e = diag(sig2.e)
	} else {
		D.e =  as.vector(sig2.e)
	}

	cov.fm = beta %*% factor.cov %*% t(beta) + D.e

	if (any(diag(chol(cov.fm))==0)) {
		warning("Covariance matrix is not positive definite!")
	}

	return(cov.fm)}
braverock/FactorAnalytics documentation built on Dec. 16, 2024, 5:51 a.m.