测试当交易货币对篮子时出现的形态第二部分·综合运用
📘

测试当交易货币对篮子时出现的形态第二部分·综合运用

第 3/3 篇

「篮子测试里形态信号的真实表现」

我们在 USD 货币篮子跑通了整套计划,终版 EA 放在附件 testEAbasketFinal.mq5 里。回测结论很直接:该形态本身不能单独拿来当市场入场信号。 剩余货币篮子还有没有必要再测一遍?结果大概率和 USD 篮子一致,边际信息量很低。 正因如此,在真实账户里把该形态叠加单均线突破,并不能构成完整的技术进场依据。我们转而把组合 WPR 指标线与移动平均的交叉作为过滤器,用组合指标刺穿超买/超卖区作为主入场触发,下一步就是验证这套过滤是否真能抬升获利能力。 外汇与贵金属属高风险品种,上述结论仅基于历史回测,实盘表现可能偏离。

用 WPR 与均线位置卡掉噪音交易

把组合 WPR 突破超卖且收线仍站住作为初筛,再叠加一条硬条件:移动平均必须低于组合 WPR 图,才允许买入货币篮子;卖出则完全反向。本质上这里只用了形态的高低过滤器版本,而非完整功能,过滤逻辑落在均线同组合 WPR 的相对位置上。 在 testEAbasket.mq5 基础上改出的 testEAbasket1.mq5,把超买/超卖水平和上述相对位置写进了开仓判定。H1 时段回测一年,曲线相对平滑、有明显获利倾向,但成交笔数偏少;切到更大周期后,信号数还会进一步下降,外汇与贵金属品种本身杠杆高、滑点跳空风险不可忽视。 下面这段输入与计时器代码就是过滤器的核心。输入参数把买卖两侧的利润线、一级极限、二级区间都拆开定义;OnTimer 里每根新 K 线才重算缓冲,避免中途抖动误触。 代码逐行看:SELLPROFIT/BUYPROFIT=0 表示平仓参考 WPR 回破 0 轴;SELL1LIMIT=70 与 BUY1LIMIT=-70 是一级阈值,WL 需先刺穿该极限;SELL2FROM/TO 与 BUY2FROM/TO 框出 50~60 / -60~-50 的二级回归区。OnTimer 中 IsNewCandle 保证只在收线后判断;CopyBuffer 取前一根缓冲做 wl/ml 旧值比对。开买要求 w[0] 在 -60~-50 且前根 wl<=-70 且 w[0]>m[0];开卖对称,交易数量少就是因为这种多重交集在自然走势里本就不常同时满足。

MQL5 / C++
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> SELLPROFIT =  <span class="number">class="num">0</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> SELL1LIMIT = <span class="number">class="num">70</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> SELL2FROM  =  <span class="number">class="num">60</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> SELL2TO     =  <span class="number">class="num">50</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> BUYPROFIT  =  <span class="number">class="num">0</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> BUY1LIMIT  = -<span class="number">class="num">70</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> BUY2FROM   = -<span class="number">class="num">60</span>;
<span class="keyword">class="kw">input</span> <span class="keyword">class="type">int</span> BUY2TO     = -<span class="number">class="num">50</span>;
<span class="comment">class=class="str">"cmt">//...................................................................</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//| 计时器函数                                                                 |</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="keyword">class="type">void</span> <span class="functions">OnTimer</span>()
  {
   <span class="keyword">if</span>(IsNewCandle())
     {
      wl=w[<span class="number">class="num">0</span>];
      <span class="functions">CopyBuffer</span>(h,<span class="number">class="num">0</span>,<span class="number">class="num">1</span>,<span class="number">class="num">1</span>,w);
      ml=m[<span class="number">class="num">0</span>];
      <span class="functions">CopyBuffer</span>(h,<span class="number">class="num">1</span>,<span class="number">class="num">1</span>,<span class="number">class="num">1</span>,m);
      <span class="keyword">if</span>(g_state==BBUY &amp;&amp; (w[<span class="number">class="num">0</span>]&gt;=BUYPROFIT))
        {
         CloseAllPos();
        }
      <span class="keyword">if</span>(g_state==BSELL &amp;&amp; (w[<span class="number">class="num">0</span>]&lt;=SELLPROFIT))
        {
         CloseAllPos();
        }
      <span class="keyword">if</span>(g_state==BCLOSE &amp;&amp; w[<span class="number">class="num">0</span>]&gt;=BUY2FROM &amp;&amp; w[<span class="number">class="num">0</span>]&lt;=BUY2TO &amp;&amp; wl&lt;=BUY1LIMIT &amp;&amp; w[<span class="number">class="num">0</span>] &gt; m[<span class="number">class="num">0</span>])
        {
         EnterBuy(lt);
         <span class="keyword">class="kw">return</span>;        
        }
      <span class="keyword">if</span>(g_state==BCLOSE &amp;&amp; w[<span class="number">class="num">0</span>]&lt;=SELL2FROM &amp;&amp; w[<span class="number">class="num">0</span>]&gt;=SELL2TO &amp;&amp; wl&gt;=SELL1LIMIT &amp;&amp; w[<span class="number">class="num">0</span>] &lt; m[<span class="number">class="num">0</span>])
        {
         EnterSell(lt);
         <span class="keyword">class="kw">return</span>;        
        }
     }
  }

◍ 篮子测试迈出的第一步与待补的窟窿

用组合 WPR 作底层的振荡指标形态,在某一货币篮子里的回测已经跑完,结论能往 RSI 和随机指标上外推,但别急着挂实盘。统计样本明显还薄,主要卡在两处:测试覆盖的 K 线区间太短,以及形态参数本身没定型,尤其是 MA 周期数至今没敲定。 我们已经顺手验证了超买/超卖阈值位的取法,也试了组合指标曲线与均线交叉的配合,还测了两点联立的联合形态。这三件事加在一起,等于把这套玩法推进到了可工程化的门口。 外汇与贵金属波动带杠杆,样本不足的形态直接上实盘属于高风险操作,建议先在 MT5 用自带 WPR 把 MA 周期从 14 调到 21 复跑一遍,看信号密度变化再谈下一步。

「收束」

这套 USD 篮子测试一共挂了 9 个文件:指标 testWPRuMA.mq5(6.02 KB)只做 WPR 与 MA 交叉计数;EA 主体 testEAbasket.mq5(5.29 KB)跑裸篮子,testEAbasket1.mq5(5.14 KB)加第一过滤器,testEAbasketFinal.mq5(6.1 KB)是终版。报告包里 testEAbasket.zip 有 581.26 KB,是裸跑的标准 html;带过滤的 testEAbasket1.zip、testEAbasket2.zip 分别为 148.42 KB、145.62 KB,Tester_EURUSD_Filter.zip 仅 110.15 KB。 回测样本全部集中在 USD 货币篮子,不涉及 EURUSD 单边方向下单,Stanislav Korotky 在讨论里指出信号图颜色与“买入工具”措辞容易误读成做多欧美,作者回称交易标的本身就是美元篮子而非具体货币对。外汇与贵金属杠杆高,篮子对冲也只降低非系统性暴露,复制 EA 前务必在 MT5 策略测试器用 tick 级重跑一遍再上模拟盘。 想验证交叉逻辑,直接把 testWPRuMA.mq5 拖进 EURUSD 的 M5 图,数蓝红标记与 MA 穿越次数是否和报告对得上;参数周期若从 14 改到 21,交叉频率大概率下降,属于可立刻动手调的点。

常见问题

正常。篮子会把相关性抵消或叠加,单品种信号在篮子层常被稀释或放大,建议分别统计单品种与篮子层的触发次数和盈亏,别直接套用单品种结论。
原文用 WPR 超买超卖区结合价格与均线相对位置卡掉反向噪音,可先按原文周期回测,再把 WPR 阈值和均线周期各调一档对比,保留触发数下降但盈亏比改善的组合。
可以。小布盯盘的 AIGC 已内置多品种形态与指标过滤诊断,打开对应篮子品种页即可看到信号分布,省去手动逐个加载测试的重复劳动。
先挑相关性中低且流动性够的跨系货币对,用一段历史数据算相关系数,高于0.8的放一组、其余单独测,避免高度同向品种堆出虚假样本。
可能是过滤过严或周期不对。先放宽 WPR 阈值看触发量,再核对K线周期是否和单品种测试一致;外汇贵金属高风险,样本少时结论别直接用于实盘。