ФОН: Интересно, можете ли вы мне помочь. Я знаком с оптимизацией портфеля. Я не эксперт, но я обычно строю свои собственные оптимизаторы для создания эффективных границ, основанных на четырехпрограммных или численных методах. Я только начинаю использовать 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))