0

背景:我想知道你是否可以帮助我。我熟悉投资组合优化。我不是专家,但我通常会根据 quadprog 或数值方法构建自己的优化器来创建有效的边界。我刚开始使用 PortfolioAnalytics,因为它看起来非常好,而且我对可用的不同求解器很感兴趣。

目标:我想使用一组历史收益来计算资产收益的第二时刻(或更高),但要指定第一时刻(即使用我自己的预期收益)。我已经按照包装文档和小插图中的说明指定了预期回报。

问题:我不明白 create.EfficientFrontier() 在做什么。我输入了自己的预期收益,有效边界没有改变。为了测试发生了什么,(i)我输入了更高的预期回报作为测试,并且边界没有上升;但是 (ii) 输入正在做某事,因为如果我将回报最高的资产归零,则前沿收缩;(iii) 如果我颠倒预期收益的顺序,使波动较大的资产具有较低的预期收益,则边界会发生变化。

问题:如果有人能告诉我如何使用我自己的预期回报而不是默认的历史回报来建立边界,我将不胜感激。

非常感谢,

约翰

可重现的例子


R version 3.6.1 (2019-07-05) -- "Action of the Toes"
Copyright (C) 2019 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)

#Load packages

library(quadprog)
library(lubridate)
library(PortfolioAnalytics)
library(ROI)
library(ROI.plugin.glpk)
library(ROI.plugin.quadprog)

#Create some fake data (no doubt there is an easier way of doing this)

set.seed(1234)
fakereturns<-matrix(rnorm(10,1.01^(1/12)-1,0.01/(5*sqrt(12))),nrow=10,ncol=1)

for(i in 2:5){

  fakereturns <- cbind(fakereturns,matrix(rnorm(10,(1+i/100)^(1/12)-1,i/(500*sqrt(12))),nrow=10,ncol=1))
}

fakedates<-as.Date(as.yearmon(seq.Date(as.Date('2019-01-01'),by='month',length.out = 10)),frac=1)
R<-xts(fakereturns,fakedates)
names(R)<-c("stock1","stock2","stock3","stock4","stock5")

#Set up portfolio spec

pspec <- portfolio.spec(assets=names(R))
pspec <- add.constraint(pspec,type="weight_sum", min_sum=1, max_sum=1)
pspec <- add.constraint(pspec,type="box",min=rep(0,5),max=rep(1,5))

#Chart efficient frontier using historical data

portfolio<-pspec
eff_example <- create.EfficientFrontier(R=R, portfolio=portfolio, type="mean-StdDev")
chart.EfficientFrontier(eff_example, match.col="StdDev",type="l")

#(i) Specify much higher expected returns to make the frontier rise

exp.returns <- (1+seq(0.06,0.1,by=0.01))^(1/12)-1
num_assets <- length(exp.returns)
momentargs <- list()
momentargs$mu <-  matrix(exp.returns, nrow=num_assets, ncol=1 )

#Plot (i) as red circles -- why are these not above the first frontier?

eff_example_moments <- create.EfficientFrontier(R=R, portfolio=portfolio, type="mean-StdDev", momentargs=momentargs)
extract<-eff_example_moments$frontier
points(extract[,1]~extract[,2],col="red")

#(ii) Zero out the highest-returning asset's expected return to see what happens

exp.returns <- (1+c(0.01,0.02,0,0.04,0))^(1/12)-1
num_assets <- length(exp.returns)
momentargs <- list()
momentargs$mu <-  matrix(exp.returns, nrow=num_assets, ncol=1 )

#Plot (ii) as green circles -- why are these on the first frontier?

eff_example_moments <- create.EfficientFrontier(R=R, portfolio=portfolio, type="mean-StdDev", momentargs=momentargs)
extract<-eff_example_moments$frontier
points(extract[,1]~extract[,2],col="green")

#(iii) Reverse the order of expected returns to see what happens

exp.returns <- (1+seq(0.05,0.01,by=-0.01))^(1/12)-1
num_assets <- length(exp.returns)
momentargs <- list()
momentargs$mu <-  matrix(exp.returns, nrow=num_assets, ncol=1 )

#Plot (iii) as blue circles -- now we are off the original frontier, but why?

eff_example_moments <- create.EfficientFrontier(R=R, portfolio=portfolio, type="mean-StdDev", momentargs=momentargs)
extract<-eff_example_moments$frontier
points(extract[,1]~extract[,2],col="blue")
legend("bottomright",legend=c("Rtns increased by 0.05 annualised","Some zeroed out","Exp rtns reversed"),lwd=1,col=c(2,3,4))
4

1 回答 1

0

回答我自己的问题。我认为这里的基本问题是,如果指定了返回目标$mu,则列表的元素moments仅通过函数传递给底层优化器。optimize.portfolio如果指定了风险目标,$mu则不使用。

为了建立一个有效的边界,我optimize.portfolio通过添加一些代码来破解该函数$mu,如下所示:

 ## A line of existing code to show where I put this

 moments <- list(mean = rep(0, N))

 ## My added bit, straight after the above

if (!is.null(mout$mu)) {
  moments[["mean"]] <- as.vector(mout$mu)
}

## My bit ends

然后,我可以通过最小化给定目标回报的标准偏差来进行优化。然后我遍历目标返回以创建一个有效的边界(而不是使用create.EfficientFrontier函数)。

于 2020-04-24T16:09:41.723 回答