C#/.NET量化开发实现财富自由【6】回归测试——寻找属于你的财富策略的必经之路

2024-08-13 19:28:19 浏览数 (3)

本篇以一个入门级策略,MACD在0轴金叉买入、MACD死叉卖出,来演示生成一个简单的历史回测数据和走势图。

有关具体的历史数据获取、MACD计算等,可以参考公众号上【Dotnet Dancer】发表的之前的文章。

以下正文:

创建一个回测测试api接口,传入大A编码和起始资金

创建一个回测结果实体类,用于存储回测交易历史数据使用

代码语言:javascript复制
 /// <summary>
 /// 回测结果
 /// </summary>
 public class BackTestInfo
 {
     /// <summary>
     /// 日期
     /// </summary>
    public DateTime DateTime { get; set; }

     /// <summary>
     /// 整体收益率
     /// </summary>
     public double RateOfReturn {  get; set; }

     /// <summary>
     /// 持股数量
     /// </summary>
     public double Count { get; set; }

     /// <summary>
     /// 买入/卖出价格
     /// </summary>
     public double Price {  get; set; }

     /// <summary>
     /// 记录上次买入价格,用于卖出计算收益
     /// </summary>
     public double OldPrice { get; set; }

     /// <summary>
     /// 实时资金
     /// </summary>
     public double Money {  get; set; }

     /// <summary>
     /// 起始资金
     /// </summary>
     public double SourceMoney { get; set; }

     /// <summary>
     /// 买入/卖出   true 买入
     /// </summary>
     public bool IsBuy {  get; set; }

     public BackTestInfo() { }
     public BackTestInfo(BackTestInfo info) {
         Count = info.Count;
         OldPrice = info.Price;
         Money = info.Money;
         SourceMoney = info.SourceMoney;
         IsBuy = info.IsBuy;
     }
 }

根据以前的文章,计算出每一天都DIF和MACD,并赋值。然后计算在0轴金叉的个股(一般情况下,前一天DIF小于0,当天DIF大于0,并且当天MACD>0,前一天MACD<0,则为0轴金叉)

买入卖出模拟测试代码如下

代码语言:javascript复制
  if (testHistory[i - 1].MACD < 0 && testHistory[i].MACD >= 0 && testHistory[i - 1].DIF<0 && testHistory[i].DIF>=0) // 例如0轴金叉
  {
      // 买入
      if (backTestInfos.Any())
      {
          var newBackInfo = new BackTestInfo(backTestInfos.Last());
          newBackInfo.DateTime = testHistory[i].Date;
          newBackInfo.Price = testHistory[i].Close.Value;
          if (newBackInfo.IsBuy)
          {
              // 已经是持仓,跳过
              continue;
          }
          else
          {
              newBackInfo.IsBuy = true;
          }
          // 计算能买多少股,去掉小数点部分
          int buyCount = (int)((newBackInfo.Money / newBackInfo.Price));

          // 梭哈买入
          newBackInfo.Count = buyCount;
          // 扣除佣金,例如万分之一
          newBackInfo.Money = newBackInfo.Money - (buyCount * newBackInfo.Price * 0.0001);

          // 实时收益率
          newBackInfo.RateOfReturn = (newBackInfo.Money - newBackInfo.SourceMoney) / newBackInfo.SourceMoney * 100;


          backTestInfos.Add(newBackInfo);
      }
      else
      {
          // 第一个数据
          var newBackInfo = new BackTestInfo();
          newBackInfo.DateTime = testHistory[i].Date;
          newBackInfo.Price = testHistory[i].Close.Value;
          newBackInfo.IsBuy = true;

          newBackInfo.Money = money;
          newBackInfo.SourceMoney = money;
          // 计算能买多少股,去掉小数点部分
          int buyCount = (int)((newBackInfo.Money / newBackInfo.Price));

          // 梭哈买入
          newBackInfo.Count = buyCount;
          // 扣除佣金,例如万分之一
          newBackInfo.Money = newBackInfo.Money - (buyCount * newBackInfo.Price * 0.0001);

          // 实时收益率
          newBackInfo.RateOfReturn = (newBackInfo.Money - newBackInfo.SourceMoney) / newBackInfo.SourceMoney * 100;

          backTestInfos.Add(newBackInfo);

      }
  }
  else if (testHistory[i].MACD <= 0 || testHistory[i].DIF<0) // DIF或MACD死叉卖出
  {
      // 卖出
      if (backTestInfos.Any())
      {
          var newBackInfo = new BackTestInfo(backTestInfos.Last());
          newBackInfo.DateTime = testHistory[i].Date;
          newBackInfo.Price = testHistory[i].Close.Value;
          if (!newBackInfo.IsBuy)
          {
              // 没有持仓,跳过
              continue;
          }
          else
          {
              newBackInfo.IsBuy = false;
          }

          // 计算清仓卖出资金收益,数量*(卖出价 - 买入价)
          double saleMoney = newBackInfo.Count * newBackInfo.Price;
          double buyMoney = newBackInfo.Count * newBackInfo.OldPrice;

          newBackInfo.Money = newBackInfo.Money   (saleMoney - buyMoney - (saleMoney * 0.0001) -(saleMoney * 0.001)); // ETF不计算印花税,股票卖出计算印花税例如千分之一。计算收益后总资金量

          // 实时收益率
          newBackInfo.RateOfReturn = (newBackInfo.Money - newBackInfo.SourceMoney) / newBackInfo.SourceMoney * 100;

          backTestInfos.Add(newBackInfo);
      }
      else
      {
          // 第一个数据,没买入,就没有卖出,跳过
          continue;
      }
  }

把回测结果写入到表格,写入方式随意。我此处使用EPPlus来实现写入表格和实现回测走势图效果:

然后启动程序,执行操作。例如代码是300532,起始资金是100,000

输出表格以后,打开可以看到数据,说明历史只有三次买点,以及最高收益达到接近40%

咱们看一下第一次买点,2019年1月30日,以及卖点MACD死叉3月18号,对应K线符合要求,说明测试的买卖点策略没问题。

再换个个股试试,例如002156,刚好前几天在操作的一只。

按照该策略回测结果如下,显示最近7-12号是一个新的买入点,但是还没死叉,所以还没统计到最新数据。至于后续会怎么样,就不知道了,毕竟只是基础策略演示使用。

差不多这样,大佬们可以自己进行变种、或者开发自己的策略进行测试。【特别注意】以上仅提供回测开发案例使用,切不可盲目跟随或套用。

祝愿各位大佬量化愉快~早日实现小目标收益~

最后,继续祝大佬们好运,早日实现小目标。如果已经实现小目标,那就更上一层楼~~

0 人点赞