前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C#/.NET量化开发实现财富自由【6】回归测试——寻找属于你的财富策略的必经之路

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

作者头像
Wesky
发布2024-08-13 19:28:19
810
发布2024-08-13 19:28:19
举报
文章被收录于专栏:Dotnet Dancer

本篇以一个入门级策略,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号是一个新的买入点,但是还没死叉,所以还没统计到最新数据。至于后续会怎么样,就不知道了,毕竟只是基础策略演示使用。

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

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Dotnet Dancer 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档