Почему существуют пропуски в средней границе эффективности PortfolioAnalytics?
Я получаю неожиданные результаты от функции create.EfficientFrontier в пакете PortfolioAnalytics (v1.0.3636). Я пытаюсь создать эффективную границу, используя оптимизацию среднего отклонения. Все мои ограничения линейны. Я установил n.portfolios = 100 в вызове. Он возвращает только 32 портфеля, показанных в таблице и на графике ниже. Неожиданное поведение заключается в том, что на границе есть пробелы. Несмотря на то, что разрывов довольно много, один из самых больших - между результатом.62 и результатом.94. Существует большой скачок в доходах и риске между двумя точками. Это то, что я имею в виду под разрывом. Я не понимаю, например, почему нет точек со средним значением около 0,04. Я могу использовать функцию optimize.portfolio с целью 0,04 и найти решение. Вектор cov 54x54, поэтому я не включил данные. Если кому-то это понравится, я опубликую его и вектор рет.R<-xts(mvrnorm(n=120,cmf.tax.adjusted$ret,cmf.tax.adjusted$cov,
empirical=TRUE),order.by=seq(as.Date("2000/12/31"),by="month",length.out=120))
eff<-create.EfficientFrontier(R=R,portfolio=pspec,
type="mean-sd",match.col="StdDev",n.portfolios=100)
А вот код для получения возврата = 0,04
pspec1<-pspec
pspec1<- add.objective(portfolio=pspec1, type="return", name="mean",target=.04,indexnum=1)
opt1<-optimize.portfolio(R,pspec1,optimize_method="ROI")
Pspec показывается после эффективной границы
32 очка, полученных с помощью create.EfficientFrontier
mean StdDev
result.1 0.004818413 0.03159756
result.2 0.005285545 0.03159756
result.3 0.005752677 0.03159757
result.9 0.008555470 0.03229847
result.10 0.009022602 0.03257118
result.11 0.009489734 0.03287380
result.12 0.009956866 0.03319658
result.13 0.010423998 0.03356550
result.23 0.015095319 0.04085273
result.25 0.016029583 0.04269109
result.26 0.016496715 0.04363220
result.27 0.016963847 0.04458671
result.29 0.017898112 0.04653263
result.31 0.018832376 0.04855024
result.32 0.019299508 0.04958316
result.33 0.019766640 0.05063005
result.52 0.028642150 0.07234101
result.53 0.029109282 0.07355126
result.54 0.029576414 0.07476445
result.55 0.030043546 0.07598045
result.56 0.030510678 0.07719941
result.57 0.030977810 0.07842371
result.59 0.031912074 0.08090880
result.60 0.032379206 0.08217014
result.61 0.032846338 0.08344324
result.62 0.033313470 0.08472759
result.94 0.048261697 0.13508563
result.95 0.048728829 0.13692166
result.96 0.049195961 0.13901611
result.97 0.049663094 0.14122860
result.98 0.050130226 0.14345820
result.99 0.050597358 0.14571323
pspec:
$assets
USCash-taxed STUSTsy-taxed LTUSTsy-taxed USTIPs-taxed USCore-taxed
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
GlobalCore-taxed HiYld-taxed BankLoans-taxed EMNonLclDebt-taxed EMLocalDebt-taxed
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
EMCurrency-taxed Commodities-taxed REIT-taxed USLarge-taxed USSmall-taxed
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
EAFEEquity-taxed EMEquity-taxed USCash-defer STUSTsy-defer LTUSTsy-defer
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
USTIPs-defer USCore-defer GlobalCore-defer HiYld-defer BankLoans-defer
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
EMNonLclDebt-defer EMLocalDebt-defer EMCurrency-defer Commodities-defer REIT-defer
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
USLarge-defer USSmall-defer EAFEEquity-defer EMEquity-defer USCash-exempt
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
STUSTsy-exempt LTUSTsy-exempt USTIPs-exempt USCore-exempt GlobalCore-exempt
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
HiYld-exempt BankLoans-exempt EMNonLclDebt-exempt EMLocalDebt-exempt EMCurrency-exempt
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
Commodities-exempt REIT-exempt USLarge-exempt USSmall-exempt EAFEEquity-exempt
0.01960784 0.01960784 0.01960784 0.01960784 0.01960784
EMEquity-exempt
0.01960784
$enabled_constraints
$enabled_constraints[[1]]
An object containing 6 constraints.
Some constraints are of type nonlinear.
$enabled_constraints[[2]]
An object containing 5 constraints.
Some constraints are of type nonlinear.
$enabled_constraints[[3]]
An object containing 6 constraints.
Some constraints are of type nonlinear.
$disabled_constraints
list()
$enabled_objectives
$enabled_objectives[[1]]
$name
[1] "mean"
$target
NULL
$arguments
list()
$enabled
[1] TRUE
$multiplier
[1] -1
$call
add.objective(portfolio = pspec, type = "return", name = "mean")
attr(,"class")
[1] "return_objective" "objective"
$enabled_objectives[[2]]
$name
[1] "StdDev"
$target
NULL
$arguments
$arguments$portfolio_method
[1] "single"
$enabled
[1] TRUE
$multiplier
[1] 1
$call
add.objective(portfolio = pspec, type = "risk", name = "StdDev")
attr(,"class")
[1] "portfolio_risk_objective" "objective"
$disabled_objectives
list()
attr(,"class")
[1] "summary.portfolio"
1 ответ
Можете ли вы попробовать это таким образом?
# Economist at Large
# Modern Portfolio Theory
# Use solve.QP to solve for efficient frontier
# Last Edited 5/3/13
# This file uses the solve.QP function in the quadprog package to solve for the
# efficient frontier.
# Since the efficient frontier is a parabolic function, we can find the solution
# that minimizes portfolio variance and then vary the risk premium to find
# points along the efficient frontier. Then simply find the portfolio with the
# largest Sharpe ratio (expected return / sd) to identify the most
# efficient portfolio
library(stockPortfolio) # Base package for retrieving returns
library(ggplot2) # Used to graph efficient frontier
library(reshape2) # Used to melt the data
library(quadprog) #Needed for solve.QP
# Create the portfolio using ETFs, incl. hypothetical non-efficient allocation
stocks <- c(
"VTSMX" = .0,
"SPY" = .20,
"EFA" = .10,
"IWM" = .10,
"VWO" = .30,
"LQD" = .20,
"HYG" = .10)
# Retrieve returns, from earliest start date possible (where all stocks have
# data) through most recent date
returns <- getReturns(names(stocks[-1]), freq="week") #Currently, drop index
#### Efficient Frontier function ####
eff.frontier <- function (returns, short="no", max.allocation=NULL,
risk.premium.up=.5, risk.increment=.005){
# return argument should be a m x n matrix with one column per security
# short argument is whether short-selling is allowed; default is no (short
# selling prohibited)max.allocation is the maximum % allowed for any one
# security (reduces concentration) risk.premium.up is the upper limit of the
# risk premium modeled (see for loop below) and risk.increment is the
# increment (by) value used in the for loop
covariance <- cov(returns)
print(covariance)
n <- ncol(covariance)
# Create initial Amat and bvec assuming only equality constraint
# (short-selling is allowed, no allocation constraints)
Amat <- matrix (1, nrow=n)
bvec <- 1
meq <- 1
# Then modify the Amat and bvec if short-selling is prohibited
if(short=="no"){
Amat <- cbind(1, diag(n))
bvec <- c(bvec, rep(0, n))
}
# And modify Amat and bvec if a max allocation (concentration) is specified
if(!is.null(max.allocation)){
if(max.allocation > 1 | max.allocation <0){
stop("max.allocation must be greater than 0 and less than 1")
}
if(max.allocation * n < 1){
stop("Need to set max.allocation higher; not enough assets to add to 1")
}
Amat <- cbind(Amat, -diag(n))
bvec <- c(bvec, rep(-max.allocation, n))
}
# Calculate the number of loops
loops <- risk.premium.up / risk.increment + 1
loop <- 1
# Initialize a matrix to contain allocation and statistics
# This is not necessary, but speeds up processing and uses less memory
eff <- matrix(nrow=loops, ncol=n+3)
# Now I need to give the matrix column names
colnames(eff) <- c(colnames(returns), "Std.Dev", "Exp.Return", "sharpe")
# Loop through the quadratic program solver
for (i in seq(from=0, to=risk.premium.up, by=risk.increment)){
dvec <- colMeans(returns) * i # This moves the solution along the EF
sol <- solve.QP(covariance, dvec=dvec, Amat=Amat, bvec=bvec, meq=meq)
eff[loop,"Std.Dev"] <- sqrt(sum(sol$solution*colSums((covariance*sol$solution))))
eff[loop,"Exp.Return"] <- as.numeric(sol$solution %*% colMeans(returns))
eff[loop,"sharpe"] <- eff[loop,"Exp.Return"] / eff[loop,"Std.Dev"]
eff[loop,1:n] <- sol$solution
loop <- loop+1
}
return(as.data.frame(eff))
}
# Run the eff.frontier function based on no short and 50% alloc. restrictions
eff <- eff.frontier(returns=returns$R, short="no", max.allocation=.50,
risk.premium.up=1, risk.increment=.001)
# Find the optimal portfolio
eff.optimal.point <- eff[eff$sharpe==max(eff$sharpe),]
# graph efficient frontier
# Start with color scheme
ealred <- "#7D110C"
ealtan <- "#CDC4B6"
eallighttan <- "#F7F6F0"
ealdark <- "#423C30"
ggplot(eff, aes(x=Std.Dev, y=Exp.Return)) + geom_point(alpha=.1, color=ealdark) +
geom_point(data=eff.optimal.point, aes(x=Std.Dev, y=Exp.Return, label=sharpe),
color=ealred, size=5) +
annotate(geom="text", x=eff.optimal.point$Std.Dev,
y=eff.optimal.point$Exp.Return,
label=paste("Risk: ",
round(eff.optimal.point$Std.Dev*100, digits=3),"\nReturn: ",
round(eff.optimal.point$Exp.Return*100, digits=4),"%\nSharpe: ",
round(eff.optimal.point$sharpe*100, digits=2), "%", sep=""),
hjust=0, vjust=1.2) +
ggtitle("Efficient Frontier\nand Optimal Portfolio") +
labs(x="Risk (standard deviation of portfolio)", y="Return") +
theme(panel.background=element_rect(fill=eallighttan),
text=element_text(color=ealdark),
plot.title=element_text(size=24, color=ealred))
ggsave("Efficient Frontier.png")
Ниже приведена ссылка, где вы можете узнать больше о том, что делает код.
http://economistatlarge.com/portfolio-theory/r-optimized-portfolio