全部 智大领峰 TBQuant功能 TBL语言 TB开户 问答专区 高手圈 其他
请教老师,关于套利,自己系统如何与帮助中的代码结合
2022-02-21 16:18

老师好!

最近碰到一些代码的问题,特向各位老师请教:

有几个基于产业链的套利系统想在TBQ中用代码实现出来,TBQ的帮助中有关于套利发单的完整的代码,我基本能看懂,但里面的函数调用比较多,如何在系统中应用,始终心里没底。想向老师请教如何把自己的套利系统与TBQ“帮助”中关于套利发单的代码结合起来实现实盘应用,帮助中的具体代码在回帖中。

还有:以前在tb6中,这个策略是基于日线的,利用TBQ帮助中现成的代码直接用在tick上不知行不行?

先谢谢老师!

例如:关于焦炭与焦煤的套利系统

产业关系:炼焦利润大致等于焦炭价格 - 1.4*焦煤价格 - 其他成本

 

  1. 按上述公式以期货价格计算炼焦利润,“其他成本”暂时忽略;
  2. 用炼焦利润计算20周期布林线;
  3. 开仓:炼焦利润跌破布林线下轨、由下向上穿越布林线下轨的时候,按1:1买入焦炭、卖出焦煤
  4. 平仓:
    1. 止损条件:设置跟踪止损,任何时候最大亏损1%或利润回撤1%清仓
    2. 止盈条件:炼焦利润由上向下穿越布林线上轨的时候,卖平焦炭、买平焦煤
duanmuyufei
  • 以下是帮助中有关套利发单的源码,想把上面的系统加入这些代码中,代码按个人理解加了注释,也请老师看看。

// 简称: 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~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    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;

    }

    

    //-------------------------------------------------------------------------

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·开仓操作处理函数~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    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公式修改和重写的权利

//------------------------------------------------------------------------

2022-02-21 16:19
您未登录,请先 登录注册 后发表评论
顶部