期货中的跨期套利,一般是指做空主力合约并做多次主力合约(或者反之),利用价差的均值回复的性质来获利,问题在于如何度量价差是否偏离正常波动区间。布林带提供了一种思路:把价差当作一个标的,考虑价差的布林带:
入场:
若价差在布林带上轨上方拐头向下,则做空价差;
若价差在布林带下轨下方拐头向上,则做多价差;
出场:
当价差回复到均线或者跌破止损价时,出场。
应用在白糖期货上,从2014/01/01到2016/06/02,5分钟频率,效果如下:
策略代码:
- function Kqtl(ShareNum,Freq,len,len2)
- targetList = traderGetTargetList();
- HandleList = traderGetHandleList();
- global s;
- n = length(targetList);
- for j = 1:2:n
- [~,~,~,~,close1,~,~,~] = traderGetKData(targetList(j).Market,targetList(j).Code,'min',Freq, 0-len, 0,true,'FWard');
- [~,~,~,~,close2,~,~,~] = traderGetKData(targetList(j+1).Market,targetList(j+1).Code,'min',Freq, 0-len, 0,true,'FWard');
- if length(close1)<len+1
- return
- end
- diff = close1-close2;
- mid = mean(diff(1:end-1));
- band = std(diff(1:end-1));
- Upper = mid+2*band;
- Lower = mid-2*band;
- if diff(end)>Upper
- s(j).con1=1;
- elseif diff(end)<Lower
- s(j).con1=-1;
- else
- s(j).con1=0;
- end
-
- s(j).con2 = 0;
- if s(j).con1==1
- if diff(end)<diff(end-1) && diff(end-1)<diff(end-2)
- s(j).con2 = 1;
- end
- end
- if s(j).con1==-1
- if diff(end)>diff(end-1) && diff(end-1)>diff(end-2)
- s(j).con2 = -1;
- end
- end
-
- if s(j).position>0
- if diff(end)>mid || diff(end)<s(j).stopprice
- traderPositionTo(HandleList(1),targetList(j).Market,targetList(j).Code,0,0,'market','close');
- traderPositionTo(HandleList(1),targetList(j+1).Market,targetList(j+1).Code,0,0,'market','close');
- s(j).position = 0;
- end
- end
- if s(j).position<0
- if diff(end)<mid || diff(end)>s(j).stopprice
- traderPositionTo(HandleList(1),targetList(j).Market,targetList(j).Code,0,0,'market','close');
- traderPositionTo(HandleList(1),targetList(j+1).Market,targetList(j+1).Code,0,0,'market','close');
- s(j).position = 0;
- end
- end
-
- if s(j).position==0
- if s(j).con2==-1
- OrderID1=traderDirectBuy(HandleList(1),targetList(j).Market,targetList(j).Code,ShareNum,0,'market','buy');
- OrderID2=traderDirectSell(HandleList(1),targetList(j+1).Market,targetList(j+1).Code,ShareNum,0,'market','buy');
- if OrderID1~=0
- s(j).stopprice=diff(end-2);
- s(j).position = 1;
- end
- end
- if s(j).con2==1
- OrderID1=traderDirectSell(HandleList(1),targetList(j).Market,targetList(j).Code,ShareNum,0,'market','sell');
- OrderID2=traderDirectBuy(HandleList(1),targetList(j+1).Market,targetList(j+1).Code,ShareNum,0,'market','sell');
- if OrderID1~=0
- s(j).stopprice=diff(end-2);
- s(j).position = -1;
- end
- end
- end
- end
- targetList(1).Market = 'CZCE';
- targetList(1).Code = 'SR000';
- targetList(2).Market = 'CZCE';
- targetList(2).Code = 'SR001';
- Freq = 5;
- ShareNum = 10;
- len = 40;
- len2 = 20;
- global s;
- for i = 1:length(targetList)
- s(i).position = 0;
- s(i).openprice = 0;
- end
- %回测
- AccountList(1) = {'FutureBackReplay'};
- traderRunBacktest('KqtlBackTest',@Kqtl,{ShareNum,Freq,len,len2},AccountList,targetList,'min',Freq,20140101,20160602,'FWard');