[R-SIG-Finance] Static Portfolio Optimization

Thomas Etheber etheber at gmx.de
Fri Oct 2 06:40:54 CEST 2009


Jorge Nieves schrieb:
> Hi,
>
> I tested Thomas' code, but I get an error message in windows R 9.2
> 1(2009-06-26).
>
> Error: class(data) == "timeSeries" is not TRUE
>   
>
> I have already spoken with Thomas. He indicated that his code seems to
> work ok in LINUX. However, Thomas gets the same error message I get in
> windows.
>
>   
I don't think the OS is relevant for the code. As I told Jorge the code 
worked on an older R Version (R version 2.6.1).

Btw Dirk mentioned a nice alternative - the tseries package. I was 
wondering, if one can also prespecify further restrictions to 
portfolio.optim or is there just support for long-only portfolios?
As the results of the optimizer are often quite sensitive, one might 
want to specify some minimum or maximum portfolio weights to get more 
suitable results.

Hth,
Thomas

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



More information about the R-SIG-Finance mailing list