您应当知道的 MQL5 向导技术(第 46 部分):Ichimoku·进阶篇
◍ 云扭曲:滞后交叉里的真假转折
云扭曲对应 Ichimoku 系统里的 Senkou Span A 与 Senkou Span B 互穿。这两条线本质就是两条偏移的移动平均,互穿可视作带滞后效应的均线交叉:A 从下穿上 B 且收其上,是看涨云扭转;从上穿下 B 且收其下,是看跌云扭转。 代码层只比对相邻两根偏移 K 线:X()+1 为前一偏移柱,X() 为当前。买侧要求前一根 A<B、当前 A>B;卖侧反之。逻辑干净,但滞后天然存在,信号出来时价格往往已离开触发区一段。 拿 GBPJPY 的 2022 全年 H1 帧回测,该形态能抓出转折,却几乎不给趋势强度或动量线索。云层厚就被多人误读成趋势强,其实厚度评估要吃市场背景,碎市里扭转极易再逆转。 别把扭转当独立圣旨 单独依赖云扭曲容易吃假信号。理想状态是等 Tenkan-sen/Kijun-sen 交叉或 Chikou Span 来确认;外汇与贵金属杠杆高、反转快,缺确认就进场等于主动接疲软段。 上面那段判定函数可直接拷进 MT5 的 CSignalIchimoku 类里跑,把 X() 换成你自己的偏移索引,先拿历史帧数一遍信号密度,再决定要不要接别的过滤器。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">3. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalIchimoku::IsPattern_3(class="type">ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && SenkouSpanA(X()+class="num">1) < SenkouSpanB(X()+class="num">1) && SenkouSpanA(X()) > SenkouSpanB(X())) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && SenkouSpanA(X()+class="num">1) > SenkouSpanB(X()+class="num">1) && SenkouSpanA(X()) < SenkouSpanB(X())) { class="kw">return(true); } class="kw">return(class="kw">false); }
滞后线突破的编码与确认边界
Chikou Span 本质是滞后缓冲区,手工看图时一眼能看出它是否穿越价格,但落到 MQL5 里读值必须算清索引偏移:当前柱是 X(),前一根是 X()+1,错一位信号就反了。 代码里形态-4 的判断逻辑很直白:做多时要求前一柱 ChikouSpan 还压在 Tenkan-sen 下方,本柱翻到上方;做空则镜像处理。这种穿越本身只代表滞后线确认了既有势头,单独用容易片面。 回测中按与其它形态相同设置跑形态-4,暴露出一个陷阱——过度依赖它而忽略 Kumo 突破或双线交叉,会把局部确认当全局信号。外汇与贵金属属高风险品种,基本面驱动行情时滞后线确认力会明显衰减,宜仅作配对过滤而非独立入场依据。 让小布替你跑这套 把下面函数直接贴进 CSignalIchimoku 类,用策略测试器对 XAUUSD 的 M15 跑一轮,观察纯形态-4 与「形态-4 + Kumo 突破」两组胜率差,比看文字直观。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">4. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalIchimoku::IsPattern_4(class="type">ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && ChikouSpan(X()+class="num">1) <= Tankensen(X()+class="num">1) && ChikouSpan(X()) > Tankensen(X())) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && ChikouSpan(X()+class="num">1) >= Tankensen(X()+class="num">1) && ChikouSpan(X()) < Tankensen(X())) { class="kw">return(true); } class="kw">return(class="kw">false); }
「云层当支撑阻力时的三个坑」
价格回踩云层却没击穿,往往被当成多头或空头的反弹信号:云在上就当支撑接多,云在下就当阻力做空。这类形态编码时只跑自己那一个,回测把形态输入赋成 32,就能屏蔽其余 10 种形态只验它。 云层由领先跨度 A/B 包出的区域构成,本身带 26 根 K 线的前向位移,所以比实时水平线慢半拍。快节奏行情里,等价格碰云反弹被确认,入场可能已经晚了一截,信号延迟会直接吃掉部分盈亏比。 它不是一条线而是一块带,止损止盈挂在哪里全靠估。和传统画线的精确位比,云中管理仓位更模糊,新手容易把止损塞进云里被毛刺扫掉。 趋势强的时候价格常毫无犹豫地穿过云,此时它更像缓冲垫而非墙。外汇和贵金属波动大、跳空多,单靠云层逆向接单可能连续踏空,建议叠加别的结构过滤再动手。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">5. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalIchimoku::IsPattern_5(class="type">ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && ((Close(X()+class="num">2) > SenkouSpanA(X()+class="num">2) && Close(X()+class="num">1) < SenkouSpanA(X()+class="num">1) && Close(X()) > SenkouSpanA(X()) && SenkouSpanA(X()) > SenkouSpanB(X())) || (Close(X()+class="num">2) > SenkouSpanA(X()+class="num">2) && Close(X()+class="num">1) < SenkouSpanB(X()+class="num">1) && Close(X()) > SenkouSpanB(X()) && SenkouSpanB(X()) > SenkouSpanA(X()))) ) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && ((Close(X()+class="num">2) < SenkouSpanA(X()+class="num">2) && Close(X()+class="num">1) > SenkouSpanA(X()+class="num">1) && Close(X()) < SenkouSpanA(X()) && SenkouSpanA(X()) < SenkouSpanB(X())) || (Close(X()+class="num">2) < SenkouSpanA(X()+class="num">2) && Close(X()+class="num">1) > SenkouSpanB(X()+class="num">1) && Close(X()) < SenkouSpanB(X()) && SenkouSpanB(X()) < SenkouSpanA(X()))) ) { class="kw">return(true); } class="kw">return(class="kw">false); }
◍ 云层之上的交叉才够硬
在 Ichimoku 体系里,Tenkan-sen 与 Kijun-sen 的交叉本身随时可能发生,但把交叉点和 Kumo(云)的相对位置绑在一起,信号强度会分化。看涨交叉若落在云层上方,视为强买入倾向;看跌交叉落在云下方,视为强卖出倾向。云内部出现的任何交叉,因市场犹豫,信号可信度明显偏弱。 把这套逻辑写成形态-6,策略测试器里赋参数值 64 跑出来的结果印证了过滤器的区分度。但 Kumo 上穿或下穿本质是滞后结构,强交叉往往出现在趋势已发生明显位移之后,单纯照此入场可能错过初期最肥的一段,外汇与贵金属品种的高波动特性会放大这种延迟成本。 波动市或消息市里,强交叉容易快速反向。价格没确认方向就围绕云层来回拉扯,会生成大量虚假信号,仅依赖该交叉持仓的交易者可能被困在逆转里。建议配合成交量或动量类辅助确认,贵金属与外汇杠杆交易属高风险,任何信号都只是概率。 下面这段 MQL5 是形态-6 的判定函数,直接可用: //+------------------------------------------------------------------+
| // | Check for Pattern 6. |
|---|
//+------------------------------------------------------------------+ bool CSignalIchimoku::IsPattern_6(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Tankensen(X()+1) < Kijunsen(X()+1) && Tankensen(X()) > Kijunsen(X()) && ((Tankensen(X()) > SenkouSpanA(X()) && SenkouSpanA(X()) > SenkouSpanB(X()))
(Tankensen(X()) > SenkouSpanB(X()) && SenkouSpanB(X()) > SenkouSpanA(X()))) ) { return(true); } else if(T == POSITION_TYPE_SELL && Tankensen(X()+1) > Kijunsen(X()+1) && Tankensen(X()) < Kijunsen(X()) && ((Tankensen(X()) < SenkouSpanA(X()) && SenkouSpanA(X()) < SenkouSpanB(X()))
(Tankensen(X()) < SenkouSpanB(X()) && SenkouSpanB(X()) < SenkouSpanA(X()))) ) { return(true); } return(false); } 逐行拆解:函数入口按持仓方向 T 分流;买向分支先要求上一根 K 线 Tenkan 在 Kijun 之下、当前根 Tenkan 上穿 Kijun,且当前 Tenkan 高于 A/B 双云Span 之一并处于云上(A 在 B 上或 B 在 A 上均可,即价格在云上方);卖向对称,要求下穿且价格位于云下方;不满足任一结构则返回 false,调用方拿不到信号。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">6. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalIchimoku::IsPattern_6(class="type">ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Tankensen(X()+class="num">1) < Kijunsen(X()+class="num">1) && Tankensen(X()) > Kijunsen(X()) && ((Tankensen(X()) > SenkouSpanA(X()) && SenkouSpanA(X()) > SenkouSpanB(X())) || (Tankensen(X()) > SenkouSpanB(X()) && SenkouSpanB(X()) > SenkouSpanA(X()))) ) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Tankensen(X()+class="num">1) > Kijunsen(X()+class="num">1) && Tankensen(X()) < Kijunsen(X()) && ((Tankensen(X()) < SenkouSpanA(X()) && SenkouSpanA(X()) < SenkouSpanB(X())) || (Tankensen(X()) < SenkouSpanB(X()) && SenkouSpanB(X()) < SenkouSpanA(X()))) ) { class="kw">return(true); } class="kw">return(class="kw">false); }
云层厚度只是趋势强度的影子
Ichimoku 的云层厚度能透露支撑阻力的虚实:薄云意味着支撑或阻力偏弱,价格突破或反转的概率偏高;厚云则代表防线扎实,当前趋势延续的可能性更大。实操里可把看涨信号框定为约 26 根柱线的上行且云层同步增厚,看跌则反之。把形态输入赋值为 128 跑回测,会输出一组对应信号,但数字本身不证明胜率。 把上面逻辑落进 MT5,核心就是比当前与 26 根前的云层绝对厚度: //+------------------------------------------------------------------+
| // | Check for Pattern 7. |
|---|
//+------------------------------------------------------------------+ bool CSignalIchimoku::IsPattern_7(ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Close(X()) > Close(X()+26) && fabs(SenkouSpanB(X()) - SenkouSpanA(X())) > fabs(SenkouSpanB(X()+26) - SenkouSpanA(X()+26))) { return(true); } else if(T == POSITION_TYPE_SELL && Close(X()) < Close(X()+26) && fabs(SenkouSpanB(X()) - SenkouSpanA(X())) > fabs(SenkouSpanB(X()+26) - SenkouSpanA(X()+26))) { return(true); } return(false); } 逐行看:函数接收持仓方向 T;买权条件是现价高于 26 根前收盘价且当下云层厚度(两 Span 差的绝对值)大于 26 根前的厚度;卖权对称;都不满足返回 false。 低波动或横盘时,厚云容易给假信号——历史价撑出的云未必对应真实趋势强度,外汇与贵金属的高风险环境下这类误导会直接引发不必要的下单。趋势逆反阶段更麻烦,云层滞后性会制造虚假安全感,若 Chikou Span 已拐头却还盯厚度,可能错过早期离场点。 厚薄本就是主观刻度。你得用自己的历史回测和干净数据定一把尺,而不是抄同行的阈值;否则同一段行情,两个人因定义不同会读出完全矛盾的信号,交易清晰度直接碎掉。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">7. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalIchimoku::IsPattern_7(class="type">ENUM_POSITION_TYPE T) { if(T == POSITION_TYPE_BUY && Close(X()) > Close(X()+class="num">26) && fabs(SenkouSpanB(X()) - SenkouSpanA(X())) > fabs(SenkouSpanB(X()+class="num">26) - SenkouSpanA(X()+class="num">26))) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(X()) < Close(X()+class="num">26) && fabs(SenkouSpanB(X()) - SenkouSpanA(X())) > fabs(SenkouSpanB(X()+class="num">26) - SenkouSpanA(X()+class="num">26))) { class="kw">return(true); } class="kw">return(class="kw">false); }