Equally Weighted Reallocation of Stock Portfolio a

2019-05-22 02:42发布

问题:

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