FangQuant › Strategies

The arbitraging strategy between CSI300 and SSE50

Fang submitted 2017-04-15 01:11:24

The data is from Aug 16, 2015 to Aug26, 2016

1. CSI300 vs SSE50

The contract multiplier for CSI300 is CNY 300, the contract multiplier for SSE50 is also CNY300, so:

Can do the linear fitting directly:

1) The formula:

CSI300=1.569*SSE50 - 160.375 # the correlation between CSI300 and SSE50 is 98.73% #

So the arbitrage portfolio is:

2 lots CSI300 vs 3 lots SSE50

2) Arbitrage strategy:

Set : Difference = 2* CSI300*300 – 3*SSE50*300

The arbitrage strategy as follows:

While CSI300: ( upr – real )/real < 1%, that is say, CSI300 is over-valued ;short 2 lots CSI300, long 3 lots SSE50.

( lwr - real)/real > -1%, that is say, CSI300 is under-valued; long 2 lots CSI300, short 3 lots SSE50.

And when real meet fit, close the position.


3) The Chart-2: (CSI300 & SSE50)*300 linear fitting model:


As shown in the picture above, because of all tickets in SSE50 Index being included in CSI300, the prediction interval is quite narrow as samples overlapping.


4) Strategy chart:


As the picture above:

The yellow lines is the trend of difference (2* CSI300 – 3*SSE50)*300

The green points mean CSI300 is under-valued, and we long CSI300,short SSE50.

The red points mean that CSI300 is over-valued, and we short CSI300, long SSE50.

The blue line below present the changing of the positions we build due to the strategy.( up one point means we long the spread one time, down one point means we short the spread one time)

The dark green and red lines below present the return and the maximum drawback of the strategy respectively.

We can see that the total long chances is 39 times while the total short chances is 40 times since 16,Apri 2015 to now.

And the starting points showed in the price trend.(Green points: long CSI300,short SSE50; Orange points: short CSI300,long SSE50 )

require(quantstrat)

strategy.lm<-function(file){
  rt<-read.table(file,head=TRUE)
  x<-as.numeric(rt[,2])
  y<-as.numeric(rt[,3])
  xname<-colnames(rt)[2]
  yname<-colnames(rt)[3]
  corvalue<-cor(y,x)
  lm1<-lm(y~x)
  intercept1<-coefficients(lm1)[1]
  weight1<-coefficients(lm1)[2]
  cat(yname,"=",intercept1,"+",weight1,"*",xname,"\n" ,seq="")
  e<-residuals(lm1)
  lm2<-lm(log(resid(lm1)^2)~x)
  lm3<-lm(y~x,weights=1/abs(e))
  intercept3<-coefficients(lm3)[1]
  weight3<-coefficients(lm3)[2]
  cat(yname,"=",intercept3,"+",weight3,"*",xname,"\n" ,seq="")
  dfp<-predict(lm3,interval = "prediction")
  mdf<-cbind(dfp,y)
  xdate<-as.Date(rt[,1])
  ylab<-paste(yname,"(real/prediction)")
  ymax<-max(mdf)
  ymin<-min(mdf)
  ymax<-ymax+(ymax-ymin)*0.2
  plot(xdate,mdf[,4],type="l",col="red",xlab="date",cex.axis=0.7,ylab=ylab,ylim=c(ymin,ymax),xaxt="n")
  lines(xdate,mdf[,1],col='grey')
  lines(xdate,mdf[,2],col='blue')
  lines(xdate,mdf[,3],col='purple')
  step=ceiling(length(xdate)/10)
  axisx=xdate[seq(1,length(xdate),step)]
  axis(1,axisx,format(axisx,"%d/%m/%y"),cex.axis=0.7)
  legend("top",c("real","fit","lwr","upr"),cex = 0.7,col=c("red","grey","blue","purple"),lty=c(1,1,1),horiz=T)
  return(mdf)
}
trade.fit.point<-function(date,mdf,yname){
  mdf=as.data.frame(mdf)
  ylab<-paste(yname,"(real/prediction)")
  ymax<-max(mdf)
  ymin<-min(mdf)
  ymax<-ymax+(ymax-ymin)*0.2
  plot(xdate,mdf$y,type="l",col="red",xlab="date",cex.axis=0.7,ylab=ylab,ylim=c(ymin,ymax),xaxt="n")
  lines(xdate,mdf$fit,col='grey')
  lines(xdate,mdf$lwr,col='blue')
  lines(xdate,mdf$upr,col='purple')
  step=ceiling(length(xdate)/10)
  axisx=xdate[seq(1,length(xdate),step)]
  axis(1,axisx,format(axisx,"%d/%m/%y"),cex.axis=0.7)
  legend("top",c("real","fit","lwr","upr"),cex = 0.7,col=c("red","grey","blue","purple"),lty=c(1,1,1),horiz=T)
  sell=xdate[(mdf$y-mdf$fit)/mdf$y>0.06]
  cat("sell number:",length(sell),"\n")
  buy=xdate[(mdf$y-mdf$fit)/mdf$y<(-0.06)]   
  cat("buy number:",length(buy),"\n")
  cat("total number:",length(xdate),"\n")
  points(xdate[xdate%in%sell],mdf$y[xdate%in%sell], pch= 6,col="orange",cex=0.85)
  points(xdate[xdate%in%buy],mdf$y[xdate%in%buy], pch= 2,col="green",cex=0.85)
  #return(mdf)
}

nearfit<-function(x=rt){
  ind<-(rt$y-rt$fit)/rt$y
  colnames(ind)<-"near.Fit"
  return(ind)
}

trade.fit.run <- function(xdate,rt){
  initDate=xdate[1]
  endDate=xdate[length(xdate)]
  currency("RMB")
  stock.str="rt"
  stock(stock.str, currency = "RMB" ,multiplier = 1)
  portfolio.st="bbands"
  account.st="bbands"
  initPortf(portfolio.st,symbols = stock.str, initDate = initDate )
  initAcct(account.st,portfolios = 'bbands', initDate = initDate)
  initOrders(portfolio = portfolio.st, initDate = initDate)

  q.strategy="myStrategy"
  startBands<-strategy(q.strategy, store = TRUE)
  add.indicator(q.strategy, name = "nearfit", 
                arguments = list(x=quote(mktdata)), label="near.Fit")
  add.signal(q.strategy, name = "sigThreshold", 
             arguments = list(column="near.Fit",threshold=0.06,relationship="gt"),label = "y.gt.UpperBand")
  add.signal(q.strategy, name = "sigCrossover", 
             arguments = list(columns=c("y","fit"),relationship="lt"),label = "y.lt.Mid")
  add.signal(q.strategy, name = "sigThreshold", 
             arguments = list(column="near.Fit",threshold=-0.06,relationship="lt"),label = "y.lt.LowerBand")
  add.signal(q.strategy, name = "sigCrossover", 
             arguments = list(columns=c("y","fit"),relationship="gt"),label = "y.gt.Mid")
  add.rule(q.strategy, name="ruleSignal", prefer="diff",
           arguments = list(sigcol="y.gt.UpperBand", sigval=TRUE,
                            orderqty=-1,ordertype="market",
                            orderside="short", threshold=NULL),
           type="enter")
  add.rule(q.strategy, name="ruleSignal", prefer="diff",
           arguments = list(sigcol="y.lt.Mid", sigval=TRUE,
                            orderqty="all",ordertype="market",
                            orderside="short", threshold=NULL),
           type="exit")
  add.rule(q.strategy, name="ruleSignal", prefer="diff",
           arguments = list(sigcol="y.lt.LowerBand", sigval=TRUE,
                            orderqty=1,ordertype="market",
                            orderside="long", threshold=NULL),
           type="enter")
  add.rule(q.strategy, name="ruleSignal", prefer="diff",
           arguments = list(sigcol="y.gt.Mid", sigval=TRUE,
                            orderqty="all",ordertype="market",
                            orderside="long", threshold=NULL),
           type="exit")
  SD=2
  N=20
  out<-try(applyStrategy(strategy = q.strategy, portfolios = portfolio.st, 
                         parameters=list(sd=SD,n=N)))
  getOrderBook("bbands")
  updatePortf(Portfolio = "bbands")#, Dates=paste("::",as.Date(Sys.time()),seq=""))
  chart.Posn(Portfolio = "bbands", Symbol = stock.str)
}

Copyright by FangQuant.com



Currently no Comments.