您应当知道的 MQL5 向导技术(第 39 部分):相对强度指数(基础篇)
用向导快速搭一个 RSI 策略骨架
MT5 的 MQL5 向导能省掉手写交易系统框架的重复劳动,尤其适合先把相对强度指数(RSI)这类经典振荡指标跑通再迭代。2025 年 6 月 13 日发布的这篇向导技术示例里,RSI 被直接接入信号模块,省去了自己写 OnTick 与订单发送样板代码的过程。 向导生成的 EA 默认把 RSI 周期设为 14,上穿 30 视作可能的多头触发、下破 70 视作可能的空头触发——这只是初始阈值,实盘前要在 MT5 策略测试器里按品种波动重调。外汇与贵金属杠杆高,信号触发仅代表概率倾斜,不代表方向必现。 要验证这套骨架,打开 MT5:「文件 → 新建 → 智能交易系统(向导)」,选 RSI 信号后再编译,就能在导航器里拖到图表上跑历史数据。先别急着改逻辑,看它怎么处理点差与库存费,往往比指标本身更影响回测曲线。
◍ 从形态6接着拆布林带信号
上篇里我们在向导里用自定义信号类挂布林带,把 8 种基础设置中的前 6 种走完了。当时篇幅顶不住,剩下两种设置、以及布林带各种设置或模式叠加后的组合测试,只点了名没实跑。 这篇直接接上形态 6 继续。对做多/做空条件做称量的交易者来说,那 6 种设置已经能覆盖大部分手动过滤场景,但缺的两种才是把信号从「能出」变成「少假信号」的关键。 外汇和贵金属品种上跑这类信号,杠杆和滑点会把布林带穿透的概率放大,复盘时建议先关掉实时成交只用历史 tick 验证。
「趋势末端布林带张口的反向博弈」
把布林带上下轨的敞口连续三根柱线拉宽,往往意味着波动性在趋势尾巴上突然抬头。此时盘面进入大量拉锯,方向感模糊,这种扩张若出现在一段走牛之后,倾向被解读为转空信号;反之走熊后的扩宽,则倾向给做多留了口子。本质是吃前期主导趋势的对立面,而不是追当前乱局。 代码里先决条件就是波动性扩张:Gap(StartIndex()) 大于前一根、再大于前两根,确认敞口在放大。通过后不盯当前趋势,而是回看波动性飙升前两三根收盘价的走向——前面连跌两段才允许触发买入,连涨两段才允许触发卖出。 这种反向单最怕假逆转:价格可能不从盘整区回头,而是直接突破延续旧趋势。所以原文强调用成交量收敛来确认,轨道扩而量缩,逆转论点才站得住;量没缩就最好等。实盘拿不到逐笔量时,可用柱线振幅或 RSI 超买超卖做代理。 外汇与贵金属杠杆高,这类末端反转信号失败率不低,开仓前应在 MT5 策略测试器跑一遍形态 6 的回测再决定参数。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">6. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_6(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(Gap(StartIndex()) > Gap(StartIndex() + class="num">1) && Gap(StartIndex() + class="num">1) > Gap(StartIndex() + class="num">2)) { if(T == POSITION_TYPE_BUY && m_close.GetData(StartIndex() + class="num">2) < m_close.GetData(StartIndex() + class="num">3) && m_close.GetData(StartIndex() + class="num">3) < m_close.GetData(StartIndex() + class="num">4)) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && m_close.GetData(StartIndex() + class="num">2) > m_close.GetData(StartIndex() + class="num">3) && m_close.GetData(StartIndex() + class="num">3) > m_close.GetData(StartIndex() + class="num">4)) { class="kw">return(true); } } class="kw">return(class="kw">false); }
下轨跑赢上轨的偏斜信号
布林带最后一类可读形态,看的是上下轨的「偏斜速度差」。当下轨连续两根 K 线上涨、且上轨走平或微降,同时下轨两期落差 ≥ 偏差参数 × 上轨两期落差时,价格向上刺穿上轨的概率倾向升高;镜像结构(上轨加速下坠、下轨钝化)则暗示向下破位可能。 单纯形态容易在震荡里互相对冲,实盘里建议等收盘价实破轨道再做判定。回测中仅启用第 7 号形态(输入映射值 80)就曾跑出一条较优曲线,但当允许 0–255 映射内多形态并行时,优化器在 107(对应形态 0、1、3、5、6)等组合上也给出过可复现结果。 代码里用按位与来筛形态:m_patterns_used & 0x01 非零才进 IsPattern_0,以此类推。八种形态固定占用 1、2、4、8、16、32、64、128 的位权,所以一个整数就能装下全部开关,调参时直接改映射值比改逻辑快得多。 外汇与贵金属杠杆高,这类轨道偏斜信号在单边延展时失效快,任何组合都先用 MT5 历史数据跑一遍再上模拟。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">7. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalBollingerBands::IsPattern_7(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 && Lower(StartIndex()) > Lower(StartIndex() + class="num">1) && Lower(StartIndex() + class="num">1) > Lower(StartIndex() + class="num">2) && Upper(StartIndex()) >= Upper(StartIndex() + class="num">1) && Upper(StartIndex() + class="num">1) >= Upper(StartIndex() + class="num">2) && Lower(StartIndex()) - Lower(StartIndex() + class="num">2) >= m_deviation * (Upper(StartIndex()) - Upper(StartIndex() + class="num">2)) ) { class="kw">return(true); } else if ( T == POSITION_TYPE_SELL && 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) && Upper(StartIndex() + class="num">2) - Upper(StartIndex()) >= m_deviation * (Lower(StartIndex() + class="num">2) - Lower(StartIndex())) ) { class="kw">return(true); } class="kw">return(class="kw">false); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| "Voting" that price will grow. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int CSignalRSI::LongCondition(class="type">void) { class="type">int result = class="num">0, results = class="num">0; class=class="str">"cmt">//--- if the model class="num">0 is used and "Price Crossing the Upper Band or the Lower Band" if(((m_patterns_used & 0x01) != class="num">0) && IsPattern_0(POSITION_TYPE_BUY)) { result += m_pattern_0; results++; } class=class="str">"cmt">//--- if the model class="num">1 is used and "Price Bouncing Off Lower Band or Upper Band " if(((m_patterns_used & 0x02) != class="num">0) && IsPattern_1(POSITION_TYPE_BUY)) { result += m_pattern_1; results++; } class=class="str">"cmt">//--- if the model class="num">2 is used and "Price Squeeze Followed by a Breakout Above Upper Band or Below Lower Band " if(((m_patterns_used & 0x04) != class="num">0) && IsPattern_2(POSITION_TYPE_BUY)) { result += m_pattern_2; results++; }
◍ 布林带多模式评分的累加与均值返回
这段逻辑把模型 3 到 7 的买向信号做统一汇总:每个模型对应一个位掩码,3 号是 0x08、4 号 0x10、5 号 0x20、6 号 0x40、7 号 0x80,只有对应位在 m_patterns_used 里被置位且 IsPattern_X(POSITION_TYPE_BUY) 为真时才累加权重并让 results 加一。 从代码看,模型 3 捕捉下轨附近双底或上轨附近双顶,模型 4 是中轨上下穿越反弹,模型 5 是上下轨的量能背离,模型 6 是趋势后带宽放大,模型 7 是带宽方向与倾角变化——五个独立特征并行参与评分,互不排斥。 最后若 results 大于 0,返回 round(result/results) 的整型均值,否则返回 0;这意味着当多个模式同时触发时,引擎给出的是等权平均打分而非简单叠加,避免单一极端模式主导信号。 在 MT5 里把这段直接挂到 EA 的评分函数末尾,改 m_pattern_3 到 7 的权重常数,就能观察不同组合对黄金 1 小时图信号频率的影响,外汇与贵金属杠杆高,回测结果仅代表历史概率。
class=class="str">"cmt">//--- if the model class="num">3 is used and "Price Double Bottoms Near Lower Band or Double Top Near Upper Band " if(((m_patterns_used & 0x08) != class="num">0) && IsPattern_3(POSITION_TYPE_BUY)) { result += m_pattern_3; results++; } class=class="str">"cmt">//--- if the model class="num">4 is used and "Price Bounces Off the Middle Band from Above & Bounce Off from Below " if(((m_patterns_used & 0x10) != class="num">0) && IsPattern_4(POSITION_TYPE_BUY)) { result += m_pattern_4; results++; } class=class="str">"cmt">//--- if the model class="num">5 is used and "Volume Divergence at Lower Band or Upper Band " if(((m_patterns_used & 0x20) != class="num">0) && IsPattern_5(POSITION_TYPE_BUY)) { result += m_pattern_5; results++; } class=class="str">"cmt">//--- if the model class="num">6 is used and "Bands Widening After Downtrend or After Uptrend " if(((m_patterns_used & 0x40) != class="num">0) && IsPattern_6(POSITION_TYPE_BUY)) { result += m_pattern_6; results++; } class=class="str">"cmt">//--- if the model class="num">7 is used and "Bands Orientation and Angle Changes " if(((m_patterns_used & 0x80) != class="num">0) && IsPattern_7(POSITION_TYPE_BUY)) { result += m_pattern_7; results++; } class=class="str">"cmt">//--- class="kw">return the result if(results > class="num">0) { class="kw">return(class="type">int(round(result / results))); } class="kw">return(class="num">0); }