Parameter Insensitive Models

In my opinion there are two enemies to successful system development. One is the “exploitability” of the anomaly  you are trying to extract profit from. The other is the parameters that you choose to exploit the anomaly with. The “exploitability” aspect is something you can’t have much control over as the profitability of any anomaly is in constant flux. One example is the profitability of trend following in general. When markets are choppy, its tough for any trend followers to extract sizeable profits.

The other area that you have absolute control over is the parameters with which you choose to trade with. The more varied the parameter selection, the more robust you are as the diversification increase will reduce probability of loss if any parameters were to suffer lack of performance. Parameters here can literally be the days you choose to employ a MA crossover strategy or it can extend to similar models like breakouts.

In the following experiment, I will test the performance of 5 different models. They are all mean reversion in nature.

Model1 (rsi1): RSI(2) 50/50

Model2 (rsi2): RSI(2) Buy: <30 Short: >70

Model3 (rsi3): RSI(2) Buy: <30 Sell: >50 Short: >70 Cover: <50

Model4 (no.reb): no rebalance but equal weight

Model5 (reb): equal weight rebalance weekly

Parameter insensitive models rest on the idea that no one knows what the future holds and how each parameter will perform. Instead of just relying on past data to select something that “was” consistent, parameter insensitive models try to avoid putting all eggs in one basket. The following is the equity curve of the strategy.

The focus should be on the bold equity curve which rebalances weekly. From the graph, it is very much correlated with the other equity curves, but it is smoother than individual strategies equity curve. What I am trying to convey here is that return to any strategy is attributed to the underlying health of the anomaly (something you cannot control) plus the efficiency of the parameters that are used to extract profit (something you have control over). The next chart is the drawdown

If we unfortunately chose to trade rsi2 (blue), our drawdowns will be markedly different.  Next a stacked horizon plot of rolling 252 day return

The first three are the models rsi1, rsi2, rsi3 and the third and fourth are no rebalance and rebalance. As you can see the overall performance is reduced, but in times when certain individual models underperform, the aggregate rebalancing model is able to mitigate it quite successfully.  An finally, the numbers…

One little experiment cannot prove anything. I am still trying the idea out in many different ways and hope that through further research, I will arrive at some more concrete conclusions.

# RSI Parameter insensitive Model
# test out rebalancing equal wait verses holding constant weight
# correctly set working directory and import in your own equity curves
# for blending, I passed in three equity curves for blending

data<-read.csv("rsi.csv") #set your own input files

#conversion to zoo object
data$date<-as.Date(data$date,"%Y-%m-%d")
rsi2.50.50<-zoo(data$rsi2.50,data$date)
rsi2.extreme<-zoo(data$rsi2.extreme,data$date)
rsi2.semi<-zoo(data$rsi2.semi,data$date)
data<-merge(rsi2.50.50,rsi2.extreme)
data<-merge(data,rsi2.semi)

names(data)<-c("rsi1",'rsi2','rsi3')
ret<-ROC(data)
ret[is.na(ret)]<-0

#normalize equity curves
ret$rsi1.equity<-cumprod(1+ret$rsi1) #simulated equity
ret$rsi2.equity<-cumprod(1+ret$rsi2)
ret$rsi3.equity<-cumprod(1+ret$rsi3)
ret$equity<-ret$rsi1.equity+ret$rsi2.equity+ret$rsi3.equity #add them together

ret$equity<-ROC(ret$equity)
ret$equity[is.na(ret$equity)]<-0
ret$equity<-cumprod(1+ret$equity)

rsi.equity1<-ret[,-(1:3)] #same allocation through time
rsi.equity2<-as.xts(rsi.equity1[,-4])

###############################
#Rebalancing of equity
###############################
# Load Systematic Investor Toolbox (SIT)
setInternet2(TRUE)
con = gzcon(url('https://github.com/systematicinvestor/SIT/raw/master/sit.gz', 'rb'))
source(con)
close(con)

#*****************************************************************
# prep input
#******************************************************************
data <- list(prices=rsi.equity2,
 rsi1=rsi.equity2$rsi1,
 rsi2=rsi.equity2$rsi2,
 rsi3=rsi.equity2$rsi3) #need to create new list to store stuff
#weight with n column as input data
data$weight<-rsi.equity2
data$weight[!is.na(data$weight)]<- NA
#execution price
data$execution.price<-rsi.equity2
data$execution.price[!is.na(data$execution.price)]<-NA
#dates
data$dates<-index(rsi.equity2)

#*****************************************************************
# Rebalancing Algo
#******************************************************************
prices = data$prices
nperiods = nrow(prices)
target.allocation = matrix(c(0.33,0.33,0.33), nrow=1)

# Rebalance periodically
models = list()

period<-'weeks' #change to whatever rebalancing preiod you want
data$weight[] = NA
data$weight[1,] = target.allocation

period.ends = endpoints(prices, period)
period.ends = period.ends[period.ends > 0]
data$weight[period.ends,] = repmat(target.allocation, len(period.ends), 1)

capital = 100000
data$weight[] = (capital / prices) * data$weight

#this works oly when your input prices are object XTS rather than zoo
models[[period]] = bt.run(data, type='share', capital=capital)

#*****************************************************************
# Create Report
#******************************************************************
#all 5 equity curves
equity1<-merge(rsi.equity1,models$weeks$equity)
names(equity1)<-c('rsi1','rsi2','rsi3','no.reb','reb')
equity1<-as.xts(equity1)

#print out all the strategies return
for(i in 1:ncol(equity1)
{
 ret<-ROC(equity1[,i])
 ret[is.na(ret)]<-0
 ret<-as.xts(ret)
 dd<-Drawdowns(ret,geometric=T) #
 print(compute.cagr(equity1[,i]))
 print(maxDrawdown(as.xts(ret)))
 print((compute.cagr(equity1[,1]))/(maxDrawdown(as.xts(ret))))
 print(compute.sharpe(ret))
}

ret<-ROC(equity1,252)
horizonplot(ret,origin=0,scales = list(y = list(relation = "same")),colorkey=T)

df<-equity1
df <- data.frame( time=index(df),rsi1=df$rsi1,rsi2=df$rsi2,rsi3=df$rsi3,no.reb=df$no.reb,reb=df$reb)
#plot Equity

ggplot(df,aes(df$time)) +
 geom_line(aes(y=rsi1,colour="rsi1")) +
 geom_line(aes(y=rsi2,colour="rsi2")) +
 geom_line(aes(y=rsi3,colour="rsi3")) +
 geom_line(aes(y=no.reb,colour="no.reb")) +
 geom_line(aes(y=reb,colour="reb"),size=1.2)
#plot drawdown
df1<-merge(dd1,dd2,dd3,dd4,dd5)
df1<-data.frame( time=index(df1),rsi1=df1$rsi1,rsi2=df1$rsi2,rsi3=df1$rsi3,no.reb=df1$no.reb,reb=df1$reb)

ggplot(df1,aes(df$time)) +
 geom_line(aes(y=rsi1,colour="rsi1")) +
 geom_line(aes(y=rsi2,colour="rsi2")) +
 geom_line(aes(y=rsi3,colour="rsi3")) +
 geom_line(aes(y=no.reb,colour="no.reb")) +
 geom_line(aes(y=reb,colour="reb"),size=1.2)
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s