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

Q:比例类回测中,某个调仓日不进行调仓该如何实现?    

简述
在数量类回测中,某个调仓日不进行调仓,我们可以直接返回空数组即可
那么在比例类回测,由于需要给的是最终的持仓情况,若给空数组的话,代表的是全部平仓的一个处理,
所以这个时候,我们有两种方式可以实现,一种是return 1;(返回一个非数组的数据类型)
另一种则是用户自定义配置比例时,用持仓里的占净值比例作为比例。
  • A:场景:指定调仓日整个组合不进行调仓。
    实现方法:
    方法一:GetTradeOrder方法中,这一期的结果可以用非数组进行替代,比如return 1;即可。(支持所有品种,当整个组合不进行调仓时推荐使用)
    方法二:GetHoldData()先取得现有持仓,然后将占净值比例作为比例返回最终持仓,不过,这种方式必须在组合配比方式为用户自定义的情况下才能有效,即FRateType=1时
    (只支持股票,一般在个股不调仓时建议使用)

    注:若是某个调仓日某个个股不进行调仓,则只能通过方法二的方式实现,必须是用户自定义配比方式下,对个别股票的比例用当前的持仓比例替代。

    案例实现:在20210916T日不进行调仓
    Function TSDN_CCBDTest_Demo01();
    Begin
      BegT:=20210901T;
      EndT:=20210928T;
      obj:= createobject('PercentPortfolio');
      //********************回测基本设置***************************//
       //回测开始时间
      obj.FBegT:=BegT;
       //回测截止时间
      obj.FEndT:=EndT;
       //调仓周期(以日线为例)
      obj.FCycle:=cy_day();
       //组合类别(比例类组合)
      obj.FGroupType:=1;
       //基准代码
      obj.FIndexId:='SH000300';
       //初始资金
      obj.FIniCash:=1000000;
       //资金配比方式-流通股本加权
      obj.FRateType:=1;
       //成交价类别-收盘价
      obj.FPriceType:=2;
       //成交量取整模式
      obj.FVolModType:=-1;
       //是否分红再投资
      obj.FDividendType:=1;
       //是否参与配股
      obj.FAllotmentType:=1;

      //********************用户自定义参数***************************//
       //每期样本个数
      obj.FTopN := 10;
      obj.FFeeRate:=0.03;
      obj.szFRateType:=obj.FRateType; //保存配置方式
       //回测
      obj.BackTest();
     
       //获取返回结果(返回结果可根据需要选择)
      return array(
             //---组合基础
            "交易明细":obj.GetTradeData(BegT,EndT),
            "资产配置":obj.GetAssetData(BegT,EndT),
            "持仓明细":obj.GetHoldData(BegT,EndT),

             //---组合收益
            "区间组合收益率": obj.GetPortfolioReturn(BegT,EndT),
            "组合和基准收益率序列":obj.GetPortfolioReturn2(BegT,EndT),
            "阶段收益":obj.GetTrailingReturn(EndT),
            "滚动收益":obj.GetRollingReturn(BegT,EndT,cy_month()),
            '最大回撤':obj.GetPorfolioMaxDrawDown(begt,endt),
            );

    End;
    Type PercentPortfolio=class(TSBackTesting)
      FTopN;  //样本个数
      FFeeRate;
      szFRateType; //保存原计划的配置方式
       //重写GetTradeOrder,获取T日选股结果(TSFL_CL_PE_EndT即T日根据PE选股结果)
      function GetTradeOrder(vEndT);override;
      begin
       echo "选股日:",datetostr(vEndT);
       setsysparam(pn_date(),vEndt);
    {//-方法一:返回1-实现不调仓
       if vEndT=20210916T then return 1;

       }
    //或方法二:自定义配比下 占净值比例作为当前比例 方法二选一即可
       if vEndT=20210916T then
       begin
         FRateType:=-1; //将配比方式临时更改为自定义配比方式
         cc:=getholddata();
         return select vEndT as '截止日',['代码'],['方向'],['乘数'],['保证金比例(%)'],
             ['占净值比例(%)'] as '比例(%)',
             FFeeRate AS '开仓费率(%)',FFeeRate AS '平仓费率(%)' from cc end;
       end
       else //将配比方式重新变更为指定方式
         FRateType:=szFRateType;

    //-选股
       LYD:=incyear(vEndt,-1);
       data:=select thisrow as '代码',vEndt as '截止日',
              spec(stockzf(LYD-15,LYD+15)-stockzf(vEndt-15,vEndt),thisrow) as 'Yzf'
              from getbkbydate('SH000300',vEndt) end;
       delete from data where ['Yzf']<5;
       t:= select drange(0 to FTopN-1) ["截止日"],["代码"]
             from data order by ["Yzf"] asc end;
       Update t set ['开仓费率(%)']=FFeeRate,['平仓费率(%)']=FFeeRate end;
       return t;
      end

    End;


    回测结果:

    交易明细-可以看出9月16日没有交易明细数据:

    持仓明细-可以看出9月16日与15日的持仓与持仓数量一致: