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

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

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

    具体实现:
    注:下面案例中,更多成员变量的值及说明请查阅:FAQ:FAQ:2023-09-25-应用专题-回测框架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;

    返回结果: