问题
I want to reallocate a strategy portfolio at specific dates:
require(PerformanceAnalytics)
require(TTR)
require(quantmod)
Get asset prices and obtain the daily discrete Returns
tickers = c("ABI.BR","AI.PA","AIR.PA","ALV.DE","ASML.AS")
getSymbols(tickers, from="2012-01-01", to="2013-12-01")
close.prices = do.call(merge, lapply(tickers, function(x) Cl(get(x))))
colnames(close.prices) = c("Anheuser-Busch InBev",
"L'Air Liquide","AIRBUS GROUP","Allianz","ASML HLDG")
assets.ret = ROC(close.prices,type="discrete")[-1]
Now I obtain RSI signals by applying the RSI function to each asset
rsi.fct = function(x) RSI(x, n=20, maType = SMA)
rsi = xts(apply(close.prices, 2, rsi.fct),
order.by=index(rsi.fct(close.prices[,1]) ) )
> tail(rsi)
Anheuser-Busch InBev L'Air Liquide AIRBUS GROUP Allianz ASML HLDG
2013-11-22 51.15171 49.36494 60.25836 61.07143 46.84159
2013-11-25 54.95495 50.82237 63.54717 61.07143 49.63168
2013-11-26 49.65470 52.55102 58.29563 58.18182 48.59023
2013-11-27 54.60575 61.81980 57.94677 62.05674 52.11640
2013-11-28 46.52778 60.76994 57.85061 63.35616 45.70000
2013-11-29 50.99905 61.90476 56.09756 65.49296 48.82479
The strategy is as follows: I buy the asset when the RSI is < 30 and do not buy when RSI >= 30
ret.mat.rsi = lag(ifelse (rsi < 30, 1, 0))*assets.ret
Now this is the part where I have problems. The returns from the ret.mat.rsi are daily returns. Assume that I want to look at the rsi matrix at the first day of the month e.g.
> rsi[110]
Anheuser-Busch InBev L'Air Liquide AIRBUS GROUP Allianz ASML HLDG
2012-06-01 39.66126 31.1599 30.39443 17.17647 43.85172
I want to buy the first 4 assets equally weighted into my portfolio since their RSI is below 30 and leave the positions unchanged for the rest of the month (regardless of further RSI signals) until the first day of the next month:
> rsi[131]
Anheuser-Busch InBev L'Air Liquide AIRBUS GROUP Allianz ASML HLDG
2012-07-02 84.69529 73.87205 66.25561 74.52642 71.65021
where I choose to buy none of the assets.
The whole question is now how to elegantly code an automatic reallocation of the portfolio at specific dates, i.e. at the beginning of each month (could also be each week or every three weeks). The portfolio return should only consist of those assets that fulfill the indicator condition (here RSI < 30) at the reallocation date.
回答1:
How I would have coded your example:
require(quantmod)
tickers <- c("ABI.BR","AI.PA","AIR.PA","ALV.DE","ASML.AS")
myEnv <- new.env()
getSymbols(tickers, from="2012-01-01", to="2013-12-01", env=myEnv)
close.prices <- do.call(merge, eapply(myEnv, Cl))
close.prices <- close.prices[,pmatch(tickers,colnames(close.prices))]
colnames(close.prices) <- c("Anheuser-Busch InBev",
"L'Air Liquide","AIRBUS GROUP","Allianz","ASML HLDG")
assets.ret <- ROC(close.prices,type="discrete")[-1]
rsi.fct <- function(x) RSI(x, n=20, maType = SMA)
rsi <- xts(apply(close.prices, 2, rsi.fct), index(close.prices))
Now, to answer your question, use GSee's startpoints function to get the first RSI value for each month. startpoints
allows you to choose any number of weeks, months, quarters, etc as the rebalancing period.
startpoints <- function (x, on = "months", k = 1) {
head(endpoints(x, on, k) + 1, -1)
}
# get the signal at the beginning of each month
rsi.signal <- lag(ifelse(rsi < 30, 1, 0))[startpoints(rsi),]
# rsi.signal is monthly; we need a daily series where each day has the
# value from the first day of the month, so we merge with an empty xts
# object that has the daily index and use na.locf to fill the gaps
rsi.signal <- merge(rsi.signal, xts(,index(rsi)), fill=na.locf)
# now calculate returns
rsi.ret <- rsi.signal * assets.ret
来源:https://stackoverflow.com/questions/27375105/equally-weighted-reallocation-of-stock-portfolio-at-specific-dates-according-to