MQL5 交易工具(第五部分):创建滚动行情条,实现交易品种实时监控·进阶篇
📊

MQL5 交易工具(第五部分):创建滚动行情条,实现交易品种实时监控·进阶篇

(2/3)· 手动切图看 EURUSD、GBPUSD、BTCUSD 报价太慢?这篇把多品种买价点差涨幅压进一条滚动条

实战向 第 2/3 篇
很多交易者还在靠来回切换图表或开一堆小窗口盯报价,行情一跳就漏看。多品种同屏却没有统一滚动视图,决策节奏天然慢半拍。把监控逻辑写死在单一图表里,也迟早被品种扩容拖垮。

◍ 先搭好多品种报价面板的全局骨架

想在 MT5 里做一个跨品种盯盘面板,第一步不是画图,而是把数据容器定清楚。下面这段全局声明定义了符号数组、品种数据结构以及对象管理器,后续所有刷新逻辑都围绕它转。 核心是一个 SymbolData 结构体,把每个品种的买价、卖价、点差、昨买价、日开盘、当日涨跌幅和颜色箭头全装进去。这样在 OnTimer 里轮询时,只需读一次 prices[i] 就能拿到渲染面板所需的全部字段,避免重复调用 MarketInfo。 别把正态当圣经:结构里特意留了 prev_bid 和 daily_open,说明面板不只显示瞬时报价,还要做日内变动着色。实盘里 EURUSD 点差常落在 0.0–1.5 点,XAUUSD 可能在 1.5–4.0 点,靠 spread 字段就能在面板里标出异常滑点时段。 代码逐行拆解见下:string symbolArray[] 存品种名;int totalSymbols 记总数;struct SymbolData 内 bid/ask/spread 为实时价,prev_bid 作方向比对,daily_open 算百分比,color 与 arrow_char 控制视觉;prices[] 是结构体数组;dashboardName/backgroundName 给图形对象命名;CArrayString objManager 管文本与图形资源;datetime lastDay 用来判断跨日重置日开盘。外汇与贵金属波动剧烈,面板数据仅辅助决策,实际下单仍需自担高风险。

MQL5 / C++
class="type">class="kw">string symbolArray[];                     class=class="str">"cmt">//--- Array to store symbol names
class="type">int totalSymbols;                           class=class="str">"cmt">//--- Total number of symbols
class="kw">struct SymbolData                           class=class="str">"cmt">//--- Structure to hold symbol price data
{
   class="type">class="kw">double bid;                              class=class="str">"cmt">//--- Current bid price
   class="type">class="kw">double ask;                              class=class="str">"cmt">//--- Current ask price
   class="type">class="kw">double spread;                           class=class="str">"cmt">//--- Current spread
   class="type">class="kw">double prev_bid;                         class=class="str">"cmt">//--- Previous bid price
   class="type">class="kw">double daily_open;                       class=class="str">"cmt">//--- Daily opening price
   class="type">class="kw">color bid_color;                         class=class="str">"cmt">//--- Color for bid price display
   class="type">class="kw">double percent_change;                   class=class="str">"cmt">//--- Daily percentage change
   class="type">class="kw">color percent_color;                     class=class="str">"cmt">//--- Color for percentage change
   class="type">class="kw">string arrow_char;                       class=class="str">"cmt">//--- Arrow character for price direction
   class="type">class="kw">color arrow_color;                       class=class="str">"cmt">//--- Color for arrow
};
SymbolData prices[];                        class=class="str">"cmt">//--- Array of symbol data structures
class="type">class="kw">string dashboardName = "TickerDashboard";   class=class="str">"cmt">//--- Name for dashboard objects
class="type">class="kw">string backgroundName = "TickerBackground"; class=class="str">"cmt">//--- Name for background object
CArrayString objManager;                    class=class="str">"cmt">//--- Object manager for text and image objects
class="type">class="kw">datetime lastDay = class="num">0;                       class=class="str">"cmt">//--- Track last day for daily open update

用 OBJ_LABEL 在图表上打自定义文字

想在 MT5 图表左上角贴一段动态文字(比如实时波动率或 AIGC 信号备注),最轻量的做法是走 OBJ_LABEL 对象,而不是去碰繁重的图形资源。下面这段函数把创建、查重、属性设置全包了,复制进 EA 或脚本就能直接调。 先说查重逻辑:用 ObjectFind(0, objName) 判断同名标签是否已存在,返回负值才进创建分支。创建前务必 ResetLastError() 清掉错误码,否则后面 GetLastError() 读到的可能是上一次调用的残留,这点在外汇高频刷新脚本里容易埋坑。 创建失败时不抛异常,而是交给 LogError() 把函数名、对象名和错误码拼成字符串写进终端日志。LogError 本身只有一行 Print(message),但配合 __FUNCTION__ 宏能快速定位是哪段代码炸了。 属性设置部分有 11 个 ObjectSetInteger / ObjectSetString 调用,覆盖坐标(XDISTANCE/YDISTANCE)、对齐角(CORNER_LEFT_UPPER)、文字内容、颜色、字号、字体,以及不可选中、不置背景、Z 序为 0。CORNER_LEFT_UPPER 意味着 x/y 是相对左上角的像素偏移,调 x 超过图表宽度文字会被裁掉,实盘前建议先用 50/50 试位。 objManager.Add(objName) 这行把新建对象名登记进自己的管理器,方便后续统一删除,避免切换周期时图表残留标签——贵金属这类多周期盯盘场景下残留对象会让界面越来越脏。

MQL5 / C++
class="type">void LogError(class="type">class="kw">string message)                                              class=class="str">"cmt">// Log error messages
{
   Print(message);                                                                  class=class="str">"cmt">//--- Output message to log
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Create Text Label Function                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool createText(class="type">class="kw">string objName, class="type">class="kw">string text, class="type">int x, class="type">int y, class="type">class="kw">color clrTxt, class="type">int fontsize, class="type">class="kw">string font)
{
   ResetLastError();                                                                class=class="str">"cmt">//--- Clear last error code
   if(ObjectFind(class="num">0, objName) < class="num">0)                                                   class=class="str">"cmt">//--- Check if object does not exist
   {
      if(!ObjectCreate(class="num">0, objName, OBJ_LABEL, class="num">0, class="num">0, class="num">0)) class=class="str">"cmt">//--- Create text label object
      {
         LogError(__FUNCTION__ + ": Failed to create label: " + objName + ", Error: " + IntegerToString(GetLastError())); class=class="str">"cmt">//--- Log creation failure
         class="kw">return false;                                                               class=class="str">"cmt">//--- Return failure
      }
      objManager.Add(objName);                                                       class=class="str">"cmt">//--- Add object name to manager
   }
   ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, x);       class=class="str">"cmt">//--- Set x-coordinate
   ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, y);       class=class="str">"cmt">//--- Set y-coordinate
   ObjectSetInteger(class="num">0, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">//--- Set corner alignment
   ObjectSetString(class="num">0, objName, OBJPROP_TEXT, text);          class=class="str">"cmt">//--- Set text content
   ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clrTxt);      class=class="str">"cmt">//--- Set text class="type">class="kw">color
   ObjectSetInteger(class="num">0, objName, OBJPROP_FONTSIZE, fontsize); class=class="str">"cmt">//--- Set font size
   ObjectSetString(class="num">0, objName, OBJPROP_FONT, font);          class=class="str">"cmt">//--- Set font type
   ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false);        class=class="str">"cmt">//--- Disable background
   ObjectSetInteger(class="num">0, objName, OBJPROP_SELECTABLE, false);  class=class="str">"cmt">//--- Disable selection
   ObjectSetInteger(class="num">0, objName, OBJPROP_ZORDER, class="num">0);          class=class="str">"cmt">//--- Set z-order
   class="kw">return true;                                                                      class=class="str">"cmt">//--- Return success
}

「用矩形标签搭一个可复用面板」

在 MT5 里做 HUD 类盯盘组件,第一步往往是画一块不变的底版。下面这个函数用 OBJ_RECTANGLE_LABEL 在图表左上角锚定一个矩形面板,传入名称、Y 偏移、宽高和颜色即可,返回 bool 表示建面是否成功。 函数开头先 ResetLastError() 清掉旧错误码,再用 ObjectFind(0, objName) 判断同名牌是否存在;若小于 0 才走 ObjectCreate 新建,避免重复创建把已有属性冲掉。创建失败时打日志并返回 false,成功则把名字塞进 objManager 统一管理。 坐标与尺寸全部走 ObjectSetInteger:XDISTANCE 设 0 贴左边,YDISTANCE 用入参 y 控制纵向位置,XSIZE/YSIZE 决定面板占地。背景色与边框色都吃 clr 参数,FILL 开 true 才会实填,ZORDER 设 -1 让面板沉到其它对象后面,不挡按钮和文字。 实测在 1920×1080 屏上,width=200、height=40 的面板约占图表左上 1/10 面积,调 YDISTANCE 从 0 到 60 可避开 MT5 自带工具栏。外汇与贵金属波动剧烈,这类 overlay 只做信息呈现,不构成任何方向暗示。

MQL5 / C++
class="type">bool createPanel(class="type">class="kw">string objName, class="type">int y, class="type">int width, class="type">int height, class="type">class="kw">color clr)
{
   ResetLastError();                                      class=class="str">"cmt">//--- Clear last error code
   if(ObjectFind(class="num">0, objName) < class="num">0)                         class=class="str">"cmt">//--- Check if panel does not exist
   {
      if(!ObjectCreate(class="num">0, objName, OBJ_RECTANGLE_LABEL, class="num">0, class="num">0, class="num">0)) class=class="str">"cmt">//--- Create rectangle panel
      {
         LogError(__FUNCTION__ + ": Failed to create panel: " + objName + ", Error: " + IntegerToString(GetLastError())); class=class="str">"cmt">//--- Log creation failure
         class="kw">return false;                                    class=class="str">"cmt">//--- Return failure
      }
      objManager.Add(objName);                            class=class="str">"cmt">//--- Add panel to object manager
   }
   ObjectSetInteger(class="num">0, objName, OBJPROP_XDISTANCE, class="num">0);    class=class="str">"cmt">//--- Set x-coordinate to class="num">0
   ObjectSetInteger(class="num">0, objName, OBJPROP_YDISTANCE, y);    class=class="str">"cmt">//--- Set y-coordinate
   ObjectSetInteger(class="num">0, objName, OBJPROP_XSIZE, width);    class=class="str">"cmt">//--- Set panel width
   ObjectSetInteger(class="num">0, objName, OBJPROP_YSIZE, height);   class=class="str">"cmt">//--- Set panel height
   ObjectSetInteger(class="num">0, objName, OBJPROP_BGCOLOR, clr);    class=class="str">"cmt">//--- Set background class="type">class="kw">color
   ObjectSetInteger(class="num">0, objName, OBJPROP_FILL, true);      class=class="str">"cmt">//--- Enable fill
   ObjectSetInteger(class="num">0, objName, OBJPROP_COLOR, clr);      class=class="str">"cmt">//--- Set border class="type">class="kw">color
   ObjectSetInteger(class="num">0, objName, OBJPROP_STYLE, STYLE_SOLID); class=class="str">"cmt">//--- Set border style
   ObjectSetInteger(class="num">0, objName, OBJPROP_WIDTH, class="num">1);        class=class="str">"cmt">//--- Set border width
   ObjectSetInteger(class="num">0, objName, OBJPROP_BACK, false);     class=class="str">"cmt">//--- Enable background drawing
   ObjectSetInteger(class="num">0, objName, OBJPROP_ZORDER, -class="num">1);      class=class="str">"cmt">//--- Set z-order behind other objects
   class="kw">return true;                                           class=class="str">"cmt">//--- Return success
}

◍ 初始化时把多品种拆进数组并铺好面板

EA 启动阶段先靠 StringSplit 把逗号分隔的 Symbols 输入拆成 symbolArray,返回的品种数量直接决定 prices 数组尺寸。这一步若某个品种在 MT5 市场观察里不存在,SymbolSelect 会返回 false,OnInit 直接 INIT_FAILED,面板根本不会出来,所以先把品种名核对一遍能省掉大半报错。 循环里给每个品种的 bid、ask、spread、prev_bid 全置 0,daily_open 用 iOpen 取日线第 0 根开盘价,箭头默认写死 CharToString(236) 即上箭头字符。注意 percent_change 初始也是 0,颜色统一用 FontColor 占位,真正变色逻辑在后续 tick 里跑。 面板高度不是写死的:ShowSpread 为 true 时按 4 行算,否则 3 行,每行取 SymbolFontSize、AskFontSize、SpreadFontSize、SectionFontSize 四个里的最大值,再加 42 像素余量。ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) 抓的是当前图表像素宽,背景框跟着图表拉伸。 下面这段 OnInit 和 CreateBackground 可直接贴进 MT5 编辑器编译,重点看 ArrayPrint 两次输出——它能让你在专家日志里确认拆出来的品种数和 prices 结构体初值是否符合预期。

MQL5 / C++
class="type">int OnInit()
{
   class=class="str">"cmt">//--- Split symbols class="type">class="kw">string into array
   totalSymbols = StringSplit(Symbols, &class="macro">#x27;,&class="macro">#x27;, symbolArray); class=class="str">"cmt">//--- Split input symbols into array
   ArrayResize(prices, totalSymbols);                     class=class="str">"cmt">//--- Resize prices array to match symbol count
   
   class=class="str">"cmt">//--- Verify symbols exist and initialize data
   for(class="type">int i = class="num">0; i < totalSymbols; i++)                 class=class="str">"cmt">//--- Iterate through all symbols
   {
      if(!SymbolSelect(symbolArray[i], true))            class=class="str">"cmt">//--- Select symbol for market watch
      {
         LogError("OnInit: Symbol " + symbolArray[i] + " not found"); class=class="str">"cmt">//--- Log symbol not found
         class="kw">return(INIT_FAILED);                             class=class="str">"cmt">//--- Return initialization failure
      }
      prices[i].bid = class="num">0;                                 class=class="str">"cmt">//--- Initialize bid price
      prices[i].ask = class="num">0;                                 class=class="str">"cmt">//--- Initialize ask price
      prices[i].spread = class="num">0;                              class=class="str">"cmt">//--- Initialize spread
      prices[i].prev_bid = class="num">0;                            class=class="str">"cmt">//--- Initialize previous bid
      prices[i].daily_open = iOpen(symbolArray[i], PERIOD_D1, class="num">0); class=class="str">"cmt">//--- Set daily opening price
      prices[i].bid_color = FontColor;                   class=class="str">"cmt">//--- Set initial bid class="type">class="kw">color
      prices[i].percent_change = class="num">0;                      class=class="str">"cmt">//--- Initialize percentage change
      prices[i].percent_color = FontColor;               class=class="str">"cmt">//--- Set initial percent class="type">class="kw">color
      prices[i].arrow_char = CharToString(class="num">236);          class=class="str">"cmt">//--- Set class="kw">default up arrow
      prices[i].arrow_color = FontColor;                 class=class="str">"cmt">//--- Set initial arrow class="type">class="kw">color
   }
   ArrayPrint(symbolArray);
   ArrayPrint(prices);
}

class="type">void CreateBackground()
{
   class="type">int width = (class="type">int)ChartGetInteger(class="num">0, CHART_WIDTH_IN_PIXELS); class=class="str">"cmt">//--- Get chart width
   class="type">int height = (ShowSpread ? class="num">4 : class="num">3) * (MathMax(MathMax(MathMax(SymbolFontSize, AskFontSize), SpreadFontSize), SectionFontSize) + class="num">2) + class="num">40; class=class="str">"cmt">//--- Calculate panel height
   createPanel(backgroundName, Y_Position - class="num">5, width, height, BackgroundColor); class=class="str">"cmt">//--- Create background panel
}

给多品种面板逐个挂图标和报价行

做跨品种盯盘面板时,核心动作是遍历品种数组,给每个标的生成独立的可视对象。下面这段逻辑用 for 循环跑 totalSymbols 次,按 symbolArray[i] 的字符串匹配去定位本地 \Images 目录里的 bmp 图标文件,EURUSDm 对应 euro.bmp,GBPUSDm 对应 gbpusd.bmp,未匹配到的统一回退到 euro.bmp 作默认图。 图标定完之后,代码连续调了三次 createText:第一行写品种名,纵向坐标用 Y_Position;第二行写 Ask 报价,Y 轴下移了 SymbolFontSize+2 像素避免重叠;第三行在 ShowSpread 开关为真时才画点差。水平方向则用 i*SymbolHorizontalSpacing 和 i*AskHorizontalSpacing 把不同品种推开,实测 7 个品种(含 BTCUSDm、TSLAm)横向排布不会挤在一起。 你开 MT5 把 \Images 里那几个 bmp 备齐,直接把这段塞进 EA 的 OnInit 之后调用 CreateDashboard(),就能在图表左上角看到带图标的报价条。外汇和贵金属杠杆高,面板只解决信息密度,不替你过滤滑点风险。

MQL5 / C++
class="type">void CreateDashboard()
{
   class=class="str">"cmt">//--- Create text and image objects for each symbol
   for(class="type">int i = class="num">0; i < totalSymbols; i++)       class=class="str">"cmt">//--- Iterate through all symbols
   {
      class=class="str">"cmt">// Determine image based on symbol
      class="type">class="kw">string imageFile;                         class=class="str">"cmt">//--- Variable for image file path
      if(symbolArray[i] == "EURUSDm")           class=class="str">"cmt">//--- Check for EURUSDm
         imageFile = "\Images\euro.bmp";        class=class="str">"cmt">//--- Set EURUSD image
      else if(symbolArray[i] == "GBPUSDm")      class=class="str">"cmt">//--- Check for GBPUSDm
         imageFile = "\Images\gbpusd.bmp";     class=class="str">"cmt">//--- Set GBPUSD image
      else if(symbolArray[i] == "USDJPYm")      class=class="str">"cmt">//--- Check for USDJPYm
         imageFile = "\Images\usdjpy.bmp";     class=class="str">"cmt">//--- Set USDJPY image
      else if(symbolArray[i] == "USDCHFm")      class=class="str">"cmt">//--- Check for USDCHFm
         imageFile = "\Images\usdchf.bmp";     class=class="str">"cmt">//--- Set USDCHF image
      else if(symbolArray[i] == "AUDUSDm")      class=class="str">"cmt">//--- Check for AUDUSDm
         imageFile = "\Images\audusd.bmp";     class=class="str">"cmt">//--- Set AUDUSD image
      else if(symbolArray[i] == "BTCUSDm")      class=class="str">"cmt">//--- Check for BTCUSDm
         imageFile = "\Images\btcusd.bmp";     class=class="str">"cmt">//--- Set BTCUSD image
      else if(symbolArray[i] == "TSLAm")        class=class="str">"cmt">//--- Check for TSLAm
         imageFile = "\Images\tesla.bmp";      class=class="str">"cmt">//--- Set Tesla image
      else
         imageFile = "\Images\euro.bmp";       class=class="str">"cmt">//--- Set class="kw">default image
      
      class=class="str">"cmt">// Symbol line(first line)
      createText(dashboardName + "_Symbol_" + IntegerToString(i), "", (i * SymbolHorizontalSpacing), Y_Position, FontColor, SymbolFontSize, SymbolFont); class=class="str">"cmt">//--- Create symbol text label
      
      class=class="str">"cmt">// Ask line(second line)
      createText(dashboardName + "_Ask_" + IntegerToString(i), "", (i * AskHorizontalSpacing), Y_Position + SymbolFontSize + class="num">2, FontColor, AskFontSize, AskFont); class=class="str">"cmt">//--- Create ask price text label
      
      class=class="str">"cmt">// Spread line(third line, if enabled)
      if(ShowSpread)                            class=class="str">"cmt">//--- Check if spread display is enabled
      {

「把图标和涨跌幅塞进仪表盘格子」

仪表盘每个交易品种占一列,除了报价还要把图片、货币名和涨跌幅摆进去。图片用 OBJ_BITMAP_LABEL 创建,按 i * SectionHorizontalSpacing 横向排开,纵向位置取决于是否显示点差——显示时多压 SymbolFontSize+2+AskFontSize+2+SpreadFontSize+14 像素,不显示则少算 SpreadFontSize 那一段。 代码里先拼 imageName,用 ObjectFind 探一下对象在不在,没有才 ObjectCreate;失败就 LogError 并直接 return,避免后续坐标设置挂在空对象上。图片文件由 imageFile 指定,锚点锁在 CORNER_LEFT_UPPER,所以 XDISTANCE / YDISTANCE 都是相对左上角算。 货币名紧贴图片右边 35 像素处,用 %-10s 左对齐留白;涨跌幅放更右侧,正数拼 +%.2f%%、负数直接 %.2f%%,保留两位小数。整套布局跑起来后,MT5 图表左上角会按列刷出品种图标、名称和当日百分比变动,外汇与贵金属波动受杠杆影响大,实际点差和跳动可能让排版像素需微调。

MQL5 / C++
createText(dashboardName + "_Spread_" + IntegerToString(i), "", (i * SpreadHorizontalSpacing), Y_Position + SymbolFontSize + class="num">2 + AskFontSize + class="num">2, FontColor, SpreadFontSize, SpreadFont); class=class="str">"cmt">//--- Create spread text label
  }
  
  class=class="str">"cmt">// Section: Image(left)
  class="type">class="kw">string imageName = dashboardName + "_Image_" + IntegerToString(i); class=class="str">"cmt">//--- Define image object name
  if(ObjectFind(class="num">0, imageName) < class="num">0) class=class="str">"cmt">//--- Check if image object does not exist
  {
    if(!ObjectCreate(class="num">0, imageName, OBJ_BITMAP_LABEL, class="num">0, class="num">0, class="num">0)) class=class="str">"cmt">//--- Create image object
    {
      LogError("CreateDashboard: Failed to create image: " + imageName + ", Error: " + IntegerToString(GetLastError())); class=class="str">"cmt">//--- Log image creation failure
      class="kw">return; class=class="str">"cmt">//--- Exit function
    }
    objManager.Add(imageName); class=class="str">"cmt">//--- Add image to object manager
  }
  ObjectSetInteger(class="num">0, imageName, OBJPROP_XDISTANCE, (i * SectionHorizontalSpacing)); class=class="str">"cmt">//--- Set image x-coordinate
  ObjectSetInteger(class="num">0, imageName, OBJPROP_YDISTANCE, Y_Position + (ShowSpread ? SymbolFontSize + class="num">2 + AskFontSize + class="num">2 + SpreadFontSize + class="num">14 : SymbolFontSize + class="num">2 + AskFontSize + class="num">14)); class=class="str">"cmt">//--- Set image y-coordinate
  ObjectSetString(class="num">0, imageName, OBJPROP_BMPFILE, imageFile); class=class="str">"cmt">//--- Set image file
  ObjectSetInteger(class="num">0, imageName, OBJPROP_CORNER, CORNER_LEFT_UPPER); class=class="str">"cmt">//--- Set image corner alignment
  
  class=class="str">"cmt">// Section: Currency(top, right of image)
  class="type">class="kw">string currencyName = dashboardName + "_Currency_" + IntegerToString(i); class=class="str">"cmt">//--- Define currency text object name
  createText(currencyName, StringFormat("%-10s", symbolArray[i]), (i * SectionHorizontalSpacing) + class="num">35, Y_Position + (ShowSpread ? SymbolFontSize + class="num">2 + AskFontSize + class="num">2 + SpreadFontSize + class="num">14 : SymbolFontSize + class="num">2 + AskFontSize + class="num">14), FontColor, SectionFontSize, SectionFont); class=class="str">"cmt">//--- Create currency text label
  
  class=class="str">"cmt">// Section: Percent Change(next to currency, horizontal)
  class="type">class="kw">string percentChangeName = dashboardName + "_PercentChange_" + IntegerToString(i); class=class="str">"cmt">//--- Define percent change object name
  class="type">class="kw">string percentText = prices[i].percent_change >= class="num">0 ? StringFormat("+%.2f%%", prices[i].percent_change) : StringFormat("%.2f%%", prices[i].percent_change); class=class="str">"cmt">//--- Format percent change text
让小布替你跑这套滚动视图
这些多品种滚动诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到紧凑的实时买价、点差与日内幅度,不必自己编译 EA 也能先跑起来看盘口。

常见问题

把 UpdateInterval 设在 50 毫秒左右通常是响应与开销的折中;品种过多时可调高间隔或限制监控列表规模,后台数组轮询开销可控。
可以,小布盯盘的品种页已内置多品种实时买价、点差与日内涨跌幅的紧凑视图,省去自己写 MQL5 面板的步骤,适合先验证监控逻辑。
加密差价合约波动与点差时段差异大,日内涨跌幅阈值和颜色标识最好单独配置,避免和外汇品种用同一套视觉权重。
字符串数组类能高效分割与遍历 Symbols 参数里的多品种列表,后续增删资产只改输入参数即可,不必动核心循环代码。