一张图表上的多个指标(第 06 部分):将 MetaTrader 5 转变为 RAD 系统(II)·综合运用
🧩

一张图表上的多个指标(第 06 部分):将 MetaTrader 5 转变为 RAD 系统(II)·综合运用

(3/3)·从只读编辑框到累计盈亏着色,把上两篇的图表 IDE 真正跑通

新手友好 第 3/3 篇
很多人以为在 MT5 图表上拖几个编辑框就算做了界面,结果对象不关联事件、文本不对齐,徒有其表。其实只要先画好 IDE 草图、把只读属性和对齐方式定好,平台就能替你管大半交互。剩下用 MQL5 补几行,界面才真正听你指挥。

从成交历史里扒出某品种累计盈亏

想在 MT5 面板实时显示某个符号的累计平仓盈亏,核心是先拉历史成交再按品种过滤累加。下面这段函数用 HistorySelect 框定从当天零点到当前的时间窗,遍历所有成交单,只把 DEAL_SYMBOL 匹配的 DEAL_PROFIT 加进 Accumulated,最后返回总和。 HistorySelect(macroGetDate(TimeLocal()), TimeLocal()); max = HistoryDealsTotal(); for (int c0 = 0; c0 < max; c0++) if ((ticket = HistoryDealGetTicket(c0)) > 0) if (HistoryDealGetString(ticket, DEAL_SYMBOL) == szSymbol) Accumulated += HistoryDealGetDouble(ticket, DEAL_PROFIT); return Accumulated; 逐行看:第一行 HistorySelect 取本地当天 0 点至现在的范围;第二行拿总数;for 循环里先取第 c0 笔成交的 ticket,大于 0 才有效;内层判断符号一致后,把该笔利润累加。回测时注意,若跨天不重选范围,零点后 Accumulated 会漏掉昨单。 外汇和贵金属杠杆高,历史利润只是已平仓结果,不代表后续概率,用它做面板参考就好,别当成仓位依据。

MQL5 / C++
HistorySelect(macroGetDate(TimeLocal()), TimeLocal());
max = HistoryDealsTotal();
for (class="type">int c0 = class="num">0; c0 < max; c0++) if ((ticket = HistoryDealGetTicket(c0)) > class="num">0)
  if (HistoryDealGetString(ticket, DEAL_SYMBOL) == szSymbol)
    Accumulated += HistoryDealGetDouble(ticket, DEAL_PROFIT);
class="kw">return Accumulated;

◍ 用静态变量累计Roof净值并刷新标签

这段逻辑的核心是把当前品种的已平盈利滚动累加进一个叫 Accumulated 的静态变量,再叠加 dValue 算出 d0,最后写进图表对象的文本与背景色。d0 为正时标签底色取 ForestGreen,为负则取 FireBrick,视觉上能直接区分当天Roof是盈余还是回吐。 UpdateRoof() 里用 memMax 缓存上一次 HistoryDealsTotal() 返回的交割单数。若 memMax == max 直接 return Accumulated,避免每帧重算;只有新成交出现才进循环把 DEAL_PROFIT 累加进 Accumulated。实测在普通外汇品种上,这种静态缓存能把每 tick 的对象刷新开销压到几乎可忽略。 OnTrade() 里调 SubWin.DispatchMessage 把 CHARTEVENT_CHART_CHANGE 和 NanoEA.UpdateRoof() 的返回值推给子窗口,等于每次成交事件触发一次Roof重算与标签更新。想验证就开 MT5 挂上这类 EA,连做几笔 XAUUSD 微单,看子窗口数字是否随平仓实时跳动——外汇与贵金属杠杆高,标签只是辅助,不代表方向判断。

MQL5 / C++
d0 = AccumulatedRoof + dValue;
ObjectSetString(Terminal.Get_ID(), m_ArrObject[eROOF_DIARY].szName, OBJPROP_TEXT, DoubleToString(MathAbs(d0), class="num">2));
ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eROOF_DIARY].szName, OBJPROP_BGCOLOR, (d0 >= class="num">0 ? clrForestGreen : clrFireBrick));
}else if (szArg == szMsgIDE[eLABEL_SYMBOL])
{
ObjectSetString(Terminal.Get_ID(), m_ArrObject[eLABEL_SYMBOL].szName, OBJPROP_TEXT, Terminal.GetSymbol());
ObjectSetInteger(Terminal.Get_ID(), m_ArrObject[eLABEL_SYMBOL].szName, OBJPROP_ALIGN, ALIGN_CENTER);
}
class="kw">break;
case CHARTEVENT_OBJECT_CLICK:
class=class="str">"cmt">// .... The rest of the code....
}
}
class="type">void OnTrade()
{
SubWin.DispatchMessage(CHARTEVENT_CHART_CHANGE, C_Chart_IDE::szMsgIDE[C_Chart_IDE::eROOF_DIARY], NanoEA.UpdateRoof());
NanoEA.UpdatePosition();
}
class="type">class="kw">double UpdateRoof(class="type">void)
{
class="type">class="kw">ulong      ticket;
class="type">class="kw">string  szSymbol = Terminal.GetSymbol();
class="type">int     max;
class="kw">static class="type">int   memMax = class="num">0;
class="kw">static class="type">class="kw">double  Accumulated = class="num">0;

HistorySelect(macroGetDate(TimeLocal()), TimeLocal());
max = HistoryDealsTotal();
if (memMax == max) class="kw">return Accumulated; else memMax = max;
for (class="type">int c0 = class="num">0; c0 < max; c0++) if ((ticket = HistoryDealGetTicket(c0)) > class="num">0)
if (HistoryDealGetString(ticket, DEAL_SYMBOL) == szSymbol)
Accumulated += HistoryDealGetDouble(ticket, DEAL_PROFIT);

「累计求和的返回收口」

上面这段 MQL5 片段是某个指标或 EA 里累加逻辑的收尾:用 return Accumulated; 把循环里攒下的总和交回调用方。 在 MT5 里直接新建一个脚本,把这段塞进自定义函数末尾,打印返回值,能验证累加是否按预期中断或跑满。外汇与贵金属杠杆高,验证时先用模拟盘,避免实盘误触。

MQL5 / C++
               class="kw">return Accumulated;
}

别急着下结论

把 RAD 思路落进 MQL5 之后,你能搭出的不再只是脚本,而是一套带 IDE 交互的半自动框架。前文那套函数库已经把界面构建和控件错误率压了下来,EA_1.05.zip(约 3274.9 KB)里就是可跑的参考实现,开 MT5 直接加载就能看事件响应链路。 真正卡住多数人的不是语法,而是把外部库思路接进 MQL5 时的对象生命周期管理——这部分原文没给现成封装,得自己补。外汇与贵金属杠杆高,这类自建界面再顺手也改变不了品种本身的风险敞口,先在模拟盘验证交互逻辑再谈实盘。 剩下的空间交给你的具体策略:同样的控件骨架,接均线过滤还是接订单流,出来的系统完全两样。

让小布替你盯盘口变化
这些界面对象的状态切换和日累计盈亏着色逻辑,小布盯盘的 AIGC 已内置,打开对应品种页即可看到实时面板,不必自己从零写事件绑定。

常见问题

不能,只读属性会阻止用户手动输入,但 EA 通过代码依然可以写入资产名和累计值,适合做展示型信息框。
因为它们没有关联任何事件,MT5 只在图表上绘制而不触发逻辑;需要你在 MQL5 里绑定事件处理函数才会生效。
小布盯盘内置了品种页的实时面板与状态着色,逻辑等价于文里的累计盈亏显示,可省去自行搭建对象事件的成本。
在 EA 里读取当日盈亏,按正负调用对象颜色属性重绘;文本居中可用 ENUM_ALIGN_MODE 的对齐属性在代码中设置。