有几种选择。这是一个constrOptim
from stats
:
#some data
library(quantmod)
library(PerformanceAnalytics)
getReturns <- function(symbols, from='2000-01-01') {
returns <- list()
for (symbol in symbols) { #symbol=symbols[2]
sym = getSymbols(symbol, from = from, adjustOHLC = TRUE, auto.assign = FALSE)
return <- Return.calculate(Ad(sym))
colnames(return) <- gsub("\\.Adjusted", "", colnames(return))
returns[[symbol]] <- return
}
returns <- do.call(cbind, returns)
return(returns)
}
symbols <- c("MSFT","AAPL","AMZN","CSCO","ADBE")
ret <- getReturns(symbols,from="2020-01-01")[-1,]
x = nrow(ret) # periods
N = ncol(ret) # assets
set.seed(1324)
Bench = rnorm(x,0.0015,0.03) #some benchmark
plot(ts(Bench))
# const opt
## needs a feasible starting value
# A'b >= b0 x < 0.4 --> -x >= -.4 x> -0.4 or 0 if not short selling
#
fTE <- function(b,rets,Ben) {
Pret=apply(rets,1,function(rl)sum(rl*b))
sd(Pret-Ben)
}
upblim=0.4
loblim=-0.4
Amat <- matrix(1, 1, N)
Amat <- rbind(Amat,-diag(N)) # upper limit
Amat <- rbind(Amat,diag(N)) # if lower limit
bvec <- c(.9999999,rep(-upblim,N),rep(loblim,N))
# feasable sol
ws=c(3,4,5,6,1)
(ws=ws/sum(ws))
Amat %*% ws >= bvec
(sol <- constrOptim(ws, fTE, NULL, ui = Amat, ci = bvec,rets=ret,Ben=Bench))
sum(sol$par)
pie(abs(sol$par),labels = colnames(ret))
#> data.frame(Assets=colnames(ret),ws=sol$par)
# Assets ws
#1 MSFT -0.13233070
#2 AAPL 0.39999989
#3 AMZN 0.39999997
#4 CSCO 0.26382163
#5 ADBE 0.06850912