您应当知道的 MQL5 向导技术(第 38 部分):布林带·进阶篇
(2/3)· 不止是超买超卖,布林带挤压与双顶双底如何写成可组装的智能系统模块
◍ 把四价合成进 used_series 标志位
在指标或 EA 初始化阶段,常用位运算把开高低收四类价格序列一次性标记为启用。MQL5 里 ENUM_USED_SERIES 的枚举值设计为互不重叠的位掩码,直接相加即可拼出复合标志。 上面这行把 USE_SERIES_OPEN、USE_SERIES_HIGH、USE_SERIES_LOW、USE_SERIES_CLOSE 四个常量相加赋给 m_used_series,等价于按位或。后续向 CopySeries 或自定义缓存传参时,只需判断该变量即可知道要拉取哪些价格分量,避免重复写四个独立布尔。 实际在 MT5 里新建一个空指标,把这段赋值贴进 OnInit,用 Print(m_used_series) 能看到输出为 15(1+2+4+8),说明四价位全部置位。外汇与贵金属行情跳动快,误配序列会导致缓存缺数据,属高风险操作疏忽。
m_used_series = USE_SERIES_OPEN + USE_SERIES_HIGH + USE_SERIES_LOW + USE_SERIES_CLOSE; ...
「外轨触价反抽的识别与代码落地」
布林带上下外轨常被视作价格短期过度延伸后的逆转区。价格触及上轨后回落,倾向视为看跌信号;跌至下轨后回升,则倾向视为看涨信号。这种逻辑背后是市场心理:当价格朝某一方向跑得太远,修正概率上升,而外轨随波动率扩张时,隐含波动也在放大。 用 MQL5 做形态判定时,可把「外轨反弹」单独映射为一个形态编号(例如 2),这样在多形态扫描里只跑这一种条件。下方代码即检查最近三根 K 线是否构成下轨看涨反抽或上轨看跌反抽。 //+------------------------------------------------------------------+
| // | Check for Pattern 1. |
|---|
//+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_1(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); if(T == POSITION_TYPE_BUY && Close(StartIndex() + 2) > Lower(StartIndex() + 2) && Close(StartIndex() + 1) <= Lower(StartIndex() + 1) && Close(StartIndex()) > Lower(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 2) < Upper(StartIndex() + 2) && Close(StartIndex() + 1) >= Upper(StartIndex() + 1) && Close(StartIndex()) < Upper(StartIndex())) { return(true); } return(false); } 逐行拆解:函数入口先 Refresh 布林带与收盘价缓冲,确保拿的是最新值;买权条件要求两根 K 线前收在下轨上方、前一根收在下轨或以下、当前收回到下轨上方,构成下轨针状反抽;卖权对称,要求前两根在上方、前一根刺穿上轨、当前缩回上轨内;都不满足则返回 false。 我们在 USDCHF 的 2023 年日线帧上跑过这套判定,可据此把外轨价位作为限价单参考,并在逆转确认后挂对应止损。外汇与贵金属属高风险品种,外轨反抽仅提高概率,不等于反转必现,实盘前请在 MT5 策略测试器复验。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">1. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_1(class="type">ENUM_POSITION_TYPE T) { m_bands.Refresh(-class="num">1); m_close.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Close(StartIndex() + class="num">2) > Lower(StartIndex() + class="num">2) && Close(StartIndex() + class="num">1) <= Lower(StartIndex() + class="num">1) && Close(StartIndex()) > Lower(StartIndex())) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + class="num">2) < Upper(StartIndex() + class="num">2) && Close(StartIndex() + class="num">1) >= Upper(StartIndex() + class="num">1) && Close(StartIndex()) < Upper(StartIndex())) { class="kw">return(true); } class="kw">return(false); }
一根K线收口就能算挤压
价格挤压的典型画法是波动收敛、布林上下轨间隙明显收窄,但收敛要持续多久本就主观。这里把定义压到最薄:只要当前柱的上轨比前一根低、且前一根又比再前一根低,同时下轨当前比前一根高、前一根比再前一根高,就视作一次挤压——哪怕只活了一根柱线。 代码里完全没去量上下轨之间的绝对宽度,只看轨道方向的「上挖坑+下尖峰」形态。挤压之后若收盘价蹭到或越过上轨,倾向看作看涨触发;若砸到下轨或以下,倾向看作看跌触发。 在 USDCHF 的 2023 年日线帧上跑过一轮未交叉验证的简要优化,仅用来示意这类形态有可抓取的空间,外汇品种高杠杆下仍属高风险,信号只是概率倾向而非确定性。 [CODE] 段里的 IsPattern_2 就是上述逻辑的落地:先 Refresh 带宽与收盘价,再用四重比较确认轨道拐点,最后按持仓方向比对收盘价与轨道位置返回 true/false,复制进 CSignalBollingerBands 类即可在 MT5 里直接验。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">2. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_2(class="type">ENUM_POSITION_TYPE T) { m_bands.Refresh(-class="num">1); m_close.Refresh(-class="num">1); if(Upper(StartIndex()) > Upper(StartIndex() + class="num">1) && Upper(StartIndex() + class="num">1) < Upper(StartIndex() + class="num">2) && Lower(StartIndex()) < Lower(StartIndex() + class="num">1) && Lower(StartIndex() + class="num">1) > Lower(StartIndex() + class="num">2)) { if(T == POSITION_TYPE_BUY && Close(StartIndex()) >= Upper(StartIndex())) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex()) <= Lower(StartIndex())) { class="kw">return(true); } } class="kw">return(false); }
◍ 外轨两次触碰的双顶与双底
这形态和单次外轨反弹的那版很像,区别只在于价格不止一次蹭到布林外轨,相当于给前一种结构加了确认。输入映射里用位图 4 锁死它:从右往左数第 4 位为 1,其余全 0,这样策略就只认这一种形态进场。 单独跑它其实信号很少。USDCHF 日线、2023 年全年回测下来,双顶或双底贴着上下轨出现的概率本来就不高,成交笔数明显少于那些常见组合。外汇与贵金属杠杆高,样本少不代表风险低,验证时请控制仓位。 有意思的是,正因为触发稀罕,它反而能脱离其他指标单用——不像有些形态必须叠过滤器才像样。想自己跑一遍,直接把下面函数塞进 CSignalBollingerBands 类里,挂日线看 year 2023 的 USDCHF 就成。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">3. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_3(class="type">ENUM_POSITION_TYPE T) { m_bands.Refresh(-class="num">1); m_close.Refresh(-class="num">1); m_high.Refresh(-class="num">1); m_low.Refresh(-class="num">1); if ( T == POSITION_TYPE_BUY && Close(StartIndex() + class="num">4) < Close(StartIndex() + class="num">3) && Close(StartIndex() + class="num">3) > Close(StartIndex() + class="num">2) && Close(StartIndex() + class="num">2) < Close(StartIndex() + class="num">1) && Close(StartIndex() + class="num">1) > Close(StartIndex()) && Close(m_close.MinIndex(StartIndex(), class="num">5)) - Upper(StartIndex()) >= -class="num">1.0 * Range(StartIndex()) ) { class="kw">return(true); } else if ( T == POSITION_TYPE_SELL && Close(StartIndex() + class="num">4) > Close(StartIndex() + class="num">3) && Close(StartIndex() + class="num">3) < Close(StartIndex() + class="num">2) && Close(StartIndex() + class="num">2) > Close(StartIndex() + class="num">1) && Close(StartIndex() + class="num">1) < Close(StartIndex()) && Lower(StartIndex()) - Close(m_close.MaxIndex(StartIndex(), class="num">5)) >= -class="num">1.0 * Range(StartIndex()) ) { class="kw">return(true); } class="kw">return(false); }