您应当知道的 MQL5 向导技术(第 38 部分):布林带(基础篇)
用向导把布林带塞进EA骨架
MT5 的 MQL5 向导能直接以布林带为基础生成交易系统雏形,省去从零写指标引用的麻烦。在 2025 年 6 月 4 日发布的该系列第 38 部分中,原文作者 Stephen Njuki 演示了这套流程,相关页面显示阅读量为 1 433、收藏 5,说明即便老指标也有人持续追新写法。 打开 MT5 点「文件 → 新建 → 智能交易系统(向导)」,在信号模块里选 Bollinger Bands,向导会自行挂好 iBands 句柄。你接下来只改通道宽度与偏移周期,就能在策略测试器里跑出初步信号分布。 外汇与贵金属波动受杠杆放大,布林带挤压或张口只代表波动率变化,不代表方向必然突破,实盘前务必用历史数据验证参数鲁棒性。
◍ 布林带的三线逻辑与信号类骨架
布林带由 John Bollinger 在 1987 年提出,核心是三条随波动率伸缩的轨道:中轨为 n 周期收盘价的简单移动平均(SMA),上轨 = 中轨 + k×标准差,下轨 = 中轨 - k×标准差,默认 k 取 2。波动率放大时两轨分叉,收窄时贴近,这种动态带宽本身就是市场情绪的温度计。 价格贴着上轨走往往暗示看涨惯性,长期赖在下轨则偏向阴跌;冲破外轨可能被判定为超买或超卖,而两轨极度靠近的「挤压」状态,意味着低波动即将被突破打破。外汇与贵金属品种受消息面扰动大,这种突破方向带假突破概率,实盘须配合止损。 本文不把回测塞到最后,而是边讲边给单形态测试结果。自定义信号类继承自 CExpertSignal,用 m_pattern_XX(0–100 权重)承载多达 8 种布林形态。一般向导汇编时只唤醒一个形态、其余休眠,本文反过来想同时跑全部形态——做多和做空不会由同一形态同帧触发,但不同形态可在不同时间分别给出开仓或平仓提示。 形态选择靠一个 uchar 位掩码,0 到 255 对应 8 个独立开关(如 1=0x01 启用形态0,2=0x02 启用形态1…128=0x80 启用形态7)。原文发现向导默认的 -1 会无视输入强行全开,因此自己写了按位解析来正确映射。下面这段类声明截出了权重变量的定义方式,可直接抄进 MT5 信号类工程里改。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Class CSignalBollingerBands. | class=class="str">"cmt">//| Purpose: Class of generator of trade signals based on | class=class="str">"cmt">//| the &class="macro">#x27;BollingerBands&class="macro">#x27; indicator. | class=class="str">"cmt">//| Is derived from the CExpertSignal class. | class=class="str">"cmt">//+------------------------------------------------------------------+ class CSignalBollingerBands : class="kw">public CExpertSignal { class="kw">protected: CiBands m_bands; class=class="str">"cmt">// object-indicator(布林指标对象实例) .... class=class="str">"cmt">//--- "weights" of market models(class="num">0-class="num">100) class="type">int m_pattern_0; class=class="str">"cmt">// model class="num">0 价格穿越上轨或下轨 class="type">int m_pattern_1; class=class="str">"cmt">// model class="num">1 价格从上/下轨反弹 class="type">int m_pattern_2; class=class="str">"cmt">// model class="num">2 挤压后突破上/下轨 class="type">int m_pattern_3; class=class="str">"cmt">// model class="num">3 下轨附近双底或上轨附近双顶 class="type">int m_pattern_4; class=class="str">"cmt">// model class="num">4 价格从中轨上方/下方反弹 class="type">int m_pattern_5; class=class="str">"cmt">// model class="num">5 上/下轨处的量能背离
「布林带信号类的模式位图与判定接口」
在 MT5 的自定义信号类里,布林带策略通常不是只判一个条件,而是把多种形态拆成 0~7 号共 8 种模式分别检测。 从成员变量看,m_pattern_6 与 m_pattern_7 分别对应“下降趋势或上升趋势后带宽放大”以及“带宽朝向与角度变化”两类形态,说明实盘里至少预留了 8 种可切换识别逻辑。 m_patterns_used 是一个 uchar 位图整数,用每一个 bit 标记对应模式是否启用,这样在 EA 初始化时就能用位运算筛选要跑的形态组合,不必改判断函数本身。 公开的构造与析构之外,protected 区暴露了 IsPattern_0 到 IsPattern_7 共 8 个布尔方法,入参都是 ENUM_POSITION_TYPE 持仓方向,返回当前 K 线是否满足该模式。 开 MT5 在 MetaEditor 建一个 CSignalBollingerBands 派生类,把上面 8 个 IsPattern 先留空壳,用 m_patterns_used 的位控制开关,就能逐步填每种形态而不动调用框架。
class="type">int m_pattern_6; class=class="str">"cmt">// model class="num">6 "Bands Widening After Downtrend or After Uptrend " class="type">int m_pattern_7; class=class="str">"cmt">// model class="num">7 "Bands Orientation and Angle Changes " class="type">uchar m_patterns_used; class=class="str">"cmt">// bit-map integer for used pattens class="kw">public: CSignalBollingerBands(class="type">void); ~CSignalBollingerBands(class="type">void); .... class="kw">protected: ... class=class="str">"cmt">//--- methods to check for patterns class="type">bool IsPattern_0(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_1(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_2(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_3(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_4(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_5(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_6(class="type">ENUM_POSITION_TYPE T); class="type">bool IsPattern_7(class="type">ENUM_POSITION_TYPE T); };
布林带破轨信号的代码落地
价格从上轨上方回落下穿,倾向看作看跌触发;从下轨下方上穿并收在其上,倾向看作看涨触发。这套逻辑在信号类里被压成形态 0 的检查函数,靠 MQL5 标准库的 CiBands 把上轨、下轨、中线的取数都封装好了,使用者不必自己管缓冲区。 下面这段 IsPattern_0 是核心:先 Refresh(-1) 刷最新柱,再用前一根与当前根的收盘价交叉下轨或上轨来判定。注意它比较的是 Close(StartIndex()+1) 与 Lower/Upper 的前值,以及 Close(StartIndex()) 与当前值,属于收盘价确认式破轨,不是刺穿即触发。 [CODE] bool CSignalBollingerBands::IsPattern_0(ENUM_POSITION_TYPE T) { m_bands.Refresh(-1); m_close.Refresh(-1); if(T == POSITION_TYPE_BUY && Close(StartIndex() + 1) < Lower(StartIndex() + 1) && Close(StartIndex()) > Lower(StartIndex())) { return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + 1) > Upper(StartIndex() + 1) && Close(StartIndex()) < Upper(StartIndex())) { return(true); } return(false); } [/CODE] 类里只需声明 CiBands m_bands 作为指标对象,构造函数中把 OHLC 句柄交给引用类,InitIndicators 里挂好即可。我们跑 USDCHF 2023 年日线回测,形态输入哈希整数设 1(只用形态 0),部分优化结果显示该单形态在当年日线有一定捕捉破轨反转的概率,但外汇品种受点差与跳空影响,实盘前务必在 MT5 用策略测试器重跑。 别把破轨当万能钥匙 布林带开口期破轨常伴趋势延续,收口期破轨才更倾向均值回归;直接抄形态 0 不加分过滤,在贵金属和交叉盘上回撤可能偏大。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">0. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_0(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">1) < Lower(StartIndex() + class="num">1) && Close(StartIndex()) > Lower(StartIndex())) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex() + class="num">1) > Upper(StartIndex() + class="num">1) && Close(StartIndex()) < Upper(StartIndex())) { class="kw">return(true); } class="kw">return(false); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Class CSignalBollingerBands. | class=class="str">"cmt">//| Purpose: Class of generator of trade signals based on | class=class="str">"cmt">//| the &class="macro">#x27;BollingerBands&class="macro">#x27; indicator. | class=class="str">"cmt">//| Is derived from the CExpertSignal class. | class=class="str">"cmt">//+------------------------------------------------------------------+ class CSignalBollingerBands : class="kw">public CExpertSignal { class="kw">protected: CiBands m_bands; class=class="str">"cmt">// object-indicator ... ... }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Create indicators. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::InitIndicators(CIndicators *indicators) { class=class="str">"cmt">//--- check pointer if(indicators == NULL) class="kw">return(false); class=class="str">"cmt">//--- initialization of indicators and timeseries of additional filters if(!CExpertSignal::InitIndicators(indicators)) class="kw">return(false); class=class="str">"cmt">//--- create and initialize MA indicator if(!InitMA(indicators)) class="kw">return(false); class=class="str">"cmt">//--- ok class="kw">return(true); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Constructor | class=class="str">"cmt">//+------------------------------------------------------------------+ CSignalBollingerBands::CSignalBollingerBands(class="type">void) ... {