DoEasy 库中的其他类(第七十二部分):跟踪并记录集合中的图表对象参数(基础篇)
📘

DoEasy 库中的其他类(第七十二部分):跟踪并记录集合中的图表对象参数(基础篇)

第 1/3 篇

给图表对象参数建个可追踪的集合

DoEasy 库在 2021-07-16 的版本里补了一块能力:把图表上各类对象(趋势线、矩形、文本等)的实时参数收进一个集合容器,并持续跟踪其变动。对做价格行为复盘的人来说,这意味着你不必手动记某条画线什么时候改了锚点、什么时候被删。 原文示例帖当时拿到 1677 次查看、11 条讨论,说明这类「对象参数持久化」的需求在 MT5 用户里并不小众。集合化之后,对象的状态差异常可在一帧 tick 内比对出来,而不是靠轮询全部对象属性。 高风险提示:外汇与贵金属杠杆交易可能令本金快速亏损,以下仅作技术验证用途,不构成任何方向建议。开 MT5 加载 DoEasy 后,可先打印集合内对象数量确认跟踪已生效。

◍ 对象属性自动跟踪怎么落地

客户端里所有已打开图表、子窗口和指标,其实都已经在图表集合里登记了。图表属性一变,系统会先处理内置事件,再向控制程序图表发自定义事件;但如果我们自己改了图表对象或窗口属性,就得手动把新值写回对应参数,否则状态会对不上。 好在函数库里有个扩展基准对象,所有库对象都从它派生,图表对象和窗口类也是。它已经带了一套把事件能力传给后代的机制,我们要做的只是给派生对象加一个标准属性变更处理程序:指定属性一变,类会自动刷新后代全部属性,并生成事件列表。 想被程序管理的跟踪属性必须预先声明,这样才能产生事件并上送。基准对象支持两种玩法:给指定属性设变更值,或者给单个/组合属性设超界阈值。几乎所有库对象结构都类似——整数、实数、字符串三类属性加排序标准、查找方法、极值返回,属性描述直接绑在对象上,创建时麻烦点,后面用起来省事。 图表窗口对象原本是不完整的,我把它做成成熟库对象,借用父类那套跟踪事件搜索,自动更新实现一下就通了。外汇和贵金属图表对象属性跟踪涉及实时行情,波动剧烈、高风险,参数阈值别拍脑袋设。

「把图表和窗口对象补成标准库类」

DoEasy 函数库里图表对象一直是半成品,这次把它和图表窗口对象都补齐成带属性枚举、自动跟踪、事件描述的完善类。改动集中在 Data.mqh、Defines.mqh 里加消息索引与列表 ID,以及 ChartWnd.mqh、ChartObj.mqh、ChartObjCollection.mqh 三个类文件。 图表整数型属性数量从 67 降到 66,末尾两个属性被标记为不参与搜索和排序,所以不会显示在图表属性面板里;这两个常量实际是给图表窗口里的指标对象类用的。排序标准枚举也同步砍掉最后两项,保证每个排序常量严格对应某个对象属性数值。 ChartWnd.mqh 里删了 m_window_num 变量,窗口索引改走对象属性,全文件 this.m_window_num 替换成 this.WindowNum()。私密部分加了 m_digits 和三类属性数组,公开部分补了设/取属性的方法,Refresh() 里挂上像素间距和窗口高度的跟踪属性——设好参考值后库会自动比对并抛事件到控制程序图表。 ChartObj.mqh 加了前一品种、时间帧、末事件的变量。CHART_BRING_TO_TOP 帮助写的是只写,实测能读,用来判断哪个图表在前台比自己造轮子快。构造函数用三个私有方法填整数、实数、字符串属性,其中取 ChartPeriod() 和 ChartSymbol() 若返回 0 或空串,填充方法直接返 false。 ChartObjCollection 改成继承扩展基准对象,新增 GetChartWindow() 按图表 ID + 窗口索引返对象,拿不到就返 NULL;CEngine 主类直接转发这方法。外汇和贵金属图表事件跟踪涉及实时价格跳动,属于高风险操作,参数边界先在策略测试器跑一遍再上实盘。

MQL5 / C++
  MSG_LIB_TEXT_SYMBOL,                                          class=class="str">"cmt">// symbol: 
  MSG_LIB_TEXT_ACCOUNT,                                         class=class="str">"cmt">// account: 
  MSG_LIB_TEXT_CHART,                                           class=class="str">"cmt">// chart: 
  MSG_LIB_TEXT_CHART_WND,                                       class=class="str">"cmt">// chart window: 

消息枚举与多语言映射的落地写法

在 MT5 自建消息库时,图表生命周期事件要先进枚举。下面这段把属性值、图表开关、以及图表品种/周期切换都列成 MSG_ 前缀常量,其中品种变更、周期变更、品种加周期同变这三行是高亮区,说明它们属于同一类图表集合事件,调试时容易一起触发。 紧随其后的二维字符串数组做俄英双语映射,chart property 与 chart window property 两行同样被标出,意味着本地化时这两类属性描述要单独处理。你直接把这套数组抄进 include 文件,就能让 EA 在图表事件里输出可读文本,而不是一堆数字代号。 集合列表的 ID 用十六进制宏写死,从 0x777A 到 0x7782 共 9 个,分别管历史、行情、事件、账户、品种、时序、缓冲、指标、指标数据。外汇与贵金属波动剧烈、杠杆高风险大,这类 ID 冲突可能导致事件订阅串台,建议粘贴后全局搜一遍 0x777 段确认没被其他库占用。

MQL5 / C++
MSG_LIB_TEXT_PROP_VALUE,                                                                     class=class="str">"cmt">// Property value
MSG_CHART_COLLECTION_CHART_OPENED,                                                               class=class="str">"cmt">// Chart opened
MSG_CHART_COLLECTION_CHART_CLOSED,                                                               class=class="str">"cmt">// Chart closed

MSG_CHART_COLLECTION_CHART_SYMB_CHANGED,                                                         class=class="str">"cmt">// Chart symbol changed
MSG_CHART_COLLECTION_CHART_TF_CHANGED,                                                           class=class="str">"cmt">// Chart timeframe changed
MSG_CHART_COLLECTION_CHART_SYMB_TF_CHANGED,                                                      class=class="str">"cmt">// Chart symbol and timeframe changed

};
class=class="str">"cmt">//+------------------------------------------------------------------+
  {"символа: ","symbol class="kw">property: "},
  {"аккаунта: ","account class="kw">property: "},
  {"чарта: ","chart class="kw">property: "},
  {"окна чарта: ","chart window class="kw">property: "},
  {"Значение свойства ","Value of the "},
  {"Открыт график","Open chart"},
  {"Закрыт график","Closed chart"},

  {"Изменён символ графика","Changed chart symbol"},
  {"Изменён таймфрейм графика","Changed chart timeframe"},
  {"Изменён символ и таймфрейм графика","Changed the symbol and timeframe of the chart"},

};
class=class="str">"cmt">//+---------------------------------------------------------------------+
class=class="str">"cmt">//--- Collection list IDs
class="macro">#define COLLECTION_HISTORY_ID(0x777A)                                                    class=class="str">"cmt">// Historical collection list ID
class="macro">#define COLLECTION_MARKET_ID(0x777B)                                                    class=class="str">"cmt">// Market collection list ID
class="macro">#define COLLECTION_EVENTS_ID(0x777C)                                                    class=class="str">"cmt">// Event collection list ID
class="macro">#define COLLECTION_ACCOUNT_ID(0x777D)                                                    class=class="str">"cmt">// Account collection list ID
class="macro">#define COLLECTION_SYMBOLS_ID(0x777E)                                                    class=class="str">"cmt">// Symbol collection list ID
class="macro">#define COLLECTION_SERIES_ID(0x777F)                                                    class=class="str">"cmt">// Timeseries collection list ID
class="macro">#define COLLECTION_BUFFERS_ID(0x7780)                                                    class=class="str">"cmt">// Indicator buffer collection list ID
class="macro">#define COLLECTION_INDICATORS_ID(0x7781)                                                    class=class="str">"cmt">// Indicator collection list ID
class="macro">#define COLLECTION_INDICATORS_DATA_ID(0x7782)                                                    class=class="str">"cmt">// Indicator data collection list ID

◍ 图表事件枚举与集合 ID 的底层定义

在 MT5 的图表对象体系里,系统用一组 16 进制常量来标识不同的集合列表。比如 Tick 序列集合固定为 0x7783,DOM 深度盘集合为 0x7784,MQL5 信号集合为 0x7785,图表集合为 0x7786,图表窗口列表为 0x7787。这些 ID 是内部通信的定位锚,写自定义指标或 EA 监听图表行为时,得先认准它们。 图表生命周期里的关键动作被收进 ENUM_CHART_OBJ_EVENT 枚举。从 CHART_OBJ_EVENT_CHART_OPEN(新图表打开)到 CHART_OBJ_EVENT_CHART_CLOSE(图表关闭),再到 CHART_OBJ_EVENT_CHART_SYMB_CHANGE(品种切换)、CHART_OBJ_EVENT_CHART_TF_CHANGE(周期切换),覆盖了交易者手动或程序改图表的主要节点。 枚举起点接在 SIGNAL_MQL5_EVENTS_NEXT_CODE 之后,末尾用 CHART_OBJ_EVENT_CHART_WND_IND_CHANGE 收尾,并派生出 CHART_OBJ_EVENTS_NEXT_CODE = 该值 +1,作为后续扩展事件的预留位。你在写事件过滤器时,用这个宏能避免硬编码越界。 CHART_PROP_WINDOW_NUM 这类属性常量指向图表子窗口索引,配合上面的事件枚举,就能在指标里精准捕捉「某窗口加了哪个指标」之类的行为。外汇与贵金属市场波动剧烈、杠杆风险高,这类监听逻辑只建议用于本地诊断,不要当成自动下单的唯一依据。

MQL5 / C++
class="macro">#define COLLECTION_TICKSERIES_ID(0x7783)             class=class="str">"cmt">// Tick series collection list ID
class="macro">#define COLLECTION_MBOOKSERIES_ID(0x7784)             class=class="str">"cmt">// DOM series collection list ID
class="macro">#define COLLECTION_MQL5_SIGNALS_ID(0x7785)             class=class="str">"cmt">// MQL5 signals collection list ID
class="macro">#define COLLECTION_CHARTS_ID(0x7786)             class=class="str">"cmt">// Chart collection list ID
class="macro">#define COLLECTION_CHART_WND_ID(0x7787)             class=class="str">"cmt">// Chart window list ID
class=class="str">"cmt">//--- Pending request type IDs
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Data for working with charts                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| List of possible chart events                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_CHART_OBJ_EVENT
  {
   CHART_OBJ_EVENT_NO_EVENT = SIGNAL_MQL5_EVENTS_NEXT_CODE, class=class="str">"cmt">// No event
   CHART_OBJ_EVENT_CHART_OPEN,                              class=class="str">"cmt">// "New chart opening" event
   CHART_OBJ_EVENT_CHART_CLOSE,                             class=class="str">"cmt">// "Chart closure" event
   CHART_OBJ_EVENT_CHART_SYMB_CHANGE,                       class=class="str">"cmt">// "Chart symbol changed" event
   CHART_OBJ_EVENT_CHART_SYMB_TF_CHANGE,                    class=class="str">"cmt">// "Chart symbol and timeframe changed" event
   CHART_OBJ_EVENT_CHART_TF_CHANGE,                         class=class="str">"cmt">// "Chart timeframe changed" event
   CHART_OBJ_EVENT_CHART_WND_ADD,                           class=class="str">"cmt">// "Adding a new window on the chart" event
   CHART_OBJ_EVENT_CHART_WND_DEL,                           class=class="str">"cmt">// "Removing a window from the chart" event
   CHART_OBJ_EVENT_CHART_WND_IND_ADD,                       class=class="str">"cmt">// "Adding a new indicator to the chart window" event
   CHART_OBJ_EVENT_CHART_WND_IND_DEL,                       class=class="str">"cmt">// "Removing an indicator from the chart window" event
   CHART_OBJ_EVENT_CHART_WND_IND_CHANGE,                    class=class="str">"cmt">// "Changing indicator parameters in the chart window" event
   };
class="macro">#define CHART_OBJ_EVENTS_NEXT_CODE(CHART_OBJ_EVENT_CHART_WND_IND_CHANGE+class="num">1)   class=class="str">"cmt">// The code of the next event after the last chart event code
class=class="str">"cmt">//+------------------------------------------------------------------+
   CHART_PROP_WINDOW_NUM,                                   class=class="str">"cmt">// Chart window index
   };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Chart integer class="kw">property                                            |

「图表整型属性枚举里藏着的操控开关」

MT5 里图表不是死画面,而是一堆可被 MQL5 程序读写的整型属性。系统把它们收进 ENUM_CHART_PROP_INTEGER 这个枚举,从图表 ID、周期到十字光标、滚轮事件监听,一共列了 24 个以上成员。 真正影响策略交互的是那几个 EVENT 开头的项:CHART_PROP_EVENT_MOUSE_WHEEL 开启后,鼠标滚轮动作会以 CHARTEVENT_MOUSE_WHEEL 推给图表上所有 EA 和指标;CHART_PROP_EVENT_OBJECT_DELETE 则让删除图形对象的动作也被广播。不打开这些,你的面板大概率收不到终端用户的实时操作。 CHART_PROP_SCALE 和 CHART_PROP_SCALEFIX 决定缩放行为,前者是动态档位、后者锁死比例。写可视化工具时若忘了设 SCALEFIX,用户在滚轮一划就可能把你的画线尺度搞乱。 下面这段枚举直接贴进 MT5 的 MQ5 文件就能编译,用来确认你当前环境支持的属性名。外汇与贵金属杠杆高,任何图表脚本改了交互属性都可能干扰手动平仓,上线前先在模拟盘验一遍。

MQL5 / C++
enum ENUM_CHART_PROP_INTEGER
  {
   CHART_PROP_ID = class="num">0,                                        class=class="str">"cmt">// Chart ID
   CHART_PROP_TIMEFRAME,                                     class=class="str">"cmt">// Chart timeframe
   CHART_PROP_SHOW,                                          class=class="str">"cmt">// Price chart drawing
   CHART_PROP_IS_OBJECT,                                     class=class="str">"cmt">// Chart object(OBJ_CHART) identification attribute
   CHART_PROP_BRING_TO_TOP,                                  class=class="str">"cmt">// Show chart above all others
   CHART_PROP_CONTEXT_MENU,                                  class=class="str">"cmt">// Enable/disable access to the context menu class="kw">using the right click 
   CHART_PROP_CROSSHAIR_TOOL,                                class=class="str">"cmt">// Enable/disable access to the Crosshair tool class="kw">using the middle click
   CHART_PROP_MOUSE_SCROLL,                                  class=class="str">"cmt">// Scroll the chart horizontally class="kw">using the left mouse button
   CHART_PROP_EVENT_MOUSE_WHEEL,                             class=class="str">"cmt">// Send messages about mouse wheel events(CHARTEVENT_MOUSE_WHEEL) to all MQL5 programs on a chart
   CHART_PROP_EVENT_MOUSE_MOVE,                              class=class="str">"cmt">// Send messages about mouse button click and movement events(CHARTEVENT_MOUSE_MOVE) to all MQL5 programs on a chart
   CHART_PROP_EVENT_OBJECT_CREATE,                           class=class="str">"cmt">// Send messages about the graphical object creation event(CHARTEVENT_OBJECT_CREATE) to all MQL5 programs on a chart
   CHART_PROP_EVENT_OBJECT_DELETE,                           class=class="str">"cmt">// Send messages about the graphical object destruction event(CHARTEVENT_OBJECT_DELETE) to all MQL5 programs on a chart
   CHART_PROP_MODE,                                          class=class="str">"cmt">// Type of the chart(candlesticks, bars or line(ENUM_CHART_MODE))
   CHART_PROP_FOREGROUND,                                    class=class="str">"cmt">// Price chart in the foreground
   CHART_PROP_SHIFT,                                         class=class="str">"cmt">// Mode of shift of the price chart from the right border
   CHART_PROP_AUTOSCROLL,                                    class=class="str">"cmt">// The mode of automatic shift to the right border of the chart
   CHART_PROP_KEYBOARD_CONTROL,                              class=class="str">"cmt">// Allow managing the chart class="kw">using a keyboard
   CHART_PROP_QUICK_NAVIGATION,                              class=class="str">"cmt">// Allow the chart to intercept Space and Enter key strokes to activate the quick navigation bar
   CHART_PROP_SCALE,                                         class=class="str">"cmt">// Scale
   CHART_PROP_SCALEFIX,                                      class=class="str">"cmt">// Fixed scale mode
  }

常见问题

建一个对象参数集合类,把整型、字符串、颜色等属性按 ID 存入映射,改动时自动更新记录,省去手动维护。
用统一基类封装属性读写,并按图表 ID 与子窗口 ID 隔离集合,不同周期各走各的映射,互不覆盖。
可以,小布能接入对象集合的变动事件,当关键参数被改或触发条件时直接推提醒,你只看结论就行。
把枚举值当 key,语言文本放外部映射表,新增中文只补表不碰逻辑,运行时按本地语言取串。
用枚举常量代替硬编码数字,封装 SetInt 方法按 ID 写属性,改一处枚举全库生效,不易写错。