使用一些現成的工具套件,我們很容易做投資組合管理:
options(digits=4, scipen=100)
rm(list=ls(all=T))
Sys.setlocale('LC_ALL', 'C')
## [1] "C"
library(fPortfolio)
library(tseries)
library(quantmod)
library(modopt.matlab)
DJ10 = c('MMM', 'AXP', 'AAPL', 'BA', 'CAT', 'CVX',
'CSCO', 'KO', 'XOM', 'GE')
K = length(DJ10)
dd = as.Date(c('2015-10-01','2017-09-30'))
mx = sapply(DJ10, function(x) {
G = getSymbols(x,from=dd[1],to=dd[2],auto.assign=F)
as.numeric(Delt(G[,6])) })[-1,]
names(mx) = DJ10
ts = as.timeSeries(mx)
cons = c('LongOnly')
spec = portfolioSpec()
setNFrontierPoints(spec) = 25
setSolver(spec) = "solveRquadprog"
frontier = portfolioFrontier(ts, spec, cons)
par(cex=0.7)
tailoredFrontierPlot(frontier)
par(cex=0.8)
weightsPlot(frontier,col=rainbow(length(DJ10)))
當然我們也可以使用R的優化(線性規劃)套件,練習自行推算效率前緣和最佳投資組合:
# Minimum Variance Portfolio, MVP
solution <- quadprog(
H = cov(mx), # objective function
f = rep(0, K), # linear terms of objective
A = NULL, # Inequality Constrains (LHS)
b = NULL, # Inequality Constrains (RHS)
Aeq = rep(1, K), # Equality Constrains (LHS)
beq = 1, # Equality Constrains (RHS)
lb = rep(0, K), # lower bound
ub = rep(1, K) # upper bound
)
(portfolio = round(solution$x, 2))
## [1] 0.20 0.14 0.08 0.00 0.00 0.00 0.00 0.46 0.10 0.03
基本上,Markowitz投資組合是一種限制平均報酬的最小變異組合。
# define a optimization function
markowitz <- function(data, mu) {
H = cov(data)
f = rep(0, K)
Aeq = rep(1, K)
beq = 1
A = -as.numeric(colMeans(data))
b = -mu
lb = rep(0, K)
ub = rep(1, K)
solution = quadprog(H, f, A, b, Aeq, beq, lb, ub)
return(round(solution$x, 2))
}
# calculate the frontier
P = 20 # number of points to draw
cm = colMeans(mx)
csd = apply(mx, 2, sd)
mu = c(); sd = c()
for(i in seq(mean(cm), max(cm)*0.99, length.out=P)) {
portfolio = markowitz(mx, i)
mu <- c(mu, mean(portfolio %*% t(mx)))
sd <- c(sd, sd(portfolio %*% t(mx))) }
# plot the frontier
plot(x = sd, y = mu, type='l', col='gold', lwd=3,
ylim=range(cm), xlim=c(min(sd),max(csd)),
xlab="Standard Deviation", ylab="Return",
main="Efficient Frontier")
# points(x = sd, y = mu, col='pink', pch=19)
abline(h=seq(0,0.002,0.00025), v=seq(0, 0.02,0.001), col='lightgray', lty=3)
points(x=csd, y=cm, type='p', col='green', pch=19, cex=1.5)
text(x=csd, y=cm, labels=DJ10, col='darkgreen', pos=2, font=2)