FAQ > 金融建模 > 应用案例 > 回测应用

Q:股票tick级别周期策略回测实现    

  • 策略:
        交易所的tick数据每三秒一笔,因此可以将回测框架的周期设置为3秒,从而实现tick级别周期策略回测。这里给出的案例是使用3秒钟收盘价构造砖形图,使用砖形K线收盘价计算移动均线,移动均线金叉买入,死叉平仓。
        砖形图:重新构建K线图,使每一个K线的长度相同。即价格每向上或向下位移一段固定距离,使用这段距离内的所有价格构成一条K线,砖形图相比于传统的K线图更平滑

    具体实现:
    注:下面案例中,更多成员变量的值及说明请查阅:FAQ:FAQ:2022-07-13-应用专题-回测框架01:策略回测框架TSBackTesting(更新版)

    Function RenkoBackTest();
    Begin
    Begt:=20191101T;
       Endt:=20201130T;
       obj:=createobject('MyTest');
          //回测开始时间
       obj.FBegT:=BegT;
          //回测截止时间
       obj.FEndT:=EndT;
          //交易品种
       obj.FStockID:='SZ000001';
          //回测周期
       obj.FCycle:=cy_3s();
          //组合类别(数量类组合)
       obj.FGroupType:=2;
          //基准代码
       obj.FIndexId:='SH000300';
          //初始资金
       obj.FIniCash:=50000;
          //成交价类别(时点价格)
       obj.FPriceType:=1;
          //成交量取整模式
       obj.FVolModType:=-1;
          //是否分红再投资(不)
       obj.FDividendType:=0;
          //是否参与配股(不)
       obj.FAllotmentType:=0;
          //费用类别
       obj.FFeeType:=1;
          //砖形K线长度
       obj.FRenkoLength:=0.3;
          //长均线周期
       obj.FLong:=20;
          //长均线周期
       obj.FShort:=10;
          //砖形收盘价数组
       obj.FRenkoCloseArr:=array();
          //上一个砖形收盘价,初始值为0
       obj.FLastRenkoClose:=0;
          //回测
       obj.BackTest();
          //获取返回结果(返回结果可根据需要选择)
       return array(
                      //---组合基础
                    "交易明细":obj.GetTradeData(BegT,EndT),
                    "资产配置":obj.GetAssetData(BegT,EndT),
                    "持仓明细":obj.GetHoldData(BegT,EndT),

                      //---组合盈亏、交易
                    "组合盈亏":obj.GetGainandLoss(BegT,EndT),
                    "交易汇总":obj.GetTradingAmount(BegT,EndT),
                    "组合盈亏(按证券)":obj.GetGainandLossBySecurity(BegT,EndT),
                    "交易汇总(按证券)":obj.GetTradingAmountBySecurity(BegT,EndT),

                      //---组合收益
                    "区间组合收益率":  obj.GetPortfolioReturn(BegT,EndT),
                    "组合和基准收益率序列":obj.GetPortfolioReturn2(BegT,EndT),
                    "阶段收益":obj.GetTrailingReturn(EndT),
                    "滚动收益":obj.GetRollingReturn(BegT,EndT,cy_month()),

                    //----组合评价
                    "风险回报":obj.GetReturnandRisk(BegT,EndT),
                    "相对回报":obj.GetRelativePerformance(BegT,EndT),
                    );
    End;

    Type  MyTest=class(TSBackTesting)
       //增加属性
       FStockID;
       FRenkoLength;
       FLong;
       FShort;
       FRenkoCloseArr;
       FLastRenkoClose;
       
       //重载下单函数,返回交易信息二维数组
       Function GetTradeOrder(vEndT);override;
       begin
           //设置临时系统参数,取收盘价
           with *,array(pn_stock():FStockID,pn_date():vEndT,pn_cycle():FCycle) do
           begin
             c:=close();
           end

           //价格位移距离大于等于
           if abs(c-FLastRenkoClose)>=FRenkoLength then
           begin
             FRenkoCloseArr[length(FRenkoCloseArr)]:=c;
             FLastRenkoClose:=c;
             echo datetimetostr(vendt);
             echo c;
           end
           else
             return 0;

           Len:=length(FRenkoCloseArr);
           //收盘价数组长度不足以计算移动均线
           if Len<FLong+1 then return 0;

           //计算长短移动均线
           longma0:=mean(FRenkoCloseArr[Len-FLong:]);
           shortma0:=mean(FRenkoCloseArr[Len-FShort:]);
           longma1:=mean(FRenkoCloseArr[Len-FLong-1:Len-2]);
           shortma1:=mean(FRenkoCloseArr[Len-FShort-1:Len-2]);

           tP:=GetHoldData(); //获取当前持仓
           jymx:=array();
           //ma10上穿ma20的时候买入
           if shortma0>longma0 and shortma1<=longma1 and not istable(tp) then
           begin
              echo '买入',datetostr(vEndt);
              jymx&=array(('截止日':vEndt,
                           '代码':FStockID,
                           '方向':1, //多单
                           '动作':0, //开仓
                           '成交量':1000,//单位 股
                           '费率(%)':0.1));
            end
            //ma10下穿ma20的时候平仓
            else if shortma0<longma0 and istable(tp) then
            begin
              Opendate:=vselect ['截止日'] from tp where ['代码']=FStockID end;
              if dateof(vendt)-dateof(Opendate)>=1 then
              begin
                echo '平仓',datetostr(vEndt);
                jymx&=array(('截止日':vEndt,
                             '代码':FStockID,
                             '方向':1,  //多单
                             '动作':1,  //平仓
                             '成交量':1000,
                             '费率(%)':0.1));
              end;
            end
            return jymx;
       end;
    End;

    返回结果: