请教老师,关于套利,自己系统如何与帮助中的代码结合

老师好! 最近碰到一些代码的问题,特向各位老师请教: 有几个基于产业链的套利系统想在TBQ中用代码实现出来,TBQ的帮助中有关于套利发单的完整的代码,我基本能看懂,但里面的函数调用比较多,如何在系统中应用,始终心里没底。想向老师请教如何把自己的套利系统与TBQ“帮助”中关于套利发单的代码结合起来实现实盘应用,帮助中的具体代码在回帖中。 还有:以前在tb6中,这个策略是基于日线的,利用TBQ帮助中现成的代码直接用在tick上不知行不行? 先谢谢老师! 例如:关于焦炭与焦煤的套利系统 产业关系:炼焦利润大致等于焦炭价格 - 1.4*焦煤价格 - 其他成本 按上述公式以期货价格计算炼焦利润,“其他成本”暂时忽略; 用炼焦利润计算20周期布林线; 开仓:炼焦利润跌破布林线下轨、由下向上穿越布林线下轨的时候,按1:1买入焦炭、卖出焦煤 平仓: 止损条件:设置跟踪止损,任何时候最大亏损1%或利润回撤1%清仓 止盈条件:炼焦利润由上向下穿越布林线上轨的时候,卖平焦炭、买平焦煤

以下是帮助中有关套利发单的源码,想把上面的系统加入这些代码中,代码按个人理解加了注释,也请老师看看。 // 简称: SpreadTrader // 名称: 套利宝 // 类别: 公式应用 // 类型: 用户应用 // 输出: Void //------------------------------------------------------------------------ Params String SpreadSection("SpreadTrader"); // 用于数据库存储的Section设置 String SymbolA("y2205.DCE"); // Data0商品信息,为盘口活跃品种 String SymbolB("y2209.DCE"); // Data1商品信息,为盘口不活跃品种 Bool ResetPosition(False); // 重设持仓数据 Integer InitPosition(0); // 初始持仓值 Integer SpreadUnitA(1); // Data0的价差计算单位 Integer SpreadUnitB(1); // Data1的价差计算单位 Bool SpreadLong(True); // True对价差做多,False对价差做空 Numeric EntryLine(0); // 价差开仓位置 Numeric ExitLine(100); // 价差平仓位置 Integer MaxPosition(1); // 最大持仓手数 Integer DeleteOrderSet(2); // 挂单后盘口变化点数设置(1-N),大于等于这个点数才撤单,设置太小会导致撤单次数太多。 Integer OrderOffset(0); // 挂单成交后补单的委托价格偏移点数 Vars Global Integer i; // 函数内使用临时变量 Global String tmpStr; // 函数内使用临时变量 Global Integer tmpInteger; // 函数内使用临时变量 Global Numeric tmpNumeric; // 函数内使用临时变量 Global Tick tmpTickData; // 函数内使用临时变量 Global Order tmpOrder; // 函数内使用临时变量 Global Bool needCancelOrder; // 是否需要撤单的临时变量 Global Bool dataReady; // 检查数据是否正确的标识 Global Bool paramReady; // 检查参数是否正确的标识 Global Numeric priceTickA; // Data0的价格变动单位 Global Numeric priceTickB; // Data1的价格变动单位 Global Array<Tick> lastTickData; // 缓存的最新Tick数据 Global Array<bool> tickDataValid; // Tick数据是否有效标识 Global Numeric spreadBidPrice; // 价差的买盘价 Global Numeric spreadAskPrice; // 价差的卖盘价 Global Numeric orderPrice; // 委托单价格 Global Numeric upPrice; // 价格上限 Global Numeric dnPrice; // 价格下限 Global String curPosKey; // 根据商品信息生成的Key,使用该Key来保存持仓数据到数据库中 Global Integer curPosition(0); // 当前持仓手数,正数为多头持仓,负数为空头持仓 Global Integer curEntryStatus(0); // 当前套利下单的开仓处理状态 共有8种 // 0 - 初始状态为0时,用OnEntryStatusNone发送data1的开仓单 // 1/3/5/7 - 等待委托单到交易所:不操作 // 2 - 撤单重发data1:用OnEntryStatusSendedData1监控data1是否需要撤单重发,行情数据错误或价格偏离委托太远就撤单重发 // 4 - Data1挂单委托成交:用OnEntryStatusFilledData1确认data1开仓成功,然后发送data0的开仓单 // 5 - Data0直接委托发送中 // 6 - 是否需要撤单重发data0:用OnEntryStatusSendedData0监控发送data0的开仓单 // 8 - 更改数据库仓位状态:用OnEntryStatusFilledData0确认data0开仓成功,更改状态 // Integer RunSpreadOrderEntry:开仓交易的主函数,根据不同的开仓状态调用前面5个函数 Global Integer curExitStatus(0); // 当前套利下单的平仓处理状态 // 0 - 初始状态是0时,用 OnExitStatusNone发送data1的平仓单 // 1 - Data1挂单委托发送中,等待委托单到交易所 // 2 - Data1挂单委托成功,用OnExitStatusSendedData1判断是否需要重发 // 3 - Data1挂单委托撤单中,等待委托单到交易所 // 4 - Data1挂单委托成交:用OnExitStatusFilledData1判断data1成交后,平仓data0 // 5 - Data0直接委托发送中,等待委托单到交易所 // 6 - Data0委托发送成功,,用OnExitStatusSendedData0判断是否需要重发data0 // 7 - Data0委托撤单中,等待委托单到交易所 // 8 - Data0委托成交,用OnExitStatusFilledData0判断data0成交后,更改数据库仓位状态 // -99 - 出错状态,需人工干预 // RunSpreadOrderExit() 平仓交易的主函数,根据不同的平仓状态调用前面5个函数 Global Array<Integer> entryPairAOrderIds; // 缓存的Data0开仓OrderIds Global Array<Integer> entryPairBOrderIds; // 缓存的Data1开仓OrderIds Global Array<Integer> exitPairAOrderIds; // 缓存的Data0平仓OrderIds Global Array<Integer> exitPairBOrderIds; // 缓存的Data1平仓OrderIds Defs bool CheckParams() { If(SpreadLong)//如果对价差做多为真 { If(EntryLine >= ExitLine) Return False;//如果开仓线大于等于平仓线,checkparams为假,不能开仓 } Else { If(EntryLine <= ExitLine) Return False;//如果开仓线小于等于平仓线,checkparams为假,不能开仓 } Return True; } bool CheckTickData(TickRef tickData)//为真时,tick数据可用 { /* Commentary("symbol="+tickData.symbol); //合约名 Commentary("time="+text(tickData.datetime)); //时间 Commentary("AskPrice="+text(tickData.bidask1.askP)); //申卖价1 Commentary("AskVol="+text(tickData.bidask1.askV)); //申卖量1 Commentary("BidPrice="+text(tickData.bidask1.bidP)); //申买价1 Commentary("BidVol="+text(tickData.bidask1.bidV)); //申买量1 Commentary("Last="+text(tickData.last)); //现价 Commentary("Open="+text(tickData.open)); //开盘价 Commentary("High="+text(tickData.high)); //最高价 Commentary("Low="+text(tickData.low)); //最低价 Commentary("Volume="+text(tickData.volume)); //现手 Commentary("TotalVolume="+text(tickData.totalVolume)); //总成交 Commentary("---------------separator---------------"); */ If(tickData.last > 0 && tickData.totalVolume > 0)//检查tick数据,如果价格和成交量都大于0,CheckTickData为真 Return True; Else Return False; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~计算两个合约价差值~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Numeric CalcSpreadPrice(Numeric p1, Numeric p2) { return p1-p2; } //~~~~~~~~~~~~~~~~~~~~~~计算下单价格,涨跌停返回-1,价差价格不利时返回-2,正常计算返回0~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&middot; Integer CalcSendOrderPrice(Bool entry,NumericRef myPrice) { If((SpreadLong&&entry)||(!SpreadLong&&!entry)) // 当前允许多头开仓或空头平仓 { if (lastTickData[0].bidask1.askP < 0.000001 || lastTickData[1].bidask1.bidP < 0.000001) return -1;//涨跌停时函数返回-1 spreadAskPrice = CalcSpreadPrice(lastTickData[0].bidask1.askP*SpreadUnitA,lastTickData[1].bidask1.bidP*SpreadUnitB);//计算价差 If(spreadAskPrice > IIF(entry,EntryLine,ExitLine)) return -2;//如果开仓时价差大于开仓线,或者非开仓时价差大于平仓线,函数返回-2 orderPrice = lastTickData[1].bidask1.bidP;//下单价格等于买一价 if (lastTickData[1].limitUp > 0.000001 && orderPrice > lastTickData[1].limitUp) return -3;//如果上一个价格涨停价不是0(未涨停)并且下单价大于前一天的涨停价函数返回-3 } Else // 多头平仓或空头开仓 { if (lastTickData[0].bidask1.bidP < 0.000001 || lastTickData[1].bidask1.askP < 0.000001) return -1;//涨跌停时函数返回-1 spreadBidPrice = CalcSpreadPrice(lastTickData[0].bidask1.bidP*SpreadUnitA,lastTickData[1].bidask1.askP*SpreadUnitB);//计算价差 If(spreadBidPrice < IIF(entry,EntryLine,ExitLine)) return -2;//如果开仓时价差大于开仓线,或者非开仓时价差大于平仓线,函数返回-2 orderPrice = lastTickData[1].bidask1.askP;//下单价格等于卖一价 if (lastTickData[1].limitDown > 0.000001 && orderPrice < lastTickData[1].limitDown) return -3;//如果上一个价格未涨停并且下单价小于前一天的跌停价,函数返回-3 } Return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~获得已发单的发单价~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` Numeric GetSendedOrderPrice(Bool entry,Bool pairB) { tmpNumeric = InvalidNumeric; tmpInteger = InvalidInteger; If(entry) { if(pairB) { tmpInteger = entryPairBOrderIds[0]; }Else { tmpInteger = entryPairAOrderIds[0]; } }Else { if(pairB) { tmpInteger = exitPairBOrderIds[0]; }Else { tmpInteger = exitPairAOrderIds[0]; } } If(tmpInteger!=InvalidInteger && A_GetOrder(tmpInteger,tmpOrder)) { tmpNumeric = tmpOrder.price; } Return tmpNumeric; } //------------------------------------------------------------------------- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&middot;开仓操作处理函数~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnEntryStatusNone() { tmpInteger = CalcSendOrderPrice(True,orderPrice); If(tmpInteger != 0) Return tmpInteger;//假如CalcSendOrderPrice不为0,对tmpInteger的赋值不变 ArrayClear(entryPairBOrderIds);//一维数组内全部清空 If(!Data1.A_SendOrderEx(IIF(SpreadLong,Enum_Sell,Enum_Buy),Enum_Entry,1,orderPrice,entryPairBOrderIds)) Return -4;//开仓挂单没有成功,函数等于-4 curEntryStatus = 1; Return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~以下对data1的委托单进行处理,如果价格偏移过大,判断是否对自己有利,有利则重新定义交易价格,不利则撤单~~~~~~~~~~~~~~~~~ Integer OnEntryStatusSendedData1() { needCancelOrder = False; If(SpreadLong)//对差价做多为真 { If (lastTickData[0].bidask1.askP > 0.000001 && lastTickData[1].bidask1.bidP > 0.000001)//假如当前没有涨停并且前一天没有涨停 { orderPrice = (SpreadUnitA*lastTickData[0].bidask1.askP-EntryLine)/SpreadUnitB;//开仓价格等于A价差的计算单位乘以买一价的积减去开仓线,再除以B价差的计算单位 if(lastTickData[1].bidask1.bidP > orderPrice) // 价格有利,则用叫买价发单 orderPrice = lastTickData[1].bidask1.bidP; }Else { needCancelOrder = True;//如果价格偏移且对成交不利,撤单 } } Else//如果对差价做多为假(做空为真) { If (lastTickData[0].bidask1.bidP > 0.000001 && lastTickData[1].bidask1.askP > 0.000001)//当前价格没有跌停且上一个价格没有涨停 { orderPrice = (SpreadUnitA*lastTickData[0].bidask1.bidP-EntryLine)/SpreadUnitB; if(lastTickData[1].bidask1.askP < orderPrice) // 价格有利,则用叫卖价发单 orderPrice = lastTickData[1].bidask1.askP; }Else { needCancelOrder = True; } } If(!needCancelOrder)//如果不需要撤单 { tmpNumeric = GetSendedOrderPrice(true,true); upPrice = tmpNumeric+priceTickB*DeleteOrderSet; dnPrice = tmpNumeric-priceTickB*DeleteOrderSet; if (orderPrice > dnPrice && orderPrice < upPrice)//如果价格偏移在设定的范围之内,则不需要撤单重发 needCancelOrder = False; // 不需要撤单重发 Else needCancelOrder = True; } If(needCancelOrder)//如果需要撤单 { For i=0 To GetArraySize(entryPairBOrderIds)-1 { Data1.A_DeleteOrderEx(entryPairBOrderIds[i]); } curEntryStatus = 3; } Return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~判断data1的开仓状态~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnEntryStatusFilledData1() { If(SpreadLong) { orderPrice = lastTickData[0].limitUp;//指令价位涨停价 If(lastTickData[0].bidask1.askP > 0.000001)//如果当前没有涨停,指令价为指令价与卖一价+设定点位的较小值 { orderPrice = Min(orderPrice,lastTickData[0].bidask1.askP+priceTickA*OrderOffset); } }Else { orderPrice = lastTickData[0].limitDown;//指令价位跌停价 If(lastTickData[0].bidask1.bidP > 0.000001)//如果没有跌停,指令价为指令价与买一价+设定点位的较大值 { orderPrice = Max(orderPrice,lastTickData[0].bidask1.bidP+priceTickA*OrderOffset); } } ArrayClear(entryPairAOrderIds); If(!Data0.A_SendOrderEx(IIF(SpreadLong,Enum_Buy,Enum_Sell),Enum_Entry,1,orderPrice,entryPairAOrderIds)) Return -1; curEntryStatus = 5; Return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~监控data0的开仓挂单~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnEntryStatusSendedData0() { If(SpreadLong)//设定做多的下单价格 { orderPrice = lastTickData[0].bidask1.askP+priceTickA*OrderOffset; }Else//设定做空的下单价格 { orderPrice = lastTickData[0].bidask1.bidP-priceTickA*OrderOffset; } tmpNumeric = GetSendedOrderPrice(true,False); if (orderPrice > tmpNumeric+0.000001 || orderPrice <= tmpNumeric-0.000001) // 新的委托价格和原委托价格不同即撤单重发 { For i=0 To GetArraySize(entryPairAOrderIds)-1 { Data0.A_DeleteOrderEx(entryPairAOrderIds[i]); } curEntryStatus = 7; } Return 0; } //~~~~~~~~~~~~~~~~~~~~~data0的开仓成交状态~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnEntryStatusFilledData0() { curEntryStatus = 0; curPosition = curPosition + 1; SetTBProfileString(SpreadSection,curPosKey,Text(curPosition)); Return 0; } Integer RunSpreadOrderEntry()//委托A或委托B已开仓成交 { if (curPosition < MaxPosition && curEntryStatus != -99) // 还可以开仓 { If(curEntryStatus == 0) { OnEntryStatusNone(); }Else if(curEntryStatus == 1 || curEntryStatus == 5) { // 等待委托单发送到交易所 }Else if(curEntryStatus == 2) { OnEntryStatusSendedData1(); }Else if(curEntryStatus == 3 || curEntryStatus == 7) { // 等待撤单发送到交易所 }Else if(curEntryStatus == 4) { OnEntryStatusFilledData1(); }Else if(curEntryStatus == 6) { OnEntryStatusSendedData0(); }Else if(curEntryStatus == 8) { OnEntryStatusFilledData0(); } } spreadAskPrice = CalcSpreadPrice(lastTickData[0].bidask1.askP*SpreadUnitA,lastTickData[1].bidask1.bidP*SpreadUnitB); spreadBidPrice = CalcSpreadPrice(lastTickData[0].bidask1.bidP*SpreadUnitA,lastTickData[1].bidask1.askP*SpreadUnitB); Commentary("SpreadPrice="+Text(spreadAskPrice)); Commentary("SpreadBid="+Text(spreadBidPrice)); FileAppend("D:\\SpreadTrader.tbf","CurPosition="+Text(curPosition)); Return 0; } //------------------------------------------------------------------------- // 以下为平仓操作处理函数 Integer OnExitStatusNone() { tmpInteger = CalcSendOrderPrice(False,orderPrice); If(tmpInteger != 0) Return tmpInteger; ArrayClear(exitPairBOrderIds); If(!Data1.A_SendOrderEx(IIF(SpreadLong,Enum_Buy,Enum_Sell),Enum_Exit,1,orderPrice,exitPairBOrderIds)) Return -4; curExitStatus = 1; Return 0; } Integer OnExitStatusSendedData1() { needCancelOrder = False; If(SpreadLong) { If (lastTickData[0].bidask1.bidP > 0.000001 && lastTickData[1].bidask1.askP > 0.000001) { orderPrice = (SpreadUnitA*lastTickData[0].bidask1.bidP-ExitLine)/SpreadUnitB; if(lastTickData[1].bidask1.askP < orderPrice) // 价格有利,则用叫卖价发单 orderPrice = lastTickData[1].bidask1.askP; }Else { needCancelOrder = True; } }Else { If (lastTickData[0].bidask1.askP > 0.000001 && lastTickData[1].bidask1.bidP > 0.000001) { orderPrice = (SpreadUnitA*lastTickData[0].bidask1.askP-ExitLine)/SpreadUnitB; if(lastTickData[1].bidask1.bidP > orderPrice) // 价格有利,则用叫买价发单 orderPrice = lastTickData[1].bidask1.bidP; }Else { needCancelOrder = True; } } If(!needCancelOrder) { tmpNumeric = GetSendedOrderPrice(False,true); upPrice = tmpNumeric+priceTickB*DeleteOrderSet; dnPrice = tmpNumeric-priceTickB*DeleteOrderSet; if (orderPrice > dnPrice && orderPrice < upPrice) needCancelOrder = False; // 不需要撤单重发 Else needCancelOrder = True; } If(needCancelOrder) { For i=0 To GetArraySize(exitPairBOrderIds)-1 { Data1.A_DeleteOrderEx(exitPairBOrderIds[i]); } curExitStatus = 3; } Return 0; } //~~~~~~~~~~~~~~~~~~~~标记data1发送平仓单~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnExitStatusFilledData1() { If(SpreadLong) { orderPrice = lastTickData[0].limitDown; If(lastTickData[0].bidask1.bidP > 0.000001) { orderPrice = Max(orderPrice,lastTickData[0].bidask1.bidP-priceTickA*OrderOffset); } }Else { orderPrice = lastTickData[0].limitUp; If(lastTickData[0].bidask1.askP > 0.000001) { orderPrice = Min(orderPrice,lastTickData[0].bidask1.askP-priceTickA*OrderOffset); } } ArrayClear(exitPairAOrderIds); If(!Data0.A_SendOrderEx(IIF(SpreadLong,Enum_Sell,Enum_Buy),Enum_Exit,1,orderPrice,exitPairAOrderIds)) Return -1; curExitStatus = 5; Return 0; } //~~~~~~~~~~~~~~~~~~~~标记data0发送平仓单~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnExitStatusSendedData0() { If(SpreadLong) { orderPrice = lastTickData[0].bidask1.bidP-priceTickA*OrderOffset; }Else { orderPrice = lastTickData[0].bidask1.askP+priceTickA*OrderOffset; } tmpNumeric = GetSendedOrderPrice(False,False); if (orderPrice > tmpNumeric+0.000001 || orderPrice < tmpNumeric-0.000001) // 新的委托价格和原委托价格不同即撤单重发 { For i=0 To GetArraySize(exitPairAOrderIds)-1 { Data0.A_DeleteOrderEx(exitPairAOrderIds[i]); } curExitStatus = 7; } Return 0; } //~~~~~~~~~~~~~~~~~~~~标记data0平仓单成交~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer OnExitStatusFilledData0() { curExitStatus = 0; curPosition = curPosition - 1; SetTBProfileString(SpreadSection,curPosKey,Text(curPosition)); Return 0; } //~~~~~~~~~~~~~~~~~~~~标记委托A或委托B平仓单成交~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Integer RunSpreadOrderExit()//委托A或委托B已平仓成交 { if (curPosition > 0 && curExitStatus != -99) // 还可以开仓 { If(curExitStatus == 0) { OnExitStatusNone(); }Else if(curExitStatus == 1 || curExitStatus == 5) { // 等待委托单发送到交易所 }Else if(curExitStatus == 2) { OnExitStatusSendedData1(); }Else if(curExitStatus == 3 || curExitStatus == 7) { // 等待撤单发送到交易所 }Else if(curExitStatus == 4) { OnExitStatusFilledData1(); }Else if(curExitStatus == 6) { OnExitStatusSendedData0(); }Else if(curExitStatus == 8) { OnExitStatusFilledData0(); } } Return 0; } //------------------------------------------------------------------------- // 以下为委托状态变化处理函数 Bool IsMyOrder(OrderRef ord,ArrayRef<Integer> orderIds)//检查委托单是否为这个套利交易的委托单 { for i=0 To GetArraySize(orderIds)-1 { If(ord.orderId==orderIds[i]) Return True; } Return False; } Integer OnNotifySending(OrderRef ord,bool pairB)//true为B委托单发送中,False为A委托单发送中 { tmpInteger = IIF(pairB,1,5); // 默认为发送中 If(ord.status==Enum_Declared) // 已报 { If(ord.exchOrderId!="") { tmpInteger = IIF(pairB,2,6); } }else If(ord.status==Enum_Deleted || ord.status==Enum_Canceled) // 废单或交易所自动撤单 { tmpInteger = IIF(pairB,0,4); // 修改为初始状态或Pair B已成交状态 }Else If(ord.status==Enum_Filled) // 跳过已报状态直接收到成交状态 { tmpInteger = IIF(pairB,4,8); // 修改为已成交状态 }Else If(ord.status==Enum_Declare) { // 等待发送成功 }Else { tmpInteger = -99; // 错误的状态 } Return tmpInteger; } Integer OnNotifySended(OrderRef ord,bool pairB)//true为B委托单发送成功,false为A委托单发送成功 { tmpInteger = IIF(pairB,2,6); // 默认为已报 If(ord.status==Enum_Filled) // 已成交 { tmpInteger = IIF(pairB,4,8); // 修改为已成交状态 }Else If(ord.status==Enum_Canceled) // 已撤单 { tmpInteger = IIF(pairB,0,4); // 修改为初始状态或Pair B已成交状态 }Else If(ord.status==Enum_FillPart) // 部分成交 { // 等待全部成交 }Else If(ord.status!=Enum_Declared) { tmpInteger = -99; // 错误的状态 } Return tmpInteger; } Integer OnNotifyCanceling(OrderRef ord,bool pairB)//true为B委托单撤单中,FALSE为A委托单撤单中 { tmpInteger = IIF(pairB,3,7); // 默认为撤单中 If(ord.status==Enum_Canceled) // 已撤单 { tmpInteger = IIF(pairB,0,4); // 修改为初始状态或Pair B已成交状态 }Else If(ord.status==Enum_Filled) // 撤单不及时,已经成交 { tmpInteger = IIF(pairB,4,8); // 修改为已成交状态 }Else If(ord.status==Enum_Declared) // 已报 { // 等待撤单成功 }Else If(ord.status!=Enum_Canceling) { tmpInteger = -99; // 错误的状态 } Return tmpInteger; } Integer OnNotifyOrder(OrderRef ord,Integer myStatus)//开仓和平仓主函数的主函数 { If(myStatus==1) // 委托B发送中 { myStatus = OnNotifySending(ord,True); }else If(myStatus==2) // 委托B发送成功 { myStatus = OnNotifySended(ord,True); }else If(myStatus==3) // 委托B撤单中 { myStatus = OnNotifyCanceling(ord,True); }else If(myStatus==5) // 委托A发送中 { myStatus = OnNotifySending(ord,False); }else If(myStatus==6) // 委托A发送成功 { myStatus = OnNotifySended(ord,False); }Else If(myStatus==7) // 委托A撤单中 { myStatus = OnNotifyCanceling(ord,False); } If(myStatus==4||myStatus==8) // 委托A或委托B已经成交 { RunSpreadOrderEntry(); RunSpreadOrderExit(); } Return myStatus; } Events OnInit() { SubscribeBar(data0.symbol,"tick");//订阅两个品种的tick行情 SubscribeBar(data1.symbol,"tick");//订阅两个品种的tick行情 A_SubscribeTradeByCreateId(Enum_Trade_Source_ALL);//根据操作源ID订阅委托 paramReady = CheckParams(); } //在所有的数据源准备完成后调用,应用在数据源的设置等操作 OnReady() { curPosKey = data0.symbol+"-"+data1.symbol+IIFString(SpreadLong,".Long",".Short")+"Pos"; If(ResetPosition) // 重置持仓数据 { curPosition = InitPosition; SetTBProfileString(SpreadSection,curPosKey,Text(curPosition)); }Else // 从数据库中读取持仓数据 { tmpStr = GetTBProfileString(SpreadSection,curPosKey); If(tmpStr!=InvalidString && tmpStr !="") curPosition = Value(tmpStr); } priceTickA = Data0.MinMove*Data0.PriceScale; priceTickB = Data1.MinMove*Data1.PriceScale; } //在新bar的第一次执行之前调用一次,参数为新bar的图层数组 OnBarOpen(ArrayRef<Integer> indexs) { } OnBar(ArrayRef<Integer> indexs) { For i=0 To GetArraySize(indexs)-1 { Data[indexs[i]].GetTick(tmpTickData); if(CheckTickData(tmpTickData)) //检查tick数据 { tickDataValid[indexs[i]] = True;//tick数据有效 lastTickData[indexs[i]] = tmpTickData; } } dataReady = True; For i=0 To DataCount-1 { If(!tickDataValid[indexs[i]]) { dataReady = False; Break; } } If(paramReady && dataReady) { RunSpreadOrderEntry(); RunSpreadOrderExit(); } } //持仓更新事件函数,参数pos表示更新的持仓结构体 OnPosition(PositionRef pos) { } //委托更新事件函数,参数ord表示更新的委托结构体 OnOrder(OrderRef ord) { If(IsMyOrder(ord,entryPairAOrderIds)||IsMyOrder(ord,entryPairBOrderIds)) // 判断是否为该系统发出的开仓单 { curEntryStatus = OnNotifyOrder(ord, curEntryStatus); }else if(IsMyOrder(ord,exitPairAOrderIds)||IsMyOrder(ord,exitPairBOrderIds)) // 判断是否为该系统发出的平仓单 { curExitStatus = OnNotifyOrder(ord, curExitStatus); } } //成交更新事件函数,参数ordFill表示更新的成交结构体 OnFill(FillRef ordFill) { } //定时器更新事件函数,参数id表示定时器的编号,millsecs表示定时间的间隔毫秒值 OnTimer(Integer id,Integer intervalMillsecs) { } //------------------------------------------------------------------------ // 编译版本: 2020/01/06 130422 // 版权所有 nopain // 更改声明 TradeBlazer Software保留对TradeBlazer平台 // 每一版本的TradeBlazer公式修改和重写的权利 //------------------------------------------------------------------------