实用且奇特的自动交易技术·综合运用
📘

实用且奇特的自动交易技术·综合运用

第 3/3 篇

「用回撤比给技术稳定性打分」

判断一个交易技术到底有没有用,不能只看最终利润。回测里最容易被误读的就是「赚了」和「碰巧没爆仓」——前者可能只是样本太小,后者可能靠的是浮盈扛单。我更看重两组比值:利润相对平均回撤、利润相对最大回撤,它们能直接暴露技术是真增强还是假平稳。 策略测试器默认只给最终利润、最大余额回撤、最大净值回撤。平均余额回撤和平均净值回撤报告里没有,但逻辑上很关键:当交易费用趋零、策略本身有正期望时,无数个半波(上涨净值段接下跌段)的平均回撤会收敛到总利润值。换句话说,平均回撤越小,同等利润下系统越「密实」,不是靠几笔运气单撑着。 基于上面的关系,可以拼一个综合量具:A = 利润/平均余额回撤,B = 利润/平均净值回撤,C = 利润/最大余额回撤,D = 利润/最大净值回撤。A、B 更准但缺数据;C、D 能直接从回测报告算,所以我实战只用后两个。C 或 D 比裸策略提高,说明加的技术真的降了极端回撤或抬了效率,外汇和贵金属杠杆高、点差跳空频繁,这种比值改善比绝对收益更有参考价值。 用法上,先找一段(或几段)策略本身已经盈利的历史区间,再叠你的技术算 C、D。若 C、D 倾向变大,该技术可保留;若变小,大概率在拖后腿。注意这只能说「概率上更有效」,不是稳赚,实盘前务必在 MT5 用真实点差重跑。

用余额半波给马丁手数踩刹车

把账户余额曲线按相邻涨跌段拆开,每两段构成一个半波。任何余额图本质都是这种半波的堆叠,而半波幅度在不同分组里忽大忽小——幅度小的分组安全,幅度大的分组藏着严重回撤。 思路是在马丁格尔里加两个外部参数:DealsMinusToBreak 记录前一周期亏损单数,触顶就把周期起始手数复位;LotDecrease 定义新周期开启时起始手数的递减步长。安全分组慢慢加手数,危险分组提前减手数,理论上能抬高整体平均量具。 实测中,原始马丁的 D 值约 1.744,开启这套手数调节后变为 1.758,盈利能力轻微偏向正方向。外汇与贵金属属高风险品种,该数值仅单次回测,多跑几次可能回落,但平均倾向略增。 下方代码只算上一周期并决定是否降手数,是策略测试器内的验证函数,直接拷进 MT5 跑一遍比看结论更快。

MQL5 / C++
class="type">class="kw">double DecreasedLot=Lot;class=class="str">"cmt">//lot to decrease
class="type">class="kw">double CalcSmartLot()class=class="str">"cmt">//calculate previous cycle
  {
  class="type">bool ord;
  class="type">int PrevCycleDeals=class="num">0;
  HistorySelect(TimeCurrent()-HistoryDaysLoadI*class="num">86400,TimeCurrent());
  for ( class="type">int i=HistoryDealsTotal()-class="num">1; i>=class="num">0; i-- )
    {
    class="type">class="kw">ulong ticket=HistoryDealGetTicket(i);
    ord=HistoryDealSelect(ticket);
    if ( ord && HistoryDealGetString(ticket,DEAL_SYMBOL) == _Symbol
    && HistoryDealGetInteger(ticket,DEAL_MAGIC) == MagicC
    && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT )
      {
      if ( HistoryDealGetDouble(ticket,DEAL_PROFIT) > class="num">0 )
        {
        for ( class="type">int j=i+class="num">1; j>=class="num">0; j-- )class=class="str">"cmt">//found a profitable deal followed by losing(count them)
          {
          ticket=HistoryDealGetTicket(j);
          ord=HistoryDealSelect(ticket);
          if ( ord && HistoryDealGetString(ticket,DEAL_SYMBOL) == _Symbol
          && HistoryDealGetInteger(ticket,DEAL_MAGIC) == MagicC
          && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT )
            {
            if ( HistoryDealGetDouble(ticket,DEAL_PROFIT) < class="num">0 )
              {
              PrevCycleDeals++;
              }
            else
              {
              class="kw">break;
              }

◍ 逆序平仓后的手数回补逻辑

上面这段收尾代码决定了一轮逆序减仓循环结束之后,下一笔下单手数怎么定。核心判断是:如果上一轮周期内成交次数 PrevCycleDeals 小于阈值 DealsMinusToBreak,就在当前 DecreasedLot 基础上再减去 LotDecrease;否则把 DecreasedLot 重置回基础 Lot。 手数不会无限往下砍。若扣减后 DecreasedLot 降到 0 或负值,直接拉回 SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN) 拿到的品种最小交易量,避免报单被拒。最后函数 return DecreasedLot 把算好的手数交还给调用方。 在 MT5 里把 DealsMinusToBreak 和 LotDecrease 打印出来对照成交历史,能看清手数阶梯是不是按你预期在收缩。外汇与贵金属杠杆高,逆序减仓仍可能连续亏损,需自行回测验证风险。

MQL5 / C++
      }
            }
         class="kw">break;
         }
         else
         {
         class="kw">break;
         }
         }
      }

   if ( PrevCycleDeals < DealsMinusToBreak ) DecreasedLot-=LotDecrease;
   else DecreasedLot=Lot;
   if ( DecreasedLot <= class="num">0.0 ) DecreasedLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   class="kw">return DecreasedLot;
   }

「把这条线请下神坛」

前面几节拆的这套多机器人协同与动态模板思路,本质只是工具箱里的一件器械,不是能自动印钱的圣杯。作者随文给的 Test_Bots.zip 约 380 KB,里面是可直接在 MT5 加载验证的样例机器人,跑通后你会看到它仍依赖两个指标交汇的底层逻辑。 外汇与贵金属自带高杠杆高风险,即便把这类技术摸熟,也只能降低盲目试错的概率,无法消除亏损可能。真要往前走,得自己改参数、加过滤,而不是等着现成系统替你赚钱。

常见问题

拉出净值曲线,用最大回撤除以平均回撤得到回撤比,比值小于3通常说明稳定性尚可,大于5就要警惕样本过短或参数过拟合。
用账户余额的半波值(余额峰值减当前余额的一半)做阈值,当浮亏接近该值就停止加仓,能明显压住极端行情下的仓位膨胀。
小布可接入品种页自动算回撤比、监控余额半波并提示降手数,你不用自己跑脚本也能实时看到风险边界。
按原开仓序列的倒序平掉后,用初始手数从第一单重新开始补,不要直接补到平仓前的最大手数,避免节奏错位。
回撤比只反映历史样本,遇到流动性断裂或点差突变会瞬间失效,必须配合余额刹车和人工干预,别神化任何单一指标。