I think I remember Adrian Trapletti implemented static portfolio optimization using quadprog in tseries. It's been a long time so I don't remember the details ( it may be restricted to long only but you can add variables to make<br />it handle long short ) but you may want to check tseries out. <br /><br /><br /><br /><br /><p>On Oct 1, 2009, <strong>Jorge Nieves</strong> <jorge.nieves@moorecap.com> wrote: </p><div class="replyBody"><blockquote style="border-left: 2px solid #267fdb; margin: 0pt 0pt 0pt 1.8ex; padding-left: 1ex">Hi,<br /><br />I tested Thomas' code, but I get an error message in windows R 9.2<br />1(2009-06-26).<br /><br />Error: class(data) == "timeSeries" is not TRUE<br />> <br /><br />I have already spoken with Thomas. He indicated that his code seems to<br />work ok in LINUX. However, Thomas gets the same error message I get in<br />windows.<br /><br /><br />I was wondering if anyone else has tested the code? Has anyone found a<br />work around the problem? It just happens that I too have the need for<br />this functionality.<br /><br />Any leads or recommendations will be highly appreciated.<br /><br /><br /><br />Jorge Nieves<br /><br /><br />-----Original Message-----<br />From: <a href="mailto:r-sig-finance-bounces@stat.math.ethz.ch" target="_blank" class="parsedEmail">r-sig-finance-bounces@stat.math.ethz.ch</a><br />[mailto:<a href="mailto:r-sig-finance-bounces@stat.math.ethz.ch" target="_blank" class="parsedEmail">r-sig-finance-bounces@stat.math.ethz.ch</a>] On Behalf Of Thomas<br />Etheber<br />Sent: Monday, September 28, 2009 02:29 PM<br />To: Brian G. Peterson<br />Cc: <a href="mailto:r-sig-finance@stat.math.ethz.ch" target="_blank" class="parsedEmail">r-sig-finance@stat.math.ethz.ch</a>; Jesse Velez<br />Subject: Re: [R-SIG-Finance] Static Portfolio Optimization<br /><br />Brian G. Peterson wrote:<br />> Jesse Velez wrote:<br />>> Is there any function or example in R or Rmetrics of static portfolio<br /><br />>> optimization, where I have a vector of expected returns for N assets <br />>> and a expected covariance matrix of said N assets all at a fixed time<br /><br />>> (say generated from a MFM risk and return model).<br />>><br />>> fPortfolio, Portfolio, portfolio.optim appear to all require time <br />>> series of returns to generate the expected return and historical <br />>> covariance matrix for use in creating weights.<br />>><br />>> Ideally, I hope to find an example that allows easily allows <br />>> Long/Short weights to make the portfolio market neutral (i.e. <br />>> Summation of Weights =0).<br />>> <br />> All the implementations of Markowitz style mean/variance optmization <br />> use quadprog in R.<br />><br />> Plenty of information on the list archives from before all these <br />> packages existed about using quadprog for optimization.<br />><br />> Regards,<br />><br />> - Brian<br />><br /><br />Hi there,<br /><br />I also had the problem with fixed parameter inputs some time ago.<br />Implementing methods to perform this tasks would certainly be a nice<br />improvement of the library (as would be some help/error messages if the<br />covariance matrix is not positive semidefinite). <br />Although Brian's comment is helpful as usual, using basic quadprog<br />sounds like reinventing the wheel, but might nevertheless be needed to<br />solve your second task of a market-neutral portfolio.<br /><br />In order to use prespecified estimates as inputs I helped myself with<br />overwriting some of the methods. It's not a nice solution, but it worked<br />for me. You will find the methods attached below.<br />I didn't check the code again, but I think it should work. Please note,<br />some other methods of Rmetrics and fPortfolio might rely on the<br />timeseries objects and might not work properly.<br /><br />Hth<br />Thomas<br /><br />>>><br />require(MBESS)<br />require(fPortfolio)<br />rm(list=ls())<br />spec <- portfolioSpec()<br />constraints <- NULL<br /><br />portfolioData <- function (data, spec = portfolioSpec()) { <br /> ans = NULL<br /> if(class(data) == "timeSeries") {<br /> data = sort(data)<br /> nAssets = dim(data)[2]<br /> statistics = portfolioStatistics(data, spec)<br /> tailRisk = spec@model$tailRisk<br /> ans <- new("fPFOLIODATA", data = list(series = data, nAssets =<br />nAssets),<br /> statistics = statistics, tailRisk = tailRisk)<br /> }<br /> if(class(data) == "list") {<br /> statistics = list(mu = data$mu, Sigma = data$Sigma )<br /> attr(statistics, "estimator") = spec@model$estimator<br /> ans <- new("fPFOLIODATA", data = list( nAssets = length(data$mu)<br />), statistics = statistics, tailRisk = list() )<br /> }<br /> ans<br />}<br /><br /><br />########################################################################<br />############<br /><br />.efficientConstrainedMVPortfolio <- function (data, spec, constraints) {<br /> if (!inherits(data, "fPFOLIODATA"))<br /> data = portfolioData(data, spec)<br /> mu = getMu(data)<br /> Sigma = getSigma(data)<br /> nAssets = getNumberOfAssets(data)<br /> targetAlpha = getTargetAlpha(spec)<br /> solver = getSolver(spec)<br /> stopifnot(solver == "quadprog" | solver == "Rdonlp2")<br /> if (solver == "quadprog") {<br /> portfolio = solveRQuadprog(data, spec, constraints)<br /> }<br /> else if (solver == "Rdonlp2") {<br /> portfolio = solveRDonlp2(data, spec, constraints)<br /> }<br /> weights = portfolio$weights<br /> attr(weights, "status") <- portfolio$status<br /> names(weights) = names(mu)<br /> targetReturn = matrix(as.numeric(mu %*% weights), nrow = 1)<br /> colnames(targetReturn) <- getEstimator(spec)[1]<br /> covTargetRisk = sqrt(as.numeric(weights %*% Sigma %*% weights))<br /># x = getSeries(data)@Data %*% weights<br /># VaR = quantile(x, targetAlpha, type = 1)<br /># CVaR = VaR - 0.5 * mean(((VaR - x) + abs(VaR - x)))/targetAlpha<br /># targetRisk = matrix(c(covTargetRisk, CVaR, VaR), nrow = 1)<br /># colnames(targetRisk) <- c("cov", paste(c("CVaR.", "VaR."),<br /># targetAlpha * 100, "%", sep = ""))<br /> targetRisk = matrix(c(covTargetRisk), nrow = 1)<br /> ## is needed to use the plotting functions....<br /> targetRisk = matrix(c(covTargetRisk, covTargetRisk ), nrow = 1)<br /> colnames(targetRisk) <- c( "cov", "dummy" )<br /> new("fPORTFOLIO", call = match.call(), data = list(data = data),<br /> spec = list(spec = spec), constraints =<br />as.character(constraints),<br /> portfolio = list(weights = weights, targetReturn = targetReturn,<br /> targetRisk = targetRisk, targetAlpha = targetAlpha,<br /> status = portfolio$status), title = paste("Constrained MV<br />Portfolio - Solver:",<br /> solver), description = .description()) }<br /><br />########################################################################<br />############<br /><br />.minvarianceConstrainedMVPortfolio <- function (data, spec, constraints)<br />{<br /> if (!inherits(data, "fPFOLIODATA"))<br /> data = portfolioData(data, spec)<br /> mu = getMu(data)<br /> Sigma = getSigma(data)<br /> nAssets = getNumberOfAssets(data)<br /> targetAlpha = getTargetAlpha(spec)<br /> .minVariancePortfolioFun = function(x, data, spec, constraints) {<br /> spec@portfolio$targetReturn = x<br /> ans = .efficientConstrainedMVPortfolio(data = data, spec = spec,<br /> constraints = constraints)<br /> f = getTargetRisk(ans)[1]<br /> attr(f, "targetReturn") <- getTargetReturn(ans)<br /> attr(f, "targetRisk") <- getTargetRisk(ans)[1]<br /> attr(f, "weights") <- getWeights(ans)<br /> f<br /> }<br /> minVar = optimize(.minVariancePortfolioFun, interval = range(mu),<br /> data = data, spec = spec, constraints = constraints,<br /> tol = .Machine$double.eps^0.5)<br /> weights = attr(minVar$objective, "weights")<br /> names(weights) = names(mu)<br /> targetReturn = spec@portfolio$targetReturn =<br />as.numeric(attr(minVar$objective,<br /> "targetReturn"))<br /> targetReturn = matrix(targetReturn, nrow = 1)<br /> colnames(targetReturn) <- spec@model$estimator[1]<br /> covTargetRisk = as.numeric(attr(minVar$objective, "targetRisk"))<br /> # x = getSeries(data)@Data %*% weights<br /> # VaR = quantile(x, targetAlpha, type = 1)<br /> # CVaR = VaR - 0.5 * mean(((VaR - x) + abs(VaR - x)))/targetAlpha<br /> #targetRisk = matrix(c(covTargetRisk, CVaR, VaR), nrow = 1)<br /> #colnames(targetRisk) <- c("cov", paste(c("CVaR.", "VaR."),<br /> targetRisk = matrix(c(covTargetRisk), nrow = 1)<br /> ## is needed to use the plotting functions....<br /> targetRisk = matrix(c(covTargetRisk, covTargetRisk ), nrow = 1)<br /> colnames(targetRisk) <- c( "cov", "dummy" )<br /> new("fPORTFOLIO", call = match.call(), data = list(data = data),<br /> spec = list(spec = spec), constraints =<br />as.character(constraints),<br /> portfolio = list(weights = weights, targetReturn = targetReturn,<br /> targetRisk = targetRisk, targetAlpha = targetAlpha,<br /> status = 0), title = "Minimum Variance Portfolio",<br /> description = .description())<br />}<br /><br />show.fPORTFOLIO <- function (object)<br />{<br /> cat("\nTitle:\n ")<br /> cat(getTitle(object), "\n")<br /> cat("\nCall:\n ")<br /> print.default(getCall(object))<br /> cat("\nPortfolio Weight(s):\n")<br /> weights = round(getWeights(object), digits = 4)<br /> if (length(weights) == 1) {<br /> cat(" ", weights, "\n")<br /> }<br /> else {<br /> print.table(weights)<br /> }<br /> cat("\nRiskBudget(s):\n")<br /> riskBudgets = round(getCovRiskBudgets(object), digits = 4)<br /> if (length(riskBudgets) == 1) {<br /> cat(" ", riskBudgets, "\n")<br /> }<br /> else {<br /> print.table(riskBudgets)<br /> }<br /> if (FALSE) {<br /> if (!is.na(getTailRiskBudgets(object))) {<br /> cat("\nRiskBudget(s):\n")<br /> riskBudgets = round(getTailRiskBudgets(object), digits = 4)<br /> if (length(riskBudgets) == 1) {<br /> cat(" ", riskBudgets, "\n")<br /> }<br /> else {<br /> print.table(riskBudgets)<br /> }<br /> }<br /> }<br /> targetReturn = object@portfolio$targetReturn<br /> targetRisk = object@portfolio$targetRisk<br /> spec = getSpec(object)<br /> cat("\nTarget Risk(s) and Return(s):\n")<br /> if (is.null(dim(targetReturn))) {<br /> targetReturn = matrix(targetReturn, nrow = 1)<br /> colnames(targetReturn) = getEstimator(spec)[1]<br /> }<br /> if (is.null(dim(targetRisk))) {<br /> targetRisk = matrix(targetRisk, nrow = length(targetRisk) )<br /> colnames(targetRisk) = getEstimator(spec)[2]<br /> }<br /> target = cbind(targetReturn, targetRisk)<br /> colnames(target) = c(colnames(targetReturn), colnames(targetRisk) )<br /> if (nrow(target) == 1) {<br /> print(target[1, ])<br /> }<br /> else {<br /> print(target)<br /> }<br /> cat("\nDescription:\n ")<br /> cat(getDescription(object), "\n")<br /> invisible(object)<br />}<br /><br />setMethod("show", "fPORTFOLIO", show.fPORTFOLIO)<br /><br />########################################################################<br />############<br /><br />.portfolioConstrainedMVFrontier <- function (data, spec, constraints) {<br /> if (!inherits(data, "fPFOLIODATA"))<br /> data = portfolioData(data, spec)<br /> mu = getMu(data)<br /> Sigma = getSigma(data)<br /> nAssets = getNumberOfAssets(data)<br /> targetAlpha = getTargetAlpha(spec)<br /> nFrontierPoints = getNFrontierPoints(spec)<br /> targetReturn = targetRisk = targetWeights = error = NULL<br /> Spec = spec<br /> solver = spec@solver$solver<br /> Spec@portfolio$weights = rep(1/nAssets, nAssets)<br /> k = 0<br /> solverType = spec@solver$solver<br /> status = NULL<br /> for (nTargetReturn in seq(min(mu), max(mu), length =<br />nFrontierPoints)) {<br /> k = k + 1<br /> setTargetReturn(Spec) <- nTargetReturn<br /> nextPortfolio = .efficientConstrainedMVPortfolio(data = data,<br /> spec = Spec, constraints = constraints)<br /> Spec@portfolio$weights = nextPortfolio@portfolio$weights<br /> targetReturn = rbind(targetReturn,<br />nextPortfolio@portfolio$targetReturn)<br /> targetRisk = rbind(targetRisk,<br />nextPortfolio@portfolio$targetRisk)<br /> nextWeights = nextPortfolio@portfolio$weights<br /> names(nextWeights) = names(mu)<br /> status = c(status, nextPortfolio@portfolio$status)<br /> targetWeights = rbind(targetWeights, t(nextWeights))<br /> }<br /> Index = (1:length(status))[status == 0]<br /> weights = targetWeights<br /> colnames(weights) = names(mu)<br /> weights = weights[Index, ]<br /> DIM = dim(targetReturn)[2]<br /> targetReturn = targetReturn[Index, ]<br /> targetReturn = matrix(targetReturn, ncol = DIM)<br /> colnames(targetReturn) = getEstimator(spec)[1]<br /> targetRisk = targetRisk[Index, ]<br /> new("fPORTFOLIO", call = match.call(), data = list(data = data),<br /> spec = list(spec = spec), constraints =<br />as.character(constraints),<br /> portfolio = list(weights = weights, targetReturn = targetReturn,<br /> targetRisk = targetRisk, targetAlpha = targetAlpha,<br /> status = status), title = "Constrained MV Frontier",<br /> description = .description())<br />}<br /><br />########################################################################<br />############<br /><br /># You should be able to specify the data in this form:<br />mu <- c( 0.1, 0.08, 0.065)<br />sigma <- c( 0.18, 0.12, 0.09 )<br /><br />correlationMatrix <- rbind( c( 1, 0.8, 0.9 ),<br /> c( 0.8, 1, 0.75),<br /> c( 0.9, 0.75, 1) )<br /><br />covarianceMatrix <- cor2cov(correlationMatrix, sigma )<br /><br /><br />data = list( mu = mu, Sigma = covarianceMatrix )<br /><br /># And then do the optimisation<br />frontier <- portfolioFrontier(data, spec = spec, constraints )<br /><br />_______________________________________________<br /><a href="mailto:R-SIG-Finance@stat.math.ethz.ch" target="_blank" class="parsedEmail">R-SIG-Finance@stat.math.ethz.ch</a> mailing list<br /><a href="https://stat.ethz.ch/mailman/listinfo/r-sig-finance" target="_blank" class="parsedLink">https://stat.ethz.ch/mailman/listinfo/r-sig-finance</a><br />-- Subscriber-posting only.<br />-- If you want to post, subscribe first.<br /><br />_______________________________________________<br /><a href="mailto:R-SIG-Finance@stat.math.ethz.ch" target="_blank" class="parsedEmail">R-SIG-Finance@stat.math.ethz.ch</a> mailing list<br /><a href="https://stat.ethz.ch/mailman/listinfo/r-sig-finance" target="_blank" class="parsedLink">https://stat.ethz.ch/mailman/listinfo/r-sig-finance</a><br />-- Subscriber-posting only.<br />-- If you want to post, subscribe first.<br /></blockquote></div>