From noreply at r-forge.r-project.org Tue Dec 2 07:42:48 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 2 Dec 2014 07:42:48 +0100 (CET) Subject: [Returnanalytics-commits] r3564 - / pkg/FactorAnalytics pkg/FactorAnalytics/R pkg/FactorAnalytics/man pkg/FactorAnalytics/vignettes Message-ID: <20141202064248.BC8E9183B39@r-forge.r-project.org> Author: pragnya Date: 2014-12-02 07:42:48 +0100 (Tue, 02 Dec 2014) New Revision: 3564 Added: returnanalytics.Rproj Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/R/fitTsfm.R pkg/FactorAnalytics/R/fmEsDecomp.R pkg/FactorAnalytics/R/plot.tsfm.r pkg/FactorAnalytics/R/print.tsfm.r pkg/FactorAnalytics/R/summary.tsfm.r pkg/FactorAnalytics/man/fitSfm.Rd pkg/FactorAnalytics/man/fitTsfm.Rd pkg/FactorAnalytics/man/fmEsDecomp.Rd pkg/FactorAnalytics/man/plot.tsfm.Rd pkg/FactorAnalytics/man/summary.tsfm.Rd pkg/FactorAnalytics/vignettes/FA.bib pkg/FactorAnalytics/vignettes/fitTsfm_vignette.R pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf Log: Minor edits to fitTsfm print, plot, summary and vignette Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-02 06:42:48 UTC (rev 3564) @@ -1,9 +1,9 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.2 -Date: 2014-11-23 -Author: Eric Zivot, Yi-An Chen and Sangeetha Srinivasan +Version: 2.0.3 +Date: 2014-12-01 +Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Description: An R package for the estimation and risk analysis of linear factor models for asset returns and portfolios. It contains model fitting methods Modified: pkg/FactorAnalytics/R/fitTsfm.R =================================================================== --- pkg/FactorAnalytics/R/fitTsfm.R 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/R/fitTsfm.R 2014-12-02 06:42:48 UTC (rev 3564) @@ -17,31 +17,35 @@ #' squares with exponentially declining weights that sum to unity), and, #' "Robust" is robust regression (using \code{\link[robust]{lmRob}}). #' -#' If \code{variable.selection="none"}, all chosen factors are used in the -#' factor model. Whereas, "stepwise" performs traditional forward/backward -#' stepwise OLS regression (using \code{\link[stats]{step}} or +#' If \code{variable.selection="none"}, uses all the factors and performs no +#' variable selection. Whereas, "stepwise" performs traditional stepwise +#' LS or Robust regression (using \code{\link[stats]{step}} or #' \code{\link[robust]{step.lmRob}}), that starts from the initial set of -#' factors and adds factors only if the regression fit, as measured by the -#' Bayesian Information Criterion (BIC) or Akaike Information Criterion (AIC), -#' improves. And, "subsets" enables subsets selection using +#' factors and adds/subtracts factors only if the regression fit, as measured +#' by the Bayesian Information Criterion (BIC) or Akaike Information Criterion +#' (AIC), improves. And, "subsets" enables subsets selection using #' \code{\link[leaps]{regsubsets}}; chooses the best performing subset of any -#' given size or within a range of subset sizes. See -#' \code{\link{fitTsfm.control}} for more details on the control arguments. +#' given size or within a range of subset sizes. Different methods such as +#' exhaustive search (default), forward or backward stepwise, or sequential +#' replacement can be employed.See \code{\link{fitTsfm.control}} for more +#' details on the control arguments. +#' #' \code{variable.selection="lars"} corresponds to least angle regression -#' using \code{\link[lars]{lars}} with variants "lasso", "lar", "stepwise" or -#' "forward.stagewise". Note: If \code{variable.selection="lars"}, +#' using \code{\link[lars]{lars}} with variants "lasso" (default), "lar", +#' "stepwise" or "forward.stagewise". Note: If \code{variable.selection="lars"}, #' \code{fit.method} will be ignored. #' #' Arguments \code{mkt.name} and \code{mkt.timing} allow for market-timing #' factors to be added to any of the above methods. Market timing accounts for #' the price movement of the general stock market relative to fixed income -#' securities. "HM" follows Henriksson & Merton (1981) and -#' \code{up.market=max(0,Rm-Rf)}, is added to the regression. The coefficient -#' of this up-market factor can be interpreted as the number of free put -#' options. Similarly, "TM" follows Treynor-Mazuy (1966), to account for market -#' timing with respect to volatility, and \code{market.sqd=(Rm-Rf)^2} is added -#' as a factor in the regression. Option "both" (default) adds both of these -#' factors. +#' securities. Specifying \code{mkt.timing="HM"}, includes +#' $up.market = max(0, R_m-R_f)$ as a factor, followinhg Henriksson & Merton +#' (1981). The coefficient of this up-market factor can be interpreted as the +#' number of free put options. Similarly, to account for market timing with +#' respect to volatility, one can specify \code{mkt.timing="TM"}. Following +#' \citet{treynor1966can}, $market.sqd = (R_m-R_f)^2$ is added as a factor. To +#' include both these market-timing factors in the model, one can specify +#' \code{mkt.timing=c("HM","TM")}. #' #' \subsection{Data Processing}{ #' @@ -70,7 +74,7 @@ #' See details. Default is "OLS". #' @param variable.selection the variable selection method, one of "none", #' "stepwise","subsets","lars". See details. Default is "none". -#' @param mkt.timing one of "HM", "TM" or "both" (default). See Details. +#' @param mkt.timing one of "HM", "TM" or "both". See Details. Default is NULL. #' \code{mkt.name} is required if any of these options are to be implemented. #' @param control list of control parameters. The default is constructed by #' the function \code{\link{fitTsfm.control}}. See the documentation for @@ -177,7 +181,7 @@ fitTsfm <- function(asset.names, factor.names, mkt.name=NULL, rf.name=NULL, data=data, fit.method=c("OLS","DLS","Robust"), variable.selection=c("none","stepwise","subsets","lars"), - mkt.timing="both", control=fitTsfm.control(...), ...) { + mkt.timing=NULL, control=fitTsfm.control(...), ...) { # record the call as an element to be returned call <- match.call() @@ -196,6 +200,10 @@ factor.names <- NULL } + if (is.null(mkt.name) && !is.null(mkt.timing)) { + stop("Missing argument: mkt.name is necessary to add market timing factors") + } + # extract arguments to pass to different fit and variable selection functions decay <- control$decay nvmin <- control$nvmin @@ -237,21 +245,19 @@ } # opt add mkt-timing factors: up.market=max(0,Rm-Rf), market.sqd=(Rm-Rf)^2 - if (!is.null(mkt.name)) { - if(mkt.timing=="HM" || mkt.timing=="both") { - up.market <- data.xts[,mkt.name] - up.market [up.market < 0] <- 0 - dat.xts <- merge.xts(dat.xts,up.market) - colnames(dat.xts)[dim(dat.xts)[2]] <- "up.market" - factor.names <- c(factor.names, "up.market") - } - if(mkt.timing=="TM" || mkt.timing=="both") { - market.sqd <- data.xts[,mkt.name]^2 - dat.xts <- merge(dat.xts, market.sqd) - colnames(dat.xts)[dim(dat.xts)[2]] <- "market.sqd" - factor.names <- c(factor.names, "market.sqd") - } + if("HM" %in% mkt.timing) { + up.market <- data.xts[,mkt.name] + up.market [up.market < 0] <- 0 + dat.xts <- merge.xts(dat.xts,up.market) + colnames(dat.xts)[dim(dat.xts)[2]] <- "up.market" + factor.names <- c(factor.names, "up.market") } + if("TM" %in% mkt.timing) { + market.sqd <- data.xts[,mkt.name]^2 + dat.xts <- merge(dat.xts, market.sqd) + colnames(dat.xts)[dim(dat.xts)[2]] <- "market.sqd" + factor.names <- c(factor.names, "market.sqd") + } # spaces get converted to periods in colnames of xts object after merge asset.names <- gsub(" ",".", asset.names, fixed=TRUE) Modified: pkg/FactorAnalytics/R/fmEsDecomp.R =================================================================== --- pkg/FactorAnalytics/R/fmEsDecomp.R 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/R/fmEsDecomp.R 2014-12-02 06:42:48 UTC (rev 3564) @@ -35,11 +35,10 @@ #' \code{\link[PerformanceAnalytics]{VaR}}. #' #' @return A list containing -#' \item{VaR.fm}{length-N vector of factor model VaRs of N-asset returns.} +#' \item{ES.fm}{length-N vector of factor model ES of N-asset returns.} #' \item{n.exceed}{length-N vector of number of observations beyond VaR for #' each asset.} #' \item{idx.exceed}{list of numeric vector of index values of exceedances.} -#' \item{ES.fm}{length-N vector of factor model ES of N-asset returns.} #' \item{mES}{N x (K+1) matrix of marginal contributions to VaR.} #' \item{cES}{N x (K+1) matrix of component contributions to VaR.} #' \item{pcES}{N x (K+1) matrix of percentage component contributions to VaR.} @@ -173,8 +172,8 @@ pcES[i,] <- 100* cES[i,] / ES.fm[i] } - fm.ES.decomp <- list(VaR.fm=VaR.fm, n.exceed=n.exceed, idx.exceed=idx.exceed, - ES.fm=ES.fm, mES=mES, cES=cES, pcES=pcES) + fm.ES.decomp <- list(ES.fm=ES.fm, n.exceed=n.exceed, idx.exceed=idx.exceed, + mES=mES, cES=cES, pcES=pcES) return(fm.ES.decomp) } @@ -258,8 +257,8 @@ pcES[i,] <- 100* cES[i,] / ES.fm[i] } - fm.ES.decomp <- list(VaR.fm=VaR.fm, n.exceed=n.exceed, idx.exceed=idx.exceed, - ES.fm=ES.fm, mES=mES, cES=cES, pcES=pcES) + fm.ES.decomp <- list(ES.fm=ES.fm, n.exceed=n.exceed, idx.exceed=idx.exceed, + mES=mES, cES=cES, pcES=pcES) return(fm.ES.decomp) } Modified: pkg/FactorAnalytics/R/plot.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/plot.tsfm.r 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/R/plot.tsfm.r 2014-12-02 06:42:48 UTC (rev 3564) @@ -14,7 +14,7 @@ #' For group plots (the default), the first \code{max.show} assets are plotted. #' For individual plots, \code{asset.name} is necessary if multiple assets #' were modeled in \code{x} and \code{plot.single=TRUE}. However, if the -#' \code{fitTsfm} object \code{x} only contains one asset's factor model fit, +#' \code{fitTsfm} object contains only one asset's factor model fit, #' \code{plot.tsfm} can infer this automatically, without user input. #' #' CUSUM plots (individual asset plot options 10, 11 and 12) are applicable Modified: pkg/FactorAnalytics/R/print.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/print.tsfm.r 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/R/print.tsfm.r 2014-12-02 06:42:48 UTC (rev 3564) @@ -36,7 +36,9 @@ cat("\nRegression Alphas:\n") print(t(x$alpha), digits=digits, ...) cat("\nFactor Betas:\n") - print(x$beta, digits=digits, ...) + B <- as.matrix(t(x$beta)) + if (x$variable.selection=="lars") { B[B==0] <- NA } + print(B, digits=digits, na.print="-", ...) cat("\nR-squared values:\n") print(x$r2, digits=digits, ...) cat("\nResidual Volatilities:\n") Modified: pkg/FactorAnalytics/R/summary.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.tsfm.r 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/R/summary.tsfm.r 2014-12-02 06:42:48 UTC (rev 3564) @@ -9,8 +9,11 @@ #' heteroskedasticity-consistent (HC) or #' heteroskedasticity-autocorrelation-consistent (HAC) standard errors and #' t-statistics using \code{\link[lmtest]{coeftest}}. This option is meaningful -#' only if \code{fit.method = "OLS" or "DLS"}. HC/HAC errors are currently not -#' available for \code{variable.selection = "lars"}. +#' only if \code{fit.method = "OLS" or "DLS"}. +#' Standard errors are currently not available for +#' \code{variable.selection="lars"} as there seems to be no consensus on a +#' statistically valid method of calculating standard errors for the lasso +#' predictions. #' #' @param object an object of class \code{tsfm} returned by \code{fitTsfm}. #' @param se.type one of "Default", "HC" or "HAC"; option for computing @@ -65,7 +68,7 @@ stop("Invalid 'tsfm' object") } # note: fit.method=NULL for "lars" objects - if (!(object$fit.method %in% c("OLS","DLS")) && se.type!="Default") { + if (object$fit.method=="Robust" && se.type!="Default") { stop("Invalid argument: HC/HAC standard errors are applicable only if fit.method = 'OLS' or 'DLS'") } @@ -117,11 +120,15 @@ n <- length(x) for (i in 3:n) { options(digits = digits) - cat("\nAsset", i-2, ": ", names(x[i]), "\n(",x$se.type, - " Standard Errors & T-stats)\n\n", sep = "") + if (dim(x[[i]]$coefficients)[2] > 1) { + cat("\nAsset", i-2, ": ", names(x[i]), "\n(", x$se.type, + " Standard Errors & T-stats)\n\n", sep="") + } else { + cat("\nAsset", i-2, ": ", names(x[i]), "\n\n", sep="") + } table.coef <- x[[i]]$coefficients - print(table.coef, digits = digits, ...) + printCoefmat(table.coef, digits=digits, ...) cat("\nR-squared: ", x[[i]]$r.squared,", Residual Volatility: " - , x[[i]]$sigma,"\n", sep = "") + , x[[i]]$sigma,"\n", sep="") } } Modified: pkg/FactorAnalytics/man/fitSfm.Rd =================================================================== --- pkg/FactorAnalytics/man/fitSfm.Rd 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-02 06:42:48 UTC (rev 3564) @@ -118,23 +118,23 @@ # pca args(fitSfm) -sfm.pca.fit <- fitSfm(sfm.dat, k=2) -class(sfm.pca.fit) -names(sfm.pca.fit) -head(sfm.pca.fit$factors) -head(sfm.pca.fit$loadings) -sfm.pca.fit$r2 -sfm.pca.fit$resid.sd -sfm.pca.fit$mimic +fit.pca <- fitSfm(sfm.dat, k=2) +class(fit.pca) +names(fit.pca) +head(fit.pca$factors) +head(fit.pca$loadings) +fit.pca$r2 +fit.pca$resid.sd +fit.pca$mimic # apca with number of factors, k=15 -sfm.apca.fit <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) # apca with the Bai & Ng method -sfm.apca.fit.bn <- fitSfm(sfm.apca.dat, k="bn") +fit.apca.bn <- fitSfm(sfm.apca.dat, k="bn") # apca with the Connor-Korajczyk method -sfm.apca.fit.ck <- fitSfm(sfm.apca.dat, k="ck") +fit.apca.ck <- fitSfm(sfm.apca.dat, k="ck") } \author{ Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Modified: pkg/FactorAnalytics/man/fitTsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/fitTsfm.Rd 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/man/fitTsfm.Rd 2014-12-02 06:42:48 UTC (rev 3564) @@ -9,7 +9,7 @@ fitTsfm(asset.names, factor.names, mkt.name = NULL, rf.name = NULL, data = data, fit.method = c("OLS", "DLS", "Robust"), variable.selection = c("none", "stepwise", "subsets", "lars"), - mkt.timing = "both", control = fitTsfm.control(...), ...) + mkt.timing = NULL, control = fitTsfm.control(...), ...) \method{coef}{tsfm}(object, ...) @@ -40,7 +40,7 @@ \item{variable.selection}{the variable selection method, one of "none", "stepwise","subsets","lars". See details. Default is "none".} -\item{mkt.timing}{one of "HM", "TM" or "both" (default). See Details. +\item{mkt.timing}{one of "HM", "TM" or "both". See Details. Default is NULL. \code{mkt.name} is required if any of these options are to be implemented.} \item{control}{list of control parameters. The default is constructed by @@ -100,31 +100,35 @@ squares with exponentially declining weights that sum to unity), and, "Robust" is robust regression (using \code{\link[robust]{lmRob}}). -If \code{variable.selection="none"}, all chosen factors are used in the -factor model. Whereas, "stepwise" performs traditional forward/backward -stepwise OLS regression (using \code{\link[stats]{step}} or +If \code{variable.selection="none"}, uses all the factors and performs no +variable selection. Whereas, "stepwise" performs traditional stepwise +LS or Robust regression (using \code{\link[stats]{step}} or \code{\link[robust]{step.lmRob}}), that starts from the initial set of -factors and adds factors only if the regression fit, as measured by the -Bayesian Information Criterion (BIC) or Akaike Information Criterion (AIC), -improves. And, "subsets" enables subsets selection using +factors and adds/subtracts factors only if the regression fit, as measured +by the Bayesian Information Criterion (BIC) or Akaike Information Criterion +(AIC), improves. And, "subsets" enables subsets selection using \code{\link[leaps]{regsubsets}}; chooses the best performing subset of any -given size or within a range of subset sizes. See -\code{\link{fitTsfm.control}} for more details on the control arguments. +given size or within a range of subset sizes. Different methods such as +exhaustive search (default), forward or backward stepwise, or sequential +replacement can be employed.See \code{\link{fitTsfm.control}} for more +details on the control arguments. + \code{variable.selection="lars"} corresponds to least angle regression -using \code{\link[lars]{lars}} with variants "lasso", "lar", "stepwise" or -"forward.stagewise". Note: If \code{variable.selection="lars"}, +using \code{\link[lars]{lars}} with variants "lasso" (default), "lar", +"stepwise" or "forward.stagewise". Note: If \code{variable.selection="lars"}, \code{fit.method} will be ignored. Arguments \code{mkt.name} and \code{mkt.timing} allow for market-timing factors to be added to any of the above methods. Market timing accounts for the price movement of the general stock market relative to fixed income -securities. "HM" follows Henriksson & Merton (1981) and -\code{up.market=max(0,Rm-Rf)}, is added to the regression. The coefficient -of this up-market factor can be interpreted as the number of free put -options. Similarly, "TM" follows Treynor-Mazuy (1966), to account for market -timing with respect to volatility, and \code{market.sqd=(Rm-Rf)^2} is added -as a factor in the regression. Option "both" (default) adds both of these -factors. +securities. Specifying \code{mkt.timing="HM"}, includes +$up.market = max(0, R_m-R_f)$ as a factor, followinhg Henriksson & Merton +(1981). The coefficient of this up-market factor can be interpreted as the +number of free put options. Similarly, to account for market timing with +respect to volatility, one can specify \code{mkt.timing="TM"}. Following +\citet{treynor1966can}, $market.sqd = (R_m-R_f)^2$ is added as a factor. To +include both these market-timing factors in the model, one can specify +\code{mkt.timing=c("HM","TM")}. \subsection{Data Processing}{ Modified: pkg/FactorAnalytics/man/fmEsDecomp.Rd =================================================================== --- pkg/FactorAnalytics/man/fmEsDecomp.Rd 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/man/fmEsDecomp.Rd 2014-12-02 06:42:48 UTC (rev 3564) @@ -29,11 +29,10 @@ } \value{ A list containing -\item{VaR.fm}{length-N vector of factor model VaRs of N-asset returns.} +\item{ES.fm}{length-N vector of factor model ES of N-asset returns.} \item{n.exceed}{length-N vector of number of observations beyond VaR for each asset.} \item{idx.exceed}{list of numeric vector of index values of exceedances.} -\item{ES.fm}{length-N vector of factor model ES of N-asset returns.} \item{mES}{N x (K+1) matrix of marginal contributions to VaR.} \item{cES}{N x (K+1) matrix of component contributions to VaR.} \item{pcES}{N x (K+1) matrix of percentage component contributions to VaR.} Modified: pkg/FactorAnalytics/man/plot.tsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/plot.tsfm.Rd 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/man/plot.tsfm.Rd 2014-12-02 06:42:48 UTC (rev 3564) @@ -87,7 +87,7 @@ For group plots (the default), the first \code{max.show} assets are plotted. For individual plots, \code{asset.name} is necessary if multiple assets were modeled in \code{x} and \code{plot.single=TRUE}. However, if the -\code{fitTsfm} object \code{x} only contains one asset's factor model fit, +\code{fitTsfm} object contains only one asset's factor model fit, \code{plot.tsfm} can infer this automatically, without user input. CUSUM plots (individual asset plot options 10, 11 and 12) are applicable Modified: pkg/FactorAnalytics/man/summary.tsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.tsfm.Rd 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/man/summary.tsfm.Rd 2014-12-02 06:42:48 UTC (rev 3564) @@ -44,8 +44,11 @@ heteroskedasticity-consistent (HC) or heteroskedasticity-autocorrelation-consistent (HAC) standard errors and t-statistics using \code{\link[lmtest]{coeftest}}. This option is meaningful -only if \code{fit.method = "OLS" or "DLS"}. HC/HAC errors are currently not -available for \code{variable.selection = "lars"}. +only if \code{fit.method = "OLS" or "DLS"}. +Standard errors are currently not available for +\code{variable.selection="lars"} as there seems to be no consensus on a +statistically valid method of calculating standard errors for the lasso +predictions. } \note{ For a more detailed printed summary for each asset, refer to Modified: pkg/FactorAnalytics/vignettes/FA.bib =================================================================== --- pkg/FactorAnalytics/vignettes/FA.bib 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/vignettes/FA.bib 2014-12-02 06:42:48 UTC (rev 3564) @@ -116,12 +116,15 @@ publisher={RISK MAGAZINE LIMITED} } - at book{sharpe1970portfolio, - title={Portfolio theory and capital markets}, - author={Sharpe, William F and Sharpe, WF}, - volume={217}, - year={1970}, - publisher={McGraw-Hill New York} + at article{sharpe1964capital, + title={Capital asset prices: A theory of market equilibrium under conditions of risk*}, + author={Sharpe, William F}, + journal={The journal of finance}, + volume={19}, + number={3}, + pages={425--442}, + year={1964}, + publisher={Wiley Online Library} } @article{treynor1966can, Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.R =================================================================== --- pkg/FactorAnalytics/vignettes/fitTsfm_vignette.R 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/vignettes/fitTsfm_vignette.R 2014-12-02 06:42:48 UTC (rev 3564) @@ -1,6 +1,7 @@ ## ----message=FALSE------------------------------------------------------- library(factorAnalytics) +options(digits=3) ## ------------------------------------------------------------------------ @@ -27,66 +28,77 @@ ## ------------------------------------------------------------------------ -fit.Sharpe <- fitTsfm(asset.names=asset.names, factor.names="SP500 TR", - rf.name="US 3m TR", data=managers) -names(fit.Sharpe) -fit.Sharpe +# Single Index Model using SP500 +fit.singleIndex <- fitTsfm(asset.names=asset.names, factor.names="SP500 TR", + rf.name="US 3m TR", data=managers) ## ------------------------------------------------------------------------ -# adding up-market timing factor ("HM") to the model -fit1 <- fitTsfm(asset.names=asset.names, factor.names=factor.names, - mkt.name="SP500 TR", mkt.timing="HM", data=managers) -fit1$beta -fit1$r2 -fit1$resid.sd +class(fit.singleIndex) +names(fit.singleIndex) ## ------------------------------------------------------------------------ -fit2 <- fitTsfm(asset.names=asset.names, factor.names=factor.names, - mkt.name="SP500 TR", data=managers, fit.method="Robust") -fit2$beta -fit2$r2 -fit2$resid.sd +fit.singleIndex # print the fitted "tsfm" object -## ----fig.cap="HAM3 Returns: fit1-OLS (top) vs fit2-Robust (bottom)", fig.show='hold'---- +## ------------------------------------------------------------------------ +# Henriksson-Merton's market timing model +fit.mktTiming <- fitTsfm(asset.names=asset.names, rf.name="US 3m TR", + mkt.name="SP500 TR", mkt.timing="HM", data=managers) +fit.mktTiming + + +## ------------------------------------------------------------------------ +fit.ols <- fitTsfm(asset.names=asset.names, factor.names=factor.names, + rf.name="US 3m TR", data=managers) +fit.ols$beta +fit.ols$r2 +fit.ols$resid.sd + + +## ------------------------------------------------------------------------ +fit.robust <- fitTsfm(asset.names=asset.names, factor.names=factor.names, + rf.name="US 3m TR", data=managers, fit.method="Robust") +fit.robust$beta +fit.robust$r2 +fit.robust$resid.sd + + +## ----fig.cap="HAM3 Returns: OLS (top) vs Robust (bottom)", fig.show='hold'---- par(mfrow=c(2,1)) -plot(fit1, plot.single=TRUE, which.plot.single=1, asset.name="HAM3", loop=FALSE) -plot(fit2, plot.single=TRUE, which.plot.single=1, asset.name="HAM3", loop=FALSE) +plot(fit.ols, plot.single=TRUE, which.plot.single=1, asset.name="HAM3", loop=FALSE) +mtext("OLS", side=3) +plot(fit.robust, plot.single=TRUE, which.plot.single=1, asset.name="HAM3", loop=FALSE) +mtext("Robust", side=3) -## ----fig.cap="Residual vol: fit1-OLS (left) vs fit2-Robust (right)", fig.width=3, fig.height=2.5, out.width='.49\\linewidth', fig.show='hold'---- +## ----fig.cap="Residual vol: OLS (left) vs Robust (right)", fig.width=3, fig.height=2.5, out.width='.49\\linewidth', fig.show='hold'---- par(mfrow=c(1,2)) -plot(fit1, which.plot.group=5, loop=FALSE, xlim=c(0,0.043)) -plot(fit2, which.plot.group=5, loop=FALSE, xlim=c(0,0.043)) +plot(fit.ols, which.plot.group=5, loop=FALSE, xlim=c(0,0.043), sub="OLS") +plot(fit.robust, which.plot.group=5, loop=FALSE, xlim=c(0,0.043), sub="Robust") -## ------------------------------------------------------------------------ -fit.lars <- fitTsfm(asset.names=colnames(managers[,(1:6)]), - factor.names=colnames(managers[,(7:9)]), data=managers, - rf.name="US 3m TR", mkt.name="SP500 TR") -fit.lars$beta -fit.lars$r2 +## ----fig.show='hide'----------------------------------------------------- +fit.lars <- fitTsfm(asset.names=asset.names, factor.names=factor.names, + data=managers, rf.name="US 3m TR", + variable.selection="lars") +fit.lars -fit.sub <- fitTsfm(asset.names=colnames(managers[,(1:6)]), - factor.names=colnames(managers[,(7:9)]), data=managers, - rf.name="US 3m TR", mkt.name="SP500 TR", - variable.selection="subsets", subset.size=4) -fit.sub$beta -fit.sub$r2 +## ------------------------------------------------------------------------ +fit.sub <- fitTsfm(asset.names=asset.names, factor.names=factor.names, + data=managers, rf.name="US 3m TR", + variable.selection="subsets", nvmin=2, nvmax=2) +fit.sub -## ----fig.cap="Factor betas: fit.lars", fig.show='hold'------------------- -plot(fit.lars, which.plot.group=2, loop=FALSE) - ## ----fig.cap="Factor betas: fit.sub", fig.show='hold'-------------------- plot(fit.sub, which.plot.group=2, loop=FALSE) -## ----tidy=TRUE----------------------------------------------------------- -args(fitTsfm.control) +## ----fig.cap="Factor betas: fit.lars", fig.show='hold'------------------- +plot(fit.lars, which.plot.group=2, loop=FALSE) ## ------------------------------------------------------------------------ @@ -94,18 +106,19 @@ ## ------------------------------------------------------------------------ -coef(fit.sub) -tail(fitted(fit.sub)) -tail(residuals(fit.sub)) +# all estimated coefficients from the OLS fit using all 3 factors +coef(fit.ols) -# comparing data, fitted and residual values for HAM1 -tail(merge(fit.sub$data[,1], fitted(fit.sub)[,1], residuals(fit.sub)[,1])) +# compare returns data with fitted and residual values for HAM1 from fit.lars +HAM1.ts <- merge(fit.lars$data[,1], fitted(fit.lars)[,1], + residuals(fit.lars)[,1]) +colnames(HAM1.ts) <- c("HAM1.return","HAM1.fitted","HAM1.residual") +tail(HAM1.ts) -# printed summary for the time series factor model +# summary for fit.sub computing HAC standard erros summary(fit.sub, se.type="HAC") - ## ----fig.cap="Factor model return correlation (pairwise complete obs)"---- fmCov(fit.sub) # return correlation plot; Angular Order of the Eigenvectors @@ -115,6 +128,7 @@ ## ----fig.cap="Percentage factor contribution to SD"---------------------- decomp <- fmSdDecomp(fit.sub) +names(decomp) # get the factor model standard deviation for all assets decomp$Sd.fm # get the component contributions to Sd @@ -128,24 +142,22 @@ ## ----fig.cap="Percentage factor contribution to VaR"--------------------- -decomp2 <- fmVaRDecomp(fit.sub) +decomp1 <- fmVaRDecomp(fit.sub) +names(decomp1) # get the factor model value-at-risk for all assets -decomp2$VaR.fm -# get the component contributions to VaR -decomp2$cVaR -# get the marginal factor contributions to VaR -decomp2$mVaR +decomp1$VaR.fm # get the percentage component contributions to VaR -decomp2$pcVaR +decomp1$pcVaR # plot the percentage component contributions to VaR plot(fit.sub, which.plot.group=10, loop=FALSE) ## ----fig.cap="Percentage factor contribution to ES"---------------------- decomp2 <- fmEsDecomp(fit.sub, method="historical") +names(decomp2) # get the factor model expected shortfall for all assets decomp2$ES.fm -# get the component contributions to ES +# get the component contributions to Sd decomp2$cES # get the marginal factor contributions to ES decomp2$mES @@ -156,7 +168,7 @@ ## ----eval=FALSE---------------------------------------------------------- -## ## S3 method for class 'tsfm' +## ## S3 method for class "tsfm" ## plot(x, which.plot.group=NULL, max.show=6, plot.single=FALSE, asset.name, ## which.plot.single=NULL, colorset=(1:12), legend.loc="topleft", las=1, ## VaR.method="historical", loop=TRUE, ...) Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-11-25 23:37:06 UTC (rev 3563) +++ pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-02 06:42:48 UTC (rev 3564) @@ -33,6 +33,7 @@ \tableofcontents \bigskip +\newpage \section{Overview} \subsection{Load Package} @@ -52,35 +53,33 @@ \begin{itemize} -\item \verb"fitTsfm(asset.names, factor.names, data, fit.method, variable.selection)": Fits a time series (a.k.a. macroeconomic) factor model for one or more asset returns or excess returns using time series regression. Ordinary least squares-OLS, discounted least squares-DLS and robust regression fitting are possible. Variable selection methods include Step-wise, Subsets and Lars. An object of class \code{"tsfm"} containing the fitted objects, model coefficients, R-squared and residual volatility are returned. +\item \verb"fitTsfm(asset.names, factor.names, data, fit.method, variable.selection)": Fits a time series (a.k.a. macroeconomic) factor model for one or more asset returns or excess returns using time series regression. Ordinary least squares (OLS), discounted least squares (DLS) and robust regression fitting are possible. Variable selection methods include "stepwise", "subsets" and "lars". An object of class "tsfm" containing the fitted objects, model coefficients, R-squared and residual volatility are returned. -\item \verb"coef(object)": Extracts the coefficient matrix (intercept and factor betas) for all assets fit by the \code{tsfm} object. +\item \verb"coef(object)": Extracts the coefficient matrix (intercept and factor betas) for all assets fit by the "tsfm" object. -\item \verb"fitted(object)": Returns an \code{xts} data object of fitted asset returns from the factor model for all assets. +\item \verb"fitted(object)": Returns an "xts" data object of fitted asset returns from the factor model for all assets. -\item \verb"residuals(object)": Returns an \code{xts} data object of residuals from the fitted factor model for all assets. +\item \verb"residuals(object)": Returns an "xts" data object of residuals from the fitted factor model for all assets. -\item \verb"fmCov(object, use)": Returns the \code{N x N} symmetric covariance matrix for asset returns based on the fitted factor model. \code{use} specifies how missing values are to be handled. +\item \verb"fmCov(object, use)": Returns the \code{N x N} symmetric covariance matrix for asset returns based on the fitted factor model. \code{"use"} specifies how missing values are to be handled. -\item \verb"fmSdDecomp(object)": Returns a list containing the standard deviation of asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{use} specifies how missing values are to be handled. +\item \verb"fmSdDecomp(object, use)": Returns a list containing the standard deviation of asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{"use"} specifies how missing values are to be handled. -\item \verb"fmVaRDecomp(object, p, method, invert)": Returns a list containing the value-at-risk for asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{p} and \code{method} specify the confidence level and method to calculate VaR. \code{invert} allows the VaR value to be expressed as a loss (vs. fund's return/profit). [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3564 From noreply at r-forge.r-project.org Tue Dec 2 08:30:59 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 2 Dec 2014 08:30:59 +0100 (CET) Subject: [Returnanalytics-commits] r3565 - in pkg/FactorAnalytics: R man Message-ID: <20141202073059.BB45C186DB2@r-forge.r-project.org> Author: pragnya Date: 2014-12-02 08:30:59 +0100 (Tue, 02 Dec 2014) New Revision: 3565 Modified: pkg/FactorAnalytics/R/fitTsfm.R pkg/FactorAnalytics/man/fitTsfm.Rd Log: Fixed typo in example Modified: pkg/FactorAnalytics/R/fitTsfm.R =================================================================== --- pkg/FactorAnalytics/R/fitTsfm.R 2014-12-02 06:42:48 UTC (rev 3564) +++ pkg/FactorAnalytics/R/fitTsfm.R 2014-12-02 07:30:59 UTC (rev 3565) @@ -43,7 +43,7 @@ #' (1981). The coefficient of this up-market factor can be interpreted as the #' number of free put options. Similarly, to account for market timing with #' respect to volatility, one can specify \code{mkt.timing="TM"}. Following -#' \citet{treynor1966can}, $market.sqd = (R_m-R_f)^2$ is added as a factor. To +#' Treynor & Mazuy (1966), $market.sqd = (R_m-R_f)^2$ is added as a factor. To #' include both these market-timing factors in the model, one can specify #' \code{mkt.timing=c("HM","TM")}. #' @@ -145,8 +145,7 @@ #' # load data from the database #' data(managers) #' fit <- fitTsfm(asset.names=colnames(managers[,(1:6)]), -#' factor.names=colnames(managers[,(7:9)]), -#' mkt.name="SP500 TR", mkt.timing="HM", data=managers) +#' factor.names=colnames(managers[,(7:9)]), data=managers) #' summary(fit) #' fitted(fit) #' # plot actual returns vs. fitted factor model returns for HAM1 @@ -157,7 +156,8 @@ #' #' # example: Market-timing factors with robust fit #' fit <- fitTsfm(asset.names=colnames(managers[,(1:6)]), factor.names=NULL, -#' mkt.name="SP500 TR", data=managers, fit.method="Robust") +#' mkt.name="SP500 TR", mkt.timing="HM", data=managers, +#' fit.method="Robust") #' #' # example using "subsets" variable selection #' fit.sub <- fitTsfm(asset.names=colnames(managers[,(1:6)]), @@ -200,8 +200,9 @@ factor.names <- NULL } - if (is.null(mkt.name) && !is.null(mkt.timing)) { - stop("Missing argument: mkt.name is necessary to add market timing factors") + if (xor(is.null(mkt.name), is.null(mkt.timing))) { + stop("Missing argument: Both mkt.name and mkt.timing are necessary to add + market timing factors") } # extract arguments to pass to different fit and variable selection functions Modified: pkg/FactorAnalytics/man/fitTsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/fitTsfm.Rd 2014-12-02 06:42:48 UTC (rev 3564) +++ pkg/FactorAnalytics/man/fitTsfm.Rd 2014-12-02 07:30:59 UTC (rev 3565) @@ -126,7 +126,7 @@ (1981). The coefficient of this up-market factor can be interpreted as the number of free put options. Similarly, to account for market timing with respect to volatility, one can specify \code{mkt.timing="TM"}. Following -\citet{treynor1966can}, $market.sqd = (R_m-R_f)^2$ is added as a factor. To +Treynor & Mazuy (1966), $market.sqd = (R_m-R_f)^2$ is added as a factor. To include both these market-timing factors in the model, one can specify \code{mkt.timing=c("HM","TM")}. @@ -146,8 +146,7 @@ # load data from the database data(managers) fit <- fitTsfm(asset.names=colnames(managers[,(1:6)]), - factor.names=colnames(managers[,(7:9)]), - mkt.name="SP500 TR", mkt.timing="HM", data=managers) + factor.names=colnames(managers[,(7:9)]), data=managers) summary(fit) fitted(fit) # plot actual returns vs. fitted factor model returns for HAM1 @@ -158,7 +157,8 @@ # example: Market-timing factors with robust fit fit <- fitTsfm(asset.names=colnames(managers[,(1:6)]), factor.names=NULL, - mkt.name="SP500 TR", data=managers, fit.method="Robust") + mkt.name="SP500 TR", mkt.timing="HM", data=managers, + fit.method="Robust") # example using "subsets" variable selection fit.sub <- fitTsfm(asset.names=colnames(managers[,(1:6)]), From noreply at r-forge.r-project.org Thu Dec 4 08:46:15 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 4 Dec 2014 08:46:15 +0100 (CET) Subject: [Returnanalytics-commits] r3566 - in pkg/FactorAnalytics: . R man vignettes Message-ID: <20141204074615.B1C2F186C27@r-forge.r-project.org> Author: pragnya Date: 2014-12-04 08:46:15 +0100 (Thu, 04 Dec 2014) New Revision: 3566 Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/R/plot.tsfm.r pkg/FactorAnalytics/man/plot.tsfm.Rd pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf Log: Edits to description and examples in plot.fitTsfm Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-12-02 07:30:59 UTC (rev 3565) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-04 07:46:15 UTC (rev 3566) @@ -1,8 +1,8 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.3 -Date: 2014-12-01 +Version: 2.0.4 +Date: 2014-12-03 Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Description: An R package for the estimation and risk analysis of linear factor Modified: pkg/FactorAnalytics/R/plot.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/plot.tsfm.r 2014-12-02 07:30:59 UTC (rev 3565) +++ pkg/FactorAnalytics/R/plot.tsfm.r 2014-12-04 07:46:15 UTC (rev 3566) @@ -37,12 +37,11 @@ #' 9 = Factor Contribution to ES,\cr #' 10 = Factor Contribution to VaR #' @param max.show maximum number of assets in a given plot. Default is 6. -#' @param plot.single a logical value. \code{TRUE} plots the characteristics of -#' an individual asset's factor model. The type of plot is given by +#' @param plot.single logical; If \code{TRUE} plots the characteristics of an +#' individual asset's factor model. The type of plot is given by #' \code{which.plot.single}. Default is \code{FALSE}. #' @param asset.name name of the individual asset to be plotted. Is necessary -#' if multiple assets factor model fits exist in \code{x} and -#' \code{plot.single=TRUE}. +#' if \code{x} contains multiple asset fits and \code{plot.single=TRUE}. #' @param which.plot.single a number to indicate the type of group plot for an #' individual asset. If \code{NULL} (default), the following menu appears: \cr #' 1 = Time series plot of actual and fitted asset returns,\cr @@ -101,9 +100,15 @@ #' fit.macro <- fitTsfm(asset.names=colnames(managers[,(1:6)]), #' factor.names=colnames(managers[,(7:8)]), #' rf.name="US 3m TR", data=managers) -#' -#' # plot the factor betas of 1st 4 assets fitted above. +#' +#' # group plot(default); select type from menu prompt +#' # menu is auto-looped to get multiple types of plots based on the same fit +#' # plot(fit.macro) +#' +#' # plot the factor betas of 1st 4 assets fitted above +#' # loop disabled to get one type of plot without interative menu #' plot(fit.macro, max.show=4, which.plot.group=2, loop=FALSE) +#' #' # plot factor model return correlation; angular order of the eigenvectors #' plot(fit.macro, which.plot.group=7, loop=FALSE, #' order="AOE", method="ellipse", tl.pos = "d") @@ -112,9 +117,6 @@ #' plot(fit.macro, plot.single=TRUE, asset.name="HAM1", which.plot.single=8, #' loop=FALSE) #' -#' # group plot; type selected from menu prompt; auto-looped for multiple plots -#' # plot(fit.macro) -#' #' @importFrom PerformanceAnalytics chart.TimeSeries chart.ACFplus #' chart.Histogram chart.QQPlot #' @importFrom lattice barchart panel.barchart panel.grid @@ -134,7 +136,7 @@ if (missing(asset.name) && length(x$asset.names)>1) { stop("Missing input: 'asset.name' is required if plot.single is TRUE and - multiple assets factor model fits exist in 'x'.") + the factor model fits multiple assets.") } else if (length(x$asset.names)==1) { i <- x$asset.names[1] } else { @@ -326,8 +328,7 @@ ## Factor model coefficients: Betas k <- ncol(coef(x))-1 if (k > max.show) { - cat(paste("Displaying only the first", max.show,"factor betas, - as the number of factors > 'max.show' =", max.show)) + cat(paste("Displaying only the first", max.show,"factor betas, as the number of factors > 'max.show' =", max.show)) k <- max.show } par(mfrow=c(ceiling(k/2),2)) @@ -343,8 +344,7 @@ ## Actual and Fitted asset returns n <- length(x$asset.names) if (n > max.show) { - cat(paste("Displaying only the first", max.show, - "assets, since the number of assets > 'max.show'")) + cat(paste("Displaying only the first", max.show, "assets, since the number of assets > 'max.show'")) n <- max.show } par(mfrow=c(ceiling(n/2),2)) Modified: pkg/FactorAnalytics/man/plot.tsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/plot.tsfm.Rd 2014-12-02 07:30:59 UTC (rev 3565) +++ pkg/FactorAnalytics/man/plot.tsfm.Rd 2014-12-04 07:46:15 UTC (rev 3566) @@ -26,13 +26,12 @@ \item{max.show}{maximum number of assets in a given plot. Default is 6.} -\item{plot.single}{a logical value. \code{TRUE} plots the characteristics of -an individual asset's factor model. The type of plot is given by +\item{plot.single}{logical; If \code{TRUE} plots the characteristics of an +individual asset's factor model. The type of plot is given by \code{which.plot.single}. Default is \code{FALSE}.} \item{asset.name}{name of the individual asset to be plotted. Is necessary -if multiple assets factor model fits exist in \code{x} and -\code{plot.single=TRUE}.} +if \code{x} contains multiple asset fits and \code{plot.single=TRUE}.} \item{which.plot.single}{a number to indicate the type of group plot for an individual asset. If \code{NULL} (default), the following menu appears: \cr @@ -103,8 +102,14 @@ factor.names=colnames(managers[,(7:8)]), rf.name="US 3m TR", data=managers) -# plot the factor betas of 1st 4 assets fitted above. +# group plot(default); select type from menu prompt +# menu is auto-looped to get multiple types of plots based on the same fit +# plot(fit.macro) + +# plot the factor betas of 1st 4 assets fitted above +# loop disabled to get one type of plot without interative menu plot(fit.macro, max.show=4, which.plot.group=2, loop=FALSE) + # plot factor model return correlation; angular order of the eigenvectors plot(fit.macro, which.plot.group=7, loop=FALSE, order="AOE", method="ellipse", tl.pos = "d") @@ -112,9 +117,6 @@ # histogram of residuals from an individual asset's factor model fit plot(fit.macro, plot.single=TRUE, asset.name="HAM1", which.plot.single=8, loop=FALSE) - -# group plot; type selected from menu prompt; auto-looped for multiple plots -# plot(fit.macro) } \author{ Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-02 07:30:59 UTC (rev 3565) +++ pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-04 07:46:15 UTC (rev 3566) @@ -265,7 +265,7 @@ \end{itemize} \newpage -\subsection{Summary, Predict, Coefficients, Fitted values and Residuals} +\subsection{S3 generic methods} <<>>= methods(class="tsfm") @@ -278,6 +278,8 @@ Note: Standard errors are currently not available for the "lars" variable selection method, as there seems to be no consensus on a statistically valid method of calculating standard errors for the lasso predictions. +Factor model covariance and risk decomposition functions are explained in section 3 and \code{plot()} method is discussed separately in Section 4. + Here are some examples using the time series factor models fitted earlier. <<>>= # all estimated coefficients from the OLS fit using all 3 factors Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf =================================================================== (Binary files differ) From noreply at r-forge.r-project.org Thu Dec 4 08:48:23 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 4 Dec 2014 08:48:23 +0100 (CET) Subject: [Returnanalytics-commits] r3567 - in pkg/FactorAnalytics: . R man Message-ID: <20141204074823.40C63186C27@r-forge.r-project.org> Author: pragnya Date: 2014-12-04 08:48:22 +0100 (Thu, 04 Dec 2014) New Revision: 3567 Added: pkg/FactorAnalytics/R/plot.sfm.r pkg/FactorAnalytics/man/plot.sfm.Rd Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/NAMESPACE pkg/FactorAnalytics/R/fitSfm.R pkg/FactorAnalytics/man/fitSfm.Rd Log: Added plot.sfm, corr option for fitSfm Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-12-04 07:46:15 UTC (rev 3566) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-04 07:48:22 UTC (rev 3567) @@ -1,7 +1,7 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.4 +Version: 2.0.5 Date: 2014-12-03 Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Modified: pkg/FactorAnalytics/NAMESPACE =================================================================== --- pkg/FactorAnalytics/NAMESPACE 2014-12-04 07:46:15 UTC (rev 3566) +++ pkg/FactorAnalytics/NAMESPACE 2014-12-04 07:48:22 UTC (rev 3567) @@ -13,6 +13,7 @@ S3method(fmVaRDecomp,sfm) S3method(fmVaRDecomp,tsfm) S3method(plot,pafm) +S3method(plot,sfm) S3method(plot,tsfm) S3method(predict,sfm) S3method(predict,tsfm) @@ -50,6 +51,7 @@ importFrom(lattice,barchart) importFrom(lattice,panel.barchart) importFrom(lattice,panel.grid) +importFrom(lattice,xyplot) importFrom(leaps,regsubsets) importFrom(lmtest,coeftest) importFrom(lmtest,coeftest.default) Modified: pkg/FactorAnalytics/R/fitSfm.R =================================================================== --- pkg/FactorAnalytics/R/fitSfm.R 2014-12-04 07:46:15 UTC (rev 3566) +++ pkg/FactorAnalytics/R/fitSfm.R 2014-12-04 07:48:22 UTC (rev 3567) @@ -3,13 +3,15 @@ #' @description Fits a statistical factor model using principal component #' analysis for one or more asset returns or excess returns. When the number of #' assets exceeds the number of time periods, APCA (Asymptotic Principal -#' Component Analysis) is performed. This function is based on the S+FinMetric -#' function \code{mfactor}. An object of class \code{"sfm"} is returned. +#' Component Analysis) is performed. An object of class \code{"sfm"} is +#' returned. This function is based on the S+FinMetric function \code{mfactor}. #' #' @details #' If \code{data} is not of class \code{"xts"}, rownames must provide an -#' \code{xts} compatible time index. If the data contains missing values, -#' \code{na.rm} should be set to \code{TRUE} to remove NAs. +#' \code{xts} compatible time index. Before model fitting, incomplete cases in +#' \code{data} are removed using \code{\link[stats]{na.omit}}. Also, if +#' \code{check=TRUE}, a warning is issued if any asset is found to have +#' identical observations. #' #' Let \code{N} be the number of columns or assets and \code{T} be the number #' of rows or observations. When \code{N < T}, Principal Component Analysis @@ -27,12 +29,17 @@ #' \code{refine} specifies whether a refinement of the APCA procedure (that may #' improve efficiency) from Connor and Korajczyk (1988) is to be used. #' -#' If \code{check=TRUE}, a warning is issued if any asset is found to have -#' identical observations. +#' \code{corr} specifies if the correlation matrix of returns should be used +#' for finding the principal components instead of the covariance matrix. This +#' is decided on a case-by-case basis. The variable with the highest variance +#' dominates the PCA when the covariance matrix is used (but, this may be +#' justified if a volatile asset is more interesting for some reason and +#' volatility information shouldn't be discarded). On the other hand, using the +#' correlation matrix standardizes the variables and makes them comparable, +#' avoiding penalizing variables with less dispersion. #' -#' Note about NAs: Before model fitting, incomplete cases in \code{data} are -#' removed using \code{\link[stats]{na.omit}}. Otherwise, all observations are -#' included. +#' Note: If the median of the 1st principal component is negative, all it's +#' factor realizations are inverted to enable more meaningful interpretation. #' #' @param data vector, matrix, data.frame, xts, timeSeries or zoo object with #' asset returns. See details. @@ -46,7 +53,9 @@ #' specified. Default is 0.05. #' @param check logical; to check if any asset has identical observations. #' Default is \code{FALSE}. -#' @param ... arguments passed to other functions. +#' @param corr logical; whether to use the correlation instead of the covariance +#' matrix when finding the principal components. Default is \code{FALSE}. +#' @param ... optional arguments passed to \code{\link[stats]{lm}}. #' #' @return fitTsfm returns an object of class \code{"sfm"} for which #' \code{print}, \code{plot}, \code{predict} and \code{summary} methods exist. @@ -118,47 +127,45 @@ #' class(sfm.dat) #' class(sfm.apca.dat) #' -#' # pca +#' # PCA #' args(fitSfm) -#' sfm.pca.fit <- fitSfm(sfm.dat, k=2) -#' class(sfm.pca.fit) -#' names(sfm.pca.fit) -#' head(sfm.pca.fit$factors) -#' head(sfm.pca.fit$loadings) -#' sfm.pca.fit$r2 -#' sfm.pca.fit$resid.sd -#' sfm.pca.fit$mimic +#' fit.pca <- fitSfm(sfm.dat, k=2) +#' class(fit.pca) +#' names(fit.pca) +#' head(fit.pca$factors) +#' head(fit.pca$loadings) +#' fit.pca$r2 +#' fit.pca$resid.sd +#' fit.pca$mimic #' -#' # apca with number of factors, k=15 -#' sfm.apca.fit <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +#' # APCA with number of factors, k=15 +#' fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) #' -#' # apca with the Bai & Ng method -#' sfm.apca.fit.bn <- fitSfm(sfm.apca.dat, k="bn") +#' # APCA with the Bai & Ng method +#' fit.apca.bn <- fitSfm(sfm.apca.dat, k="bn") #' -#' # apca with the Connor-Korajczyk method -#' sfm.apca.fit.ck <- fitSfm(sfm.apca.dat, k="ck") +#' # APCA with the Connor-Korajczyk method +#' fit.apca.ck <- fitSfm(sfm.apca.dat, k="ck") #' #' @importFrom PerformanceAnalytics checkData #' #' @export -fitSfm <- function(data, k=1, max.k=NULL, refine=TRUE, sig=0.05, check=FALSE) { +fitSfm <- function(data, k=1, max.k=NULL, refine=TRUE, sig=0.05, check=FALSE, + corr=FALSE, ...) { # record the call as an element to be returned call <- match.call() - # check input data type and format and coerce to desired type for use - R.xts <- checkData(data, method="xts") - R.mat <- coredata(R.xts) + # check input data type and coerce to xts; remove NAs + R.xts <- na.omit(checkData(data, method="xts")) - # remove NAs - R.mat <- na.omit(R.mat) + # dim and dimnames of R.mat + n <- ncol(R.xts) + obs <- nrow(R.xts) - # dim and dimnames of R.mat - n <- ncol(R.mat) - obs <- nrow(R.mat) - if (is.null(dimnames(data))) { - dimnames(R.mat) <- list(1:obs, paste("V", 1:n, sep = ".")) + # assign generic variable names, if they are missing + if (is.null(colnames(data))) { colnames(R.xts) <- paste("V", 1:n, sep = ".") } @@ -185,29 +192,32 @@ # check input vailidity or assign default for argument max.k if (is.null(max.k)) { max.k <- min(10, obs - 1) + } else if (!is.numeric(max.k) || max.k <= 0 || round(max.k) != max.k) { + stop("Invalid argument: max.k, the maximum number of factors, must be a + positive integer.") } else if (max.k >= obs) { stop("Invalid argument: max.k must be less than the number of observations") } # check if any asset has identical observations - temp <- apply(data, 2, range) - if(any(abs(temp[2, ] - temp[1, ]) < .Machine$single.eps)) { - warning("Some variables have identical observations.") + if (check) { + temp <- apply(data, 2, range) + if(any(abs(temp[2, ] - temp[1, ]) < .Machine$single.eps)) { + warning("Some variables have identical observations.") + } } # select method to estimate factors based on k and n # in each case a partial list of return values are obtained if (n < obs) { - result <- UsePCA(R.xts=R.xts, R.mat=R.mat, k=k, n=n, obs=obs) - } else if (k == "ck") { - result <- UseAPCA_ck(R.xts=R.xts, R.mat=R.mat, max.k=max.k, refine=refine, - sig=sig, n=n, obs=obs) - } else if (k == "bn") { - result <- UseAPCA_bn(R.xts=R.xts, R.mat=R.mat, max.k=max.k, refine=refine, - n=n, obs=obs) + result <- UsePCA(R.xts=R.xts, k=k, corr=corr, ...) + } else if (k=="ck") { + result <- UseAPCA_ck(R.xts=R.xts, max.k=max.k, refine=refine, sig=sig, + corr=corr, ...) + } else if (k=="bn") { + result <- UseAPCA_bn(R.xts=R.xts, max.k=max.k, refine=refine, corr=corr, ...) } else { - result <- UseAPCA(R.xts=R.xts, R.mat=R.mat, k=k, refine=refine, n=n, - obs=obs) + result <- UseAPCA(R.xts=R.xts, k=k, refine=refine, corr=corr, ...) } # create list of return values. @@ -217,14 +227,21 @@ return(result) } + ### Principal Component Analysis when N < T # -UsePCA <- function(R.xts=R.xts, R.mat=R.mat, k=k, n=n, obs=obs) { +UsePCA <- function(R.xts=R.xts, k=k, corr=corr, ...) { + R.mat <- coredata(R.xts) # TxN + n <- ncol(R.mat) + obs <- nrow(R.mat) # demean TxN matrix of returns R.mat.d <- t(t(R.mat) - colMeans(R.mat)) # NxN return covariance matrix Omega.N <- crossprod(R.mat.d)/obs + if (corr) { + Omega.N <- cov2cor(Omega.N) + } # get eigen decomposition eig.decomp <- eigen(Omega.N, symmetric=TRUE) eig.val <- eig.decomp$values @@ -233,10 +250,12 @@ # get TxK factor realizations f <- R.mat %*% X colnames(f) <- paste("F", 1:k, sep = ".") + # invert 1st principal component if most values are negative + if (median(f[,1]) < 0) {f[,1] <- -f[,1]} # OLS time series regression to get B: NxK matrix of factor loadings f <- xts(f, index(R.xts)) - asset.fit <- lm(R.xts ~ f) + asset.fit <- lm(R.xts ~ f, ...) B <- t(coef(asset.fit)[-1, , drop=FALSE]) alpha <- coef(asset.fit)[1,] @@ -252,8 +271,9 @@ mimic <- X / colSums(X) # assign row and column names - names(eig.val) = names(r2) = names(resid.sd) = colnames(R.xts) - colnames(B) <- colnames(f) + names(eig.val) <- paste("F", 1:n, sep = ".") + names(r2) = names(resid.sd) = colnames(R.xts) + colnames(B) = colnames(f) # return list list(asset.fit=asset.fit, k=k, factors=f, loadings=B, alpha=alpha, r2=r2, @@ -264,22 +284,30 @@ ### Asymptotic Principal Component Analysis when N >= T # -UseAPCA <- function(R.xts=R.xts, R.mat=R.mat, k=k, refine=refine, n=n, obs=obs) { +UseAPCA <- function(R.xts=R.xts, k=k, refine=refine, corr=corr, ...) { + R.mat <- coredata(R.xts) # TxN + n <- ncol(R.mat) + obs <- nrow(R.mat) # demean TxN matrix of returns R.mat.d <- t(t(R.mat) - colMeans(R.mat)) # TxT return covariance matrix Omega.T <- tcrossprod(R.mat.d)/n + if (corr) { + Omega.T <- cov2cor(Omega.T) + } # get eigen decomposition eig.decomp <- eigen(Omega.T, symmetric=TRUE) eig.val <- eig.decomp$values # get TxK factor realizations X <- eig.decomp$vectors[, 1:k, drop=FALSE] # TxK dimnames(X) <- list(1:obs, paste("F", 1:k, sep = ".")) + f <- xts(X, index(R.xts)) + # invert 1st principal component if most values are negative + if (median(f[,1]) < 0) {f[,1] <- -f[,1]} # OLS time series regression to get B: NxK matrix of factor loadings - f <- xts(X, index(R.xts)) - asset.fit <- lm(R.xts ~ f) + asset.fit <- lm(R.xts ~ f, ...) B <- t(coef(asset.fit)[-1, , drop=FALSE]) alpha <- coef(asset.fit)[1,] @@ -289,12 +317,16 @@ if (refine) { R.mat.rescaled <- t(R.mat.d)/resid.sd Omega.T <- crossprod(R.mat.rescaled)/n + if (corr) { + Omega.T <- cov2cor(Omega.T) + } eig.decomp <- eigen(Omega.T, symmetric=TRUE) eig.val <- eig.decomp$values X <- eig.decomp$vectors[, 1:k, drop=FALSE] dimnames(X) <- list(1:obs, paste("F", 1:k, sep = ".")) f <- xts(X, index(R.xts)) - asset.fit <- lm(R.xts ~ f) + if (median(f[,1]) < 0) {f[,1] <- -f[,1]} + asset.fit <- lm(R.xts ~ f, ...) B <- t(coef(asset.fit)[-1, , drop=FALSE]) alpha <- coef(asset.fit)[1,] resid.sd <- as.numeric(sapply(X=summary(asset.fit), FUN="[", "sigma")) @@ -311,9 +343,9 @@ r2 <- as.numeric(sapply(X=summary(asset.fit), FUN="[", "r.squared")) # assign row and column names - names(eig.val) = 1:obs + names(eig.val) = paste("F", 1:obs, sep = ".") names(r2) = names(resid.sd) = colnames(R.xts) - colnames(B) <- colnames(f) + colnames(B) = colnames(f) # return list list(asset.fit=asset.fit, k=k, factors=f, loadings=B, alpha=alpha, r2=r2, @@ -324,20 +356,21 @@ ### Asymptotic Principal Component Analysis using 'ck' method to determine k # -UseAPCA_ck <- function(R.xts=R.xts, R.mat=R.mat, max.k=max.k, refine=refine, - sig=sig, n=n, obs=obs) { - +UseAPCA_ck <- function(R.xts=R.xts, max.k=max.k, refine=refine, sig=sig, + corr=corr, ...) { + n <- ncol(R.xts) + obs <- nrow(R.xts) idx <- 2*(1:(obs/2)) # dof-adjusted squared residuals for k=1 - fit <- UseAPCA(R.xts=R.xts, R.mat=R.mat, k=1, n=n, obs=obs, refine=refine) + fit <- UseAPCA(R.xts=R.xts, k=1, refine=refine, corr=corr, ...) eps2 <- fit$residuals^2 / (1-2/obs-1/n) for (k in 2:max.k) { f <- fit mu <- rowMeans(eps2[idx-1,,drop=FALSE]) # dof-adjusted squared residuals for k - fit <- UseAPCA(R.xts=R.xts, R.mat=R.mat, k=k, n=n, obs=obs, refine=refine) + fit <- UseAPCA(R.xts=R.xts, k=k, refine=refine, corr=corr, ...) eps2.star <- fit$residuals^2 / (1-(k+1)/obs-k/n) mu.star <- rowMeans(eps2.star[idx,,drop=FALSE]) # cross sectional differences in sqd. errors btw odd & even time periods @@ -352,14 +385,16 @@ ### Asymptotic Principal Component Analysis using 'bn' method to determine k # -UseAPCA_bn <- function(R.xts=R.xts, R.mat=R.mat, max.k=max.k, refine=refine, - n=n, obs=obs) { +UseAPCA_bn <- function(R.xts=R.xts, max.k=max.k, refine=refine, corr=corr, ...) { + + n <- ncol(R.xts) + obs <- nrow(R.xts) # intialize sigma sigma <- rep(NA, max.k) for (k in 1:max.k) { # fit APCA for k factors - fit <- UseAPCA(R.xts=R.xts, R.mat=R.mat, k=k, n=n, obs=obs, refine=refine) + fit <- UseAPCA(R.xts=R.xts, k=k, refine=refine, corr=corr, ...) # get cross-sectional average of residual variances sigma[k] <- mean(fit$resid.sd^2) } @@ -374,7 +409,7 @@ used.") } k <- min(order(PC_p1)[1], order(PC_p2)[1]) - UseAPCA(R.xts=R.xts, R.mat=R.mat, k=k, n=n, obs=obs, refine=refine) + UseAPCA(R.xts=R.xts, k=k, refine=refine, corr=corr, ...) } Added: pkg/FactorAnalytics/R/plot.sfm.r =================================================================== --- pkg/FactorAnalytics/R/plot.sfm.r (rev 0) +++ pkg/FactorAnalytics/R/plot.sfm.r 2014-12-04 07:48:22 UTC (rev 3567) @@ -0,0 +1,432 @@ +#' @title Plots from a fitted statistical factor model +#' +#' @description Generic \code{plot} method for object of class \code{sfm}. +#' Plots chosen characteristic(s) for one or more assets. +#' +#' @details +#' If the plot type argument is not specified, a menu prompts for user input +#' and the corresponding plot is output. And, the menu is repeated for +#' user convenience in plotting multiple characteristics. Selecting '0' from +#' the menu exits the current \code{plot.sfm} call. Alternately, setting +#' \code{loop=FALSE} will exit after plotting any one chosen characteristic +#' without the need for menu selection. +#' +#' Group plots are the default. The first \code{n.max} variables and +#' \code{n.max} factors are plotted depending on the characteristic chosen. +#' +#' Individual asset plots are selected by specifying \code{plot.single=TRUE}. +#' In which case, \code{asset.name} is necessary if multiple assets +#' were modeled in \code{x}. However, if the \code{fitSfm} object contains only +#' one asset's factor model fit, \code{plot.sfm} can infer this automatically, +#' without user input. +#' +#' @param x an object of class \code{sfm} produced by \code{fitSfm}. +#' @param which.plot.group a number to indicate the type of group plot for +#' multiple assets. If \code{NULL} (default), the following menu appears: \cr +#' 1 = Screeplot of eigenvalues, \cr +#' 2 = Time series plot of estimated factors, \cr +#' 3 = Estimated factor loadings, \cr +#' 4 = Histogram of R-squared, \cr +#' 5 = Histogram of Residual volatility,\cr +#' 6 = Factor model residual correlation \cr +#' 7 = Factor model correlation,\cr +#' 8 = Factor contribution to SD,\cr +#' 9 = Factor contribution to ES,\cr +#' 10 = Factor contribution to VaR +#' @param k.max maximum number of factors to add per plot device for group +#' plots. Default is 6. +#' @param n.max maximum number of variables to add per plot device for group +#' plots. Default is 10. +#' @param plot.single logical; If \code{TRUE} plots the characteristics of an +#' individual asset's factor model. The type of plot is given by +#' \code{which.plot.single}. Default is \code{FALSE}. +#' @param asset.name name of the individual asset to be plotted. Is necessary +#' if \code{x} contains multiple asset fits and \code{plot.single=TRUE}. +#' @param which.plot.single a number to indicate the type of group plot for an +#' individual asset. If \code{NULL} (default), the following menu appears: \cr +#' 1 = Time series plot of actual and fitted asset returns,\cr +#' 2 = Time series plot of residuals with standard error bands, \cr +#' 3 = Time series plot of squared residuals, \cr +#' 4 = Time series plot of absolute residuals,\cr +#' 5 = SACF and PACF of residuals,\cr +#' 6 = SACF and PACF of squared residuals,\cr +#' 7 = SACF and PACF of absolute residuals,\cr +#' 8 = Histogram of residuals with normal curve overlayed,\cr +#' 9 = Normal qq-plot of residuals,\cr +#' 10 = CUSUM test-Recursive residuals,\cr +#' 11 = CUSUM test-OLS residuals,\cr +#' 12 = Recursive estimates (RE) test of OLS regression coefficients,\cr +#' 13 = Rolling estimates over a 24-period observation window +#' @param colorset color palette to use for all the plots. Default is +#' \code{c(1:12)}. The 1st element will be used for individual time series +#' plots or the 1st series plotted, the 2nd element for the 2nd object in the +#' plot and so on. +#' @param legend.loc places a legend into one of nine locations on the chart: +#' "bottomright", "bottom", "bottomleft", "left", "topleft", "top", "topright", +#' "right", or "center". Default is "bottomright". Use \code{legend.loc=NULL} +#' to suppress the legend. +#' @param las one of {0, 1, 2, 3} to set the direction of axis labels, same as +#' in \code{plot}. Default here is 1. +#' @param VaR.method a method for computing VaR; one of "modified", "gaussian", +#' "historical" or "kernel". VaR is computed using +#' \code{\link[PerformanceAnalytics]{VaR}}. Default is "historical". +#' @param eig.max scalar in (0,1] for limiting the screeplot to factors that +#' explain a given percent of the variance. Default is 0.9. +#' @param cum.var logical; If \code{TRUE}, the cumulative fraction of the +#' variance is printed above each bar in the screeplot of eigenvalues. Default +#' is \code{TRUE}. +#' @param loop logical to indicate if the plot menu should be repeated. Default +#' is \code{TRUE}. +#' @param ... further arguments to be passed to other plotting functions. +#' +#' @author Eric Zivot, Sangeetha Srinivasan and Yi-An Chen +#' +#' @seealso \code{\link{fitSfm}} and \code{\link{summary.sfm}} for details +#' about the time series factor model fit, extractor functions and summary +#' statistics. +#' +#' \code{\link[strucchange]{efp}} for CUSUM tests. +#' +#' \code{\link[xts]{plot.xts}}, +#' \code{\link[PerformanceAnalytics]{chart.TimeSeries}}, +#' \code{\link[PerformanceAnalytics]{chart.ACFplus}}, +#' \code{\link[PerformanceAnalytics]{chart.Histogram}}, +#' \code{\link[PerformanceAnalytics]{chart.QQPlot}}, +#' \code{\link[graphics]{barplot}}, \code{\link[lattice]{barchart}} and +#' \code{\link[corrplot]{corrplot}} for plotting methods used. +#' +#' \code{\link{fmSdDecomp}}, \code{\link{fmEsDecomp}}, +#' \code{\link{fmVaRDecomp}} for factor model risk measures. +#' +#' @examples +#' +#' # load data from the database +#' data(stat.fm.data) +#' +#' # APCA with number of factors, k=15 +#' fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +#' +#' # group plot(default); select type from menu prompt +#' # menu is auto-looped to get multiple types of plots based on the same fit +#' # plot(fit.apca) +#' +#' # plot the factor betas of 1st 4 assets fitted above +#' # loop disabled to get one type of plot without interative menu +#' plot(fit.apca, n.max=4, which.plot.group=3, loop=FALSE) +#' +#' # plot factor model return correlation; angular order of the eigenvectors +#' plot(fit.apca, which.plot.group=7, loop=FALSE, +#' order="AOE", method="ellipse", tl.pos = "d") +#' +#' # histogram of residuals from an individual asset's factor model fit +#' plot(fit.apca, plot.single=TRUE, asset.name="AFL", which.plot.single=8, +#' loop=FALSE) +#' +#' @importFrom PerformanceAnalytics chart.TimeSeries chart.ACFplus +#' chart.Histogram chart.QQPlot +#' @importFrom lattice barchart xyplot panel.barchart panel.grid +#' @importFrom corrplot corrplot +#' @importFrom strucchange efp +#' +#' @method plot sfm +#' @export + +plot.sfm <- function(x, which.plot.group=NULL, k.max=6, n.max=10, + plot.single=FALSE, asset.name, which.plot.single=NULL, + colorset=(1:12), legend.loc="topleft", las=1, + VaR.method="historical", cum.var=TRUE, eig.max=0.9, + loop=TRUE, ...) { + + if (plot.single==TRUE) { + + if (missing(asset.name) && length(x$asset.names)>1) { + stop("Missing input: 'asset.name' is required if plot.single is TRUE and + the factor model fits multiple assets.") + } else if (length(x$asset.names)==1) { + i <- x$asset.names[1] + } else { + i <- asset.name + } + # extract info from the fitSfm object + plotData <- merge.xts(x$data[,i], fitted(x)[,i]) + colnames(plotData) <- c("Actual","Fitted") + Residuals <- residuals(x)[,i] + fit <- lm(x$data[,i] ~ x$factors) + + # plot selection + repeat { + if (is.null(which.plot.single)) { + which.plot.single <- + menu(c("Time series plot of actual and fitted asset returns", + "Time series plot of residuals with standard error bands", + "Time series plot of squared residuals", + "Time series plot of absolute residuals", + "SACF and PACF of residuals", + "SACF and PACF of squared residuals", + "SACF and PACF of absolute residuals", + "Histogram of residuals with normal curve overlayed", + "Normal qq-plot of residuals", + "CUSUM test-Recursive residuals", + "CUSUM test-OLS residuals", + "Recursive estimates (RE) test of OLS regression coefficients", + "Rolling estimates over a 24-period observation window"), + title="\nMake a plot selection (or 0 to exit):") + } + + par(las=las) # default horizontal axis labels + + switch(which.plot.single, + "1L" = { + ## time series plot of actual and fitted asset returns + chart.TimeSeries(plotData, main=paste("Returns:",i), + colorset=colorset, xlab="", + ylab="Actual and fitted asset returns", + legend.loc=legend.loc, pch=NULL, las=las, ...) + }, "2L" = { + ## time series plot of residuals with standard error bands + chart.TimeSeries(Residuals, main=paste("Residuals:",i), + colorset=colorset, xlab="", ylab="Residuals", + lwd=2, lty="solid", las=las, ...) + abline(h=1.96*x$resid.sd[i], lwd=2, lty="dotted", col="red") + abline(h=-1.96*x$resid.sd[i], lwd=2, lty="dotted", col="red") + legend(x=legend.loc, lty=c("solid","dotted"), + col=c(colorset[1],"red"), lwd=2, + legend=c("Residuals",expression("\u00b1 1.96"*sigma))) + }, "3L" = { + ## time series plot of squared residuals + chart.TimeSeries(Residuals^2, colorset=colorset, xlab="", + ylab=" Squared Residuals", + main=paste("Squared Residuals:",i), + legend.loc=legend.loc, pch=NULL, las=las, ...) + }, "4L" = { + ## time series plot of absolute residuals + chart.TimeSeries(abs(Residuals), colorset=colorset, xlab="", + ylab="Absolute Residuals", + main=paste("Absolute Residuals:",i), + legend.loc=legend.loc, pch=NULL, las=las, ...) + }, "5L" = { + ## SACF and PACF of residuals + chart.ACFplus(Residuals, col=colorset[1], + main=paste("SACF & PACF - Residuals:",i), ...) + }, "6L" = { + ## SACF and PACF of squared residuals + chart.ACFplus(Residuals^2, col=colorset[1], ..., + main=paste("SACF & PACF - Squared residuals:",i)) + }, "7L" = { + ## SACF and PACF of absolute residuals + chart.ACFplus(abs(Residuals), col=colorset[1], ..., + main=paste("SACF & PACF - Absolute Residuals:",i)) + }, "8L" = { + ## histogram of residuals with normal curve overlayed + methods <- c("add.density","add.normal","add.rug") + chart.Histogram(Residuals, xlab="Return residuals", + methods=methods, colorset=colorset, + main=paste("Histogram of Residuals:",i), ...) + }, "9L" = { + ## normal qq-plot of residuals + chart.QQPlot(Residuals, envelope=0.95, col=colorset, + main=paste("QQ-plot of Residuals:",i), ...) + legend(x=legend.loc, col="red", lty="dotted", lwd=1, + legend=c("0.95 confidence envelope")) + }, "10L" = { + ## Recursive CUSUM test + cusum.rec <- efp(formula(fit), type="Rec-CUSUM", data=fit$model) + plot(cusum.rec, main=paste("Recursive CUSUM test:",i), las=las, + col=colorset, ...) + }, "11L" = { + ## OLS-based CUSUM test + cusum.ols <- efp(formula(fit), type="OLS-CUSUM", data=fit$model) + plot(cusum.ols, main=paste("OLS-based CUSUM test:",i), las=las, + col=colorset, ...) + }, "12L" = { + ## Recursive estimates (RE) test of OLS regression coefficients + cusum.est <- efp(formula(fit), type="RE", data=fit$model) + plot(cusum.est, functional=NULL, col=colorset, las=0, + main=paste("RE test (Recursive estimates test):",i), ...) + }, "13L" = { + ## Rolling estimates over 24-period observation window + rollReg <- function(data.z, formula) { + coef(lm(formula, data=as.data.frame(data.z))) + } + reg.z <- zoo(fit$model, as.Date(rownames(fit$model))) + rollReg.z <- rollapply(reg.z, FUN=rollReg, formula(fit), + width=24, by.column=FALSE, align="right") + par(las=0) + plot(rollReg.z, ..., las=las, + main=paste("Rolling estimates (24-period obs window):",i)) + par(las=las) + }, + invisible() + ) + # repeat menu if user didn't choose to exit from the plot options + if (which.plot.single==0 || loop==FALSE) {break} + else {which.plot.single=NULL} + } + } else { # start of group asset plots + + # plot selection + repeat { + if (is.null(which.plot.group)) { + which.plot.group <- + menu(c("Screeplot of eigenvalues", + "Time series plot of estimated factors", + "Estimated factor loadings", + "Histogram of R-squared", + "Histogram of Residual volatility", + "Factor model residual correlation", + "Factor model return correlation", + "Factor contribution to SD", + "Factor contribution to ES", + "Factor contribution to VaR"), + title="\nMake a plot selection (or 0 to exit):") + } + + par(las=las) # default horizontal axis labels + k <- x$k + n <- nrow(x$loadings) + + switch(which.plot.group, + "1L" = { + ## Screeplot of eigenvalues + cumv <- cumsum(x$eigen)/sum(x$eigen) + limit <- length(cumv[cumv k.max) { + cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) + k <- k.max + } + plot( + xyplot(x$factors[,1:k],type=c("l","g"),xlab="", + scales=list(y=list(rot=0)), strip.left=TRUE, strip=FALSE) + ) + }, + "3L" = { + ## Estimated factor loadings + if (k > k.max) { + cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) + k <- k.max + } + if (n > n.max) { + cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) + n <- n.max + } + par(mfrow=c(ceiling(k/2),2)) + for (i in 1:k) { + main=paste("Beta values for ", colnames(x$loadings)[i]) + barplot(x$loadings[1:n,i], main=main, names.arg=x$asset.names[1:n], + col="darkblue", las=las, horiz=TRUE, ...) + abline(v=0, lwd=1, lty=1, col=1) + } + par(mfrow=c(1,1)) + }, + "4L" ={ + ## Histogram of R-squared + methods <- c("add.density","add.rug") + chart.Histogram(x$r2, xlab="R-squared", + methods=methods, colorset=colorset, + main=paste("Histogram of R-squared values"), ...) + }, + "5L" = { + ## Histogram of Residual Volatility + methods <- c("add.density","add.rug") + chart.Histogram(x$resid.sd, xlab="Residual volatility", + methods=methods, colorset=colorset, + main=paste("Histogram of Residual volatilities"), ...) + }, + "6L" = { + ## Factor Model Residual Correlation + if (n > n.max) { + cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) + n <- n.max + } + cor.resid <- cor(residuals(x)[,1:n], use="pairwise.complete.obs") + corrplot(cor.resid, ...) + # mtext("pairwise complete obs", line=0.5) + }, + "7L" = { + ## Factor Model Return Correlation + if (n > n.max) { + cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) + n <- n.max + } + cor.fm <- cov2cor(fmCov(x))[1:n,1:n] + corrplot(cor.fm, ...) + # mtext("pairwise complete obs", line=0.5) + }, + "8L" = { + ## Factor Percentage Contribution to SD + if (k > k.max) { + cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) + k <- k.max + } + if (n > n.max) { + cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) + n <- n.max + } + pcSd.fm <- fmSdDecomp(x)$pcSd[1:n,1:k] + plot( + barchart(pcSd.fm, main="Factor % Contribution to SD", xlab="", + auto.key=list(space="bottom",columns=3, + points=FALSE,rectangles=TRUE), [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3567 From noreply at r-forge.r-project.org Fri Dec 5 03:36:34 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 5 Dec 2014 03:36:34 +0100 (CET) Subject: [Returnanalytics-commits] r3568 - in pkg/FactorAnalytics: . R man vignettes Message-ID: <20141205023634.E7F4B1861AC@r-forge.r-project.org> Author: pragnya Date: 2014-12-05 03:36:33 +0100 (Fri, 05 Dec 2014) New Revision: 3568 Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/NAMESPACE pkg/FactorAnalytics/R/fitSfm.R pkg/FactorAnalytics/R/print.tsfm.r pkg/FactorAnalytics/R/summary.sfm.r pkg/FactorAnalytics/R/summary.tsfm.r pkg/FactorAnalytics/man/fitSfm.Rd pkg/FactorAnalytics/man/summary.sfm.Rd pkg/FactorAnalytics/man/summary.tsfm.Rd pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf Log: Edits to print and summary methods for fitTsfm and fitSfm Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-05 02:36:33 UTC (rev 3568) @@ -1,8 +1,8 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.5 -Date: 2014-12-03 +Version: 2.0.6 +Date: 2014-12-04 Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Description: An R package for the estimation and risk analysis of linear factor Modified: pkg/FactorAnalytics/NAMESPACE =================================================================== --- pkg/FactorAnalytics/NAMESPACE 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/NAMESPACE 2014-12-05 02:36:33 UTC (rev 3568) @@ -53,11 +53,9 @@ importFrom(lattice,panel.grid) importFrom(lattice,xyplot) importFrom(leaps,regsubsets) -importFrom(lmtest,coeftest) importFrom(lmtest,coeftest.default) importFrom(robust,lmRob) importFrom(robust,step.lmRob) importFrom(sandwich,vcovHAC.default) -importFrom(sandwich,vcovHC) importFrom(sandwich,vcovHC.default) importFrom(strucchange,efp) Modified: pkg/FactorAnalytics/R/fitSfm.R =================================================================== --- pkg/FactorAnalytics/R/fitSfm.R 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/R/fitSfm.R 2014-12-05 02:36:33 UTC (rev 3568) @@ -67,8 +67,8 @@ #' #' An object of class \code{"sfm"} is a list containing the following #' components: -#' \item{asset.fit}{list of fitted objects of class \code{lm} for each asset, -#' from the time-series OLS regression of asset returns on estimated factors.} +#' \item{asset.fit}{fitted object of class \code{"mlm"} or \code{"lm"} from the +#' time-series OLS regression of asset returns on estimated factors.} #' \item{k}{number of factors; as input or determined by "ck" or "bn" methods.} #' \item{factors}{T x K xts object of estimated factor realizations.} #' \item{loadings}{N x K matrix of factor loadings estimated by Modified: pkg/FactorAnalytics/R/print.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/print.tsfm.r 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/R/print.tsfm.r 2014-12-05 02:36:33 UTC (rev 3568) @@ -38,7 +38,7 @@ cat("\nFactor Betas:\n") B <- as.matrix(t(x$beta)) if (x$variable.selection=="lars") { B[B==0] <- NA } - print(B, digits=digits, na.print="-", ...) + print(B, digits=digits, na.print=".", ...) cat("\nR-squared values:\n") print(x$r2, digits=digits, ...) cat("\nResidual Volatilities:\n") Modified: pkg/FactorAnalytics/R/summary.sfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.sfm.r 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/R/summary.sfm.r 2014-12-05 02:36:33 UTC (rev 3568) @@ -6,12 +6,13 @@ #' @details The default \code{summary} method for a fitted \code{lm} object #' computes the standard errors and t-statistics under the assumption of #' homoskedasticty. Argument \code{se.type} gives the option to compute -#' heteroskedasticity-consistent (HC) standard errors and t-statistics using -#' \code{\link[lmtest]{coeftest}}. +#' heteroskedasticity-consistent (HC) or +#' heteroskedasticity-autocorrelation-consistent (HAC) standard errors and +#' t-statistics using \code{\link[lmtest]{coeftest}}. #' #' @param object an object of class \code{sfm} returned by \code{fitSfm}. -#' @param se.type one of "Default" or "HC"; option for computing HC standard -#' errors and t-statistics. +#' @param se.type one of "Default", "HC" or "HAC"; option for computing HC/HAC +#' standard errors and t-statistics. #' @param x an object of class \code{summary.sfm}. #' @param digits number of significants digits to use when printing. #' Default is 3. @@ -25,14 +26,10 @@ #' Object of class \code{summary.sfm} is a list of length N+2 containing: #' \item{call}{the function call to \code{fitSfm}} #' \item{se.type}{standard error type as input} -#' \item{}{summary of the fit object of class \code{mlm} for the factor model.} +#' \item{sum.list}{list of summaries for the N fit objects of class \code{lm} +#' for each asset in the factor model.} +#' \item{mimic}{N x K matrix of factor mimicking portfolio weights.} #' -#' @note For a more detailed printed summary for each asset, refer to -#' \code{\link[stats]{summary.lm}}, which includes F-statistics, -#' Multiple R-squared, Adjusted R-squared, further formats the coefficients, -#' standard errors, etc. and additionally gives significance stars if -#' \code{signif.stars} is TRUE. -#' #' @author Sangeetha Srinivasan #' #' @seealso \code{\link{fitSfm}}, \code{\link[stats]{summary.lm}} @@ -45,8 +42,8 @@ #' # summary of factor model fit for all assets #' summary(fit, "HAC") #' -#' @importFrom lmtest coeftest -#' @importFrom sandwich vcovHC +#' @importFrom lmtest coeftest.default +#' @importFrom sandwich vcovHC.default vcovHAC.default #' #' @method summary sfm #' @export @@ -58,19 +55,26 @@ stop("Invalid 'sfm' object") } - # extract list of mlm summary object for the entire model - mlm.fit.summary <- summary(object$asset.fit) + # extract list of summary.lm objects for all assets + sum.list <- summary(object$asset.fit) + names(sum.list) <- object$asset.names - # get coefficients and convert to HC standard errors and t-stats if specified - coefficients <- coeftest(object$asset.fit, vcov.=vcovHC, data=sfm.data[,1]) - if (se.type=="HC") { - coefficients <- coeftest(object$asset.fit, vcov.=vcovHC) + # convert to HC standard errors and t-stats if specified + if (se.type=="HC" || se.type=="HAC") { + for (i in object$asset.names) { + # need to get lm objects because "mlm" method doesn't exist for vcovHAC + f <- lm(as.numeric(object$data[,i]) ~ object$factors) + if (se.type=="HC") { + sum.list[[i]]$coefficients <- coeftest.default(f, vcov.=vcovHC.default)[,1:4] + } else if (se.type=="HAC") { + sum.list[[i]]$coefficients <- coeftest.default(f, vcov.=vcovHAC.default)[,1:4] + } + } } # include the call and se.type to fitSfm - sum <- list(call=object$call, se.type=se.type, coefficients=coefficients, - mlm.fit.summary=mlm.fit.summary, r.squared=object$r2, - sigma=object$resid.sd) + sum <- list(call=object$call, se.type=se.type, sum.list=sum.list, + mimic=object$mimic) class(sum) <- "summary.sfm" return(sum) } @@ -85,12 +89,20 @@ cat("\nCall:\n") dput(cl) } - cat("\nFactor Model Coefficients:", "\n(", x$se.type, - " Standard Errors & T-stats)\n\n", sep="") - c <- x$coefficients - print(c, digits=digits, ...) - r2 <- x$r.squared - print(r2, digits=digits, ...) - sig <- x$sigma - print(sig, digits=digits, ...) + cat("\nFactor Model Coefficients:\n", sep="") + n <- length(x$sum.list) + for (i in 1:n) { + options(digits = digits) + table.coef <- (x$sum.list)[[i]]$coefficients + if (dim(table.coef)[2] > 1) { + cat("\nAsset", i, ": ", names(x$sum.list[i]), "\n(", x$se.type, + " Standard Errors & T-stats)\n\n", sep="") + } else { + cat("\nAsset", i, ": ", names(x$sum.list[i]), "\n\n", sep="") + } + r2 <- x$sum.list[[i]]$r.squared + sigma <- x$sum.list[[i]]$sigma + printCoefmat(table.coef, digits=digits, ...) + cat("\nR-squared: ", r2,", Residual Volatility: ", sigma,"\n", sep="") + } } Modified: pkg/FactorAnalytics/R/summary.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.tsfm.r 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/R/summary.tsfm.r 2014-12-05 02:36:33 UTC (rev 3568) @@ -31,15 +31,9 @@ #' Object of class \code{summary.tsfm} is a list of length N + 2 containing: #' \item{call}{the function call to \code{fitTsfm}} #' \item{se.type}{standard error type as input} -#' \item{}{summaries of the N fit objects (of class \code{lm}, \code{lmRob} -#' or \code{lars}) for each asset in the factor model.} +#' \item{sum.list}{list of summaries of the N fit objects (of class \code{lm}, +#' \code{lmRob} or \code{lars}) for each asset in the factor model.} #' -#' @note For a more detailed printed summary for each asset, refer to -#' \code{\link[stats]{summary.lm}} or \code{\link[robust]{lmRob}}, which -#' include F-statistics, Multiple R-squared, Adjusted R-squared and further -#' format the coefficients, standard errors, etc. and additionally give -#' significance stars if \code{signif.stars} is TRUE. -#' #' @author Sangeetha Srinivasan & Yi-An Chen. #' #' @seealso \code{\link{fitTsfm}}, \code{\link[stats]{summary.lm}} @@ -74,33 +68,33 @@ } # extract summary.lm objects for each asset - sum <- lapply(object$asset.fit, summary) + sum.list <- lapply(object$asset.fit, summary) # convert to HC/HAC standard errors and t-stats if specified # extract coefficients separately for "lars" variable.selection method for (i in object$asset.names) { if (se.type=="HC") { - sum[[i]]$coefficients <- coeftest.default(object$asset.fit[[i]], - vcov.=vcovHC.default)[,1:4] + sum.list[[i]]$coefficients <- coeftest.default(object$asset.fit[[i]], + vcov.=vcovHC.default)[,1:4] } else if (se.type=="HAC") { - sum[[i]]$coefficients <- coeftest.default(object$asset.fit[[i]], - vcov.=vcovHAC.default)[,1:4] + sum.list[[i]]$coefficients <- coeftest.default(object$asset.fit[[i]], + vcov.=vcovHAC.default)[,1:4] } } if (object$variable.selection=="lars") { - sum <- list() + sum.list <- list() for (i in object$asset.names) { - sum[[i]]$coefficients <- as.matrix(c(object$alpha[i], object$beta[i,])) - rownames(sum[[i]]$coefficients)[1]="(Intercept)" - colnames(sum[[i]]$coefficients)[1]="Estimate" - sum[[i]]$r.squared <- as.numeric(object$r2[i]) - sum[[i]]$sigma <- as.numeric(object$resid.sd[i]) + sum.list[[i]]$coefficients <- as.matrix(c(object$alpha[i], object$beta[i,])) + rownames(sum.list[[i]]$coefficients)[1]="(Intercept)" + colnames(sum.list[[i]]$coefficients)[1]="Estimate" + sum.list[[i]]$r.squared <- as.numeric(object$r2[i]) + sum.list[[i]]$sigma <- as.numeric(object$resid.sd[i]) } } # include the call and se.type to fitTsfm - sum <- c(list(call=object$call, se.type=se.type), sum) + sum <- list(call=object$call, se.type=se.type, sum.list=sum.list) class(sum) <- "summary.tsfm" return(sum) } @@ -115,20 +109,20 @@ cat("\nCall:\n") dput(cl) } - cat("\nFactor Model Coefficients:\n", - sep="") - n <- length(x) - for (i in 3:n) { + cat("\nFactor Model Coefficients:\n", sep="") + n <- length(x$sum.list) + for (i in 1:n) { options(digits = digits) - if (dim(x[[i]]$coefficients)[2] > 1) { - cat("\nAsset", i-2, ": ", names(x[i]), "\n(", x$se.type, + table.coef <- (x$sum.list)[[i]]$coefficients + if (dim(table.coef)[2] > 1) { + cat("\nAsset", i, ": ", names(x$sum.list[i]), "\n(", x$se.type, " Standard Errors & T-stats)\n\n", sep="") } else { - cat("\nAsset", i-2, ": ", names(x[i]), "\n\n", sep="") + cat("\nAsset", i, ": ", names(x$sum.list[i]), "\n\n", sep="") } - table.coef <- x[[i]]$coefficients + r2 <- x$sum.list[[i]]$r.squared + sigma <- x$sum.list[[i]]$sigma printCoefmat(table.coef, digits=digits, ...) - cat("\nR-squared: ", x[[i]]$r.squared,", Residual Volatility: " - , x[[i]]$sigma,"\n", sep="") + cat("\nR-squared: ", r2,", Residual Volatility: ", sigma,"\n", sep="") } } Modified: pkg/FactorAnalytics/man/fitSfm.Rd =================================================================== --- pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-05 02:36:33 UTC (rev 3568) @@ -53,8 +53,8 @@ An object of class \code{"sfm"} is a list containing the following components: -\item{asset.fit}{list of fitted objects of class \code{lm} for each asset, -from the time-series OLS regression of asset returns on estimated factors.} +\item{asset.fit}{fitted object of class \code{"mlm"} or \code{"lm"} from the +time-series OLS regression of asset returns on estimated factors.} \item{k}{number of factors; as input or determined by "ck" or "bn" methods.} \item{factors}{T x K xts object of estimated factor realizations.} \item{loadings}{N x K matrix of factor loadings estimated by Modified: pkg/FactorAnalytics/man/summary.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-05 02:36:33 UTC (rev 3568) @@ -11,8 +11,8 @@ \arguments{ \item{object}{an object of class \code{sfm} returned by \code{fitSfm}.} -\item{se.type}{one of "Default" or "HC"; option for computing HC standard -errors and t-statistics.} +\item{se.type}{one of "Default", "HC" or "HAC"; option for computing HC/HAC +standard errors and t-statistics.} \item{...}{futher arguments passed to or from other methods.} @@ -30,7 +30,9 @@ Object of class \code{summary.sfm} is a list of length N+2 containing: \item{call}{the function call to \code{fitSfm}} \item{se.type}{standard error type as input} -\item{}{summary of the fit object of class \code{mlm} for the factor model.} +\item{sum.list}{list of summaries for the N fit objects of class \code{lm} +for each asset in the factor model.} +\item{mimic}{N x K matrix of factor mimicking portfolio weights.} } \description{ \code{summary} method for object of class \code{sfm}. @@ -40,16 +42,10 @@ The default \code{summary} method for a fitted \code{lm} object computes the standard errors and t-statistics under the assumption of homoskedasticty. Argument \code{se.type} gives the option to compute -heteroskedasticity-consistent (HC) standard errors and t-statistics using -\code{\link[lmtest]{coeftest}}. +heteroskedasticity-consistent (HC) or +heteroskedasticity-autocorrelation-consistent (HAC) standard errors and +t-statistics using \code{\link[lmtest]{coeftest}}. } -\note{ -For a more detailed printed summary for each asset, refer to -\code{\link[stats]{summary.lm}}, which includes F-statistics, -Multiple R-squared, Adjusted R-squared, further formats the coefficients, -standard errors, etc. and additionally gives significance stars if -\code{signif.stars} is TRUE. -} \examples{ data(stat.fm.data) # fit the factor model with PCA Modified: pkg/FactorAnalytics/man/summary.tsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.tsfm.Rd 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/man/summary.tsfm.Rd 2014-12-05 02:36:33 UTC (rev 3568) @@ -30,8 +30,8 @@ Object of class \code{summary.tsfm} is a list of length N + 2 containing: \item{call}{the function call to \code{fitTsfm}} \item{se.type}{standard error type as input} -\item{}{summaries of the N fit objects (of class \code{lm}, \code{lmRob} -or \code{lars}) for each asset in the factor model.} +\item{sum.list}{list of summaries of the N fit objects (of class \code{lm}, +\code{lmRob} or \code{lars}) for each asset in the factor model.} } \description{ \code{summary} method for object of class \code{tsfm}. @@ -50,13 +50,6 @@ statistically valid method of calculating standard errors for the lasso predictions. } -\note{ -For a more detailed printed summary for each asset, refer to -\code{\link[stats]{summary.lm}} or \code{\link[robust]{lmRob}}, which -include F-statistics, Multiple R-squared, Adjusted R-squared and further -format the coefficients, standard errors, etc. and additionally give -significance stars if \code{signif.stars} is TRUE. -} \examples{ data(managers) fit <- fitTsfm(asset.names=colnames(managers[,(1:6)]), Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-04 07:48:22 UTC (rev 3567) +++ pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-05 02:36:33 UTC (rev 3568) @@ -53,7 +53,7 @@ \begin{itemize} -\item \verb"fitTsfm(asset.names, factor.names, data, fit.method, variable.selection)": Fits a time series (a.k.a. macroeconomic) factor model for one or more asset returns or excess returns using time series regression. Ordinary least squares (OLS), discounted least squares (DLS) and robust regression fitting are possible. Variable selection methods include "stepwise", "subsets" and "lars". An object of class "tsfm" containing the fitted objects, model coefficients, R-squared and residual volatility are returned. +\item \verb"fitTsfm(asset.names, factor.names, data, fit.method, variable.selection)": Fits a time series (a.k.a. macroeconomic) factor model for one or more asset returns or excess returns using time series regression. Ordinary least squares (OLS), discounted least squares (DLS) and robust regression fitting are possible. Variable selection methods include "stepwise", "subsets" and "lars". An object of class "tsfm" containing the fitted objects, model coefficients, R-squared and residual volatility is returned. \item \verb"coef(object)": Extracts the coefficient matrix (intercept and factor betas) for all assets fit by the "tsfm" object. @@ -69,7 +69,7 @@ \item \verb"fmEsDecomp(object, p, method, invert)": Returns a list containing the expected shortfall for asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. Arguments \code{"p"}, \code{"method"} and \code{invert} are the same as above. -\item \verb"plot(x)": The \code{plot} method for class "tsfm" can be used for plotting factor model characteristics of an individual asset or a group of assets (default). The type of individual/group plot can be specified or chosen from a menu prompt (default if type not specified). Further the menu reappears (default) to enable multiple plots for the same asset(s) unless looping is disabled by setting \code{loop=FALSE}. +\item \verb"plot(x)": The \code{plot} method for class "tsfm" can be used for plotting factor model characteristics of an individual asset or a group of assets (default). The type of individual/group plot can be specified or chosen from a menu prompt, which is the default if type is not specified. Further the menu reappears (default) to access multiple plots for the same asset(s) unless looping is disabled by setting \code{loop=FALSE}. \item \verb"predict(object, newdata)": The \code{predict} method for class "tsfm" returns a vector or matrix of predicted values for a new data sample or simulated values. @@ -274,7 +274,7 @@ Many useful generic accessor functions are available for "tsfm" fit objects. \code{coef()} returns a matrix of estimated model coefficients including the intercept. \code{fitted()} returns an xts data object of the component of asset returns explained by the factor model. \code{residuals()} returns an xts data object with the component of asset returns not explained by the factor model. \code{predict()} uses the fitted factor model to estimate asset returns given a set of new or simulated factor return data. -\code{summary()} prints standard errors and t-statistics for all estimated coefficients in addition to R-squared values and residual volatilities. The \code{se.type} argument enables computing heteroskedasticity and auto-correlation consistent ("HC" and "HAC") estimates and standard errors whenever possible. A "summary.tsfm" object is returned which contains the summary objects returned by "lm", "lm.Rob" or "lars" for each asset fit. +\code{summary()} prints standard errors and t-statistics for all estimated coefficients in addition to R-squared values and residual volatilities. The \code{se.type} argument enables computing heteroskedasticity and auto-correlation consistent ("HC" and "HAC") estimates and standard errors whenever possible. A "summary.tsfm" object is returned which contains a list of summary objects returned by "lm", "lm.Rob" or "lars" for each asset fit. Note: Standard errors are currently not available for the "lars" variable selection method, as there seems to be no consensus on a statistically valid method of calculating standard errors for the lasso predictions. Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf =================================================================== (Binary files differ) From noreply at r-forge.r-project.org Fri Dec 5 03:38:36 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 5 Dec 2014 03:38:36 +0100 (CET) Subject: [Returnanalytics-commits] r3569 - pkg/PerformanceAnalytics/sandbox Message-ID: <20141205023836.AAFEB1861AC@r-forge.r-project.org> Author: peter_carl Date: 2014-12-05 03:38:35 +0100 (Fri, 05 Dec 2014) New Revision: 3569 Added: pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd Log: - incomplete first draft Added: pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd =================================================================== --- pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd (rev 0) +++ pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd 2014-12-05 02:38:35 UTC (rev 3569) @@ -0,0 +1,376 @@ +--- +title: "How to Contribute to Performance Analytics" +author: "Peter Carl, Brian Peterson" +date: "11/30/2014" +output: + rmarkdown::tufte_handout: +# toc: true +# toc_depth: 2 +# number_sections: true +--- + +# Introduction +This is a "how to" guide for writing and improving functions for packages that are being developed within the `returnanalytics` project on R-Forge. It is primarily being developed with the `PerformanceAnalytics` package in mind, but many of the principles are carried into other packages as well. The specifics and examples in this document, however, will focus on `PerformanceAnalytics`. + +`PerformanceAnalytics` is a collection of functionality for doing returns-based analysis in finance. Most of what it does is focused on performance and risk evaluation. Companion projects under development in the `returnsanalytics` projects on R-Forge include: + +- `PortfolioAnalytics`: focuses on portfolio construction and ex-ante analysis of portfolios; +- `PortfolioAttribution`: calculates ex-post performance attribution of portfolios given returns and weights; and +- `FactorAnalytics`: provides factor-based analysis of returns. + +If you are reading this document, you are likely already using `PerformanceAnalytics` or another of our packages. Perhaps you have some code that you think would be relevant to include, or would like to collaborate on a project to develop ideas from your own or other research. Maybe you've identified ways that the package can be improved or identified a bug. If so, we appreciate you taking the time to help -- your participation is critical to us continuing to improve these packages. + +This document is written with two types of contributors in mind. The first kind is one whose contribution is limited in scope - say, a bug fix to an existing function or a new function thought to be useful. This document should be helpful for this type of contributor, but it may seem like overkill. Be assured that we welcome contributions of all kinds -- not just 'finished' ones. If you think you are in this camp, this document will hopefully answer some questions but please do not hesitate to contact us with ideas and snippets. + +The second type of contributor we have in mind is more the focus of this document. This kind of contributor is working on a defined project around a body of research, porting existing code from another language, or developing an idea in collaboration with us. We encourage this type of contribution and for many years have collaborated with students through the Google Summer of Code [add link] program. This type of project-oriented collaboration requires more organization and structure -- sometimes there's a plan and a schedule, a mentor or three, maybe a book, a dissertation, or a few journal articles. + +Either way, this guide assembles the things that we've said in answer to questions over the years to those we've collaborated with. We hope it provides a good foundation for you to get started, but please do not hesistate to ask for more detail or help where there isn't enough. And finally, please don't let our strident list of requirements below prevent you from contributing -- we value hastily constructed, first-draft, proof-of-concept code, too. + +## How to become a contributor +As mentioned above, the easiest way to become a contributor is to email us. We like to hear about what you are using the package for, answer any questions you might have, chase down bugs you encounter, or consider changes and additions that would improve the package. + +We ask more of those seeking longer-term developer membership in the `returnanalytics` projects. Packages included in the R-Forge returnanalytics project are used by professionals and educators around the world. As such, we are careful when vetting new members of the project. + +Typically, the process starts by you becoming a member of the community - perhaps asking good questions, identifying issues with the code or proposing new functionality. The next step is usually for you to propose patches to existing code, but new additions, bug fixes, and adjustments to documentation are all welcome. All patches are reviewed by one of the core team members. After several accepted patches, and once we get to know you and your needs, then the core team will discuss adding another member to the team. + +We look forward to hearing more from you as you use and enhance the `returnanalytics` packages. Hopefully you'll be able to join us as a contributor in the near future. + +[ one paragraph on Copyrights and licensing? ] + +The remainder of this paper is in three sections. The first provides a brief introduction to the tools we use, and might be generally helpful if you are newer to R. The second section describes the principals we use to guide our development, and the third section discusses in more detail and with examples how to use these principles as you develop functions. By the end of this document, you should have a good understanding about not only *how* but *why* we do things the way that we do. + +# Getting Established +This section introduces the tools we use for development. While these aren't all required to be successfull, we find that it is easier to help people through issues when we are all working with the same tools. + +## How to create patches +One of the easiest ways to become a contributor is to send us patches. Patches are a text description of changes made to a function that will add a new feature, fix a bug, or add documentation. To create a patch for a single file, use `diff` or a Windows-equivalent (either UnxUtils or WinMerge) to create a unified diff patch file. For example, in a shell you might run something like: +``` +diff -u original.R revised.R > original.patch +``` +In a Linux shell, you can learn more by typing `man diff` or `man patch`. + +## Find the project on R-Forge +This project uses R-Forge[1] for development. R-Forge provides a set of tools for source code management (Subversion) and various web-based features. To use Subversion (svn) on R-Forge you'll need to register as a site user[2] and then login[3]. If you are unfamiliar with R-Forge, you may want to review a copy of the User's Manual[4]. + +If you are interested in becoming a long-term contributor, we will need your r-forge id to get you set up with svn commit access on R-Forge. In addition, you should join the r-forge commit list for the project the code is being submitted into. For example, go to the returnanalytics[7] project on R-Forge. You?ll see a link for mailing lists, with one public mailing list called ?returnanalytics-commits?. Subscribe to that, and you?ll be notified by email of any commits made to the project. + +## Get proficient at using SVN +R-Forge uses svn for version control, and it is very important for you to be adept at using svn. For more specifics about how to use svn, take a look at the book Version Control with Subversion[5]. You will need to install the client of your choice (e.g., Tortoise SVN[6] on Windows or svnX on Mac OSX) and check out the repository. Please do not hesitate to ask for help if you get stuck - this is a critical component of our workflow and will be important for keeping everyone up to date with current code. + +If you want to commit to R-forge, it needs to be checked out using the instructions for developer checkout, via ssh, not the normal anonymous checkout. If you?ve previously checked out the code anonymously, you?ll need to check it out again using your R-Forge id (and ssh key) before you?ll be able to commit your changes. + +When making modifications or adding new functions, make frequent, small, tested commits. Those are easier for us to stay on top of. Please try to make commits to svn at least daily while coding. If you make an improvement and it works - check it in. This way we will be able to test code more frequently and we?ll know quickly if something is broken. + +We believe that there are thousands of financial professionals around the world who regularly use and rely on `PerformanceAnalytics`. When things break we hear about it, and often only minutes after a source commit. All code has bugs, of course, and we work hard to fix bugs as we are made aware of them. We also try as hard as we can to not introduce new bugs when we touch code. + +Make sure to test other behaviors beyond what you are working on to make sure that other functionality is unaffected by the changes you introduced. + +We suggest an iterative approach to development: first make it work, then make it work *correctly*, and finally make it work fast (if needed). Do not try to make it perfect or even pretty before checking something in. + +Make sure you provide a useful log message for each commit. Look at the log of the repository you will be working with to get a feel for the logging style. + +We do not have plans at this time to migrage to git, but thanks for asking. + +## Create a project structure +Functions that are candidates for inclusion in `PerformanceAnalytics` should be checked into the `\sandbox` directory on R-Forge. That directory is excluded from the production build testing, and is ideal for development. When a function is complete, documented, and tested, we will move it into the package and generate the associated Roxygen documentation. + +If you are working with us on a project over a longer period of time or with multiple functions, you should set up a project directory structure in that same directory. That will allow you arrange your code for compiling roxygen and testing that everything will build correctly without affecting the main package. Such a structure would be: +``` +sandbox/ + [your directory]/ + DESCRIPTION + R/ + man/ + src/ + tests/ + inst/ + vignettes/ +``` +If you've already started, mse svn move to move your existing functions into the appropriate directories to preserve the history of their development. Then try to build the roxygen documents. + +This structure provides an easy way for you to test whether the functions will "build" correctly. The next section will describe how you should be able to use `R CMD check` on your "package", so that the check process runs all your examples and demonstrates that everything is working the way you expect. + +## Install build tools and use `R CMD check` +Everyone should know how to build packages from source, although once-daily builds may be available on R-Forge. R-Forge uses CRAN's stringent standards for creating builds, so when the code is not ready for distribution R-Forge will not build the package. As a result, we recommend that you learn how to build packages in your own environment. + +A *nix machine should have everything needed (see Appendix A of ?R Installation and Administration?[13]), but a regular Windows machine will not. Windows users will need to install RTools [12], a collection of resources for building packages for R under Microsoft Windows (see Appendix D of ?R Installation and Administration?[13]). + +Once all tools are in place, you should be able to build a package by opening a shell, moving to the directory of the package, and typing ?R CMD INSTALL packagename?. The R-Forge Manual provides more detail in section 4. + +## Use `roxygen2` for documentation +We either have or are currently converting all of our packages' documentation to `roxygen2`[8], an in-source 'literate programming'[9] documentation system for generating Rd, collation, and NAMESPACE files. What that means is that the documentation will be in the same file as the functions (as comments before each function) which will make writing and synchronizing the documentation easier for everyone. Every function file will have the documentation and roxygen tags in the file, and `roxygenize` will be run before the package build process to generate the Rd documentation files required by R. `Roxygen2` is available on CRAN. + +For more information on documentation and R package development in general, read 'Writing R Extensions'[10]. + +## Use `xts` and `zoo` internally +PerformanceAnalytics uses the xts package for managing time series data for several reasons. Besides being fast and efficient, xts includes functions that test the data for periodicity and draw attractive and readable time-based axes on charts. Another benefit is that xts provides compatability with Rmetrics' timeSeries, zoo and other time series classes, such that PerformanceAnalytics functions that return a time series will return the results in the same format as the object that was passed in. Jeff Ryan and Josh Ulrich, the authors of xts, have been extraordinarily helpful to the development of PerformanceAnalytics and we are very greatful for their contributions to the community. + +The xts package extends the excellent zoo package written by Achim Zeileis and Gabor Grothendieck. zoo provides more general time series support, whereas xts provides functionality that is specifically aimed at users in finance. + +## Learn how to ask good questions +This might be your most important tool. + +If you're having trouble, try to provide a small, reproducible example that someone can actually run on easily available data. If more complex data structures are required, `dump("x", file=stdout())` will print an expression that will recreate the object `x`. + +A good place to ask questions is the r-sig-finance mailing list, where the authors and several contributors to our packages are known to hang out: +https://stat.ethz.ch/mailman/listinfo/r-sig-finance +Before asking a question, make sure to read the posting guide +http://www.r-project.org/posting-guide.html +and then read Eric Raymond's essay: +http://www.catb.org/~esr/faqs/smart-questions.html + +## Make your life easier with RStudio +Although RStudio is not required for contributing to `PerformanceAnalytics`, it is worth pointing out that it is a very capable IDE for R and has a number of tools for automating some of the workflow described above. Highly recommended. + + + +# Writing Calculation Functions +This section discusses some of the key principles that we've tried to adhere to when writing functions for `PerformanceAnalytics` in the belief that they help make the package easier for users to adopt into their work. With the principles in mind and tools in hand, we'll take a closer look at some specific examples. These examples won't be exhaustive or complete, so take a look at similar functions in the package for alternative methods as well. + +## Provide useful analysis of returns +`PerformanceAnalytics` is carefully scoped to focus on the analysis of returns rather than prices. If you are concerned that a function may not fit the package for some reason, please reach out to us and we can discuss what to do. We are authors of several other packages such as `quantstrat` and `blotter` that analyze prices and positions rather than returns and weights. + +It is important to note that `PerformanceAnalytics` does not aim to be exhaustive. Instead, we see it as a well-curated package of useful functions. We do not aspire to include every method ever conceived, but rather focus on functions that can affect investment decisions made by practitioners in real-world circumstances. + +`PerformanceAnalytics` is also not a reporting tool. Other packages and tools should be expected to use functions in this package for creating reports, but that functionality is beyond the scope of this package. For example, users wanting to export output to Excel have several packages to choose from, including `xlsx` or `XLConnect`. Those wanting a more interactive browswer-based experience should look at `shiny`. + +## Write readable and maintainable code +Although preferences for code style do vary, when there are a number of contributors to the package it can be important for readability and future maintainability of the code. You should strive (as much as is practical) to match the style in the existing code. When in doubt, rely on Google?s R Style Guide[11] or ask us. + +## Provide consistent and standard interfaces +Given the number of users that PerformanceAnalytics has right now and the institutions in which they work, we try to be as 'stable' as possible for our users. That stability comes from allowing users to expect two things: that similar functions will work similarly to one another, and that interfaces to functions won't change without backward compatability and warning. + +For the first aspect, `PerformanceAnalytics` uses standardized argument names and calling conventions throughout the package. For example, in every function where a time series of returns is used, the argument for the data is named `R`. If two such series are used, such as an asset and a benchmark time series, they are referred to as `Ra` and `Rb`, respectively. Several other similar conventions exist, such as using `p` for specifying the quantile parameter in `VaR`, `ES`, `CDaR`, and other similar functions. When writing or modifying a function, please use argument names that match similar functions. + +Secondly, the public interfaces of functions must not change in ways that break the users' existing code. In particular, do not change the names, the order of the arguments or the format of the results delivered if at all possible. Exceptions that are made for good reason require warnings about deprecation and handling for backward compatibility. + +We prefer that new arguments be added after dots (`...`). When arguments appear after dots, the user is required to pass the argument in explicitly, using the argument name. That prevents users from being confused about the order of the inputs. [Needs more detail? See also?] + +Parameter inputs should be the same periodicity as the data provided. For example, if a user is providing monthly returns data and specifying a "minimum acceptable return" (such as `MAR` in `DownsideDeviation`), the `MAR` parameter is assumed to also be a monthly return - the same periodicity as the input data. + +## Provide convenient analysis +This largely means hiding complexity from the end user. For example, given how we expect the input data to be organized functions will handle multi-column input and provide a calculated result (or NA) for each column, with the outputs labeled completely and delivered in a rational data structure. + +Functions will use `xts` internally where possible, mainly because `xts` is fast, efficient, and makes it easy to merge and subset data. + +Where the output is a time series derived from a time series input, the function will provide the output in the same format as the input series. See `?xts::reclass` for more information. + +## Write documentation first +Document as you write. It is really important to write the documentation as you write functions, perhaps even *before* you write the function, at least to describe what it should do. + +When documenting a function: + +- make sure function and argument naming is consistent; +- make sure equations are correct and cited; +- make sure all user-facing functions have examples; +- make sure you know the expected results of the examples (these will become tests); +- make sure relevant literature is cited everywhere; and +- apply a standard mathematical notation. In most cases, follow the notation from the original paper. + +Ideally, the documentation will go a step further to briefly describe how to interpret results. + +Make sure you use the author tag in roxygen with your name behind it. Credit is yours, and we want to remember who wrote it so we can ask you questions later! Also in the documentation, refer to any related code that is included, where it is, and how you matched it against known data to ensure it gives the same result. + +And think about see also tags in roxygen, linking charts and underlying functions in the documentation (such as `benchmarkSR` and its plot). + +Equations in documentation should have both full LaTeX code for printing in the PDF and a text representation that will be used in the console help. Use: +``` +\eqn{\LaTeX}{ascii} +``` +or +``` +\deqn{\LaTeX}{ascii} +``` +Greek letters will also be rendered in the HTML help. However, the only way to get the full mathematical equation layout is in the PDF rendered from LaTeX. + +At a minimum, use the following template to start your documentation. Feel free to add other tags as well. +``` +#' A brief, one line description +#' +#' Detailed description, including equations +#' \deqn{\LaTeX}{ascii} +#' @param ... +#' @author +#' @seealso \cr +#' @references +#' @examples +#' @aliases +#' @export +``` +There is more detail about the text formatting and tags in the `roxygen2` package. A good place to start is with the vignette, which can be read by typing `vignette('roxygen2')` in an R session after loading the package. + +## Accept inputs generously +Package functions will allow the user to provide input in any format. Users are able to pass in a data object without being concerned that the internal calculation function requires a matrix, data.frame, vector, xts, or timeSeries object. + +The functions within `PerformanceAnalytics` assume that input data is organized with asset returns in columns and dates represented in rows. All of the metrics are calculated by column and return values for each column in the results. This is the default arrangement of time series data in xts. + +Some sample data is available in the managers dataset. +```{r} +library(PerformanceAnalytics, verbose = FALSE, warn.conflicts = FALSE, quietly = TRUE) +data(managers) +head(managers) +``` +The `managers` data is an xts object that contains columns of monthly returns for six hypothetical asset managers (HAM1 through HAM6), the EDHEC Long-Short Equity hedge fund index, the S&P 500 total returns, and total return series for the US Treasury 10-year bond and 3-month bill. Monthly returns for all series end in December 2006 and begin at different periods starting from January 1996. That data set is used extensively in our examples and should serve as a model for how to expect the user to provide data to your functions. + +As you can see from the sample, returns are represented as a decimal number, rather than as a whole number with a percentile sign. + +`PerformanceAnalytics` provides a function, `checkData` that examines input data and coerces it into a specified format. This function was created to make the different kinds of data classes at least seem more fungible to the end user. It allows the user to pass in a data object without being concerned that the underlying functions require a matrix, data.frame, vector, xts, or timeSeries object. + +It allows the user to provide any type of data as input: a vector, matrix, data.frame, xts, timeSeries or zoo object. `checkData` will identify and coerce the data into any of "xts" (the default), "zoo", "data.frame", "matrix", or "vector". See `?checkData` for more details. + +## Handle missing data +Calculations will be made with the appropriate handling for missing data. Contributors should not assume that users will provide complete or equal length data sets. If only equal length data sets are required for the calculation, users should be warned with a message describing how the data was truncated. + +## Warn the user when making assumptions +If a function encounters an issue where there is a likely work-around to be applied or the function needs to make an assumption about what the user wants to do, the function should do so but inform the user by using `warning`. For example, in `Return.rebalancing` the function warns the user that it zero-filled any missing data that it encountered. +``` +Warning message: +In Return.rebalancing(managers[, 1:4]) : + NA's detected: filling NA's with zeros +``` +See `?warning` for more detail. + +## Provide clear error messages when stopping +In cases where the function cannot continue with the inputs provided, it should stop and give a clear reason. For example, when `Return.rebalancing` encounters a different number of assets and weights it will stop with the message "number of assets is greater than number of columns in return object". + +## Provide multi-column support +There is more than one way to provide multi-column support for calculation functions. We'll give a couple of short examples here, but peruse the code for other cases. + +Sometimes, functions don't need to have explicit handling for columns. See `Return.calculate` as an example. + +If the calculation is simple, use `apply`. A generic example might have a form like: +``` +exampleFunction <- function(R){ + R = checkData(R) + foo <- function(x) 1+x + result = apply (R, FUN=foo, MARGIN=2) + result +} +``` +[is there an outside reference/tutorial for apply?] + +For functions that may encounter multiple assets and multiple benchmarks, `expand.grid` is useful. `CAPM.alpha` shows an example of how the columns can be combined, then used with `apply`: +``` +pairs = expand.grid(1:NCOL(Ra), 1:NCOL(Rb)) +result = apply(pairs, 1, FUN = function(n, xRa, xRb) alpha(xRa[,n[1]], xRb[,n[2]]), xRa = xRa, xRb = xRb) +``` +If the calculation is more difficult, resort to simple `for` loops for columns. Speed optimization can come later, if necessary. + +## Provide support for different frequencies of data +Some functions should try to identify the periodicity of the returns data. For example, `SharpeRatio.annualized` identifies the frequency of the returns data input, and selects the appropriate multiplier for the user (e.g., daily returns would use `252`, monthly `12`, etc.). It also provides a parameter, `scale`, so that the user can directly specify the number of periods in a year if needed. + +The following snippet shows how `xts::periodicity` can be used to find the frequency of the data, and a variable can be set depending on its outcome. +``` +if(is.na(scale)) { + freq = periodicity(R) + switch(freq$scale, + minute = {stop("Data periodicity too high")}, + hourly = {stop("Data periodicity too high")}, + daily = {scale = 252}, + weekly = {scale = 52}, + monthly = {scale = 12}, + quarterly = {scale = 4}, + yearly = {scale = 1} + ) +} +``` +The `scale` variable is then set by how `xts` detects the data frequency. + +## Use reclass for time series output + +``` +result=reclass(result,match.to=R) +return(result) +``` + +## Label outputs clearly +Be clear about what the calculation has returned, labeling columns and rows of outputs as necessary, and using key input assumptions where useful. For example, you might use something like: +``` +rownames(result) = paste0("Modified Foo ratio (Risk free = ",Rf,")") +``` +Although that might seem like overkill, conditioning the labels is frequently useful for keeping track of key assumptions. + +In some cases, it is important to keep data pairs straight. For example, in functions where a set of returns and a set of benchmarks are possible inputs, individual results should be tagged with both the subject return name and the benchmark return name. + +## Create good tests + + +## How to pass functions and related arguments +Example? +the function is modify.args in quantstrat, in utils.R +and you can see how it's called in applyIndicators in indicators.R + +# Writing Chart Functions +## Use base graphics +## Use plot.xts for time series charts +## How to structure chart multiples +## Do NOT use menu interactions +## Writing to devices + +# Writing Table Functions +## Output to data.frame +## Formatting and displaying digits +## Writing to devices + +# Summary +## Thank you for contributing +## Ask questions to the list +Which list? + +# References +[1] R-Forge + +http://r-forge.r-project.org + +[2] R-Forge registration + +https://r-forge.r-project.org/account/register.php + +[3] R-Forge login + +https://r-forge.r-project.org/account/login.php + +[4] R-Forge User Manual + +http://download.r-forge.r-project.org/R-Forge_Manual.pdf + +[5] SVN Book + +http://svnbook.red-bean.com + +[6] Tortoise SVN + +http://tortoisesvn.tigris.org + +[7] ReturnAnalytics on R-Forge + +https://r-forge.r-project.org/projects/returnanalytics/ + +[8] roxygen2 + +http://cran.r-project.org/web/packages/roxygen2/index.html + +[9] literate programming + +http://en.wikipedia.org/wiki/Literate_programming + +[10] Writing R Extensions + +http://cran.r-project.org/doc/manuals/R-exts.pdf + +[11] Google?s R style guide + +http://google-styleguide.googlecode.com/svn/trunk/google-r-style.html + +[12] Rtools + +http://cran.r-project.org/bin/windows/Rtools/ + +[13] R Installation and Administration + +http://cran.r-project.org/doc/manuals/R-admin.pdf + +# Appendixes +## Use foreach for parallel computations +## Handle long labels when possible +## Writing to spreadsheets \ No newline at end of file From noreply at r-forge.r-project.org Fri Dec 5 21:52:29 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Fri, 5 Dec 2014 21:52:29 +0100 (CET) Subject: [Returnanalytics-commits] r3570 - pkg/PerformanceAnalytics/sandbox Message-ID: <20141205205229.AD30B18779D@r-forge.r-project.org> Author: braverock Date: 2014-12-05 21:52:29 +0100 (Fri, 05 Dec 2014) New Revision: 3570 Modified: pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd Log: - spell check, minor updates Modified: pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd =================================================================== --- pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd 2014-12-05 02:38:35 UTC (rev 3569) +++ pkg/PerformanceAnalytics/sandbox/howto-write-PA-functions.Rmd 2014-12-05 20:52:29 UTC (rev 3570) @@ -24,7 +24,7 @@ The second type of contributor we have in mind is more the focus of this document. This kind of contributor is working on a defined project around a body of research, porting existing code from another language, or developing an idea in collaboration with us. We encourage this type of contribution and for many years have collaborated with students through the Google Summer of Code [add link] program. This type of project-oriented collaboration requires more organization and structure -- sometimes there's a plan and a schedule, a mentor or three, maybe a book, a dissertation, or a few journal articles. -Either way, this guide assembles the things that we've said in answer to questions over the years to those we've collaborated with. We hope it provides a good foundation for you to get started, but please do not hesistate to ask for more detail or help where there isn't enough. And finally, please don't let our strident list of requirements below prevent you from contributing -- we value hastily constructed, first-draft, proof-of-concept code, too. +Either way, this guide assembles the things that we've said in answer to questions over the years to those we've collaborated with. We hope it provides a good foundation for you to get started, but please do not hesitate to ask for more detail or help where there isn't enough. And finally, please don't let our strident list of requirements below prevent you from contributing -- we value hastily constructed, first-draft, proof-of-concept code, too. ## How to become a contributor As mentioned above, the easiest way to become a contributor is to email us. We like to hear about what you are using the package for, answer any questions you might have, chase down bugs you encounter, or consider changes and additions that would improve the package. @@ -37,10 +37,10 @@ [ one paragraph on Copyrights and licensing? ] -The remainder of this paper is in three sections. The first provides a brief introduction to the tools we use, and might be generally helpful if you are newer to R. The second section describes the principals we use to guide our development, and the third section discusses in more detail and with examples how to use these principles as you develop functions. By the end of this document, you should have a good understanding about not only *how* but *why* we do things the way that we do. +The remainder of this paper is in three sections. The first provides a brief introduction to the tools we use, and might be generally helpful if you are newer to R. The second section describes the principles we use to guide our development, and the third section discusses in more detail and with examples how to use these principles as you develop functions. By the end of this document, you should have a good understanding about not only *how* but *why* we do things the way that we do. # Getting Established -This section introduces the tools we use for development. While these aren't all required to be successfull, we find that it is easier to help people through issues when we are all working with the same tools. +This section introduces the tools we use for development. While these aren't all required to be successful, we find that it is easier to help people through issues when we are all working with the same tools. ## How to create patches One of the easiest ways to become a contributor is to send us patches. Patches are a text description of changes made to a function that will add a new feature, fix a bug, or add documentation. To create a patch for a single file, use `diff` or a Windows-equivalent (either UnxUtils or WinMerge) to create a unified diff patch file. For example, in a shell you might run something like: @@ -69,7 +69,7 @@ Make sure you provide a useful log message for each commit. Look at the log of the repository you will be working with to get a feel for the logging style. -We do not have plans at this time to migrage to git, but thanks for asking. +We do not have plans at this time to migrate to git, but thanks for asking. ## Create a project structure Functions that are candidates for inclusion in `PerformanceAnalytics` should be checked into the `\sandbox` directory on R-Forge. That directory is excluded from the production build testing, and is ideal for development. When a function is complete, documented, and tested, we will move it into the package and generate the associated Roxygen documentation. @@ -86,7 +86,7 @@ inst/ vignettes/ ``` -If you've already started, mse svn move to move your existing functions into the appropriate directories to preserve the history of their development. Then try to build the roxygen documents. +If you've already started, use svn move to move your existing functions into the appropriate directories to preserve the history of their development. Then try to build the roxygen documents. This structure provides an easy way for you to test whether the functions will "build" correctly. The next section will describe how you should be able to use `R CMD check` on your "package", so that the check process runs all your examples and demonstrates that everything is working the way you expect. @@ -103,7 +103,7 @@ For more information on documentation and R package development in general, read 'Writing R Extensions'[10]. ## Use `xts` and `zoo` internally -PerformanceAnalytics uses the xts package for managing time series data for several reasons. Besides being fast and efficient, xts includes functions that test the data for periodicity and draw attractive and readable time-based axes on charts. Another benefit is that xts provides compatability with Rmetrics' timeSeries, zoo and other time series classes, such that PerformanceAnalytics functions that return a time series will return the results in the same format as the object that was passed in. Jeff Ryan and Josh Ulrich, the authors of xts, have been extraordinarily helpful to the development of PerformanceAnalytics and we are very greatful for their contributions to the community. +PerformanceAnalytics uses the xts package for managing time series data for several reasons. Besides being fast and efficient, xts includes functions that test the data for periodicity and draw attractive and readable time-based axes on charts. Another benefit is that xts provides compatibility with Rmetrics' timeSeries, zoo and other time series classes, such that PerformanceAnalytics functions that return a time series will return the results in the same format as the object that was passed in. Jeff Ryan and Josh Ulrich, the authors of xts, have been extraordinarily helpful to the development of PerformanceAnalytics and we are very grateful for their contributions to the community. The xts package extends the excellent zoo package written by Achim Zeileis and Gabor Grothendieck. zoo provides more general time series support, whereas xts provides functionality that is specifically aimed at users in finance. @@ -132,13 +132,13 @@ It is important to note that `PerformanceAnalytics` does not aim to be exhaustive. Instead, we see it as a well-curated package of useful functions. We do not aspire to include every method ever conceived, but rather focus on functions that can affect investment decisions made by practitioners in real-world circumstances. -`PerformanceAnalytics` is also not a reporting tool. Other packages and tools should be expected to use functions in this package for creating reports, but that functionality is beyond the scope of this package. For example, users wanting to export output to Excel have several packages to choose from, including `xlsx` or `XLConnect`. Those wanting a more interactive browswer-based experience should look at `shiny`. +`PerformanceAnalytics` is also not a reporting tool. Other packages and tools should be expected to use functions in this package for creating reports, but that functionality is beyond the scope of this package. For example, users wanting to export output to Excel have several packages to choose from, including `xlsx` or `XLConnect`. Those wanting a more interactive browser-based experience should look at `shiny`. ## Write readable and maintainable code Although preferences for code style do vary, when there are a number of contributors to the package it can be important for readability and future maintainability of the code. You should strive (as much as is practical) to match the style in the existing code. When in doubt, rely on Google?s R Style Guide[11] or ask us. ## Provide consistent and standard interfaces -Given the number of users that PerformanceAnalytics has right now and the institutions in which they work, we try to be as 'stable' as possible for our users. That stability comes from allowing users to expect two things: that similar functions will work similarly to one another, and that interfaces to functions won't change without backward compatability and warning. +Given the number of users that PerformanceAnalytics has right now and the institutions in which they work, we try to be as 'stable' as possible for our users. That stability comes from allowing users to expect two things: that similar functions will work similarly to one another, and that interfaces to functions won't change without backward compatibility and warning. For the first aspect, `PerformanceAnalytics` uses standardized argument names and calling conventions throughout the package. For example, in every function where a time series of returns is used, the argument for the data is named `R`. If two such series are used, such as an asset and a benchmark time series, they are referred to as `Ra` and `Rb`, respectively. Several other similar conventions exist, such as using `p` for specifying the quantile parameter in `VaR`, `ES`, `CDaR`, and other similar functions. When writing or modifying a function, please use argument names that match similar functions. @@ -181,7 +181,7 @@ ``` \deqn{\LaTeX}{ascii} ``` -Greek letters will also be rendered in the HTML help. However, the only way to get the full mathematical equation layout is in the PDF rendered from LaTeX. +Greek letters will also be rendered in the HTML help. However, the only way to get the full mathematical equation layout is in the PDF rendered from \LaTeX. At a minimum, use the following template to start your documentation. Feel free to add other tags as well. ``` @@ -204,11 +204,13 @@ The functions within `PerformanceAnalytics` assume that input data is organized with asset returns in columns and dates represented in rows. All of the metrics are calculated by column and return values for each column in the results. This is the default arrangement of time series data in xts. -Some sample data is available in the managers dataset. +Some sample data is available in the managers data set. ```{r} library(PerformanceAnalytics, verbose = FALSE, warn.conflicts = FALSE, quietly = TRUE) data(managers) +options(width=200) head(managers) +options(width=80) ``` The `managers` data is an xts object that contains columns of monthly returns for six hypothetical asset managers (HAM1 through HAM6), the EDHEC Long-Short Equity hedge fund index, the S&P 500 total returns, and total return series for the US Treasury 10-year bond and 3-month bill. Monthly returns for all series end in December 2006 and begin at different periods starting from January 1996. That data set is used extensively in our examples and should serve as a model for how to expect the user to provide data to your functions. From noreply at r-forge.r-project.org Sat Dec 6 07:21:17 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sat, 6 Dec 2014 07:21:17 +0100 (CET) Subject: [Returnanalytics-commits] r3571 - in pkg/FactorAnalytics: . R data man vignettes Message-ID: <20141206062117.DBCB91875B8@r-forge.r-project.org> Author: pragnya Date: 2014-12-06 07:21:16 +0100 (Sat, 06 Dec 2014) New Revision: 3571 Added: pkg/FactorAnalytics/data/StockReturns.RData pkg/FactorAnalytics/data/TreasuryYields.RData pkg/FactorAnalytics/man/StockReturns.Rd pkg/FactorAnalytics/man/TreasuryYields.Rd Removed: pkg/FactorAnalytics/data/stat.fm.data.RData pkg/FactorAnalytics/man/stat.fm.data.Rd Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/R/Misc.R pkg/FactorAnalytics/R/fitSfm.R pkg/FactorAnalytics/R/fmCov.R pkg/FactorAnalytics/R/fmEsDecomp.R pkg/FactorAnalytics/R/fmSdDecomp.R pkg/FactorAnalytics/R/fmVaRDecomp.R pkg/FactorAnalytics/R/plot.sfm.r pkg/FactorAnalytics/R/predict.sfm.r pkg/FactorAnalytics/R/print.sfm.r pkg/FactorAnalytics/R/summary.sfm.r pkg/FactorAnalytics/man/fitSfm.Rd pkg/FactorAnalytics/man/fmCov.Rd pkg/FactorAnalytics/man/fmEsDecomp.Rd pkg/FactorAnalytics/man/fmSdDecomp.Rd pkg/FactorAnalytics/man/fmVaRDecomp.Rd pkg/FactorAnalytics/man/plot.sfm.Rd pkg/FactorAnalytics/man/predict.sfm.Rd pkg/FactorAnalytics/man/print.sfm.Rd pkg/FactorAnalytics/man/summary.sfm.Rd pkg/FactorAnalytics/vignettes/FA.bib pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf Log: Added TreasuryYields data. Renamed stat.fm.data to StockReturns Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-06 06:21:16 UTC (rev 3571) @@ -1,8 +1,8 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.6 -Date: 2014-12-04 +Version: 2.0.7 +Date: 2014-12-05 Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Description: An R package for the estimation and risk analysis of linear factor Modified: pkg/FactorAnalytics/R/Misc.R =================================================================== --- pkg/FactorAnalytics/R/Misc.R 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/Misc.R 2014-12-06 06:21:16 UTC (rev 3571) @@ -11,7 +11,7 @@ #' @importFrom lars lars cv.lars #' @importFrom lmtest coeftest.default #' @importFrom sandwich vcovHC.default vcovHAC.default -#' @importFrom lattice barchart panel.barchart panel.grid +#' @importFrom lattice barchart panel.barchart panel.grid xyplot #' @importFrom corrplot corrplot #' @importFrom strucchange efp #' @importFrom MASS ginv \ No newline at end of file Modified: pkg/FactorAnalytics/R/fitSfm.R =================================================================== --- pkg/FactorAnalytics/R/fitSfm.R 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/fitSfm.R 2014-12-06 06:21:16 UTC (rev 3571) @@ -1,9 +1,9 @@ #' @title Fit a statistical factor model using principal component analysis #' -#' @description Fits a statistical factor model using principal component -#' analysis for one or more asset returns or excess returns. When the number of -#' assets exceeds the number of time periods, APCA (Asymptotic Principal -#' Component Analysis) is performed. An object of class \code{"sfm"} is +#' @description Fits a statistical factor model using Principal Component +#' Analysis (PCA) for one or more asset returns or excess returns. When the +#' number of assets exceeds the number of time periods, Asymptotic Principal +#' Component Analysis (APCA) is performed. An object of class \code{"sfm"} is #' returned. This function is based on the S+FinMetric function \code{mfactor}. #' #' @details @@ -119,17 +119,19 @@ #' #' @examples #' -#' # load data for fitSfm.r -#' data(stat.fm.data) -#' # data is from finmetric berndt.dat and folio.dat +#' # load return data +#' data(StockReturns) #' -#' # PCA is performed on sfm.dat and APCA on sfm.apca.dat -#' class(sfm.dat) -#' class(sfm.apca.dat) +#' # PCA is performed on r.M and APCA on r.W +#' class(r.M) +#' dim(r.M) +#' range(rownames(r.M)) +#' class(r.W) +#' dim(r.W) #' #' # PCA #' args(fitSfm) -#' fit.pca <- fitSfm(sfm.dat, k=2) +#' fit.pca <- fitSfm(r.M, k=2) #' class(fit.pca) #' names(fit.pca) #' head(fit.pca$factors) @@ -139,13 +141,13 @@ #' fit.pca$mimic #' #' # APCA with number of factors, k=15 -#' fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +#' fit.apca <- fitSfm(r.W, k=15, refine=TRUE) #' #' # APCA with the Bai & Ng method -#' fit.apca.bn <- fitSfm(sfm.apca.dat, k="bn") +#' fit.apca.bn <- fitSfm(r.W, k="bn") #' #' # APCA with the Connor-Korajczyk method -#' fit.apca.ck <- fitSfm(sfm.apca.dat, k="ck") +#' fit.apca.ck <- fitSfm(r.W, k="ck") #' #' @importFrom PerformanceAnalytics checkData #' Modified: pkg/FactorAnalytics/R/fmCov.R =================================================================== --- pkg/FactorAnalytics/R/fmCov.R 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/fmCov.R 2014-12-06 06:21:16 UTC (rev 3571) @@ -53,8 +53,8 @@ #' fmCov(fit) #' #' # Statistical Factor Model -#' data(stat.fm.data) -#' sfm.pca.fit <- fitSfm(sfm.dat, k=2) +#' data(StockReturns) +#' sfm.pca.fit <- fitSfm(r.M, k=2) #' fmCov(sfm.pca.fit) #' #' \dontrun{ Modified: pkg/FactorAnalytics/R/fmEsDecomp.R =================================================================== --- pkg/FactorAnalytics/R/fmEsDecomp.R 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/fmEsDecomp.R 2014-12-06 06:21:16 UTC (rev 3571) @@ -77,8 +77,8 @@ #' ES.decomp$cES #' #' # Statistical Factor Model -#' data(stat.fm.data) -#' sfm.pca.fit <- fitSfm(sfm.dat, k=2) +#' data(StockReturns) +#' sfm.pca.fit <- fitSfm(r.M, k=2) #' ES.decomp <- fmEsDecomp(sfm.pca.fit) #' ES.decomp$cES #' Modified: pkg/FactorAnalytics/R/fmSdDecomp.R =================================================================== --- pkg/FactorAnalytics/R/fmSdDecomp.R 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/fmSdDecomp.R 2014-12-06 06:21:16 UTC (rev 3571) @@ -64,8 +64,8 @@ #' decomp$pcSd #' #' # Statistical Factor Model -#' data(stat.fm.data) -#' sfm.pca.fit <- fitSfm(sfm.dat, k=2) +#' data(StockReturns) +#' sfm.pca.fit <- fitSfm(r.M, k=2) #' decomp <- fmSdDecomp(sfm.pca.fit) #' decomp$pcSd #' Modified: pkg/FactorAnalytics/R/fmVaRDecomp.R =================================================================== --- pkg/FactorAnalytics/R/fmVaRDecomp.R 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/fmVaRDecomp.R 2014-12-06 06:21:16 UTC (rev 3571) @@ -74,8 +74,8 @@ #' VaR.decomp$cVaR #' #' # Statistical Factor Model -#' data(stat.fm.data) -#' sfm.pca.fit <- fitSfm(sfm.dat, k=2) +#' data(StockReturns) +#' sfm.pca.fit <- fitSfm(r.M, k=2) #' VaR.decomp <- fmVaRDecomp(sfm.pca.fit) #' VaR.decomp$cVaR #' Modified: pkg/FactorAnalytics/R/plot.sfm.r =================================================================== --- pkg/FactorAnalytics/R/plot.sfm.r 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/plot.sfm.r 2014-12-06 06:21:16 UTC (rev 3571) @@ -101,10 +101,10 @@ #' @examples #' #' # load data from the database -#' data(stat.fm.data) +#' data(StockReturns) #' #' # APCA with number of factors, k=15 -#' fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +#' fit.apca <- fitSfm(r.W, k=15, refine=TRUE) #' #' # group plot(default); select type from menu prompt #' # menu is auto-looped to get multiple types of plots based on the same fit Modified: pkg/FactorAnalytics/R/predict.sfm.r =================================================================== --- pkg/FactorAnalytics/R/predict.sfm.r 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/predict.sfm.r 2014-12-06 06:21:16 UTC (rev 3571) @@ -17,12 +17,12 @@ #' #' @examples #' # load data from the database -#' data(stat.fm.data) +#' data(StockReturns) #' # fit the factor model with PCA -#' fit <- fitSfm(sfm.dat, k=2) +#' fit <- fitSfm(r.M, k=2) #' #' pred.fit <- predict(fit) -#' newdata <- data.frame("EDHEC LS EQ"=rnorm(n=120), "SP500 TR"=rnorm(n=120)) +#' newdata <- data.frame("CITCRP"=rnorm(n=120), "CONED"=rnorm(n=120)) #' rownames(newdata) <- rownames(fit$data) #' pred.fit2 <- predict(fit, newdata, interval="confidence") #' Modified: pkg/FactorAnalytics/R/print.sfm.r =================================================================== --- pkg/FactorAnalytics/R/print.sfm.r 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/print.sfm.r 2014-12-06 06:21:16 UTC (rev 3571) @@ -14,8 +14,8 @@ #' @seealso \code{\link{fitSfm}}, \code{\link{summary.sfm}} #' #' @examples -#' data(stat.fm.data) -#' fit <- fitSfm(sfm.dat, k=2) +#' data(StockReturns) +#' fit <- fitSfm(r.M, k=2) #' print(fit) #' #' @method print sfm Modified: pkg/FactorAnalytics/R/summary.sfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.sfm.r 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/R/summary.sfm.r 2014-12-06 06:21:16 UTC (rev 3571) @@ -35,9 +35,9 @@ #' @seealso \code{\link{fitSfm}}, \code{\link[stats]{summary.lm}} #' #' @examples -#' data(stat.fm.data) +#' data(StockReturns) #' # fit the factor model with PCA -#' fit <- fitSfm(sfm.dat, k=2) +#' fit <- fitSfm(r.M, k=2) #' #' # summary of factor model fit for all assets #' summary(fit, "HAC") Added: pkg/FactorAnalytics/data/StockReturns.RData =================================================================== (Binary files differ) Property changes on: pkg/FactorAnalytics/data/StockReturns.RData ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: pkg/FactorAnalytics/data/TreasuryYields.RData =================================================================== (Binary files differ) Property changes on: pkg/FactorAnalytics/data/TreasuryYields.RData ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Deleted: pkg/FactorAnalytics/data/stat.fm.data.RData =================================================================== (Binary files differ) Added: pkg/FactorAnalytics/man/StockReturns.Rd =================================================================== --- pkg/FactorAnalytics/man/StockReturns.Rd (rev 0) +++ pkg/FactorAnalytics/man/StockReturns.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -0,0 +1,53 @@ +\name{StockReturns} +\alias{StockReturns} +\alias{r.M} +\alias{r.W} +\docType{data} +\title{Stock Return Data} +\description{ +\code{r.M}: A "data.frame" object with monthly returns (ranging from January 1978 to December 1987) for 15 assets whose names are given in the 'Details'. + +\code{r.W}: A "data.frame" object with weekly returns (ranging from January 8, 1997 to June 28, 2000) for 1618 U.S. stocks. +} +\details{ +The 15 assets in \code{r.M} are as follows: + CITCRP monthly returns of Citicorp. + CONED monthly returns of Consolidated Edison. + CONTIL monthly returns of Continental Illinois. + DATGEN monthly returns of Data General. + DEC monthly returns of Digital Equipment Company. + DELTA monthly returns of Delta Airlines. + GENMIL monthly returns of General Mills. + GERBER monthly returns of Gerber. + IBM monthly returns of International Business Machines. + MARKET a value-weighted composite monthly returns based on transactions from the New York Stock Exchange and the American Exchange. + MOBIL monthly returns of Mobile. + PANAM monthly returns of Pan American Airways. + PSNH monthly returns of Public Service of New Hampshire. + TANDY monthly returns of Tandy. + TEXACO monthly returns of Texaco. + WEYER monthly returns of Weyerhauser. + RKFREE monthly returns on 30-day U.S. Treasury bills. +} +\usage{data(StockReturns)} +\format{ +data.frame object +\describe{ + \item{\code{r.M}}{monthly from Jan-1998 through Dec-1987} + \item{\code{r.W}}{weekly from Jan-08-1997 through Jun-28-2000} + } +} +\source{ + S+FinMetrics Berndt.dat & folio.dat +} +\references{ +Berndt, E. R. (1991). The practice of econometrics: classic and contemporary. Reading, MA: Addison-Wesley. +} +\examples{ +data(StockReturns) +dim(r.M) +range(rownames(r.M)) +dim(r.W) +range(rownames(r.W)) +} +\keyword{datasets} Added: pkg/FactorAnalytics/man/TreasuryYields.Rd =================================================================== --- pkg/FactorAnalytics/man/TreasuryYields.Rd (rev 0) +++ pkg/FactorAnalytics/man/TreasuryYields.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -0,0 +1,37 @@ +\name{TreasuryYields} +\alias{TreasuryYields} +\alias{tr.yields} +\docType{data} +\title{ +Treasury yields at different maturities +} +\description{ +The following is adapted from chapter 17 of Ruppert (2010). + +The data object contains yields on Treasury bonds at 11 maturities, T = 1, 3, and 6 months and 1, 2, 3, 5, 7, 10, 20, and 30 years. Daily yields were taken from a U.S. Treasury website for the time period January 2, 1990, to October 31, 2008. + +Daily yields were missing from some values of T because, for example to quote the website, "Treasury discontinued the 20-year constant maturity series at the +end of calendar year 1986 and reinstated that series on October 1, 1993." Dif- +ferencing may cause a few additional days to have missing values. +} +\usage{data(TreasuryYields)} +\format{ +xts time series object +\describe{ + \item{\code{tr.yields}}{Jan-02-1990 through Oct-31-2008} + } +} +\source{ +SDAFE author's website: \url{http://people.orie.cornell.edu/davidr/SDAFE/index.html} +} +\references{ +Ruppert, D. (2010). Statistics and data analysis for financial engineering. Springer. +} +\examples{ +data(TreasuryYields) +# preview the data +head(tr.yields) +} +\keyword{datasets} +\keyword{ts} + Modified: pkg/FactorAnalytics/man/fitSfm.Rd =================================================================== --- pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -76,10 +76,10 @@ \item{asset.ret}{N x T matrix of fitted asset returns from the factor model.} } \description{ -Fits a statistical factor model using principal component -analysis for one or more asset returns or excess returns. When the number of -assets exceeds the number of time periods, APCA (Asymptotic Principal -Component Analysis) is performed. An object of class \code{"sfm"} is +Fits a statistical factor model using Principal Component +Analysis (PCA) for one or more asset returns or excess returns. When the +number of assets exceeds the number of time periods, Asymptotic Principal +Component Analysis (APCA) is performed. An object of class \code{"sfm"} is returned. This function is based on the S+FinMetric function \code{mfactor}. } \details{ @@ -118,17 +118,19 @@ factor realizations are inverted to enable more meaningful interpretation. } \examples{ -# load data for fitSfm.r -data(stat.fm.data) -# data is from finmetric berndt.dat and folio.dat +# load return data +data(StockReturns) -# PCA is performed on sfm.dat and APCA on sfm.apca.dat -class(sfm.dat) -class(sfm.apca.dat) +# PCA is performed on r.M and APCA on r.W +class(r.M) +dim(r.M) +range(rownames(r.M)) +class(r.W) +dim(r.W) # PCA args(fitSfm) -fit.pca <- fitSfm(sfm.dat, k=2) +fit.pca <- fitSfm(r.M, k=2) class(fit.pca) names(fit.pca) head(fit.pca$factors) @@ -138,13 +140,13 @@ fit.pca$mimic # APCA with number of factors, k=15 -fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +fit.apca <- fitSfm(r.W, k=15, refine=TRUE) # APCA with the Bai & Ng method -fit.apca.bn <- fitSfm(sfm.apca.dat, k="bn") +fit.apca.bn <- fitSfm(r.W, k="bn") # APCA with the Connor-Korajczyk method -fit.apca.ck <- fitSfm(sfm.apca.dat, k="ck") +fit.apca.ck <- fitSfm(r.W, k="ck") } \author{ Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Modified: pkg/FactorAnalytics/man/fmCov.Rd =================================================================== --- pkg/FactorAnalytics/man/fmCov.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/fmCov.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -59,8 +59,8 @@ fmCov(fit) # Statistical Factor Model -data(stat.fm.data) -sfm.pca.fit <- fitSfm(sfm.dat, k=2) +data(StockReturns) +sfm.pca.fit <- fitSfm(r.M, k=2) fmCov(sfm.pca.fit) \dontrun{ Modified: pkg/FactorAnalytics/man/fmEsDecomp.Rd =================================================================== --- pkg/FactorAnalytics/man/fmEsDecomp.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/fmEsDecomp.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -75,8 +75,8 @@ ES.decomp$cES # Statistical Factor Model -data(stat.fm.data) -sfm.pca.fit <- fitSfm(sfm.dat, k=2) +data(StockReturns) +sfm.pca.fit <- fitSfm(r.M, k=2) ES.decomp <- fmEsDecomp(sfm.pca.fit) ES.decomp$cES } Modified: pkg/FactorAnalytics/man/fmSdDecomp.Rd =================================================================== --- pkg/FactorAnalytics/man/fmSdDecomp.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/fmSdDecomp.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -61,8 +61,8 @@ decomp$pcSd # Statistical Factor Model -data(stat.fm.data) -sfm.pca.fit <- fitSfm(sfm.dat, k=2) +data(StockReturns) +sfm.pca.fit <- fitSfm(r.M, k=2) decomp <- fmSdDecomp(sfm.pca.fit) decomp$pcSd } Modified: pkg/FactorAnalytics/man/fmVaRDecomp.Rd =================================================================== --- pkg/FactorAnalytics/man/fmVaRDecomp.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/fmVaRDecomp.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -75,8 +75,8 @@ VaR.decomp$cVaR # Statistical Factor Model -data(stat.fm.data) -sfm.pca.fit <- fitSfm(sfm.dat, k=2) +data(StockReturns) +sfm.pca.fit <- fitSfm(r.M, k=2) VaR.decomp <- fmVaRDecomp(sfm.pca.fit) VaR.decomp$cVaR } Modified: pkg/FactorAnalytics/man/plot.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/plot.sfm.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/plot.sfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -106,10 +106,10 @@ } \examples{ # load data from the database -data(stat.fm.data) +data(StockReturns) # APCA with number of factors, k=15 -fit.apca <- fitSfm(sfm.apca.dat, k=15, refine=TRUE) +fit.apca <- fitSfm(r.W, k=15, refine=TRUE) # group plot(default); select type from menu prompt # menu is auto-looped to get multiple types of plots based on the same fit Modified: pkg/FactorAnalytics/man/predict.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/predict.sfm.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/predict.sfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -22,12 +22,12 @@ } \examples{ # load data from the database -data(stat.fm.data) +data(StockReturns) # fit the factor model with PCA -fit <- fitSfm(sfm.dat, k=2) +fit <- fitSfm(r.M, k=2) pred.fit <- predict(fit) -newdata <- data.frame("EDHEC LS EQ"=rnorm(n=120), "SP500 TR"=rnorm(n=120)) +newdata <- data.frame("CITCRP"=rnorm(n=120), "CONED"=rnorm(n=120)) rownames(newdata) <- rownames(fit$data) pred.fit2 <- predict(fit, newdata, interval="confidence") } Modified: pkg/FactorAnalytics/man/print.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/print.sfm.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/print.sfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -19,8 +19,8 @@ volatilities from the fitted object. } \examples{ -data(stat.fm.data) -fit <- fitSfm(sfm.dat, k=2) +data(StockReturns) +fit <- fitSfm(r.M, k=2) print(fit) } \author{ Deleted: pkg/FactorAnalytics/man/stat.fm.data.Rd =================================================================== --- pkg/FactorAnalytics/man/stat.fm.data.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/stat.fm.data.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -1,42 +0,0 @@ -\docType{data} -\name{stat.fm.data} -\alias{sfm.apca.dat} -\alias{sfm.dat} -\alias{stat.fm.data} -\title{Monthly Stock Return Data || Portfolio of Weekly Stock Returns} -\source{ - S+FinMetrics Berndt.dat & folio.dat -} -\description{ - sfm.dat: This is a monthly "data.frame" object from - January 1978 to December 1987, with seventeen columns - representing monthly returns of certain assets, as in - Chapter 2 of Berndt (1991). sfm.apca.dat: This is a - weekly "data.frame" object with dimension 182 x 1618, - which runs from January 8, 1997 to June 28, 2000 and - represents the stock returns on 1618 U.S. stocks. -} -\details{ - CITCRP monthly returns of Citicorp. CONED monthly - returns of Consolidated Edison. CONTIL monthly returns - of Continental Illinois. DATGEN monthly returns of Data - General. DEC monthly returns of Digital Equipment - Company. DELTA monthly returns of Delta Airlines. GENMIL - monthly returns of General Mills. GERBER monthly returns - of Gerber. IBM monthly returns of International Business - Machines. MARKET a value-weighted composite monthly - returns based on transactions from the New York Stock - Exchange and the American Exchange. MOBIL monthly - returns of Mobile. PANAM monthly returns of Pan American - Airways. PSNH monthly returns of Public Service of New - Hampshire. TANDY monthly returns of Tandy. TEXACO - monthly returns of Texaco. WEYER monthly returns of - Weyerhauser. RKFREE monthly returns on 30-day U.S. - Treasury bills. -} -\references{ - Berndt, E. R. (1991). The Practice of Econometrics: - Classic and Contemporary. Addison-Wesley Publishing Co. -} -\keyword{datasets} - Modified: pkg/FactorAnalytics/man/summary.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) @@ -47,9 +47,9 @@ t-statistics using \code{\link[lmtest]{coeftest}}. } \examples{ -data(stat.fm.data) +data(StockReturns) # fit the factor model with PCA -fit <- fitSfm(sfm.dat, k=2) +fit <- fitSfm(r.M, k=2) # summary of factor model fit for all assets summary(fit, "HAC") Modified: pkg/FactorAnalytics/vignettes/FA.bib =================================================================== --- pkg/FactorAnalytics/vignettes/FA.bib 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/vignettes/FA.bib 2014-12-06 06:21:16 UTC (rev 3571) @@ -9,6 +9,13 @@ publisher={Wiley Online Library} } + at book{berndt1991practice, + title={The practice of econometrics: classic and contemporary}, + author={Berndt, Ernst R}, + year={1991}, + publisher={Addison-Wesley Reading, MA} +} + @article{chen1986economic, title={Economic forces and the stock market}, author={Chen, Nai-Fu and Roll, Richard and Ross, Stephen A}, @@ -116,6 +123,13 @@ publisher={RISK MAGAZINE LIMITED} } + at book{ruppert2010statistics, + title={Statistics and data analysis for financial engineering}, + author={Ruppert, David}, + year={2010}, + publisher={Springer} +} + @article{sharpe1964capital, title={Capital asset prices: A theory of market equilibrium under conditions of risk*}, author={Sharpe, William F}, Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-05 20:52:29 UTC (rev 3570) +++ pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-06 06:21:16 UTC (rev 3571) @@ -53,27 +53,27 @@ \begin{itemize} -\item \verb"fitTsfm(asset.names, factor.names, data, fit.method, variable.selection)": Fits a time series (a.k.a. macroeconomic) factor model for one or more asset returns or excess returns using time series regression. Ordinary least squares (OLS), discounted least squares (DLS) and robust regression fitting are possible. Variable selection methods include "stepwise", "subsets" and "lars". An object of class "tsfm" containing the fitted objects, model coefficients, R-squared and residual volatility is returned. +\item \verb"fitTsfm(asset.names, factor.names, data, fit.method, variable.selection, ...)": Fits a time series (a.k.a. macroeconomic) factor model for one or more asset returns or excess returns using time series regression. Ordinary least squares (OLS), discounted least squares (DLS) and robust regression fitting are possible. Variable selection methods include "stepwise", "subsets" and "lars". An object of class "tsfm" containing the fitted objects, model coefficients, R-squared and residual volatility is returned. -\item \verb"coef(object)": Extracts the coefficient matrix (intercept and factor betas) for all assets fit by the "tsfm" object. +\item \verb"coef(object, ...)": Extracts the coefficient matrix (intercept and factor betas) for all assets fit by the "tsfm" object. -\item \verb"fitted(object)": Returns an "xts" data object of fitted asset returns from the factor model for all assets. +\item \verb"fitted(object, ...)": Returns an "xts" data object of fitted asset returns from the factor model for all assets. -\item \verb"residuals(object)": Returns an "xts" data object of residuals from the fitted factor model for all assets. +\item \verb"residuals(object, ...)": Returns an "xts" data object of residuals from the fitted factor model for all assets. -\item \verb"fmCov(object, use)": Returns the \code{N x N} symmetric covariance matrix for asset returns based on the fitted factor model. \code{"use"} specifies how missing values are to be handled. +\item \verb"fmCov(object, use, ...)": Returns the \code{N x N} symmetric covariance matrix for asset returns based on the fitted factor model. \code{"use"} specifies how missing values are to be handled. -\item \verb"fmSdDecomp(object, use)": Returns a list containing the standard deviation of asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{"use"} specifies how missing values are to be handled. +\item \verb"fmSdDecomp(object, use, ...)": Returns a list containing the standard deviation of asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{"use"} specifies how missing values are to be handled. -\item \verb"fmVaRDecomp(object, p, method, invert)": Returns a list containing the value-at-risk for asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{"p"} and \code{"method"} specify the confidence level and method (one of "modified","gaussian", "historical" or "kernel") to calculate VaR. VaR is by default a positive quantity and specifying \code{"invert=TRUE"} allows the VaR value to be expressed as a negative quantity. These 3 arguments, \code{"p"}, \code{"method"} and \code{"invert"} are passed on to the \code{VaR} function in the \code{PerformanceAnalytics} package to calculate VaR. +\item \verb"fmVaRDecomp(object, p, method, invert, ...)": Returns a list containing the value-at-risk for asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. \code{"p"} and \code{"method"} specify the confidence level and method (one of "modified","gaussian", "historical" or "kernel") to calculate VaR. VaR is by default a positive quantity and specifying \code{"invert=TRUE"} allows the VaR value to be expressed as a negative quantity. These 3 arguments, \code{"p"}, \code{"method"} and \code{"invert"} are passed on to the \code{VaR} function in the \code{PerformanceAnalytics} package to calculate VaR. -\item \verb"fmEsDecomp(object, p, method, invert)": Returns a list containing the expected shortfall for asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. Arguments \code{"p"}, \code{"method"} and \code{invert} are the same as above. +\item \verb"fmEsDecomp(object, p, method, invert, ...)": Returns a list containing the expected shortfall for asset returns based on the fitted factor model and the marginal, component and percentage component factor contributions estimated from the given sample. Arguments \code{"p"}, \code{"method"} and \code{invert} are the same as above. \item \verb"plot(x)": The \code{plot} method for class "tsfm" can be used for plotting factor model characteristics of an individual asset or a group of assets (default). The type of individual/group plot can be specified or chosen from a menu prompt, which is the default if type is not specified. Further the menu reappears (default) to access multiple plots for the same asset(s) unless looping is disabled by setting \code{loop=FALSE}. -\item \verb"predict(object, newdata)": The \code{predict} method for class "tsfm" returns a vector or matrix of predicted values for a new data sample or simulated values. +\item \verb"predict(object, newdata, ...)": The \code{predict} method for class "tsfm" returns a vector or matrix of predicted values for a new data sample or simulated values. -\item \verb"summary(object, se.type)": The \code{summary} method for class "tsfm" returns an object of class \code{"summary.tsfm"} containing the summaries of the fitted "lm", "lmRob" or "lars" objects and the chosen type (HC/HAC) of standard errors and t-statistics to display. Printing the factor model summary object outputs the call, coefficients (with standard errors and t-statistics), r-squared and residual volatility (under the homo-skedasticity assumption) for all assets. +\item \verb"summary(object, se.type, ...)": The \code{summary} method for class "tsfm" returns an object of class \code{"summary.tsfm"} containing the summaries of the fitted "lm", "lmRob" or "lars" objects and the chosen type (HC/HAC) of standard errors and t-statistics to display. Printing the factor model summary object outputs the call, coefficients (with standard errors and t-statistics), r-squared and residual volatility (under the homo-skedasticity assumption) for all assets. \end{itemize} Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf =================================================================== (Binary files differ) From noreply at r-forge.r-project.org Sun Dec 7 07:36:05 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 7 Dec 2014 07:36:05 +0100 (CET) Subject: [Returnanalytics-commits] r3572 - in pkg/FactorAnalytics: . R man Message-ID: <20141207063605.A185F18787B@r-forge.r-project.org> Author: pragnya Date: 2014-12-07 07:36:03 +0100 (Sun, 07 Dec 2014) New Revision: 3572 Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/NAMESPACE pkg/FactorAnalytics/R/fitSfm.R pkg/FactorAnalytics/R/plot.sfm.r pkg/FactorAnalytics/R/summary.sfm.r pkg/FactorAnalytics/man/plot.sfm.Rd pkg/FactorAnalytics/man/summary.sfm.Rd Log: Added summary, plot for factor mimicking portfolios. Updated plot.sfm options. Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-07 06:36:03 UTC (rev 3572) @@ -1,8 +1,8 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.7 -Date: 2014-12-05 +Version: 2.0.8 +Date: 2014-12-06 Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Description: An R package for the estimation and risk analysis of linear factor @@ -27,7 +27,8 @@ strucchange, lmtest, sandwich, - lattice + lattice, + MASS Suggests: testthat, quantmod, knitr LazyLoad: yes Modified: pkg/FactorAnalytics/NAMESPACE =================================================================== --- pkg/FactorAnalytics/NAMESPACE 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/NAMESPACE 2014-12-07 06:36:03 UTC (rev 3572) @@ -38,6 +38,7 @@ export(paFm) export(qCornishFisher) export(rCornishFisher) +importFrom(MASS,ginv) importFrom(PerformanceAnalytics,Return.cumulative) importFrom(PerformanceAnalytics,VaR) importFrom(PerformanceAnalytics,chart.ACFplus) Modified: pkg/FactorAnalytics/R/fitSfm.R =================================================================== --- pkg/FactorAnalytics/R/fitSfm.R 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/R/fitSfm.R 2014-12-07 06:36:03 UTC (rev 3572) @@ -150,6 +150,7 @@ #' fit.apca.ck <- fitSfm(r.W, k="ck") #' #' @importFrom PerformanceAnalytics checkData +#' @importFrom MASS ginv #' #' @export @@ -270,7 +271,7 @@ Omega.fm <- B %*% var(f) %*% t(B) + diag(resid.sd^2) # compute factor mimicking portfolio weights: NxK - mimic <- X / colSums(X) + mimic <- t(t(X)/colSums(X)) # assign row and column names names(eig.val) <- paste("F", 1:n, sep = ".") @@ -338,7 +339,8 @@ Omega.fm <- B %*% var(f) %*% t(B) + diag(resid.sd^2) # compute factor mimicking portfolio weights - mimic <- X / colSums(X) + mimic <- ginv(R.mat) %*% f + mimic <- t(t(mimic)/colSums(mimic)) # extract r2, residuals resid.xts <- do.call(merge, sapply(X=summary(asset.fit), FUN="[", "residuals")) @@ -346,7 +348,7 @@ # assign row and column names names(eig.val) = paste("F", 1:obs, sep = ".") - names(r2) = names(resid.sd) = colnames(R.xts) + names(r2) = names(resid.sd) = rownames(mimic) = colnames(R.xts) colnames(B) = colnames(f) # return list Modified: pkg/FactorAnalytics/R/plot.sfm.r =================================================================== --- pkg/FactorAnalytics/R/plot.sfm.r 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/R/plot.sfm.r 2014-12-07 06:36:03 UTC (rev 3572) @@ -11,8 +11,9 @@ #' \code{loop=FALSE} will exit after plotting any one chosen characteristic #' without the need for menu selection. #' -#' Group plots are the default. The first \code{n.max} variables and -#' \code{n.max} factors are plotted depending on the characteristic chosen. +#' Group plots are the default. The variables in \code{asset.subset} and factors +#' in \code{asset.subset} are plotted depending on the characteristic chosen. +#' The default is to show the first 4 factors and first 5 assets. #' #' Individual asset plots are selected by specifying \code{plot.single=TRUE}. #' In which case, \code{asset.name} is necessary if multiple assets @@ -27,16 +28,20 @@ #' 2 = Time series plot of estimated factors, \cr #' 3 = Estimated factor loadings, \cr #' 4 = Histogram of R-squared, \cr -#' 5 = Histogram of Residual volatility,\cr +#' 5 = Histogram of residual volatility,\cr #' 6 = Factor model residual correlation \cr #' 7 = Factor model correlation,\cr #' 8 = Factor contribution to SD,\cr #' 9 = Factor contribution to ES,\cr -#' 10 = Factor contribution to VaR -#' @param k.max maximum number of factors to add per plot device for group -#' plots. Default is 6. -#' @param n.max maximum number of variables to add per plot device for group -#' plots. Default is 10. +#' 10 = Factor contribution to VaR, \cr +#' 11 = Factor mimicking portfolio weights - top long and short positions in each factor, \cr +#' 12 = Asset correlations - top long and short positions in each factor +#' @param factor.subset vector of names/indices of factors to show for group +#' plots. Default is 1:4. +#' @param asset.subset vector of names/indices of assets to show for group +#' plots. Default is 1:5. +#' @param n.top scalar; number of largest and smallest weights to display for +#' each factor mimicking portfolio. Default is 3. #' @param plot.single logical; If \code{TRUE} plots the characteristics of an #' individual asset's factor model. The type of plot is given by #' \code{which.plot.single}. Default is \code{FALSE}. @@ -112,7 +117,7 @@ #' #' # plot the factor betas of 1st 4 assets fitted above #' # loop disabled to get one type of plot without interative menu -#' plot(fit.apca, n.max=4, which.plot.group=3, loop=FALSE) +#' plot(fit.apca, asset.subset=1:4, which.plot.group=3, loop=FALSE) #' #' # plot factor model return correlation; angular order of the eigenvectors #' plot(fit.apca, which.plot.group=7, loop=FALSE, @@ -131,11 +136,11 @@ #' @method plot sfm #' @export -plot.sfm <- function(x, which.plot.group=NULL, k.max=6, n.max=10, - plot.single=FALSE, asset.name, which.plot.single=NULL, - colorset=(1:12), legend.loc="topleft", las=1, - VaR.method="historical", cum.var=TRUE, eig.max=0.9, - loop=TRUE, ...) { +plot.sfm <- function(x, which.plot.group=NULL, factor.subset=1:4, + asset.subset=1:5, n.top=3, plot.single=FALSE, asset.name, + which.plot.single=NULL, colorset=(1:12), + legend.loc="topleft", las=1, VaR.method="historical", + cum.var=TRUE, eig.max=0.9, loop=TRUE, ...) { if (plot.single==TRUE) { @@ -272,63 +277,62 @@ "Time series plot of estimated factors", "Estimated factor loadings", "Histogram of R-squared", - "Histogram of Residual volatility", + "Histogram of residual volatility", "Factor model residual correlation", "Factor model return correlation", "Factor contribution to SD", "Factor contribution to ES", - "Factor contribution to VaR"), + "Factor contribution to VaR", + "Factor mimicking portfolio weights - top long and short positions in each factor", + "Asset correlations - top long and short positions in each factor"), title="\nMake a plot selection (or 0 to exit):") } par(las=las) # default horizontal axis labels k <- x$k + f.names <- paste("F", 1:k, sep = ".") + a.names <- x$asset.names n <- nrow(x$loadings) + if (!(all(factor.subset %in% f.names) || all(factor.subset %in% 1:k))) { + stop("Invalid argument: factor.subset is not a valid subset of factor names in the fit object.") + } + if (!(all(asset.subset %in% a.names) || all(asset.subset %in% 1:n))) { + stop("Invalid argument: factor.subset is not a valid subset of factor names in the fit object.") + } + switch(which.plot.group, "1L" = { ## Screeplot of eigenvalues cumv <- cumsum(x$eigen)/sum(x$eigen) limit <- length(cumv[cumv k.max) { - cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) - k <- k.max - } plot( - xyplot(x$factors[,1:k],type=c("l","g"),xlab="", - scales=list(y=list(rot=0)), strip.left=TRUE, strip=FALSE) + xyplot(x$factors[,factor.subset], type=c("l","g"), xlab="", + scales=list(y=list(rot=0)), strip.left=TRUE, strip=FALSE, ...) ) }, "3L" = { ## Estimated factor loadings - if (k > k.max) { - cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) - k <- k.max - } - if (n > n.max) { - cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) - n <- n.max - } - par(mfrow=c(ceiling(k/2),2)) - for (i in 1:k) { + par(mfrow=c(ceiling(length(factor.subset)/2),2)) + for (i in factor.subset) { main=paste("Beta values for ", colnames(x$loadings)[i]) - barplot(x$loadings[1:n,i], main=main, names.arg=x$asset.names[1:n], + barplot(x$loadings[asset.subset,i], main=main, names.arg=asset.subset, col="darkblue", las=las, horiz=TRUE, ...) abline(v=0, lwd=1, lty=1, col=1) } par(mfrow=c(1,1)) }, - "4L" ={ + "4L" = { ## Histogram of R-squared methods <- c("add.density","add.rug") chart.Histogram(x$r2, xlab="R-squared", @@ -344,35 +348,19 @@ }, "6L" = { ## Factor Model Residual Correlation - if (n > n.max) { - cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) - n <- n.max - } - cor.resid <- cor(residuals(x)[,1:n], use="pairwise.complete.obs") + cor.resid <- cor(residuals(x)[,asset.subset], use="pairwise.complete.obs") corrplot(cor.resid, ...) # mtext("pairwise complete obs", line=0.5) }, "7L" = { ## Factor Model Return Correlation - if (n > n.max) { - cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) - n <- n.max - } - cor.fm <- cov2cor(fmCov(x))[1:n,1:n] + cor.fm <- cov2cor(fmCov(x))[asset.subset,asset.subset] corrplot(cor.fm, ...) # mtext("pairwise complete obs", line=0.5) }, "8L" = { ## Factor Percentage Contribution to SD - if (k > k.max) { - cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) - k <- k.max - } - if (n > n.max) { - cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) - n <- n.max - } - pcSd.fm <- fmSdDecomp(x)$pcSd[1:n,1:k] + pcSd.fm <- fmSdDecomp(x)$pcSd[asset.subset,factor.subset] plot( barchart(pcSd.fm, main="Factor % Contribution to SD", xlab="", auto.key=list(space="bottom",columns=3, @@ -382,17 +370,9 @@ panel.barchart(...)}, ...) ) }, - "9L"={ + "9L" = { ## Factor Percentage Contribution to ES - if (k > k.max) { - cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) - k <- k.max - } - if (n > n.max) { - cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) - n <- n.max - } - pcES.fm <- fmEsDecomp(x, method=VaR.method)$pcES[1:n,1:k] + pcES.fm <- fmEsDecomp(x, method=VaR.method)$pcES[asset.subset,factor.subset] plot( barchart(pcES.fm, main="Factor % Contribution to ES", xlab="", auto.key=list(space="bottom",columns=3, @@ -402,17 +382,9 @@ panel.barchart(...)}, ...) ) }, - "10L" ={ + "10L" = { ## Factor Percentage Contribution to VaR - if (k > k.max) { - cat(paste("Displaying only the first", k.max,"factors, as the number of factors > 'k.max' =", k.max)) - k <- k.max - } - if (n > n.max) { - cat(paste("Displaying only the first", n.max,"variables, as the number of variables > 'n.max' =", n.max)) - n <- n.max - } - pcVaR.fm <- fmVaRDecomp(x, method=VaR.method)$pcVaR[1:n,1:k] + pcVaR.fm <- fmVaRDecomp(x, method=VaR.method)$pcVaR[asset.subset,factor.subset] plot( barchart(pcVaR.fm, main="Factor % Contribution to VaR", xlab="", auto.key=list(space="bottom",columns=3, @@ -422,6 +394,30 @@ panel.barchart(...)}, ...) ) }, + "11L" = { + ## Factor mimicking portfolio weights - top long and short positions in each factor + par(mfrow=c(ceiling(length(factor.subset)/2),2)) + for (i in factor.subset) { + main=paste("Top positions in ", colnames(x$loadings)[i]) + s <- summary(x, n.top=n.top)$mimic.sum[[i]] + top <- as.numeric(s[,c(2,4)]) + names.arg <- as.vector(s[,c(1,3)]) + barplot(top, main=main, names.arg=names.arg, col="darkblue", + las=las, horiz=TRUE, ...) + abline(v=0, lwd=1, lty=1, col=1) + } + par(mfrow=c(1,1)) + }, + "12L" = { + ## Asset correlations - top long and short positions in each factor + for (i in factor.subset) { + main=paste("Correlations of top positions in ", colnames(x$loadings)[i]) + s <- summary(x, n.top=n.top)$mimic.sum[[i]] + names.arg <- as.vector(s[,c(1,3)]) + cor.fm <- cov2cor(fmCov(x))[names.arg,names.arg] + corrplot(cor.fm, ...) + } + }, invisible() ) # repeat menu if user didn't choose to exit from the plot options Modified: pkg/FactorAnalytics/R/summary.sfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.sfm.r 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/R/summary.sfm.r 2014-12-07 06:36:03 UTC (rev 3572) @@ -13,6 +13,8 @@ #' @param object an object of class \code{sfm} returned by \code{fitSfm}. #' @param se.type one of "Default", "HC" or "HAC"; option for computing HC/HAC #' standard errors and t-statistics. +#' @param n.top scalar; number of largest and smallest weights to display for +#' each factor mimicking portfolio. Default is 3. #' @param x an object of class \code{summary.sfm}. #' @param digits number of significants digits to use when printing. #' Default is 3. @@ -21,14 +23,16 @@ #' @return Returns an object of class \code{summary.sfm}. #' The print method for class \code{summary.sfm} outputs the call, #' coefficients (with standard errors and t-statistics), r-squared and -#' residual volatilty (under the homoskedasticity assumption) for all assets. +#' residual volatilty (under the homoskedasticity assumption) for all assets as +#' well as a summary of the factor mimicking portfolio weights. #' #' Object of class \code{summary.sfm} is a list of length N+2 containing: #' \item{call}{the function call to \code{fitSfm}} #' \item{se.type}{standard error type as input} #' \item{sum.list}{list of summaries for the N fit objects of class \code{lm} #' for each asset in the factor model.} -#' \item{mimic}{N x K matrix of factor mimicking portfolio weights.} +#' \item{mimic.sum}{list of matrices containing \code{n.top} largest and +#' smallest weights for each factor mimicking portfolio.} #' #' @author Sangeetha Srinivasan #' @@ -48,7 +52,7 @@ #' @method summary sfm #' @export -summary.sfm <- function(object, se.type="Default", ...){ +summary.sfm <- function(object, se.type="Default", n.top=3, ...){ # check input object validity if (!inherits(object, "sfm")) { @@ -72,9 +76,22 @@ } } + # get n.top largest and smallest weights for each factor mimicking portfolio + mimic <- object$mimic + mimic.sum <- list() + for (j in 1:object$k) { + short <- sort(mimic[,j])[1:n.top] + long <- sort(mimic[,j], decreasing=TRUE)[1:n.top] + mimic.sum[[j]] <- cbind(names(long),long,names(short),short) + rownames(mimic.sum[[j]]) <- 1:n.top + colnames(mimic.sum[[j]]) <- c("Top.Long.Name", "Top.Long.Weight", + "Top.Short.Name", "Top.Short.Weight") + } + names(mimic.sum) <- paste("F", 1:object$k, sep = ".") + # include the call and se.type to fitSfm sum <- list(call=object$call, se.type=se.type, sum.list=sum.list, - mimic=object$mimic) + mimic.sum=mimic.sum) class(sum) <- "summary.sfm" return(sum) } @@ -105,4 +122,6 @@ printCoefmat(table.coef, digits=digits, ...) cat("\nR-squared: ", r2,", Residual Volatility: ", sigma,"\n", sep="") } + cat("\nFactor mimicking portfolio weights:\n\n", sep="") + print(x$mimic.sum, digits=digits, ...) } Modified: pkg/FactorAnalytics/man/plot.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/plot.sfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/man/plot.sfm.Rd 2014-12-07 06:36:03 UTC (rev 3572) @@ -3,11 +3,11 @@ \alias{plot.sfm} \title{Plots from a fitted statistical factor model} \usage{ -\method{plot}{sfm}(x, which.plot.group = NULL, k.max = 6, n.max = 10, - plot.single = FALSE, asset.name, which.plot.single = NULL, - colorset = (1:12), legend.loc = "topleft", las = 1, - VaR.method = "historical", cum.var = TRUE, eig.max = 0.9, loop = TRUE, - ...) +\method{plot}{sfm}(x, which.plot.group = NULL, factor.subset = 1:4, + asset.subset = 1:5, n.top = 3, plot.single = FALSE, asset.name, + which.plot.single = NULL, colorset = (1:12), legend.loc = "topleft", + las = 1, VaR.method = "historical", cum.var = TRUE, eig.max = 0.9, + loop = TRUE, ...) } \arguments{ \item{x}{an object of class \code{sfm} produced by \code{fitSfm}.} @@ -18,19 +18,24 @@ 2 = Time series plot of estimated factors, \cr 3 = Estimated factor loadings, \cr 4 = Histogram of R-squared, \cr -5 = Histogram of Residual volatility,\cr +5 = Histogram of residual volatility,\cr 6 = Factor model residual correlation \cr 7 = Factor model correlation,\cr 8 = Factor contribution to SD,\cr 9 = Factor contribution to ES,\cr -10 = Factor contribution to VaR} +10 = Factor contribution to VaR, \cr +11 = Factor mimicking portfolio weights - top long and short positions in each factor, \cr +12 = Asset correlations - top long and short positions in each factor} -\item{k.max}{maximum number of factors to add per plot device for group -plots. Default is 6.} +\item{factor.subset}{vector of names/indices of factors to show for group +plots. Default is 1:4.} -\item{n.max}{maximum number of variables to add per plot device for group -plots. Default is 10.} +\item{asset.subset}{vector of names/indices of assets to show for group +plots. Default is 1:5.} +\item{n.top}{scalar; number of largest and smallest weights to display for +each factor mimicking portfolio. Default is 3.} + \item{plot.single}{logical; If \code{TRUE} plots the characteristics of an individual asset's factor model. The type of plot is given by \code{which.plot.single}. Default is \code{FALSE}.} @@ -95,8 +100,9 @@ \code{loop=FALSE} will exit after plotting any one chosen characteristic without the need for menu selection. -Group plots are the default. The first \code{n.max} variables and -\code{n.max} factors are plotted depending on the characteristic chosen. +Group plots are the default. The variables in \code{asset.subset} and factors +in \code{asset.subset} are plotted depending on the characteristic chosen. +The default is to show the first 4 factors and first 5 assets. Individual asset plots are selected by specifying \code{plot.single=TRUE}. In which case, \code{asset.name} is necessary if multiple assets @@ -117,7 +123,7 @@ # plot the factor betas of 1st 4 assets fitted above # loop disabled to get one type of plot without interative menu -plot(fit.apca, n.max=4, which.plot.group=3, loop=FALSE) +plot(fit.apca, asset.subset=1:4, which.plot.group=3, loop=FALSE) # plot factor model return correlation; angular order of the eigenvectors plot(fit.apca, which.plot.group=7, loop=FALSE, Modified: pkg/FactorAnalytics/man/summary.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-06 06:21:16 UTC (rev 3571) +++ pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-07 06:36:03 UTC (rev 3572) @@ -4,7 +4,7 @@ \alias{summary.sfm} \title{Summarizing a fitted time series factor model} \usage{ -\method{summary}{sfm}(object, se.type = "Default", ...) +\method{summary}{sfm}(object, se.type = "Default", n.top = 3, ...) \method{print}{summary.sfm}(x, digits = 3, ...) } @@ -14,6 +14,9 @@ \item{se.type}{one of "Default", "HC" or "HAC"; option for computing HC/HAC standard errors and t-statistics.} +\item{n.top}{scalar; number of largest and smallest weights to display for +each factor mimicking portfolio. Default is 3.} + \item{...}{futher arguments passed to or from other methods.} \item{x}{an object of class \code{summary.sfm}.} @@ -25,14 +28,16 @@ Returns an object of class \code{summary.sfm}. The print method for class \code{summary.sfm} outputs the call, coefficients (with standard errors and t-statistics), r-squared and -residual volatilty (under the homoskedasticity assumption) for all assets. +residual volatilty (under the homoskedasticity assumption) for all assets as +well as a summary of the factor mimicking portfolio weights. Object of class \code{summary.sfm} is a list of length N+2 containing: \item{call}{the function call to \code{fitSfm}} \item{se.type}{standard error type as input} \item{sum.list}{list of summaries for the N fit objects of class \code{lm} for each asset in the factor model.} -\item{mimic}{N x K matrix of factor mimicking portfolio weights.} +\item{mimic.sum}{list of matrices containing \code{n.top} largest and +smallest weights for each factor mimicking portfolio.} } \description{ \code{summary} method for object of class \code{sfm}. From noreply at r-forge.r-project.org Mon Dec 8 09:13:18 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 8 Dec 2014 09:13:18 +0100 (CET) Subject: [Returnanalytics-commits] r3573 - in pkg/FactorAnalytics: . R man vignettes Message-ID: <20141208081318.E33ED1801A5@r-forge.r-project.org> Author: pragnya Date: 2014-12-08 09:13:18 +0100 (Mon, 08 Dec 2014) New Revision: 3573 Added: pkg/FactorAnalytics/vignettes/fitSfm_vignette.R pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitSfm_vignette.pdf Modified: pkg/FactorAnalytics/DESCRIPTION pkg/FactorAnalytics/R/fitSfm.R pkg/FactorAnalytics/R/plot.sfm.r pkg/FactorAnalytics/R/summary.sfm.r pkg/FactorAnalytics/R/summary.tsfm.r pkg/FactorAnalytics/man/fitSfm.Rd pkg/FactorAnalytics/man/summary.sfm.Rd pkg/FactorAnalytics/man/summary.tsfm.Rd pkg/FactorAnalytics/vignettes/fitTsfm_vignette.R pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf Log: Added fitSfm_vignette. Minor edits to summary and plot. Fixed typos in fitTsfm_vignette. Modified: pkg/FactorAnalytics/DESCRIPTION =================================================================== --- pkg/FactorAnalytics/DESCRIPTION 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/DESCRIPTION 2014-12-08 08:13:18 UTC (rev 3573) @@ -1,8 +1,8 @@ Package: factorAnalytics Type: Package Title: Factor Analytics -Version: 2.0.8 -Date: 2014-12-06 +Version: 2.0.9 +Date: 2014-12-07 Author: Eric Zivot, Sangeetha Srinivasan and Yi-An Chen Maintainer: Sangeetha Srinivasan Description: An R package for the estimation and risk analysis of linear factor Modified: pkg/FactorAnalytics/R/fitSfm.R =================================================================== --- pkg/FactorAnalytics/R/fitSfm.R 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/R/fitSfm.R 2014-12-08 08:13:18 UTC (rev 3573) @@ -8,10 +8,10 @@ #' #' @details #' If \code{data} is not of class \code{"xts"}, rownames must provide an -#' \code{xts} compatible time index. Before model fitting, incomplete cases in -#' \code{data} are removed using \code{\link[stats]{na.omit}}. Also, if -#' \code{check=TRUE}, a warning is issued if any asset is found to have -#' identical observations. +#' \code{"xts"} compatible time index. Before model fitting, incomplete cases in +#' \code{data} are removed using \code{\link[stats]{na.omit}}. Specifying +#' \code{check=TRUE}, issues a warning if any asset is found to have identical +#' observations. #' #' Let \code{N} be the number of columns or assets and \code{T} be the number #' of rows or observations. When \code{N < T}, Principal Component Analysis @@ -23,23 +23,24 @@ #' Alternately, for APCA, a method to determine the number of factors can be #' specified: \code{k="bn"} corresponds to Bai and Ng (2002) and \code{k="ck"} #' corresponds to Connor and Korajczyk (1993). User can specify the maximum -#' number of factors, \code{max.k} to consider with these methods. If not, a -#' default maximum is calculated from \code{min(10, T-1)}. +#' number of factors, \code{max.k} to consider with these methods. If not, it +#' is assumed to be either 10 or $T-1$, whichever is smaller. #' -#' \code{refine} specifies whether a refinement of the APCA procedure (that may -#' improve efficiency) from Connor and Korajczyk (1988) is to be used. +#' \code{refine} specifies whether a refinement of the APCA procedure from +#' Connor and Korajczyk (1988) that may improve efficiency is to be used. #' -#' \code{corr} specifies if the correlation matrix of returns should be used -#' for finding the principal components instead of the covariance matrix. This -#' is decided on a case-by-case basis. The variable with the highest variance -#' dominates the PCA when the covariance matrix is used (but, this may be -#' justified if a volatile asset is more interesting for some reason and -#' volatility information shouldn't be discarded). On the other hand, using the -#' correlation matrix standardizes the variables and makes them comparable, -#' avoiding penalizing variables with less dispersion. +#' When \code{corr=TRUE}, the correlation matrix of returns are used for +#' finding the principal components instead of the covariance matrix. This is +#' typically decided by practioners on a case-by-case basis. The variable with +#' the highest variance dominates the PCA when the covariance matrix is used. +#' However, this may be justified if a volatile asset is more interesting for +#' some reason and volatility information shouldn't be discarded. On the other +#' hand, using the correlation matrix standardizes the variables and makes them +#' comparable, avoiding penalizing variables with less dispersion. #' -#' Note: If the median of the 1st principal component is negative, all it's -#' factor realizations are inverted to enable more meaningful interpretation. +#' Finally, if the median of the 1st principal component is negative, all it's +#' factor realizations are automatically inverted to enable more meaningful +#' interpretation. #' #' @param data vector, matrix, data.frame, xts, timeSeries or zoo object with #' asset returns. See details. @@ -78,7 +79,8 @@ #' \item{resid.sd}{length-N vector of residual standard deviations.} #' \item{residuals}{T x N xts object of residuals from the OLS regression.} #' \item{Omega}{N x N return covariance matrix estimated by the factor model.} -#' \item{eigen}{length-K vector of eigenvalues of the sample covariance matrix.} +#' \item{eigen}{length-N (or length-T for APCA) vector of eigenvalues of the +#' sample covariance matrix.} #' \item{mimic}{N x K matrix of factor mimicking portfolio weights.} #' \item{call}{the matched function call.} #' \item{data}{T x N xts data object containing the asset returns.} @@ -86,9 +88,6 @@ #' Where N is the number of assets, K is the number of factors, and T is the #' number of observations. #' -#' \item{residuals}{T x N matrix of residuals from the regression.} -#' \item{asset.ret}{N x T matrix of fitted asset returns from the factor model.} -#' #' @author Eric Zivot, Sangeetha Srinivasan and Yi-An Chen #' #' @references Modified: pkg/FactorAnalytics/R/plot.sfm.r =================================================================== --- pkg/FactorAnalytics/R/plot.sfm.r 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/R/plot.sfm.r 2014-12-08 08:13:18 UTC (rev 3573) @@ -326,7 +326,8 @@ par(mfrow=c(ceiling(length(factor.subset)/2),2)) for (i in factor.subset) { main=paste("Beta values for ", colnames(x$loadings)[i]) - barplot(x$loadings[asset.subset,i], main=main, names.arg=asset.subset, + barplot(x$loadings[asset.subset,i], main=main, + names.arg=rownames(x$loadings)[asset.subset], col="darkblue", las=las, horiz=TRUE, ...) abline(v=0, lwd=1, lty=1, col=1) } @@ -398,10 +399,10 @@ ## Factor mimicking portfolio weights - top long and short positions in each factor par(mfrow=c(ceiling(length(factor.subset)/2),2)) for (i in factor.subset) { - main=paste("Top positions in ", colnames(x$loadings)[i]) + main=paste("Top positions (%) in ", colnames(x$loadings)[i]) s <- summary(x, n.top=n.top)$mimic.sum[[i]] - top <- as.numeric(s[,c(2,4)]) - names.arg <- as.vector(s[,c(1,3)]) + top <- 100*stack(s[,c(2,4)])$values + names.arg <- stack(s[,c(1,3)])$values barplot(top, main=main, names.arg=names.arg, col="darkblue", las=las, horiz=TRUE, ...) abline(v=0, lwd=1, lty=1, col=1) @@ -413,7 +414,7 @@ for (i in factor.subset) { main=paste("Correlations of top positions in ", colnames(x$loadings)[i]) s <- summary(x, n.top=n.top)$mimic.sum[[i]] - names.arg <- as.vector(s[,c(1,3)]) + names.arg <- stack(s[,c(1,3)])$values cor.fm <- cov2cor(fmCov(x))[names.arg,names.arg] corrplot(cor.fm, ...) } Modified: pkg/FactorAnalytics/R/summary.sfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.sfm.r 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/R/summary.sfm.r 2014-12-08 08:13:18 UTC (rev 3573) @@ -12,7 +12,7 @@ #' #' @param object an object of class \code{sfm} returned by \code{fitSfm}. #' @param se.type one of "Default", "HC" or "HAC"; option for computing HC/HAC -#' standard errors and t-statistics. +#' standard errors and t-statistics. Default is "Default". #' @param n.top scalar; number of largest and smallest weights to display for #' each factor mimicking portfolio. Default is 3. #' @param x an object of class \code{summary.sfm}. @@ -31,8 +31,8 @@ #' \item{se.type}{standard error type as input} #' \item{sum.list}{list of summaries for the N fit objects of class \code{lm} #' for each asset in the factor model.} -#' \item{mimic.sum}{list of matrices containing \code{n.top} largest and -#' smallest weights for each factor mimicking portfolio.} +#' \item{mimic.sum}{list of data.frame objects containing \code{n.top} largest +#' and smallest weights for each factor mimicking portfolio.} #' #' @author Sangeetha Srinivasan #' @@ -52,13 +52,16 @@ #' @method summary sfm #' @export -summary.sfm <- function(object, se.type="Default", n.top=3, ...){ +summary.sfm <- function(object, se.type=c("Default","HC","HAC"), n.top=3, ...){ # check input object validity if (!inherits(object, "sfm")) { stop("Invalid 'sfm' object") } + #set default for se.type + se.type = se.type[1] + # extract list of summary.lm objects for all assets sum.list <- summary(object$asset.fit) names(sum.list) <- object$asset.names @@ -82,10 +85,11 @@ for (j in 1:object$k) { short <- sort(mimic[,j])[1:n.top] long <- sort(mimic[,j], decreasing=TRUE)[1:n.top] - mimic.sum[[j]] <- cbind(names(long),long,names(short),short) + mimic.sum[[j]] <- data.frame(names(long), long, names(short), short, + stringsAsFactors=FALSE) rownames(mimic.sum[[j]]) <- 1:n.top - colnames(mimic.sum[[j]]) <- c("Top.Long.Name", "Top.Long.Weight", - "Top.Short.Name", "Top.Short.Weight") + names(mimic.sum[[j]]) <- c("Top.Long.Name", "Top.Long.Weight", + "Top.Short.Name", "Top.Short.Weight") } names(mimic.sum) <- paste("F", 1:object$k, sep = ".") Modified: pkg/FactorAnalytics/R/summary.tsfm.r =================================================================== --- pkg/FactorAnalytics/R/summary.tsfm.r 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/R/summary.tsfm.r 2014-12-08 08:13:18 UTC (rev 3573) @@ -10,6 +10,7 @@ #' heteroskedasticity-autocorrelation-consistent (HAC) standard errors and #' t-statistics using \code{\link[lmtest]{coeftest}}. This option is meaningful #' only if \code{fit.method = "OLS" or "DLS"}. +#' #' Standard errors are currently not available for #' \code{variable.selection="lars"} as there seems to be no consensus on a #' statistically valid method of calculating standard errors for the lasso @@ -17,7 +18,7 @@ #' #' @param object an object of class \code{tsfm} returned by \code{fitTsfm}. #' @param se.type one of "Default", "HC" or "HAC"; option for computing -#' HC/HAC standard errors and t-statistics. +#' HC/HAC standard errors and t-statistics. Default is "Default". #' @param x an object of class \code{summary.tsfm}. #' @param digits number of significants digits to use when printing. #' Default is 3. @@ -56,11 +57,16 @@ #' @method summary tsfm #' @export -summary.tsfm <- function(object, se.type="Default", ...){ +summary.tsfm <- function(object, se.type=c("Default","HC","HAC"), ...){ + # check input object validity if (!inherits(object, "tsfm")) { stop("Invalid 'tsfm' object") } + + #set default for se.type + se.type = se.type[1] + # note: fit.method=NULL for "lars" objects if (object$fit.method=="Robust" && se.type!="Default") { stop("Invalid argument: HC/HAC standard errors are applicable only if Modified: pkg/FactorAnalytics/man/fitSfm.Rd =================================================================== --- pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/man/fitSfm.Rd 2014-12-08 08:13:18 UTC (rev 3573) @@ -64,16 +64,14 @@ \item{resid.sd}{length-N vector of residual standard deviations.} \item{residuals}{T x N xts object of residuals from the OLS regression.} \item{Omega}{N x N return covariance matrix estimated by the factor model.} -\item{eigen}{length-K vector of eigenvalues of the sample covariance matrix.} +\item{eigen}{length-N (or length-T for APCA) vector of eigenvalues of the +sample covariance matrix.} \item{mimic}{N x K matrix of factor mimicking portfolio weights.} \item{call}{the matched function call.} \item{data}{T x N xts data object containing the asset returns.} \item{asset.names}{length-N vector of column names from data.} Where N is the number of assets, K is the number of factors, and T is the number of observations. - -\item{residuals}{T x N matrix of residuals from the regression.} -\item{asset.ret}{N x T matrix of fitted asset returns from the factor model.} } \description{ Fits a statistical factor model using Principal Component @@ -84,10 +82,10 @@ } \details{ If \code{data} is not of class \code{"xts"}, rownames must provide an -\code{xts} compatible time index. Before model fitting, incomplete cases in -\code{data} are removed using \code{\link[stats]{na.omit}}. Also, if -\code{check=TRUE}, a warning is issued if any asset is found to have -identical observations. +\code{"xts"} compatible time index. Before model fitting, incomplete cases in +\code{data} are removed using \code{\link[stats]{na.omit}}. Specifying +\code{check=TRUE}, issues a warning if any asset is found to have identical +observations. Let \code{N} be the number of columns or assets and \code{T} be the number of rows or observations. When \code{N < T}, Principal Component Analysis @@ -99,23 +97,24 @@ Alternately, for APCA, a method to determine the number of factors can be specified: \code{k="bn"} corresponds to Bai and Ng (2002) and \code{k="ck"} corresponds to Connor and Korajczyk (1993). User can specify the maximum -number of factors, \code{max.k} to consider with these methods. If not, a -default maximum is calculated from \code{min(10, T-1)}. +number of factors, \code{max.k} to consider with these methods. If not, it +is assumed to be either 10 or $T-1$, whichever is smaller. -\code{refine} specifies whether a refinement of the APCA procedure (that may -improve efficiency) from Connor and Korajczyk (1988) is to be used. +\code{refine} specifies whether a refinement of the APCA procedure from +Connor and Korajczyk (1988) that may improve efficiency is to be used. -\code{corr} specifies if the correlation matrix of returns should be used -for finding the principal components instead of the covariance matrix. This -is decided on a case-by-case basis. The variable with the highest variance -dominates the PCA when the covariance matrix is used (but, this may be -justified if a volatile asset is more interesting for some reason and -volatility information shouldn't be discarded). On the other hand, using the -correlation matrix standardizes the variables and makes them comparable, -avoiding penalizing variables with less dispersion. +When \code{corr=TRUE}, the correlation matrix of returns are used for +finding the principal components instead of the covariance matrix. This is +typically decided by practioners on a case-by-case basis. The variable with +the highest variance dominates the PCA when the covariance matrix is used. +However, this may be justified if a volatile asset is more interesting for +some reason and volatility information shouldn't be discarded. On the other +hand, using the correlation matrix standardizes the variables and makes them +comparable, avoiding penalizing variables with less dispersion. -Note: If the median of the 1st principal component is negative, all it's -factor realizations are inverted to enable more meaningful interpretation. +Finally, if the median of the 1st principal component is negative, all it's +factor realizations are automatically inverted to enable more meaningful +interpretation. } \examples{ # load return data Modified: pkg/FactorAnalytics/man/summary.sfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/man/summary.sfm.Rd 2014-12-08 08:13:18 UTC (rev 3573) @@ -4,7 +4,8 @@ \alias{summary.sfm} \title{Summarizing a fitted time series factor model} \usage{ -\method{summary}{sfm}(object, se.type = "Default", n.top = 3, ...) +\method{summary}{sfm}(object, se.type = c("Default", "HC", "HAC"), + n.top = 3, ...) \method{print}{summary.sfm}(x, digits = 3, ...) } @@ -12,7 +13,7 @@ \item{object}{an object of class \code{sfm} returned by \code{fitSfm}.} \item{se.type}{one of "Default", "HC" or "HAC"; option for computing HC/HAC -standard errors and t-statistics.} +standard errors and t-statistics. Default is "Default".} \item{n.top}{scalar; number of largest and smallest weights to display for each factor mimicking portfolio. Default is 3.} @@ -36,8 +37,8 @@ \item{se.type}{standard error type as input} \item{sum.list}{list of summaries for the N fit objects of class \code{lm} for each asset in the factor model.} -\item{mimic.sum}{list of matrices containing \code{n.top} largest and -smallest weights for each factor mimicking portfolio.} +\item{mimic.sum}{list of data.frame objects containing \code{n.top} largest +and smallest weights for each factor mimicking portfolio.} } \description{ \code{summary} method for object of class \code{sfm}. Modified: pkg/FactorAnalytics/man/summary.tsfm.Rd =================================================================== --- pkg/FactorAnalytics/man/summary.tsfm.Rd 2014-12-07 06:36:03 UTC (rev 3572) +++ pkg/FactorAnalytics/man/summary.tsfm.Rd 2014-12-08 08:13:18 UTC (rev 3573) @@ -4,7 +4,7 @@ \alias{summary.tsfm} \title{Summarizing a fitted time series factor model} \usage{ -\method{summary}{tsfm}(object, se.type = "Default", ...) +\method{summary}{tsfm}(object, se.type = c("Default", "HC", "HAC"), ...) \method{print}{summary.tsfm}(x, digits = 3, ...) } @@ -12,7 +12,7 @@ \item{object}{an object of class \code{tsfm} returned by \code{fitTsfm}.} \item{se.type}{one of "Default", "HC" or "HAC"; option for computing -HC/HAC standard errors and t-statistics.} +HC/HAC standard errors and t-statistics. Default is "Default".} \item{...}{futher arguments passed to or from other methods.} @@ -45,6 +45,7 @@ heteroskedasticity-autocorrelation-consistent (HAC) standard errors and t-statistics using \code{\link[lmtest]{coeftest}}. This option is meaningful only if \code{fit.method = "OLS" or "DLS"}. + Standard errors are currently not available for \code{variable.selection="lars"} as there seems to be no consensus on a statistically valid method of calculating standard errors for the lasso Added: pkg/FactorAnalytics/vignettes/fitSfm_vignette.R =================================================================== --- pkg/FactorAnalytics/vignettes/fitSfm_vignette.R (rev 0) +++ pkg/FactorAnalytics/vignettes/fitSfm_vignette.R 2014-12-08 08:13:18 UTC (rev 3573) @@ -0,0 +1,300 @@ + +## ----message=FALSE------------------------------------------------------- +library(factorAnalytics) +options(digits=3) + + +## ------------------------------------------------------------------------ +# load the Rdata object +data(StockReturns) +# view class and dimensions +class(r.M) +dim(r.M) +# variable names +colnames(r.M) +# range of observations +range(rownames(r.M)) + + +## ------------------------------------------------------------------------ +class(r.W) +dim(r.W) +range(rownames(r.W)) + + +## ------------------------------------------------------------------------ +data(TreasuryYields) +head(tr.yields) +range(index(tr.yields)) + + +## ----tidy=TRUE----------------------------------------------------------- +args(fitSfm) + + +## ------------------------------------------------------------------------ +fit.pca <- fitSfm(r.M, k=2) + + +## ------------------------------------------------------------------------ +class(fit.pca) +names(fit.pca) + + +## ------------------------------------------------------------------------ +fit.pca # print the fitted "sfm" object + + +## ----fig.cap="Screeplot of eigenvalues from PCA fit", fig.width=6, fig.height=4---- +plot(fit.pca, which.plot.group=1, factor.subset=1:2, loop=FALSE, eig.max=0.9, + cex.names=0.9, cex.axis=0.9, cex.main=0.8) + + +## ----fig.cap="Estimated factors from PCA fit", fig.width=7, fig.height=4---- +plot(fit.pca, which.plot.group=2, factor.subset=1:2, loop=FALSE) + + +## ----fig.cap="Estimated loadings on PCA factors", fig.width=7, fig.height=5---- +plot(fit.pca, which.plot.group=3, asset.subset=1:15, factor.subset=1:2, + loop=FALSE, cex.names=0.8, cex.axis=0.8, cex.main=0.8) + + +## ----fig.cap="Largest and smallest weights in factor mimicking portfolios from PCA fit", fig.width=7, fig.height=4.5, fig.show='asis'---- +# Factor mimicking portfolio weights from PCA fit +t(fit.pca$mimic) +plot(fit.pca, which.plot.group=11, factor.subset=1:2, n.top=3, loop=FALSE, + cex.names=0.8, cex.axis=0.8, cex.main=0.8) + + +## ------------------------------------------------------------------------ +fit.apca <- fitSfm(r.W, k=15) + + +## ----fig.cap="Screeplot of eigenvalues from APCA fit",fig.width=7,fig.height=4.5---- +plot(fit.apca, which.plot.group=1, loop=FALSE, eig.max=0.4, cex.names=0.75, + cex.axis=0.8, cex.main=0.8) + + +## ----fig.cap="First four factor returns from APCA fit", fig.width=7,fig.height=4.5---- +plot(fit.apca, which.plot.group=2, loop=FALSE) + + +## ----fig.cap="Histogram of R-squared values for APCA fit", fig.width=6, fig.height=4---- +plot(fit.apca, which.plot.group=4, loop=FALSE) + + +## ----fig.cap="Histogram of Residual volatilities for APCA fit", fig.width=6, fig.height=4---- +plot(fit.apca, which.plot.group=5, loop=FALSE) + + +## ----fig.cap="Asset correlations: largest and smallest positions in the first factor portfolio of the APCA fit", fig.width=6, fig.height=6---- +plot(fit.apca, which.plot.group=12, factor.subset=1, loop=FALSE, n.top=5, + method="ellipse") + + +## ------------------------------------------------------------------------ +# APCA with the Bai & Ng method +fit.apca.bn <- fitSfm(r.W, k="bn") +summary(fit.apca.bn$loadings) + +# APCA with the Connor-Korajczyk method +fit.apca.ck <- fitSfm(r.W, k="ck", sig=0.05) +fit.apca.ck$k + + +## ------------------------------------------------------------------------ +methods(class="sfm") + + +## ----eval=FALSE---------------------------------------------------------- +## ## S3 method for class "sfm" +## summary.sfm (object, se.type="Default", n.top=3, ...) + + +## ------------------------------------------------------------------------ +# all estimated coefficients from PCA example +coef(fit.pca) + +# compare returns data with fitted and residual values for CITCRP: fit.pca +CITCRP.ts <- merge(fit.pca$data[,1], fitted(fit.pca)[,1], + residuals(fit.pca)[,1]) +colnames(CITCRP.ts) <- c("CITCRP.return","CITCRP.fitted","CITCRP.residual") +tail(CITCRP.ts) + +# summary for fit.pca computing HAC standard erros +sum.pca <- summary(fit.pca, se.type="HAC", n.top=3) +names(sum.pca) + +# print the summary for the 1st asset +sum.pca$sum.list[[1]] + +# print the summary for the factor mimicking portfolio weights +sum.pca$mimic.sum + + +## ----fig.cap="Treasury yields data for 11 different maturities", fig.width=7, fig.height=6---- +plot.zoo(tr.yields, main="Treasury yields", col=4) + + +## ----fig.cap="Treasury yield curve at 3 different dates", fig.width=7, fig.height=4---- +# remove NAs +dat <- na.omit(tr.yields) +time = c(1/12,.25,.5,1, 2, 3, 5, 7, 10, 20, 30) +plot(time, as.vector(dat[1,]), ylim=c(0,6), type="b", col=1, lwd=2, pch=19, + ylab="Yield", xlab="T") +lines(time, as.vector(dat[486,]), type="b", lwd=2, col=2, pch=19) +lines(time, as.vector(dat[821,]), type="b", lwd=2, col=4, pch=19) +legend("bottomright", c("07/31/01","07/02/07","10/31/08"), col=c(1,2,4), lwd=2) + + +## ------------------------------------------------------------------------ +diff.yield <- na.omit(diff(tr.yields)) +dim(diff.yield) +yield.pca <- fitSfm(diff.yield, k=3, corr=TRUE) + + +## ----fig.cap="Screeplot of eigenvalues from APCA fit",fig.width=7,fig.height=4.5---- +plot(yield.pca, which.plot.group=1, factor.subset=1:3, eig.max=1, loop=FALSE, + cex.names=0.9, cex.axis=0.9, cex.main=0.9) + + +## ------------------------------------------------------------------------ +beta <- yield.pca$loadings +summary(beta) +summary(yield.pca)$mimic.sum + + +## ----fig.cap="Factor loadings on the 1st three Principal components"----- +plot(yield.pca, which.plot.group=3, factor.subset=1:3, asset.subset=1:11, + loop=FALSE, cex.names=0.9, cex.axis=0.9, cex.main=0.9) + + +## ----fig.cap="The loadings on the 1st three factors across maturities", fig.width=7, fig.height=4---- +plot(time, beta[,1], ylim=c(-.8,.8), type="b", col=1, lwd=2, pch=19, + ylab="Factor loading", xlab="T") +lines(time, beta[,2], type="b", lwd=2, col=2, pch=19) +lines(time, beta[,3], type="b", lwd=2, col=4, pch=19) +legend("bottomright", c("F.1","F.2","F.3"), col=c(1,2,4), lwd=2) + + +## ----fig.cap="Effect of a unit change in the first 3 factors on the yield curve", fig.width=7, fig.height=10---- +mu <- colMeans(dat) +par(mfrow=c(3,1)) +for (i in 1:3) { + plot(time, mu, ylim=c(2,5.3), type="b", col=1, lwd=4, pch=19, ylab="Yield", + xlab="T") + lines(time, mu+beta[,i], type="b", lwd=2, col=3, pch=19) + lines(time, mu-beta[,i], type="b", lwd=2, col=2, pch=19) + legend("bottomright", + c("mean", paste("mean+F.",i,sep=""), paste("mean-F.",i,sep="")), + col=c(1,3,2), lwd=c(4,2,2)) +} + + +## ----fig.cap="Factor model return correlation (pairwise complete obs)", warning=FALSE, fig.width=7, fig.height=7---- +Omega <- fmCov(fit.pca) +# return correlation plot for all 15 assets; Angular Order of Eigenvectors +plot(fit.pca, which.plot.group=7, factor.subset=1:2, asset.subset=1:15, + loop=FALSE, order="AOE", method="ellipse") + + +## ----fig.cap="Percentage factor contribution to SD", fig.width=7, fig.height=6, warning=FALSE---- +decomp <- fmSdDecomp(fit.pca) +names(decomp) +# get the factor model standard deviation for all assets +decomp$Sd.fm +# get the component contributions to Sd; print first 6 assets +head(decomp$cSd) +# plot the percentage component contributions to Sd for all 15 assets +plot(fit.pca, which.plot.group=8, factor.subset=1:2, asset.subset=1:15, + loop=FALSE) + + +## ----fig.cap="Percentage factor contribution to VaR", fig.width=7, fig.height=5---- +decomp1 <- fmVaRDecomp(fit.apca, method="historical") +names(decomp1) +# factor model Value-at-Risk; print first 6 assets +head(decomp1$VaR.fm) +# marginal factor contributions to VaR from 1st 4 factors; print first 6 assets +head(decomp1$mVaR[,1:4]) +# plot the 1st 4 factors % component contributions to VaR for the 1st 6 assets +plot(fit.apca, which.plot.group=10, loop=FALSE, asset.subset=1:6) + + +## ----fig.cap="Percentage factor contribution to ES", fig.width=7, fig.height=5---- +decomp2 <- fmEsDecomp(fit.apca, method="historical") +names(decomp2) +# factor model Expected Shortfall; print first 6 assets +head(decomp2$ES.fm) +# percentage component contributions to ES from 1st 4 factors; show 1st 6 assets +head(decomp2$pcES[,1:4]) +# plot the 1st 4 factors % component contributions to ES for the 1st 6 assets +plot(fit.apca, which.plot.group=9, loop=FALSE, asset.subset=1:6) + + +## ----eval=FALSE---------------------------------------------------------- +## ## S3 method for class "sfm" +## plot(x, which.plot.group=NULL, factor.subset=1:4, asset.subset=1:5, n.top=3, +## plot.single=FALSE, asset.name, which.plot.single=NULL, colorset=(1:12), +## legend.loc="topleft", las=1, VaR.method="historical", cum.var=TRUE, +## eig.max=0.9, loop=TRUE, ...) + + +## ----eval=FALSE, results='hide'------------------------------------------ +## plot(fit.pca) +## +## ## Make a plot selection (or 0 to exit): +## ## +## ## 1: Screeplot of eigenvalues +## ## 2: Time series plot of estimated factors +## ## 3: Estimated factor loadings +## ## 4: Histogram of R-squared +## ## 5: Histogram of residual volatility +## ## 6: Factor model residual correlation +## ## 7: Factor model return correlation +## ## 8: Factor contribution to SD +## ## 9: Factor contribution to ES +## ## 10: Factor contribution to VaR +## ## 11: Factor mimicking portfolio weights - top long and short positions in each factor +## ## 12: Asset correlations - top long and short positions in each factor +## ## +## ## Selection: + + +## ----eval=FALSE, results='hide'------------------------------------------ +## plot(fit.pca, plot.single=TRUE, asset.name="CITCRP") +## +## ## Make a plot selection (or 0 to exit): +## ## +## ## 1: Time series plot of actual and fitted asset returns +## ## 2: Time series plot of residuals with standard error bands +## ## 3: Time series plot of squared residuals +## ## 4: Time series plot of absolute residuals +## ## 5: SACF and PACF of residuals +## ## 6: SACF and PACF of squared residuals +## ## 7: SACF and PACF of absolute residuals +## ## 8: Histogram of residuals with normal curve overlayed +## ## 9: Normal qq-plot of residuals +## ## 10: CUSUM test-Recursive residuals +## ## 11: CUSUM test-OLS residuals +## ## 12: Recursive estimates (RE) test of OLS regression coefficients +## ## 13: Rolling estimates over a 24-period observation window +## ## +## ## Selection: + + +## ----fig.cap="Time series plot of residuals with standard error bands: CITCRP", fig.show='asis', fig.width=7, fig.height=4.5---- +plot(fit.pca, plot.single=TRUE, asset.name="CITCRP", which.plot.single=2, + loop=FALSE) + + +## ----fig.cap="SACF and PACF of absolute residuals: CITCRP", fig.show='asis', fig.width=7, fig.height=4.5---- +plot(fit.pca, plot.single=TRUE, asset.name="CITCRP", which.plot.single=7, + loop=FALSE) + + +## ----fig.cap="Histogram of residuals with normal curve overlayed for CITCRP", fig.show='asis', fig.width=7, fig.height=4.5---- +plot(fit.pca, plot.single=TRUE, asset.name="CITCRP", which.plot.single=8, + loop=FALSE) + + Added: pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw (rev 0) +++ pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw 2014-12-08 08:13:18 UTC (rev 3573) @@ -0,0 +1,561 @@ +\documentclass[a4paper]{article} +\usepackage{Rd} +\usepackage{amsmath} +\usepackage[round]{natbib} +\usepackage{bm} +\usepackage{verbatim} +\usepackage[latin1]{inputenc} +\bibliographystyle{abbrvnat} +\usepackage{url} + +\let\proglang=\textsf +\renewcommand{\topfraction}{0.85} +\renewcommand{\textfraction}{0.1} +\renewcommand{\baselinestretch}{1.5} +\setlength{\textwidth}{15cm} \setlength{\textheight}{22cm} \topmargin-1cm \evensidemargin0.5cm \oddsidemargin0.5cm + +\usepackage{lmodern} +\usepackage[T1]{fontenc} + +% \VignetteIndexEntry{Fitting Statistical Factor Models: factorAnalytics vignette} +%\VignetteEngine{knitr::knitr} + +\begin{document} + +\title{Fitting Statistical Factor Models: factorAnalytics vignette} +\author{Sangeetha Srinivasan} +\maketitle + +\begin{abstract} +The purpose of this vignette is to demonstrate the use of \code{fitSfm} and related control, analysis and plot functions in the \code{factorAnalytics} package. +\end{abstract} + +\tableofcontents +\bigskip + +\newpage +\section{Overview} + +\subsection{Load Package} + +The latest version of the \verb"factorAnalytics" package can be downloaded from R-forge through the following command: +\begin{verbatim} +install.packages("factorAnalytics", repos="http://R-Forge.R-project.org") +\end{verbatim} +Load the package and it's dependencies. +<>= +library(factorAnalytics) +options(digits=3) +@ + +\subsection{Summary of related functions} +Here's a list of the functions and methods demonstrated in this vignette: + +\begin{itemize} + +\item \verb"fitSfm(data, k, max.k, refine, sig, check, corr, ...)": Fits a statistical factor model for one or more asset returns using Principal Component Analysis (PCA). When the number of assets exceeds the number of time periods, Asymptotic Principal Component Analysis (APCA) is performed. Additionaly for APCA, user can specify a method (one of \citet{connor1993test} or \citet{bai2002determining}) to determine the number of factors and/or choose to use the \citet{connor1988risk} refinement to the APCA procedure. The returned object is of class "sfm" and contains the fitted "lm" object, estimated factor realizations, factor loadings, R-squared, residual volatility, factor model return covariance and the factor mimicking portfolio weights. + +\item \verb"coef(object, ...)": Extracts the coefficient matrix (intercept and factor betas) for all assets fit by the "sfm" object. + +\item \verb"fitted(object, ...)": Returns an "xts" data object of fitted asset returns from the factor model for all assets. + +\item \verb"residuals(object, ...)": Returns an "xts" data object of residuals from the fitted factor model for all assets. + +\item \verb"fmCov(object, use, ...)": Returns the \code{N x N} symmetric covariance matrix for asset returns based on the fitted factor model. \code{"use"} specifies how missing values are to be handled. + [TRUNCATED] To get the complete diff run: svnlook diff /svnroot/returnanalytics -r 3573 From noreply at r-forge.r-project.org Mon Dec 8 17:18:15 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Mon, 8 Dec 2014 17:18:15 +0100 (CET) Subject: [Returnanalytics-commits] r3574 - in pkg/PerformanceAnalytics: . R Message-ID: <20141208161815.C10CB186766@r-forge.r-project.org> Author: braverock Date: 2014-12-08 17:18:15 +0100 (Mon, 08 Dec 2014) New Revision: 3574 Modified: pkg/PerformanceAnalytics/DESCRIPTION pkg/PerformanceAnalytics/R/PortfolioRisk.R Log: - add component method for historical VaR per request at http://stackoverflow.com/questions/27243094/ - normalize labels for historical component ES Modified: pkg/PerformanceAnalytics/DESCRIPTION =================================================================== --- pkg/PerformanceAnalytics/DESCRIPTION 2014-12-08 08:13:18 UTC (rev 3573) +++ pkg/PerformanceAnalytics/DESCRIPTION 2014-12-08 16:18:15 UTC (rev 3574) @@ -12,7 +12,7 @@ , person(given="Kyle",family="Balkissoon",role="ctb") , person(given="Diethelm",family="Wuertz",role="ctb") ) -Version: 1.4.3558 +Version: 1.4.3574 Date: $Date$ Description: Collection of econometric functions for performance and risk analysis. This package aims to aid Modified: pkg/PerformanceAnalytics/R/PortfolioRisk.R =================================================================== --- pkg/PerformanceAnalytics/R/PortfolioRisk.R 2014-12-08 08:13:18 UTC (rev 3573) +++ pkg/PerformanceAnalytics/R/PortfolioRisk.R 2014-12-08 16:18:15 UTC (rev 3574) @@ -550,7 +550,7 @@ ES.historical.portfolio = function(R,p,w) { - VaR = VaR.historical.portfolio(R,p,w) + hvar = as.numeric(VaR.historical.portfolio(R,p,w)$hVaR) T = dim(R)[1] N = dim(R)[2] c_exceed = 0; @@ -560,17 +560,19 @@ { rt = as.vector(R[t,]) rp = sum(w*rt) - if(rp<= -VaR){ + if(rp<= -hvar){ c_exceed = c_exceed + 1; r_exceed = r_exceed + rp; for( i in c(1:N) ){ realizedcontrib[i] =realizedcontrib[i] + w[i]*rt[i] } } } - realizedcontrib=as.numeric(realizedcontrib)/r_exceed ; - names(realizedcontrib)<-names(w) - ret <- list(-r_exceed/c_exceed,c_exceed,realizedcontrib) - names(ret) <- c("-r_exceed/c_exceed","c_exceed","realizedcontrib") + pct.contrib=as.numeric(realizedcontrib)/r_exceed ; + names(pct.contrib)<-names(w) + # TODO construct realized contribution + + ret <- list(-r_exceed/c_exceed,c_exceed,pct.contrib) + names(ret) <- c("-r_exceed/c_exceed","c_exceed","pct_contrib_hES") return(ret) } @@ -589,18 +591,31 @@ } colnames(result)<-colnames(R) return(result) -} -VaR.historical.portfolio = function(R,p,w) +} + +VaR.historical.portfolio = function(R,p,w=NULL) { - alpha = .setalphaprob(p) - portret = c(); - T = dim(R)[1] - N = dim(R)[2] - for( t in c(1:T) ){ - portret = c(portret,sum(w*as.numeric(R[t,]))) - } - hVaR = -1* sort(portret)[floor(alpha*T)] - return(hVaR) + alpha = .setalphaprob(p) + rp = Return.portfolio(R,w, contribution=TRUE) + hvar = -quantile(zerofill(rp$portfolio.returns),probs=alpha) + names(hvar) = paste0('hVaR ',100*(1-alpha),"%") + + # extract negative periods, + zl<-rp[rp$portfolio.returns<0,] + + # and construct weighted contribution + zl.contrib <- colMeans(zl)[-1] + ratio <- -hvar/sum(colMeans(zl)) + zl.contrib <- ratio * zl.contrib + + # and construct percent contribution + zl.pct.contrib <- (1/sum(zl.contrib))*zl.contrib + + ret=list(hVaR = hvar, + contribution = zl.contrib, + pct_contrib_hVaR = zl.pct.contrib) + + return(ret) } ############################################################################### From noreply at r-forge.r-project.org Tue Dec 9 20:56:39 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Tue, 9 Dec 2014 20:56:39 +0100 (CET) Subject: [Returnanalytics-commits] r3575 - pkg/FactorAnalytics/vignettes Message-ID: <20141209195639.D0A1B186F8E@r-forge.r-project.org> Author: pragnya Date: 2014-12-09 20:56:39 +0100 (Tue, 09 Dec 2014) New Revision: 3575 Modified: pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitSfm_vignette.pdf pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf Log: Edited fitTsfm and fitSfm vignette plot method description Modified: pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw 2014-12-08 16:18:15 UTC (rev 3574) +++ pkg/FactorAnalytics/vignettes/fitSfm_vignette.Rnw 2014-12-09 19:56:39 UTC (rev 3575) @@ -109,7 +109,7 @@ @ The "xts" data object, \code{tr.yields}, contains yields on Treasury bonds at 11 maturities, T = 1, 3, and 6 months and 1, 2, 3, 5, 7, 10, 20, and 30 years. Daily yields were taken from a U.S. Treasury website for the time period January 2, 1990, to October 31, 2008. -Daily yields are missing from some values of T because, the 20-year constant maturity series were discontinued at the end of calendar year 1986 and reinstated on October 1, 1993. Omitting the missing values of the differenced data, leaves 819 days of observations. Excluding the one-month and 30-year series would leave us with a longer series. +Daily yields are missing from some values of T. For example, the 20-year constant maturity series were discontinued at the end of calendar year 1986 and reinstated on October 1, 1993. Omitting the missing values of the differenced data, leaves 819 days of observations. Excluding the one-month and 20-year yields would leave us with a longer series. \newpage \section{Fit a statistical factor model} @@ -165,7 +165,7 @@ fit.pca # print the fitted "sfm" object @ -The screeplot of eigenvalues is illustrated in Figure 1, created by selecting option 1 on the plot menu (Refer to section 4 for a list of all the options). The first principal component explains about thirty five percent of the total variance, and the first two components explain about half of the total variance. Specifying \code{eig.max=0.9} displays the first set of components that explain at least ninety percent of the total variance. +The screeplot of eigenvalues is illustrated in Figure 1, created by selecting option 1 on the plot menu (Refer to section 5 for a list of all the options). The first principal component explains about thirty five percent of the total variance, and the first two components explain about half of the total variance. Specifying \code{eig.max=0.9} displays the first set of components that explain at least ninety percent of the total variance. <>= plot(fit.pca, which.plot.group=1, factor.subset=1:2, loop=FALSE, eig.max=0.9, cex.names=0.9, cex.axis=0.9, cex.main=0.8) @@ -200,7 +200,7 @@ fit.apca <- fitSfm(r.W, k=15) @ -Since the optional argument \code{refine=TRUE} by default, the APCA refinement will be used. This procedure involves recaling the returns using the residual variances obtained from one iteration of the APCA procedure, recomputing the $T \times T$ covariance matrix and performing a second iteration of the APCA procedure using this covariance matrix. This refinement may improve the efficiency of the procedure. +Since the optional argument \code{refine=TRUE} by default, the APCA refinement will be used. This procedure involves recaling the returns using the residual variances obtained from one iteration of the APCA procedure, recomputing the $T \times T$ covariance matrix and performing a second iteration of the APCA procedure using this covariance matrix. This refinement may improve efficiency. Figures 5 and 6 give the screeplot of eigenvalues and the estimated time series of the first 4 factor realizations. <>= @@ -222,14 +222,14 @@ @ The correlations of the assets giving the top five largest and smallest weights for each factor mimicking portfolio can be illustrated with group plot option number 12. This is illustrated in Figure 8 for the first factor. -<>= +<>= plot(fit.apca, which.plot.group=12, factor.subset=1, loop=FALSE, n.top=5, method="ellipse") @ -Note that the number of factors was known or pre-specified in fit.pca above. In practice, the number of factors is unknown and must be determined from the data. Two such procedures are available via \code{fitSfm} via the argument \code{k}: \code{"bn"} corresponds to \citet{bai2002determining} and \code{"ck"} corresponds to \citet{connor1993test}. The maximum number of factors to be considered with these methods is specified via \code{max.k}. By default, it is assumed to be either ten or $T-1$, whichever is smaller. For the "ck" method, \code{sig} specifies the desired level of significance. +Note that the number of factors was known or pre-specified in fit.apca above. In practice, the number of factors is unknown and must be determined from the data. Two such procedures are available via \code{fitSfm} via the argument \code{k}: \code{"bn"} corresponds to \citet{bai2002determining} and \code{"ck"} corresponds to \citet{connor1993test}. The maximum number of factors to be considered with these methods is specified via \code{max.k}. By default, it is assumed to be either ten or $T-1$, whichever is smaller. For the "ck" method, \code{sig} specifies the desired level of significance. -Here are some examples using the "ck" or "bn" method for performing APCA with the weekly return data for 1618 U.S. stocks. We find that both these methods select 2 factors and hence output the same factor model. +Here are some examples using the "ck" or "bn" method for performing APCA with the weekly return data for 1618 U.S. stocks. We find that both these methods select 2 factors and hence output the same factor model in this case. <<>>= # APCA with the Bai & Ng method fit.apca.bn <- fitSfm(r.W, k="bn") @@ -270,7 +270,7 @@ colnames(CITCRP.ts) <- c("CITCRP.return","CITCRP.fitted","CITCRP.residual") tail(CITCRP.ts) -# summary for fit.pca computing HAC standard erros +# summary for fit.pca with HAC standard erros sum.pca <- summary(fit.pca, se.type="HAC", n.top=3) names(sum.pca) @@ -307,8 +307,8 @@ yield.pca <- fitSfm(diff.yield, k=3, corr=TRUE) @ -Figure 12 shows a screeplot of all the eigenvalues. Approximately 95 percent of the variation is explained by the first 3 principal components and 99 percent explained by the first five. So, the choice of $k=3$ when fitting the model is not inappropriate. -<>= +Figure 12 shows a screeplot of all the eigenvalues. Approximately 94 percent of the variation is explained by the first 3 principal components and 99 percent explained by the first five. So, the choice of $k=3$ when fitting the model is not inappropriate. +<>= plot(yield.pca, which.plot.group=1, factor.subset=1:3, eig.max=1, loop=FALSE, cex.names=0.9, cex.axis=0.9, cex.main=0.9) @ @@ -335,9 +335,9 @@ legend("bottomright", c("F.1","F.2","F.3"), col=c(1,2,4), lwd=2) @ -All the weights in the first portfolio are positive and roughly the same amounts and any change in the first factor affects all the variables by similar amounts, causing somewhat paralell shifts. So, this might be interpreted as a level factor. The factor loadings for the second principal component are decreasing and any change in this factor affects the slope of the yield curve. Finally, the factor loadings for the third principal component are decreasing and then increasing and any change in this factor affects the curvature of the yield curve. This is illustrated next in Figure 15. +All the weights in the first portfolio are positive and roughly the same and any change in the first factor affects all the variables by similar amounts, causing somewhat paralell shifts. So, this might be interpreted as a level factor. The factor loadings for the second principal component are decreasing and any change in this factor affects the slope of the yield curve. Finally, the factor loadings for the third principal component are decreasing and then increasing and any change in this factor affects the curvature of the yield curve. This is illustrated next in Figure 15. -<>= +<>= mu <- colMeans(dat) par(mfrow=c(3,1)) for (i in 1:3) { @@ -374,7 +374,7 @@ \code{fmCov()} computes the factor model covariance from a fitted factor model. Options for handling missing observations include "pairwise.complete.obs" (default), "everything", "all.obs", "complete.obs" and "na.or.complete". -<>= +<>= Omega <- fmCov(fit.pca) # return correlation plot for all 15 assets; Angular Order of Eigenvectors plot(fit.pca, which.plot.group=7, factor.subset=1:2, asset.subset=1:15, @@ -471,22 +471,6 @@ eig.max=0.9, loop=TRUE, ...) @ -\subsection{Menu and looping} - -If the plot type argument (\code{which.plot.single} or \code{which.plot.group}) is not specified, a menu prompts for user input and the corresponding plot is output. Then, the menu is repeated (default) for user convenience in plotting multiple characteristics. Selecting '0' from the menu exits the current \code{plot.sfm} call. Alternately, setting \code{loop=FALSE} will exit after plotting any one chosen characteristic without the need for menu selection. - -For group plots (which are the default), only a subset of factors and assets specified via the arguments \code{factor.subset} and \code{asset.subset} are displayed due to space constraints. - -For individual plots, \code{asset.name} is necessary if multiple assets were modeled in \code{x} and \code{plot.single=TRUE}. However, if the \code{fitSfm} object \code{x} only contains one asset's factor model fit, \code{plot.sfm} can infer this automatically, without user input. - -Remarks: -\begin{itemize} -\item \code{cum.var} applies to group plot 1 (see menu in the next section), and specifies whether the cumulative fraction of the variance is printed above each bar in the screeplot of eigenvalues. -\item \code{eig.max=0.9} also applies to group plot 1, and diplays the largest eigenvalues that cumulatively explain at least 90 percent of the total variance . -\item \code{n.top} applies to group plots 11 and 12, which involve summarizing the factor mimicking portfolios, and specifies the number of top positions to display. -\item \code{VaR.method} applies to group plots 9 and 10, which are factor model risk ES and VaR decompositions respectively. -\end{itemize} - \subsection{Group plots} This is the default option for plotting. Simply running \code{plot(fit)}, where \code{fit} is any "sfm" object, will bring up a menu (shown below) for group plots. @@ -511,12 +495,30 @@ ## Selection: @ +For group plots, only a subset of factors and assets specified via the arguments \code{factor.subset} and \code{asset.subset} are displayed due to space constraints. + +Remarks: +\begin{itemize} +\item \code{cum.var} applies to group plot 1, and specifies whether the cumulative fraction of the variance is printed above each bar in the screeplot of eigenvalues. +\item \code{eig.max=0.9} also applies to group plot 1, and diplays the largest eigenvalues that cumulatively explain at least 90 percent of the total variance . +\item \code{n.top} applies to group plots 11 and 12, which involve summarizing the factor mimicking portfolios, and specifies the number of top positions to display. +\item \code{VaR.method} applies to group plots 9 and 10, which are factor model risk ES and VaR decompositions respectively. +\end{itemize} + + +\subsection{Menu and looping} + +If the plot type argument (\code{which.plot.group} or \code{which.plot.single}) is not specified, a menu prompts for user input and the corresponding plot is output. Then, the menu is repeated (default) for user convenience in plotting multiple characteristics. Selecting '0' from the menu exits the current \code{plot.sfm} call. Alternately, setting \code{loop=FALSE} will disable the looping and exit after plotting any one chosen characteristic. + All the figures in the vignette plotted so far are group plots with the looping disabled. + \newpage \subsection{Individual plots} -Setting \code{plot.single=TRUE} enables individual asset plots. If there is more than one asset fit by the fit object, \code{asset.name} is also necessary. Here's the individual plot menu. +Setting \code{plot.single=TRUE} enables individual asset plots. If there is more than one asset fit by the fit object, \code{asset.name} is also necessary. However, if the \code{fitSfm} object \code{x} only contains one asset's factor model fit, \code{plot.sfm} can infer this automatically, without user input. + +Here's the individual plot menu. <>= plot(fit.pca, plot.single=TRUE, asset.name="CITCRP") @@ -539,7 +541,7 @@ ## Selection: @ -Here are some examples of individual plots for the CITCRP asset in the PCA fit illustrated earlier. +Here are some examples which don't need interactive user input. These are individual plots for the CITCRP asset in the PCA fit illustrated earlier. <>= plot(fit.pca, plot.single=TRUE, asset.name="CITCRP", which.plot.single=2, loop=FALSE) Modified: pkg/FactorAnalytics/vignettes/fitSfm_vignette.pdf =================================================================== (Binary files differ) Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw =================================================================== --- pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-08 16:18:15 UTC (rev 3574) +++ pkg/FactorAnalytics/vignettes/fitTsfm_vignette.Rnw 2014-12-09 19:56:39 UTC (rev 3575) @@ -421,21 +421,6 @@ VaR.method="historical", loop=TRUE, ...) @ -\subsection{Menu and looping} - -If the plot type argument (\code{which.plot.single} or \code{which.plot.group}) is not specified, a menu prompts for user input and the corresponding plot is output. Then, the menu is repeated (default) for user convenience in plotting multiple characteristics. Selecting '0' from the menu exits the current \code{plot.tsfm} call. Alternately, setting \code{loop=FALSE} will exit after plotting any one chosen characteristic without the need for menu selection. - -For group plots (the default), the first \code{max.show} assets are plotted. For individual plots, \code{asset.name} is necessary if multiple assets were modeled in \code{x} and \code{plot.single=TRUE}. However, if the \code{fitTsfm} object \code{x} only contains one asset's factor model fit, \code{plot.tsfm} can infer this automatically, without user input. - -Remarks: -\begin{itemize} -\item CUSUM plots (individual asset plot options 10, 11 and 12) are applicable -only for \code{fit.method="OLS"}. -\item Rolling estimates (individual asset plot option 13) is not applicable for -\code{variable.slection="lars"}. -\item \code{VaR.method} applies to group plots 9 and 10 (see menu in the next section), which are factor model risk ES and VaR decompositions respectively. -\end{itemize} - \subsection{Group plots} This is the default option for plotting. Simply running \code{plot(fit)}, where \code{fit} is any "tsfm" object, will bring up a menu (shown below) for group plots. @@ -453,20 +438,32 @@ ## 7: Factor Model Return Correlation ## 8: Factor Contribution to SD ## 9: Factor Contribution to ES -## 10: Factor Contribution to VaR +## 10: Factor Contribution to VaR ## ## Selection: @ -Here's an example where the looping is disabled and the number of assets displayed is restricted to 4. -<>= +Remarks: +\begin{itemize} +\item For group plots, only the first \code{max.show} assets are plotted. +\item \code{VaR.method} applies to group plots 9 and 10, which are factor model risk ES and VaR decompositions respectively. +\end{itemize} + +<>= +# Example of a group plot: looping disabled & no. of assets displayed = 4. plot(fit.sub, which.plot.group=3, max.show=4, legend.loc=NULL, loop=FALSE) @ + +\subsection{Menu and looping} + +If the plot type argument (\code{which.plot.group} or \code{which.plot.single}) is not specified, a menu prompts for user input and the corresponding plot is output. Then, the menu is repeated (default) for user convenience in plotting multiple characteristics. Selecting '0' from the menu exits the current \code{plot.tsfm} call. Alternately, setting \code{loop=FALSE} will disable the looping and exit after plotting any one chosen characteristic. + \newpage - \subsection{Individual plots} -Setting \code{plot.single=TRUE} enables individual asset plots. If there is more than one asset fit by the fit object, \code{asset.name} is also necessary. Here's the individual plot menu. +Setting \code{plot.single=TRUE} enables individual asset plots. If there is more than one asset fit by the fit object, \code{asset.name} is also necessary. However, if the \code{fitSfm} object \code{x} only contains one asset's factor model fit, \code{plot.sfm} can infer this automatically, without user input. + +Here's the individual plot menu. <>= plot(fit.sub, plot.single=TRUE, asset.name="HAM1") @@ -489,18 +486,26 @@ ## Selection: @ -Here are a few more examples. -<>= +Remarks: +\begin{itemize} +\item CUSUM plots (individual asset plot options 10, 11 and 12) are applicable +only for \code{fit.method="OLS"}. +\item Rolling estimates (individual asset plot option 13) is not applicable for +\code{variable.slection="lars"}. +\end{itemize} + +Here are a few more examples which don't need interactive user input. +<>= plot(fit.sub, plot.single=TRUE, asset.name="HAM1", which.plot.single=2, loop=FALSE) @ -<>= +<>= plot(fit.sub, plot.single=TRUE, asset.name="HAM1", which.plot.single=7, loop=FALSE) @ -<>= +<>= plot(fit.sub, plot.single=TRUE, asset.name="HAM1", which.plot.single=8, loop=FALSE) @ Modified: pkg/FactorAnalytics/vignettes/fitTsfm_vignette.pdf =================================================================== (Binary files differ) From noreply at r-forge.r-project.org Thu Dec 11 20:23:22 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Thu, 11 Dec 2014 20:23:22 +0100 (CET) Subject: [Returnanalytics-commits] r3576 - pkg/PerformanceAnalytics/sandbox Message-ID: <20141211192322.61D541874C4@r-forge.r-project.org> Author: peter_carl Date: 2014-12-11 20:23:22 +0100 (Thu, 11 Dec 2014) New Revision: 3576 Modified: pkg/PerformanceAnalytics/sandbox/to.period.returns.R Log: - now preserves NA instead of zerofilling Modified: pkg/PerformanceAnalytics/sandbox/to.period.returns.R =================================================================== --- pkg/PerformanceAnalytics/sandbox/to.period.returns.R 2014-12-09 19:56:39 UTC (rev 3575) +++ pkg/PerformanceAnalytics/sandbox/to.period.returns.R 2014-12-11 19:23:22 UTC (rev 3576) @@ -41,9 +41,12 @@ if(err) stop("Period specified is higher than data periodicity. Specify a lower frequency instead.") # Calculate cumulative return for aggregation periods - period.apply(x, INDEX=endpoints(x, period), FUN=Return.cumulative, geometric=geometric) - - return(period.ret) +# result=period.apply(x, INDEX=endpoints(x, period), FUN=Return.cumulative, geometric=geometric) + result=NULL + for(i in 1:NCOL(x)){ + result = cbind(result,period.apply(x[,i], INDEX=endpoints(x, period), FUN=function(x, geometric) {ifelse(length(na.omit(x))==0, NA, Return.cumulative(x, geometric) )}, geometric=geometric)) + } + return(result) } #' @export From noreply at r-forge.r-project.org Sun Dec 21 16:30:53 2014 From: noreply at r-forge.r-project.org (noreply at r-forge.r-project.org) Date: Sun, 21 Dec 2014 16:30:53 +0100 (CET) Subject: [Returnanalytics-commits] r3577 - pkg/PerformanceAnalytics/R Message-ID: <20141221153053.6DB871878FC@r-forge.r-project.org> Author: rossbennett34 Date: 2014-12-21 16:30:53 +0100 (Sun, 21 Dec 2014) New Revision: 3577 Modified: pkg/PerformanceAnalytics/R/Return.portfolio.R Log: Fixes bug that occurs when first rebalance date is after first date of returns Modified: pkg/PerformanceAnalytics/R/Return.portfolio.R =================================================================== --- pkg/PerformanceAnalytics/R/Return.portfolio.R 2014-12-11 19:23:22 UTC (rev 3576) +++ pkg/PerformanceAnalytics/R/Return.portfolio.R 2014-12-21 15:30:53 UTC (rev 3577) @@ -237,10 +237,12 @@ # bop = beginning of period # eop = end of period # Initialize objects - bop_weights = matrix(0, NROW(R), NCOL(R)) + # portfolio returns are only accounted for after the first rebalancing date + R.idx = index(R[paste0(as.Date(index(weights[1,]))+1, "/")]) + bop_weights = matrix(0, NROW(R.idx), NCOL(R)) colnames(bop_weights) = colnames(R) eop_weights = period_contrib = bop_weights - ret = vector("numeric", NROW(R)) + ret = vector("numeric", NROW(R.idx)) # initialize counter k = 1 @@ -254,7 +256,6 @@ to = as.Date(index(weights[(i+1),])) } returns = R[paste0(from, "::", to)] - # Only enter the loop if we have a valid returns object if(nrow(returns) >= 1){ # inner loop counter @@ -266,13 +267,11 @@ period_contrib[k,] = coredata(returns[j,]) * bop_weights[k,] eop_weights[k,] = (period_contrib[k,] + bop_weights[k,]) / sum(c(period_contrib[k,], bop_weights[k,])) ret[k] = sum(period_contrib[k,]) - # increment the counters k = k + 1 } } } - R.idx = index(R) ret = xts(ret, R.idx) colnames(ret) = "portfolio.returns" @@ -312,7 +311,9 @@ # bop = beginning of period # eop = end of period # Initialize objects - bop_value = matrix(0, NROW(R), NCOL(R)) + # portfolio returns are only accounted for after the first rebalancing date + R.idx = index(R[paste0(as.Date(index(weights[1,]))+1, "/")]) + bop_value = matrix(0, NROW(R.idx), NCOL(R)) colnames(bop_value) = colnames(R) eop_value = bop_value @@ -323,7 +324,7 @@ eop_weights = bop_value } } - ret = eop_value_total = bop_value_total = vector("numeric", NROW(R)) + ret = eop_value_total = bop_value_total = vector("numeric", NROW(R.idx)) # The end_value is the end of period total value from the prior period end_value <- value @@ -340,7 +341,6 @@ to = as.Date(index(weights[(i+1),])) } returns = R[paste0(from, "::", to)] - # Only enter the loop if we have a valid returns object if(nrow(returns) >= 1){ # inner loop counter @@ -385,7 +385,7 @@ } } } - R.idx = index(R) + #R.idx = index(R) ret = xts(ret, R.idx) colnames(ret) = "portfolio.returns"