The data is from Apr 16, 2010 to Aug 26, 2016
1. CSI300 vs A50
1) Transform:
The contract multiplier for CSI300 is CNY 300, the contract multiplier for A50 is USD 1,so:
If we want to do the arbitraging, we should do some conversion:
Set:
A50^ = A50 * USDCNY
CSI300^ = CSI300 * 300
Then calculate the linear fitting model about these two variants:
2) The formula:
CSI300^ = 16.495 * A50^ - 56100.18 # the correlation between A50 and CSI300 is 96.13% #
So the arbitrage portfolio is:
33 lots A50 vs 2 lots CSI300
3) The Chart-1:(CSI300^ & A50^ linear fitting model)
As shown in the picture above, because of all tickets in A50 Index being included in CSI300, the prediction interval is quite narrow as samples overlapping.
4) Arbitrage strategy:
Set : Difference = 2* CSI300^ – 33*A50^
The arbitrage strategy as follows:
While CSI300^: ( upr – real )/real < 1%, that is say, CSI300 is over-valued ;short 2 lots CSI300, long 33 lots A50.
( lwr - real)/real > -1%, that is say, CSI300 is under-valued; long 2 lots CSI300, short 33 lots A50.
And when real meet fit, close the position.
As the picture followed:
The yellow lines is the trend of Difference (2* CSI300^ – 33*A50^)
The green points mean CSI300 is under-valued, and we long CSI300,short A50.
The red points mean that CSI300 is over-valued, and we short CSI300, long A50.
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.
And the starting points showed in the price trend. (Green points: long CSI300,short A50; Orange points: short CSI300,long A50 )
We can see that the total long chances is 31 times while the total short chances is 50 times since 16,April 2010 to now.
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