从新手到专家:使用 MQL5 制作动画新闻标题 (三) 指标洞察(基础篇)
用 MQL5 给新闻标题做动画的底层思路
在 MT5 里把新闻标题做成动画,本质是用指标缓冲区承载字符串并在 OnCalculate 里按帧刷新,而不是另开一个独立窗口进程。这套做法依赖 MQL5 的 IndicatorCreate 与自定义绘制缓冲,能在图表左上角叠加滚动文字而不阻塞报价。 原文给出的示例工程在 2026 年 2 月 2 日 08:55 发布,截至统计时点已有 423 次查看、0 条评论,说明这类偏可视化改造的内容在交易者社区里关注度不低但互动偏冷。你可以在 MT5 的 MQL5 向导里新建一个指标工程,把文本绘制逻辑塞进缓冲区来验证这个路径是否跑得通。 外汇与贵金属市场高杠杆、价格跳空频繁,任何基于新闻的视觉提示都只是辅助,不能替代仓位与止损纪律;动画标题可能帮你更快注意到事件,但也可能因过度醒目诱发频繁操作。
「把振荡指标塞回主图而不是占子窗口」
传统振荡指标大多挂在主图下方的独立子窗口,窗口一多,主图可视高度就被吃掉,价格走势的细节空间随之压缩。 我们用 MQL5 的 CCanvas 类在图表内直接画一个指标洞察通道,通过 MQL5 API 取数、处理并在不切分工作区的前提下显示信号,避免像素被子窗口抢占。 原文给过一张可视化示例:叠加多个指标子窗口后,主图视图高度明显变小。开 MT5 随便挂 MACD + RSI + Stochastic 三个子窗口,再对比无子窗口的主图,就能复现这种压缩现象。外汇与贵金属波动剧烈,界面空间受限会放大误判风险,通道化呈现更利于盯盘。
◍ 四振荡指标的核心用法与阈值
小布盯盘计划默认在 MT5 图表上用一条滚动通道聚合四个振荡指标:RSI、CCI、随机震荡指标和 MACD。偏好细节的人可展开成独立通道,每指标占一条。后续若接入分析师 API,还会挂一个精选见解区,把专家评论直接铺在图上。 RSI 由 Wilder 在 1978 年提出,默认 14 周期。0–100 区间,70 以上算超买、30 以下算超卖,50 是多空分水岭。区间震荡市里,突破 30 向上常看作买入倾向,跌破 70 向下常看作卖出倾向;价格新高但 RSI 高点更低则是看跌背离。外汇与贵金属波动大,单看 RSI 容易假突破,需结合价格行为确认。 CCI 由 Lambert 于 1980 年提出,典型价=(高+低+收)/3,常用 20 周期、系数 0.015 缩放。它绕零波动,+100 上方超买、-100 下方超卖,趋势强时可冲到 ±200。注意 CCI 跌破 -100 后价格还可能再跌几个点才反转,这是高频假信号源,必须等回穿 -100 或别的指标确认。 随机震荡指标是 Lane 上世纪 50 年代的东西,%K 为快线、%D 为 3 周期均线的慢线。80 上超买、20 下超卖;%K 上穿 %D 且都在 20 下,是偏强的买入信号。MACD 用 12EMA-26EMA 得快线,再取 9EMA 作信号线,柱图是二者差。零轴上方看涨、下方看跌,柱图变窄往往意味着动能衰减、反转概率上升。 一张速查表收一下关键点:RSI 看 30/70、适合区间;CCI 看 ±100、适合趋势;随机看 20/80 与双线交叉、横盘趋势通吃;MACD 看信号线交叉与零轴、专跟趋势。下一节我们直接拆代码看这些怎么落地。
把指标读数塞进 EA 的滚动画布
在 MT5 里抓内置指标值,核心就三步:用 iRSI、iStochastic 这类函数建句柄时把品种和周期参数留空,自动吃当前图表上下文;拿 CopyBuffer 从输出缓冲区读最新一根;读完马上 IndicatorRelease 释放句柄。每个指标周期只建一次句柄,能压住资源占用,也避免 EA 跑久了句柄泄漏。 下面这段输入和全局声明决定了画布怎么分:InpSeparateLanes 控制是四条独立通道还是合并成一屏,InpInsightSpeed 是滚动像素步长,默认 3。CCanvas 对象必须挂全局,否则定时器回调后句柄就丢了,滚动偏移量也跟着没。 [CODE] 里的 ComputeRSIInsight 就是标准模板:iRSI(NULL,PERIOD_CURRENT,14,PRICE_CLOSE) 建句柄,CopyBuffer(h,0,1,1,b) 取倒数第 1 根(即最新已闭合 K),释放后按 30/70 阈值贴 Oversold / Overbought / Neutral 标签。Stoch 同理,阈值用的是 20/80。把四个信号拼成一串,组合通道的渲染逻辑能短一大截。 OnInit 里按模式建画布,组合模式只建一个并写死 “Indicator Insights:” 前缀,独立模式建四个;OnTimer 每次重定位画布、重载数据、最后批量更新,减少闪烁。OnDeinit 里 CreateBitmapLabel 和 Destroy 一一对应,并 KillTimer,否则 EA 移除后残留位图和回调。外汇和贵金属波动大、杠杆高,这类叠加指标文字的 EA 仅供辅助观察,信号误报概率不低,实盘前先在策略测试器跑一轮。
<span class="keyword">input</span> <span class="keyword">class="type">bool</span> <span style="background-class="type">color:rgb(class="num">249, class="num">204, class="num">202);">InpSeparateLanes </span> = <span class="macro">class="kw">false</span>; <span class="comment">class=class="str">"cmt">// combined vs separate insights</span> <span class="keyword">input</span> <span class="keyword">class="type">int</span> <span style="background-class="type">color:rgb(class="num">255, class="num">242, class="num">153);">InpInsightSpeed </span> = <span class="number">class="num">3</span>; <span class="comment">class=class="str">"cmt">// scroll speed for insight text</span> <span class="comment">class=class="str">"cmt">//--- Globals ---------------------------------------------</span> CCanvas combinedCanvas; <span class="comment">class=class="str">"cmt">// holds all four insights in one lane</span> CCanvas rsiCanvas, stochCanvas, macdCanvas, cciCanvas; <span class="comment">class=class="str">"cmt">// separate lanes</span> <span class="keyword">class="type">int</span> offCombined, offRSI, offStoch, offMACD, offCCI; <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//| Compute indicator insights |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">class="kw">string</span> ComputeRSIInsight() { <span class="keyword">class="type">int</span> h=<span class="indicators">iRSI</span>(<span class="macro">NULL</span>,<span class="macro">PERIOD_CURRENT</span>,<span class="number">class="num">14</span>,<span class="macro">PRICE_CLOSE</span>); <span class="keyword">if</span>(h==<span class="macro">INVALID_HANDLE</span>) <span class="keyword">class="kw">return</span> <span class="class="type">class="kw">string">"["</span>+<span class="functions">Symbol</span>()+<span class="class="type">class="kw">string">"] RSI err"</span>; <span class="keyword">class="type">class="kw">double</span> b[]; <span class="functions">CopyBuffer</span>(h,<span class="number">class="num">0</span>,<span class="number">class="num">1</span>,<span class="number">class="num">1</span>,b); <span class="functions">IndicatorRelease</span>(h); <span class="keyword">class="type">class="kw">double</span> v=b[<span class="number">class="num">0</span>]; <span class="keyword">class="type">class="kw">string</span> s=<span class="functions">DoubleToString</span>(v,<span class="number">class="num">1</span>); <span class="keyword">class="type">class="kw">string</span> m=v<<span class="number">class="num">30</span>?<span class="class="type">class="kw">string">"Oversold("</span>+s+<span class="class="type">class="kw">string">")"</span>:v><span class="number">class="num">70</span>?<span class="class="type">class="kw">string">"Overbought("</span>+s+<span class="class="type">class="kw">string">")"</span>:<span class="class="type">class="kw">string">"Neutral("</span>+s+<span class="class="type">class="kw">string">")"</span>; <span class="keyword">class="kw">return</span> <span class="class="type">class="kw">string">"["</span>+<span class="functions">Symbol</span>()+<span class="class="type">class="kw">string">"] RSI:"</span>+m; } <span class="keyword">class="type">class="kw">string</span> ComputeStochInsight() { <span class="keyword">class="type">int</span> h=<span class="indicators">iStochastic</span>(<span class="macro">NULL</span>,<span class="macro">PERIOD_CURRENT</span>,<span class="number">class="num">14</span>,<span class="number">class="num">3</span>,<span class="number">class="num">3</span>,<span class="macro">MODE_SMA</span>,<span class="macro">STO_LOWHIGH</span>); <span class="keyword">if</span>(h==<span class="macro">INVALID_HANDLE</span>) <span class="keyword">class="kw">return</span> <span class="class="type">class="kw">string">"["</span>+<span class="functions">Symbol</span>()+<span class="class="type">class="kw">string">"] Stoch err"</span>; <span class="keyword">class="type">class="kw">double</span> b[]; <span class="functions">CopyBuffer</span>(h,<span class="number">class="num">0</span>,<span class="number">class="num">1</span>,<span class="number">class="num">1</span>,b); <span class="functions">IndicatorRelease</span>(h); <span class="keyword">class="type">class="kw">double</span> v=b[<span class="number">class="num">0</span>]; <span class="keyword">class="type">class="kw">string</span> s=<span class="functions">DoubleToString</span>(v,<span class="number">class="num">1</span>); <span class="keyword">class="type">class="kw">string</span> m=v<<span class="number">class="num">20</span>?<span class="class="type">class="kw">string">"Oversold("</span>+s+<span class="class="type">class="kw">string">")"</span>:v><span class="number">class="num">80</span>?<span class="class="type">class="kw">string">"Overbought("</span>+s+<span class="class="type">class="kw">string">")"</span>:<span class="class="type">class="kw">string">"Neutral("</span>+s+<span class="class="type">class="kw">string">")"</span>; <span class="keyword">class="kw">return</span> <span class="class="type">class="kw">string">"["</span>+<span class="functions">Symbol</span>()+<span class="class="type">class="kw">string">"] Stoch:"</span>+m; } <span class="keyword">class="type">class="kw">string</span> ComputeMACDInsight() {