使用套利合约进行对冲优点是双向开仓速度快, 滑点少, 策略实盘测试通过.
function Hedge(q, e, initAccount, symbol, hedgeSpread, coverSpread, rHedgeSpread, rCoverSpread) {
var self = {}
self.q = q
self.initAccount = initAccount
self.status = 0
self.symbol = symbol
self.e = e
self.isBusy = false
self.hedgeSpread = hedgeSpread
self.coverSpread = coverSpread
self.rHedgeSpread = rHedgeSpread
self.rCoverSpread = rCoverSpread
self.insDetail = null;
self.opAmount = OpAmount
var arr = symbol.split('&');
if (arr.length != 2) {
throw "合约名称必须是套利合约";
}
self.pairA = arr[0].replace('SPD ', '').replace('SP ', '');
self.pairB = arr[1];
self.reset = function() {
self.isBusy = false;
self.status = 0;
}
self.init = function() {
LogStatus("正在尝试恢复仓位");
var positions = _C(exchange.GetPosition);
for (var i = 0; i < positions.length; i++) {
if (positions[i].ContractType == self.symbol) {
self.status = (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) ? 1 : 2;
break;
}
}
Log("恢复状态成功, 当前状态为: ", ["闲置", "多仓", "空仓"][self.status]);
LogStatus("Running");
}
self.poll = function() {
if (self.isBusy || (!exchange.IO("status")) || (!$.IsTrading(self.symbol))) {
Sleep(1000);
return
}
var insDetail = exchange.SetContractType(self.symbol)
if (!insDetail) {
Sleep(1000);
return
}
if (self.insDetail == null) {
self.insDetail = insDetail;
Log("合约", insDetail.InstrumentName, "一手", insDetail.VolumeMultiple, "份, 最大下单量", insDetail.MaxLimitOrderVolume);
}
var ticker = exchange.GetTicker()
if (!ticker) {
Sleep(1000);
return
}
// _D()是内置时间格式化函数, 不传参就是取当前时间, 可以传时间戳
LogStatus(_D(), self.pairA, "卖", self.pairB, "买", ticker.Sell, " -- ", self.pairA, "买", self.pairB, "卖", ticker.Buy)
var action = 0; // 1: A sell B buy 2: A buy B sell
if (self.status == 0) {
if (ticker.Buy >= self.hedgeSpread) {
Log("开仓 ", self.pairA, "卖", self.pairB, "买", ticker.Buy, '#ff0000')
action = 2
} else if (ticker.Sell <= self.rHedgeSpread) {
Log("开仓 ", self.pairA, "买", self.pairB, "卖", ticker.Sell, '#ff0000')
action = 1
}
} else if (self.status == 2 && ticker.Sell <= self.coverSpread) {
Log("平仓", self.pairA, "买", self.pairB, "卖", ticker.Sell, '#ff0000')
action = 2
} else if (self.status == 1 && ticker.Buy >= self.rCoverSpread) {
Log("平仓", self.pairA, "卖", self.pairB, "买",ticker.Buy, '#ff0000')
action = 1
}
if (action == 0) {
return
}
self.isBusy = true
var taskDirection = "";
if (action == 1) {
taskDirection = self.status == 0 ? "buy" : "closebuy";
} else if (action == 2) {
taskDirection = self.status == 0 ? "sell" : "closesell";
}
self.q.pushTask(self.e, self.symbol, taskDirection, self.opAmount, function(task, ret) {
self.isBusy = false
if (task.action == "sell") {
self.status = 2
} else if (task.action == "buy") {
self.status = 1
} else {
self.status = 0
var account = _C(exchange.GetAccount)
LogProfit(account.Balance - self.initAccount.Balance, account)
}
})
}
return self
}
function main() {
if (IsVirtual()) {
throw "回测不支持套利合约, 请用模拟盘或者实盘测试"
}
SetErrorFilter("ready|login|timeout")
Log("正在与交易服务器连接...")
while (!exchange.IO("status")) Sleep(1000);
Log("与交易服务器连接成功")
var initAccount = _C(exchange.GetAccount)
Log(initAccount)
var n = 0
var q = $.NewTaskQueue(function(task, ret) {
Log(task.desc, ret ? "成功" : "失败", ret)
})
if (Reset) {
LogReset()
LogProfitReset()
}
if (CoverAll) {
Log("开始平掉所有残余仓位...");
$.NewPositionManager().CoverAll();
Log("操作完成");
}
var t = Hedge(q, exchanges[0], initAccount, Symbol, HedgeSpread, CoverSpread, RHedgeSpread, RCoverSpread)
if (AutoRestore) {
t.init();
}
while (true) {
var cmd = GetCommand();
if (cmd == 'CoverALL') {
Log("开始平掉仓位...");
$.NewPositionManager().CoverAll();
t.reset();
}
q.poll()
t.poll()
}
}