创建一个行情卷播面板:改进版(基础篇)
📘

创建一个行情卷播面板:改进版(基础篇)

第 1/2 篇

「用多周期分屏把行情塞进一块面板」

想在 MT5 里少切图表、又能同时盯多个品种的节奏,最直接的办法是做一个卷播面板:把若干货币对或贵金属的报价、涨跌和关键技术位,按固定间隔轮播到同一块子窗口。外汇与贵金属波动受杠杆和流动性影响,跳空与滑点风险高,面板只解决“看”的效率,不解决“一定看懂”。 原文作者 Daniel Jose 于 2023 年 2 月 22 日发布该改进版思路,截至统计显示有 2012 次查看、17 条讨论,说明多品种同屏监控是实盘高频痛点。你可以先开 MT5 的 Indicators 目录,新建一个空指标把多符号循环写进 OnCalculate,验证轮播是否卡顿。 真正值得调的参数有两个:轮播间隔(毫秒)和同屏最大符号数。间隔太短 CPU 占用陡增,太长又漏掉瞬时刺穿;符号数超过 8 个时,小周期图表刷新延迟会明显偏高,建议先用 5 个观察一天。

面板为什么要从基础版继续往下做

前一篇里我们用指标形式搭了个实时价格卷播面板,但当时刻意只写了最少代码,目的只是演示‘让面板看起来在动’的过程:用户只要指定数值递增还是递减,指标就能向右、向左或静止滑动,根本不用专门写位移算法。 这种极简做法的代价是信息密度太低。光靠滚动的数字,交易者很难一眼分辨当前播的是哪个品种,尤其在同时盯黄金、欧美、美日等多个标的时,认知负担反而比看普通报价窗口更高。 所以这一节先不动计算逻辑,而是改视图层:给面板加上资产徽标或自定义图像,用视觉锚点替代纯文字识别。外汇和贵金属市场波动剧烈、杠杆风险极高,盯盘效率的微小提升,都可能减少误读导致的随手错单。 至于只加图的新面板,单独拿出来依然不够实用——后面还得补别的机制,否则它比直接用 MT5 原有市场观察窗口没多少优势。

◍ 报价面板的类抽象与图像呈现

新版报价面板第一步是建一个抽象位图类 C_Object_BtnBitMap,它只管把资产图像贴到图表上,不暴露底层细节。Create 里先建 OBJ_BITMAP_LABEL 对象,再指定 BMP 路径、关掉按钮选中态,调用方完全不用管屏幕绘制逻辑。 这种抽象的直接代价是:若图像缺失或格式不对,ObjectSetString 会返回 false,但示例代码没做删除处理,图表上只会留一块空白区暗示出错。外汇与贵金属图表挂 EA 时这类静默失败很常见,手动开对象列表核对路径能省掉误判。 位图类的硬限制是不能用透明背景,强行套现有代码会得到怪异贴图而非资产徽标。想上 GIF 或透明 PNG,得绕到位图资源直读那套思路——改类内部实现即可,面板其余代码一行不用动。 C_Object_Edit 也升了级:字体类型和字号变成可调参数,文本类能承载更杂的信息。运行时按传入类型分流,字符串原样写、double 型当报价上色,还能挂后缀做调用提示,最后统一调色呈现。 拼起来后面板左上角是资产图、代码紧随,右上日变动、左下涨跌箭头、右下最新报价,全部由 C_Widget 调度这几个类输出。

MQL5 / C++
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include "C_Object_Base.mqh"
class=class="str">"cmt">//+------------------------------------------------------------------+
class C_Object_BtnBitMap : class="kw">public C_Object_Base
{
      class="kw">public  :
class=class="str">"cmt">//+------------------------------------------------------------------+
            class="type">void Create(class="type">class="kw">string szObjectName, class="type">class="kw">string szResource1)
              {
                C_Object_Base::Create(szObjectName, OBJ_BITMAP_LABEL);
                ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_BMPFILE, class="num">0, "\\Images\\Widget\\Bitmaps\\" + szResource1 + ".bmp");
                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_STATE, false);
              };
class=class="str">"cmt">//+------------------------------------------------------------------+
};
class="kw">template < class="kw">typename T >
class="type">void Create(class="type">class="kw">string szObjectName, class="type">color corTxt, class="type">color corBack, T InfoValue, class="type">class="kw">string szFont = "Lucida Console", class="type">int iSize = class="num">10)
    {
      C_Object_Base::Create(szObjectName, OBJ_EDIT);
      ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_FONT, szFont);
      ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_FONTSIZE, iSize);
      ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_ALIGN, ALIGN_LEFT);

「用模板函数统一面板文字与配色」

在 MT5 里给图表对象批量写值,最怕类型判断散落各处。下面这段模板把字符串、双精度、未知类型三种情况收口到一个入口,省得每次手搓分支。 代码里先按传入颜色优先、否则沿用对象原有颜色决定 clr;若传入的是 double 且为负,则套用 def_ColorNegative,否则用 def_ColoPositive(注意原文拼写,复制时别手改)。绝对值经 Terminal.ViewDouble 格式化后拼后缀再显示,未知类型直接回退到 "?#?" 便于排错。 对象属性设置走 Terminal.Get_ID() 拿图表句柄:背景色、边框色与只读标记在前一段一次性写完,文本与前景色在 SetTextValue 内落盘。外汇与贵金属行情跳动快,这类只读标签若忘了设 OBJPROP_READONLY 为 true,手动误触改值可能让面板显示偏离实际,建议开 MT5 把这段直接挂到自己的 HUD 绘制流程里验证。

MQL5 / C++
ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BGCOLOR, corBack);
ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BORDER_COLOR, corBack);
ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_READONLY, true);
SetTextValue(szObjectName, InfoValue, corTxt);
};
class="kw">template < class="kw">typename T >
class="type">void SetTextValue(class="type">class="kw">string szObjectName, T InfoValue, class="type">color cor = clrNONE, class="kw">const class="type">class="kw">string szSufix = "")
	{
		class="type">color clr = (cor != clrNONE ? cor : (class="type">color)ObjectGetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR));
		class="type">class="kw">string sz0;
		
		if (class="kw">typename(T) == "class="type">class="kw">string") sz0 = (class="type">class="kw">string)InfoValue; else
		if (class="kw">typename(T) == "class="type">class="kw">double")
		{
			clr = (cor != clrNONE ? cor : ((class="type">class="kw">double)InfoValue < class="num">0.0 ? def_ColorNegative : def_ColoPositive));
			sz0 = Terminal.ViewDouble((class="type">class="kw">double)InfoValue < class="num">0.0 ? -((class="type">class="kw">double)InfoValue) : (class="type">class="kw">double)InfoValue) + szSufix;
		}else  sz0 = "?#?";
		ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TEXT, sz0);
		ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, clr);
	};

常见问题

用分屏坐标算法把不同周期K线按比例缩放到同一画布区域,基础篇给出的类结构可直接套用。
基础版只解决单品种轮播,缺少多周期同屏与配色统一,改进版补的是可读性和维护成本。
可以,小布能按你选的品种和周期自动排好分屏坐标与配色,你只需确认参数即可上屏。
把文字与配色收进模板函数统一调用,减少重复创建对象,重绘时只更新差异区域。
用模板函数集中管字体大小、对齐方式和调色板,所有面板元素都从同一处取样式。