您应当知道的 MQL5 向导技术(第 38 部分):布林带·综合运用
(3/3)·从反弹到量价背离,手把手把布林带多信号写成可组装的自定义类,省去反复造轮子
多数交易者把布林带只当通道看,碰上轨卖、碰下轨买,却漏掉了反弹中轨、量能背离这类组合信号。更麻烦的是,每试一个思路就重写一套 EA,回测一改全崩。本篇把 8 个布林带信号收进同一个 MQL5 向导信号类,边讲边测。
「中轨缓冲区的趋势中继反弹」
趋势中途很少一路不回头,价格往往在延续前先蹭一下动态支撑或阻力。布林中轨(基线缓冲)在这种拉锯里常扮演临时墙:上升趋势中价格从下方探中轨再弹起,倾向看涨中继;下降趋势里从上方碰中轨再回落,倾向看跌中继。注意这不是必然,只是概率倾斜。 全文测试统一用周期 20、偏差 2 的布林带设置,中轨即 20 周期均值。下面这段逻辑就是形态 4 的判定核心:用最近三根 K 线收盘价与中轨的位置关系确认「触碰—反弹」。 别把中轨当硬地板。外汇与贵金属波动里假突破频发,中轨被瞬时刺穿后不反弹反而加速的情况并不少,验证时建议叠加成交量或更高周期方向过滤。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">4. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_4(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) > Base(StartIndex() + class="num">2) && Close(StartIndex() + class="num">1) <= Base(StartIndex() + class="num">1) && Close(StartIndex()) > Base(StartIndex())) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + class="num">2) < Base(StartIndex() + class="num">2) && Close(StartIndex() + class="num">1) >= Base(StartIndex() + class="num">1) && Close(StartIndex()) < Base(StartIndex())) { class="kw">return(true); } class="kw">return(false); }
◍ 用柱线范围替补交易量看布林带背离
外汇交易者大多拿不到跨经纪商整合的真实成交量,MT5 上只能用价格柱线范围当次优替身。逻辑在于:买盘和卖盘合约总量虽不都反映在收盘价位移里,但柱线高低差至少能旁证一段博弈的剧烈程度衰减。 当连续 3 根柱线范围递减,且收盘价贴近或跌破布林下轨,倾向解读为看涨;反之 3 根范围收窄、收盘贴近或越过上轨缓冲区,则发出看跌倾向。这一般对应原有趋势动能耗尽,极端「缩距」暗示逆转或至少回调概率上升。 下面这段 MQL5 是实际判定函数,命名为 Pattern_5 而非字面「第六种形态」。它先刷新带宽与高低收缓存,再比最近三根 Range 是否严格递减;买权要求收盘离下轨比离中轨更近,卖权要求离上轨更近,才返 true。 //+------------------------------------------------------------------+
| // | Check for Pattern 5. |
|---|
//+------------------------------------------------------------------+ bool CSignalBollingerBands::IsPattern_5(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); m_high.Refresh(-1); m_low.Refresh(-1); if(Range(StartIndex()) < Range(StartIndex() + 1) && Range(StartIndex() + 1) < Range(StartIndex() + 2)) { if(T == POSITION_TYPE_BUY && fabs(m_close.GetData(StartIndex()) - Lower(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex()))) { return(true); } else if(T == POSITION_TYPE_SELL && fabs(m_close.GetData(StartIndex()) - Upper(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex()))) { return(true); } } return(false); } 代码逐行拆解:m_bands / m_close / m_high / m_low 四个 Refresh(-1) 是强制重算最新柱;Range() 取某索引柱线范围(high-low);if 首层确认 StartIndex、+1、+2 三根范围严格变小。买侧用 fabs 比收盘到下轨与中轨距离,更靠下轨才 true;卖侧对称看上轨。外汇与贵金属杠杆高,信号失效时回撤可能很快,仅作 MT5 回测验证用。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">5. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_5(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(Range(StartIndex()) < Range(StartIndex() + class="num">1) && Range(StartIndex() + class="num">1) < Range(StartIndex() + class="num">2)) { if(T == POSITION_TYPE_BUY && fabs(m_close.GetData(StartIndex()) - Lower(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex()))) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && fabs(m_close.GetData(StartIndex()) - Upper(StartIndex())) < fabs(m_close.GetData(StartIndex()) - Base(StartIndex()))) { class="kw">return(true); } } class="kw">return(false); }
画得少,看得清
这一篇只拆解了布林带 8 类信号形态里的 5 种,附带的 SignalWZ_38.mqh(21.4 KB)与 wz_38.mq5(8.67 KB)里,输入参数其实预留了多形态开关,没在本文全开。 两条外轨带缓冲区让布林带同时咬住趋势与波动率,再叠一点市场心理,单形态就能独立出信号;但把参数放开做组合优化,才可能更贴不同行情。外汇与贵金属杠杆高,这类形态信号只代表概率倾向,实盘前请在 MT5 用历史数据自测。 下一篇若把剩下 3 种形态与多选择参数补齐,设置会动态得多。现在你手头这份代码,先改一个 StartIndex 窗口长度,就能看出信号密度怎么变。
Close(m_close.MinIndex(StartIndex(), class="num">5)) - Upper(StartIndex()) >= -class="num">1.0 * Range(StartIndex())