您应当知道的 MQL5 向导技术(第 39 部分):相对强度指数·进阶篇
(2/3)· 接上篇未尽的两种布林带形态,本篇把 RSI 超买超卖与背离嵌进向导信号类
RSI 在汇市区间里的先手价值
RSI 是跟踪价格变化率的震荡指标,核心逻辑是用一段周期内的平均收益与平均亏损之比(RS)来刻画动能,从而给趋势可能的反转提供概率参考。公式层面,RS = 指定周期平均收益 / 平均亏损,再映射成 0–100 的读数;周期长度就是指标输入框里的 N,MQL5 标准库已封装好计算,不用自己重造轮子。 从 2002 年 6 月到现在,欧元兑美元技术上的波动箱体始终落在 0.95 到 1.60 之间,22 年没真正破出去;对比股票指数多数较 2002 年净上涨,外汇对这种长期区间属性意味着超买超卖的「抢跑」仍有现实用处。 本篇延续前作思路,挑 USDJPY 的 2023 年日线帧做样本,把 RSI 的 8 种形态逐个拉出回测,每种都附带形态说明与孤立测试结果,方便你直接开 MT5 复刻验证。外汇与贵金属杠杆高、滑点跳空频繁,RSI 信号只代表概率倾向,不构成方向承诺。
「30/70 阈值在 RSI 里的实战边界」
RSI 最经典的用法就是拿 30 和 70 当超卖、超买线:价格跌破 30 往往暗示资产进入超卖区,倾向看涨信号;站上 70 则反过来,概率上更偏空头机会。下面这段自定义信号类的代码,就是把这种传统形态直接写进了 EA 的入场判断里。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">0. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalRSI::IsPattern_0(class="type">ENUM_POSITION_TYPE T) { m_rsi.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Base(StartIndex()) <= class="num">30.0) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) >= class="num">70.0) { class="kw">return(true); } class="kw">return(class="kw">false); }
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">0. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalRSI::IsPattern_0(class="type">ENUM_POSITION_TYPE T) { m_rsi.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Base(StartIndex()) <= class="num">30.0) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex()) >= class="num">70.0) { class="kw">return(true); } class="kw">return(class="kw">false); }
◍ RSI 失败摇摆:用振荡器中轴确认情绪偏转
失败摇摆和单纯破阈值的区别在于,它先碰关键线,再回头穿回中轴另一侧,这种往返让反转意图比一根线破位更干净。具体落地:看涨要看 RSI 先探到 30 下方、随后收回到 30 上方;看跌则是先冲过 70、再收低于 70。 回测里形态 1 给出的信号质量倾向优于裸破 30/70,因为它用两次 RSI 移动确认了情绪偏转,不强制等价格本身收破。有交易者认为失败摇摆比 RSI 与价格背离更不容易骗线,但外汇和贵金属波动大,这仅是概率优势而非确定性。 下面这段 MT5 代码可直接塞进你的 RSI 信号类里验证。逻辑就两行判断:买条件是前一根 RSI 低于 30 且当前高于 30;卖条件是前一根高于 70 且当前低于 70。 //+------------------------------------------------------------------+
| // | Check for Pattern 1. |
|---|
//+------------------------------------------------------------------+
bool CSignalRSI::IsPattern_1(ENUM_POSITION_TYPE T)
{ m_rsi.Refresh(-1);
if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) < 30.0 && Base(StartIndex()) > 30.0)
{ return(true);
}
else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) > 70.0 && Base(StartIndex()) < 70.0)
{ return(true);
}
return(false);
}
逐行拆一下:m_rsi.Refresh(-1) 是先刷新指标缓冲避免用旧值;买分支里 Base(StartIndex()+1)<30.0 是上一根在超卖线下的证明,Base(StartIndex())>30.0 是当前已拉回线上;卖分支对称,把 30 换成 70、方向反过来即可。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">1. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalRSI::IsPattern_1(class="type">ENUM_POSITION_TYPE T) { m_rsi.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + class="num">1) < class="num">30.0 && Base(StartIndex()) > class="num">30.0) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + class="num">1) > class="num">70.0 && Base(StartIndex()) < class="num">70.0) { class="kw">return(true); } class="kw">return(class="kw">false); }
RSI 背离的编码与真假信号过滤
价格连刷更低的低点、RSI 却抬高低点,这是看涨背离;价格更高高点、RSI 反而低点更低,则是看跌背离。它本质暗示当前趋势动能衰减,反转倾向出现,但外汇与贵金属市场高杠杆下,这类信号只作概率参考,不能直接当入场令。 下面这段自定义信号类的判断函数,把形态 2 写死成连续三根 K 线的比较。买侧要求收盘价逐根走低、RSI 基值逐根走高;卖侧反过来。逻辑干净,但只认最近三段,不做平滑。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">2. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalRSI::IsPattern_2(class="type">ENUM_POSITION_TYPE T) { m_rsi.Refresh(-class="num">1); m_close.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Close(StartIndex()) < Close(StartIndex() + class="num">1) && Close(StartIndex() + class="num">1) < Close(StartIndex() + class="num">2) && Base(StartIndex()) > Base(StartIndex() + class="num">1) && Base(StartIndex() + class="num">1) > Base(StartIndex() + class="num">2) ) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex()) > Close(StartIndex() + class="num">1) && Close(StartIndex() + class="num">1) > Close(StartIndex() + class="num">2) && Base(StartIndex()) < Base(StartIndex() + class="num">1) && Base(StartIndex() + class="num">1) < Base(StartIndex() + class="num">2) ) { class="kw">return(true); } class="kw">return(class="kw">false); }
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">2. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalRSI::IsPattern_2(class="type">ENUM_POSITION_TYPE T) { m_rsi.Refresh(-class="num">1); m_close.Refresh(-class="num">1); if(T == POSITION_TYPE_BUY && Close(StartIndex()) < Close(StartIndex() + class="num">1) && Close(StartIndex() + class="num">1) < Close(StartIndex() + class="num">2) && Base(StartIndex()) > Base(StartIndex() + class="num">1) && Base(StartIndex() + class="num">1) > Base(StartIndex() + class="num">2) ) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Close(StartIndex()) > Close(StartIndex() + class="num">1) && Close(StartIndex() + class="num">1) > Close(StartIndex() + class="num">2) && Base(StartIndex()) < Base(StartIndex() + class="num">1) && Base(StartIndex() + class="num">1) < Base(StartIndex() + class="num">2) ) { class="kw">return(true); } class="kw">return(class="kw">false); }
「拿 50 中线当 RSI 的过滤器」
RSI 的 50 水平本身不代表方向,只是多空力量的分水岭。下穿倾向看跌、上破倾向看涨,但默认参数下它更接近“无信号”状态,所以单纯的中线交叉通常只作暗示,需要别的趋势工具确认,或者反过来拿它去过滤别的信号。外汇与贵金属波动剧烈,单靠这条线下单风险偏高。 在观望阶段,中线交叉有两种用法:顺势时,RSI 上穿 50 可能确认看涨延续,下穿可能确认看跌延续;反转时,从下方破 50 再跌回下方可能确认反转看跌,相反 U 形则倾向看涨反转。实测仅用该形态、输入参数设为 8 跑出来的信号偏多但确定性最低。 实务上常见做法是挂单配合该信号,并跨多个时间帧使用。它也能当尾随止损的开关:多头只要 RSI 稳在 50 上方就持有,跌破就离场;空头反过来。下面这段 MT5 代码只判断最近两根 K 线的中线穿越,买条件看前一根低于 50、当前高于 50,卖条件反之。 //+------------------------------------------------------------------+
| // | Check for Pattern 3. |
|---|
//+------------------------------------------------------------------+ bool CSignalRSI::IsPattern_3(ENUM_POSITION_TYPE T) { m_rsi.Refresh(-1); m_close.Refresh(-1); m_high.Refresh(-1); m_low.Refresh(-1); if(T == POSITION_TYPE_BUY && Base(StartIndex() + 1) < 50.0 && Base(StartIndex()) > 50.0) { return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + 1) > 50.0 && Base(StartIndex()) < 50.0) { return(true); } return(false); } 逐行拆解:函数入口先刷新 RSI 与高低收缓存,确保拿的是最新值;买分支比较前一根 Base 值小于 50、当前大于 50,捕捉上穿;卖分支逻辑镜像,捕捉下穿;都不满足返回 false,即本根 K 线未触发形态 3。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Check for Pattern class="num">3. | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">bool CSignalRSI::IsPattern_3(class="type">ENUM_POSITION_TYPE T) { m_rsi.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 && Base(StartIndex() + class="num">1) < class="num">50.0 && Base(StartIndex()) > class="num">50.0) { class="kw">return(true); } else if(T == POSITION_TYPE_SELL && Base(StartIndex() + class="num">1) > class="num">50.0 && Base(StartIndex()) < class="num">50.0) { class="kw">return(true); } class="kw">return(class="kw">false); }