在MQL5中创建动态多品种、多周期相对强弱指数(RSI)指标仪表盘(基础篇)
📘

在MQL5中创建动态多品种、多周期相对强弱指数(RSI)指标仪表盘(基础篇)

第 1/3 篇

◍ 用 MQL5 搭一个跨品种跨周期 RSI 仪表盘

想在 MT5 里一眼看清多个品种、多个周期的 RSI 强弱分布,原生终端做不到,得自己写指标。核心思路是:在一个独立窗口里,用二维网格把品种列在纵轴、周期排在横轴,每个格子实时算出对应 RSI 值并染色。 实现上靠 iRSI 拿句柄、CopyBuffer 取缓冲,再用 Canvas 或标准画布对象把数值画成色块。下面这段是取 RSI 句柄与读缓冲的最小骨架,跑通它你就能在终端里验证多周期拉取是否真的无阻塞。 外汇与贵金属波动大,RSI 只是概率性超买超卖参考,跨周期共振也不代表方向必现,实盘前请在策略测试器用 2024 年 XAUUSD 数据回测确认延迟。

MQL5 / C++
class="type">int rsi_handle = iRSI(_Symbol, PERIOD_M15, class="num">14, PRICE_CLOSE);
if(rsi_handle == INVALID_HANDLE) class="kw">return;
class="type">class="kw">double rsi_buf[class="num">1];
CopyBuffer(rsi_handle, class="num">0, class="num">0, class="num">1, rsi_buf);
class="type">class="kw">double current_rsi = rsi_buf[class="num">0];

「为什么要在MT5里搭一个RSI总控面板」

做多品种盯盘的人都知道,切图表看RSI是件反人性的事。MT5原生副图一次只绑一个符号、一个周期,想横比 EURUSD 与 XAUUSD 在 M15、H1 的强弱,得手动翻四五个窗口。用 MQL5 写一个动态仪表盘,把多标的、多周期的 RSI 值塞进同一个界面,这类摩擦能直接消掉。 RSI 本身还是那个 0–100 的相对强弱指数,14 周期默认算法没变。仪表盘的价值不在改指标,而在把超买(>70)超卖(<30)信号从「翻窗才发现」变成「一眼扫完」。外汇与贵金属波动属性不同,同一时刻 XAUUSD 可能卡在 72 的超买区,EURUSD 还在 45 的中性带,这种跨市场背离靠单图根本来不及抓。 这篇要落地的东西很具体:初始化时把品种列表和周期按钮画出来;实时根据 tick 重算并显示 RSI;按钮的创建与刷新函数逐行拆给你看;最后讲怎么按自己的品种池改参数。读完你该去开 MetaEditor 建一个空白指标工程,把后面给的代码贴进去编译,而不是只停留在「原来还能这样」。 开发环境锁定 MetaTrader 5 加 MetaEditor,MQL5 是唯一的编写语言。没有 MT5 终端和对应编辑器,后面的函数原型你连编译入口都找不到,先确认版本再往下走。

把多周期RSI塞进一个面板

做这个面板的核心目的,是在 MT5 一个窗口里同时盯住多个品种、多个时间框架的 RSI,不用来回切图表。初始化时先放一个主按钮在顶部,它既是 UI 焦点也作为后续控件的定位基准。 主按钮旁边横向排一排时间框架按钮,各自标上周期缩写(M1、M5、H1 等),点击即展示对应周期的 RSI。主按钮下方垂直生成品种按钮,直接读终端「市场观察」里的品种列表,当前激活品种用亮绿色高亮,一眼能认出在看哪一个。 品种列表最底下压一个基础按钮,宽度等于所有周期按钮之和,写仪表盘名字或当前品种信号摘要,顺带把品种区和数值区隔开。 RSI 用 MQL5 内置函数按收盘价实时算,结果存数组,每来一个新 tick 就刷新。显示逻辑很直接:低于 30 超卖刷绿底,高于 70 超买刷红底,30–70 之间留白底。外汇和贵金属波动大、滑点凶,这种颜色预警只帮你快速扫市场状态,不代表反向开仓就稳,真要下单还得结合自己的风控。

◍ 用 EA 模板搭按钮仪表盘的底子

在 MT5 里做指标仪表盘,载体选 EA 而不是脚本。开 MetaEditor 用 F4 或工具栏 IDE 图标,CTRL+N 新建文档,向导里勾 EA(模板)一路下一步,文件会落进 Experts\ 目录,想换子目录就在名字前加反斜杠。 按钮不能一个个手写,先封一个可复用的 createButton 布尔函数,成功返 true 失败返 false,接 11 个参数:objName 与 text 是字符串,xD/yD 是到角落的像素偏移,xS/yS 是宽高,clrTxt/clrBg/clrBorder 是颜色,fontSize 默认 12,font 默认 Arial Rounded MT Bold。参数里带默认值的,调用时省略就走默认值,比如边框默认 clrNONE。 函数体先用 ResetLastError 清掉旧错误码,再 ObjectCreate(0, objName, OBJ_BUTTON, 0, 0, 0) 在主窗口建按钮——后两个 0 是时间价格坐标,因为我们用像素贴窗口而不是绑 K 线。创建失败就 Print 错误并 return false;成功则用 ObjectSetInteger 挨个设 OBJPROP_XDISTANCE / YDISTANCE / XSIZE / YSIZE / CORNER,CORNER 只能取四个角之一。最后 ChartRedraw 强制重绘,return true。 为省事用 #define 给按钮名和尺寸上宏:BTN1 存主按钮名,Desc/Symb/Base/RSI 做前缀拼出唯一名,XS1=90、YS1=25 像素,clrW/clrB 引白黑,自定义 clrW_Gray=C'230,230,230' 走 RGB。周期塞进 static ENUM_TIMEFRAMES periods[] = {PERIOD_M1,M5,H1,H4,D1},RSI 句柄用 int handleName_Id 接,值倒进 double rsi_Data_Val[] 动态数组,全设全局变量方便实时刷。 初始化放 OnInit,调 createButton(BTN1," ",600,50,XS1,YS1,clrW,clrW_Gray,15,clrW_Gray) 就从右上角偏移 600/50 像素画出 90x25 的灰底白字按钮;图表缩到 0 时两十字光标间柱数约等于水平像素数,可据此估坐标。周期按钮不写死,用 for(i=0;i<ArraySize(periods);i++) 拼 Desc+IntegerToString(i) 动态建,标签用 truncPrds 把周期截成 M1/M5 这类再加 "RSI 14"。外汇贵金属 GUI 自动化高风险,像素坐标因屏幕 DPI 可能偏位,实机核对再固参。

「把交易商品种和周期做成动态按钮矩阵」

MT5 里想做多品种多周期监控,第一步是把周期枚举转成干净标签。ENUM_TIMEFRAMES 经 EnumToString 会得到带 "PERIOD_" 前缀的字符串,用 StringSubstr 从第 7 个字符截起,刚好剥掉这 7 个字符(含下划线),按钮上只留 M1、H1 这类短名。 品种侧不能写死数组。SymbolsTotal(false) 在实测环境返回 396,全部塞进图表必然挤成一团;改成 SymbolsTotal(true) 只取市场观察窗口里的,实测打印出 12 个,这才是能用的规模。配合 for 循环加 SymbolName(i, true),按钮名用 "Symb " 拼 IntegerToString(i) 保证唯一,x 固定 600、y 按 (50+YS1)+i*YS1 下排,YS1=25 像素,自动跟随市场观察增删。 活跃品种要一眼分辨:用 _Symbol 比对,命中就把背景改亮绿、文字黑、边框白,其余走灰底白字默认款。末尾再补一个基准按钮,名称拼 "Base"+i,标签写 "RSI仪表盘",y 落在最后品种下方,宽度用 XS1+XS2*ArraySize(periods) 盖住整排周期键。 RSI 网格用双循环:外循环 i 跑品种、内循环 j 跑周期,按钮名拼 "RSI"+j+品种名,x=(600-XS1)+j*(-XS2)、y=(50+YS1)+i*YS1,宽高各减 1 像素留出缝隙形成网格感。iRSI 句柄从 10 起算,12 品种 ×5 周期 = 60 个,加上前面 9 个占位,最大句柄 ID 到 69。CopyBuffer 取 1 个点前务必 ArraySetAsSeries(...,true),让最新值落在数组头。 [CODE]string TF_ToStr(ENUM_TIMEFRAMES tf) { string s = EnumToString(tf); return StringSubstr(s, 7); } [/CODE] 更新不用重建对象:ObjectFind 返回负数即对象缺失,直接报错返回 false;找到就用 ObjectSetString/ObjectSetInteger 改文本与配色。超卖判定写死 RSI<30 时文字白、背景与边框绿,提示潜在买入倾向——外汇贵金属波动剧烈,这种颜色信号只是概率参考,不是进场指令。

MQL5 / C++
class="type">class="kw">string TF_ToStr(ENUM_TIMEFRAMES tf)
{
   class="type">class="kw">string s = EnumToString(tf);
   class="kw">return StringSubstr(s, class="num">7);
}

让仪表盘随 tick 活起来并干净退场

RSI 高于 70 时把按钮文字刷成白色、背景与边框刷成红色,这种红块在视觉上提示超买倾向,配合 30–70 区间的默认中性配色,能让看图的人一眼分辨状态。每帧更新靠 OnTick 事件处理器:把初始化里的内外双循环原样搬进 void OnTick(),报价一变就重算指标并调 update_Button 传参,仪表盘才谈得上实时。 EA 撤出图表时必须清场,否则按钮和文字对象会残留在窗口里。OnDeinit 里对 "BTN1"、"Desc"、"Symb"、"Base"、"RSI" 五个前缀各调一次 ObjectDeleteAll,再跑 ChartRedraw 刷新,图表就回到干净状态。外汇与贵金属波动剧烈,这类可视化只是辅助参考,信号误报概率不低,实盘前务必在 MT5 策略测试器里跑通。 下面这段 createButton 的核心设置代码,可直接抄进你的 EA 工程里改坐标和颜色:

MQL5 / C++
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="comment">class=class="str">"cmt">//| Function to create a button                                                        |</span>
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span>
<span class="keyword">class="type">bool</span> createButton(<span class="keyword">class="type">class="kw">string</span> objName, <span class="keyword">class="type">class="kw">string</span> text, <span class="keyword">class="type">int</span> xD, <span class="keyword">class="type">int</span> yD, <span class="keyword">class="type">int</span> xS, <span class="keyword">class="type">int</span> yS,
   <span class="keyword">class="type">class="kw">color</span> clrTxt, <span class="keyword">class="type">class="kw">color</span> clrBg, <span class="keyword">class="type">int</span> fontSize = <span class="number">class="num">12</span>, <span class="keyword">class="type">class="kw">color</span> clrBorder = <span class="macro">clrNONE</span>,
   <span class="keyword">class="type">class="kw">string</span> font = <span class="class="type">class="kw">string">"Arial Rounded MT Bold"</span>
) {
...
}
   <span class="comment">class=class="str">"cmt">// Attempt to create the button</span>
   <span class="keyword">if</span> (!<span class="functions">ObjectCreate</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJ_BUTTON</span>, <span class="number">class="num">0</span>, <span class="number">class="num">0</span>, <span class="number">class="num">0</span>)) {
      <span class="functions">Print</span>(<span class="keyword">__FUNCTION__</span>, <span class="class="type">class="kw">string">": failed to create Btn: ERR Code: "</span>, <span class="functions">GetLastError</span>()); <span class="comment">class=class="str">"cmt">// Print error message if button creation fails</span>
      <span class="keyword">class="kw">return</span> (<span class="macro">false</span>); <span class="comment">class=class="str">"cmt">// Return false if creation fails</span>
   }
   <span class="functions">ResetLastError</span>(); <span class="comment">class=class="str">"cmt">// Reset the last error code</span>
   <span class="comment">class=class="str">"cmt">// Set button properties</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_XDISTANCE</span>, xD); <span class="comment">class=class="str">"cmt">// Set X distance</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_YDISTANCE</span>, yD); <span class="comment">class=class="str">"cmt">// Set Y distance</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_XSIZE</span>, xS); <span class="comment">class=class="str">"cmt">// Set X size</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_YSIZE</span>, yS); <span class="comment">class=class="str">"cmt">// Set Y size</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_CORNER</span>, <span class="macro">CORNER_RIGHT_UPPER</span>); <span class="comment">class=class="str">"cmt">// Set corner position</span>
   <span class="functions">ObjectSetString</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_TEXT</span>, text); <span class="comment">class=class="str">"cmt">// Set button text</span>
   <span class="functions">ObjectSetString</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_FONT</span>, font); <span class="comment">class=class="str">"cmt">// Set font type</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_FONTSIZE</span>, fontSize); <span class="comment">class=class="str">"cmt">// Set font size</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_COLOR</span>, clrTxt); <span class="comment">class=class="str">"cmt">// Set text class="type">class="kw">color</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_BGCOLOR</span>, clrBg); <span class="comment">class=class="str">"cmt">// Set background class="type">class="kw">color</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_BORDER_COLOR</span>, clrBorder); <span class="comment">class=class="str">"cmt">// Set border class="type">class="kw">color</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_BACK</span>, <span class="macro">false</span>); <span class="comment">class=class="str">"cmt">// Set background class="kw">property</span>
   <span class="functions">ObjectSetInteger</span>(<span class="number">class="num">0</span>, objName, <span class="macro">OBJPROP_STATE</span>, <span class="macro">false</span>); <span class="comment">class=class="str">"cmt">// Set button state</span>

常见问题

可以用MQL5写一个动态按钮矩阵仪表盘,把品种和周期做成可点击按钮,RSI值随tick实时刷新,不用反复切换图表。
单图表子窗口只能看当前品种,总控面板能把多品种多周期RSI集中一屏,扫盘效率更高,也方便对比强弱分化。
小布盯盘已内置多品种RSI诊断,打开对应品种页即可直接看到各周期RSI状态,不用自己搭面板也能扫场。
在OnDeinit里遍历删除自建的按钮和标签对象,并释放动态数组,保证指标或EA卸载后图表干净无残留。
只在OnTick里更新可见按钮的RSI文本与配色,不重建对象;品种数控制在十几个内,实测对常规电脑无明显卡顿。