轻松快捷开发 MetaTrader 程序的函数库 (第十九部分) : 函数库消息类·进阶篇
📨

轻松快捷开发 MetaTrader 程序的函数库 (第十九部分) : 函数库消息类·进阶篇

(2/3)· 当函数库散落各处的俄英文本开始拖累编译体积,重构消息存储与显示已避不开

实战向进阶 第 2/3 篇
把提示文本硬编码进每个类文件,初看省事,等项目里对象一多,重复字符串会悄悄撑大 EX5。更麻烦的是想加一门语言,就得全网搜替换。提前把消息收口到数组和类里,后续扩展只动一处。

◍ 标准库消息宏的英文词表映射

在 MT5 标准函数库的本地化消息体系中,一组 MSG_LIB_TEXT_* 宏专门承载交易动作与星期的中文/英文切换。上面列出的 26 个定义,覆盖了从 Yes/No 逻辑词到 Opened/Closed 等订单状态,再到周一到周四的交易日标识。 这些宏本身只是枚举或字符串常量,真正价值在于让 EA 日志和弹窗不依赖俄语默认文案。你在 MT5 里打开 Standard Library 的 Lang 宏文件,搜 MSG_LIB_TEXT_CLOSED_BY 就能看到 'close by' 的英文原串,改一处即可影响所有平仓关联提示。 外汇与贵金属市场高杠杆、滑点随机,这类文本映射虽不改变成交逻辑,但能让你在多品种复盘时少看几眼乱码。建议直接复制下面这段宏表进自己的头文件做对照。

MQL5 / C++
  MSG_LIB_TEXT_YES,                                                                     class=class="str">"cmt">// Yes
  MSG_LIB_TEXT_NO,                                                                     class=class="str">"cmt">// No
  MSG_LIB_TEXT_AND,                                                                    class=class="str">"cmt">// and
  MSG_LIB_TEXT_IN,                                                                     class=class="str">"cmt">// in
  MSG_LIB_TEXT_TO,                                                                     class=class="str">"cmt">// to
  MSG_LIB_TEXT_OPENED,                                                                 class=class="str">"cmt">// Opened
  MSG_LIB_TEXT_PLACED,                                                                 class=class="str">"cmt">// Placed
  MSG_LIB_TEXT_DELETED,                                                                class=class="str">"cmt">// Deleted
  MSG_LIB_TEXT_CLOSED,                                                                 class=class="str">"cmt">// Closed
  MSG_LIB_TEXT_CLOSED_BY,                                                              class=class="str">"cmt">// close by
  MSG_LIB_TEXT_CLOSED_VOL,                                                             class=class="str">"cmt">// Closed volume
  MSG_LIB_TEXT_AT_PRICE,                                                               class=class="str">"cmt">// at price
  MSG_LIB_TEXT_ON_PRICE,                                                               class=class="str">"cmt">// on price
  MSG_LIB_TEXT_TRIGGERED,                                                              class=class="str">"cmt">// Triggered
  MSG_LIB_TEXT_TURNED_TO,                                                              class=class="str">"cmt">// turned to
  MSG_LIB_TEXT_ADDED,                                                                  class=class="str">"cmt">// Added
  MSG_LIB_TEXT_SYMBOL_ON_SERVER,                                                       class=class="str">"cmt">// on server
  MSG_LIB_TEXT_SYMBOL_TO_LIST,                                                         class=class="str">"cmt">// to list
  MSG_LIB_TEXT_FAILED_ADD_TO_LIST,                                                     class=class="str">"cmt">// failed to add to list
  MSG_LIB_TEXT_SUNDAY,                                                                 class=class="str">"cmt">// Sunday
  MSG_LIB_TEXT_MONDAY,                                                                 class=class="str">"cmt">// Monday
  MSG_LIB_TEXT_TUESDAY,                                                                class=class="str">"cmt">// Tuesday
  MSG_LIB_TEXT_WEDNESDAY,                                                              class=class="str">"cmt">// Wednesday
  MSG_LIB_TEXT_THURSDAY,                                                               class=class="str">"cmt">// Thursday

标准库消息宏的命名与注释对照

在 MT5 标准库的消息文本定义段里,一组 MSG_LIB_TEXT_* 宏承担了多语言界面与日志输出的底层字符串映射。上面这段未命名小节列出了从星期、交易品种到计数器错误、推送开关等数十个常量,每个宏后面紧跟英文注释,实际编译时这些注释就是开发者调试时看到的语义提示。 比如 MSG_LIB_TEXT_FRIDAY 对应周五、MSG_LIB_TEXT_SYMBOL 对应「symbol:」前缀、MSG_LIB_TEXT_INC_BY 与 MSG_LIB_TEXT_DEC_BY 分别表达「increased by / decreased by」,这类命名规则让 EA 在回测日志里输出「Property value increased by 2.5」成为可能,而不是一堆数字代号。 留意 MSG_LIB_TEXT_NOT_MAIL_ENABLED 等三个终端开关宏:它们直接读取 MT5 客户端是否禁用了邮件、推送、FTP 发送。若你的告警脚本在真实账户无反应,优先查这三个宏对应的终端配置,而不是怀疑代码逻辑——这是实盘外汇与贵金属自动化里的高频坑点,相关操作杠杆品种风险较高,须先在模拟盘验证。 数组类宏也值得单独看:MSG_LIB_TEXT_ARRAY_DATA_INTEGER_NULL 指明「受控整型属性数组尺寸为零」的错误,配套 MSG_LIB_TEXT_NEED_SET_INTEGER_VALUE 要求先把数组大小设为对象整型属性数量。复制这段宏定义进你的 include 文件,搜 MSG_LIB_TEXT_ 前缀就能快速定位标准库所有内置提示语。

MQL5 / C++
  MSG_LIB_TEXT_FRIDAY,                                                                     class=class="str">"cmt">// Friday
  MSG_LIB_TEXT_SATURDAY,                                                                   class=class="str">"cmt">// Saturday
  MSG_LIB_TEXT_SYMBOL,                                                                     class=class="str">"cmt">// symbol: 
  MSG_LIB_TEXT_ACCOUNT,                                                                    class=class="str">"cmt">// account: 
  
  MSG_LIB_TEXT_PROP_VALUE,                                                                 class=class="str">"cmt">// Property value
  MSG_LIB_TEXT_INC_BY,                                                                     class=class="str">"cmt">// increased by
  MSG_LIB_TEXT_DEC_BY,                                                                     class=class="str">"cmt">// decreased by
  MSG_LIB_TEXT_MORE_THEN,                                                                  class=class="str">"cmt">// more than
  MSG_LIB_TEXT_LESS_THEN,                                                                  class=class="str">"cmt">// less than
  MSG_LIB_TEXT_EQUAL,                                                                      class=class="str">"cmt">// equal
  
  MSG_LIB_TEXT_ERROR_COUNTER_WITN_ID,                                                      class=class="str">"cmt">// Error. Counter with ID 
  MSG_LIB_TEXT_STEP,                                                                       class=class="str">"cmt">// , step
  MSG_LIB_TEXT_AND_PAUSE,                                                                  class=class="str">"cmt">//  and pause 
  MSG_LIB_TEXT_ALREADY_EXISTS,                                                             class=class="str">"cmt">// already exists
  
  MSG_LIB_TEXT_BASE_OBJ_UNKNOWN_EVENT,                                                     class=class="str">"cmt">// Base object unknown event
  
  MSG_LIB_TEXT_NOT_MAIL_ENABLED,                                                           class=class="str">"cmt">// Sending emails disabled in terminal
  MSG_LIB_TEXT_NOT_PUSH_ENABLED,                                                           class=class="str">"cmt">// Sending push notifications disabled in terminal
  MSG_LIB_TEXT_NOT_FTP_ENABLED,                                                            class=class="str">"cmt">// Sending files to FTP address disabled in terminal
  
  MSG_LIB_TEXT_ARRAY_DATA_INTEGER_NULL,                                                    class=class="str">"cmt">// Controlled integer properties data array has zero size
  MSG_LIB_TEXT_NEED_SET_INTEGER_VALUE,                                                     class=class="str">"cmt">// You should first set the size of the array equal to the number of object integer properties
  MSG_LIB_TEXT_TODO_USE_INTEGER_METHOD,                                                    class=class="str">"cmt">// To do this, use the method
  MSG_LIB_TEXT_WITH_NUMBER_INTEGER_VALUE,                                                  class=class="str">"cmt">// with number value of integer properties of object in the parameter
  
  MSG_LIB_TEXT_ARRAY_DATA_DOUBLE_NULL,                                                     class=class="str">"cmt">// Controlled class="type">class="kw">double properties data array has zero size
  MSG_LIB_TEXT_NEED_SET_DOUBLE_VALUE,                                                      class=class="str">"cmt">// You should first set the size of the array equal to the number of object class="type">class="kw">double properties

「对象属性与订单消息的枚举映射」

在 MT5 标准库的消息宏定义里,双精度数值类属性被集中枚举,方便后续用统一方法取对象参数。比如 MSG_LIB_PROP_BID 对应买价、MSG_LIB_PROP_ASK 对应卖价,MSG_LIB_PROP_LAST 对应最后一笔成交价,这些都属于 double 类型的可读属性。 止损价、止盈价与浮动盈利也走同一套映射:MSG_LIB_PROP_PRICE_SL、MSG_LIB_PROP_PRICE_TP、MSG_LIB_PROP_PROFIT 分别指向 SL、TP 和当前利润。账户侧则有 MSG_LIB_PROP_BALANCE、MSG_LIB_PROP_CREDIT、MSG_LIB_PROP_ACCOUNT 等,覆盖余额、信用操作和账户对象。 订单与成交方向被拆成细粒度常量。COrder 相关里,MSG_ORD_BUY / MSG_ORD_SELL 是即时买卖,MSG_ORD_TO_BUY / MSG_ORD_TO_SELL 是挂单,MSG_DEAL_TO_BUY / MSG_DEAL_TO_SELL 是已成交易,外加 MSG_ORD_HISTORY 与 MSG_ORD_DEAL 区分历史订单和成交。开 MT5 在 Include\Trade\SymbolInfo.mqh 附近搜这些宏,能直接看到原始定义并改自己的提示语。 外汇与贵金属波动大、杠杆高,上述属性取值仅反映某一刻终端状态,实际下单前仍需结合实时点差与风控参数核对。

MQL5 / C++
  MSG_LIB_TEXT_TODO_USE_DOUBLE_METHOD,              class=class="str">"cmt">// To do this, use the method
  MSG_LIB_TEXT_WITH_NUMBER_DOUBLE_VALUE,            class=class="str">"cmt">// with number value of class="type">class="kw">double properties of object in the parameter

  MSG_LIB_PROP_BID,                                 class=class="str">"cmt">// Bid price
  MSG_LIB_PROP_ASK,                                 class=class="str">"cmt">// Ask price
  MSG_LIB_PROP_LAST,                                class=class="str">"cmt">// Last deal price
  MSG_LIB_PROP_PRICE_SL,                            class=class="str">"cmt">// StopLoss price
  MSG_LIB_PROP_PRICE_TP,                            class=class="str">"cmt">// TakeProfit price
  MSG_LIB_PROP_PROFIT,                              class=class="str">"cmt">// Profit
  MSG_LIB_PROP_SYMBOL,                              class=class="str">"cmt">// Symbol
  MSG_LIB_PROP_BALANCE,                             class=class="str">"cmt">// Balance operation
  MSG_LIB_PROP_CREDIT,                              class=class="str">"cmt">// Credit operation
  MSG_LIB_PROP_CLOSE_BY_SL,                         class=class="str">"cmt">// Closing by StopLoss
  MSG_LIB_PROP_CLOSE_BY_TP,                         class=class="str">"cmt">// Closing by TakeProfit
  MSG_LIB_PROP_ACCOUNT,                             class=class="str">"cmt">// Account

class=class="str">"cmt">//--- COrder
  MSG_ORD_BUY,                                      class=class="str">"cmt">// Buy
  MSG_ORD_SELL,                                     class=class="str">"cmt">// Sell
  MSG_ORD_TO_BUY,                                   class=class="str">"cmt">// Buy order
  MSG_ORD_TO_SELL,                                  class=class="str">"cmt">// Sell order
  MSG_DEAL_TO_BUY,                                  class=class="str">"cmt">// Buy deal
  MSG_DEAL_TO_SELL,                                 class=class="str">"cmt">// Sell deal
  MSG_ORD_HISTORY,                                  class=class="str">"cmt">// Historical order
  MSG_ORD_DEAL                                     class=class="str">"cmt">// Deal

◍ 订单状态与类型的枚举常量拆解

在 MT5 的 EA 或指标里,交易事件提示往往依赖一组 MSG_ORD_* / MSG_POS_* 的枚举常量。上面这段声明把持仓、挂单、成交与订单生命周期状态都映射成了可读字符串,方便在日志或面板直接输出。 比如 MSG_ORD_STATE_STARTED 表示「订单已校验但尚未被经纪商接受」,而 MSG_ORD_STATE_PLACED 才是「已被接受」;两者中间可能存在几毫秒到数百毫秒的网络延迟,做高频逻辑时要分开判断。 MSG_ORD_STATE_PARTIAL 与 MSG_ORD_STATE_FILLED 区分了部分成交与完全成交,统计滑点时应只取 FILLED 或累加 PARTIAL 的成交量。外汇与贵金属杠杆交易高风险,状态误判可能导致重复下单。 下面逐行看关键常量:MSG_ORD_POSITION 对应已开持仓;MSG_ORD_PENDING 是未激活挂单;MSG_ORD_SL_ACTIVATED 说明平仓因止损触发;MSG_ORD_TP_ACTIVATED 则是止盈触发;MSG_ORD_PLACED_FROM_MQL4 标记由旧版 MQL4 程序下的单。

MQL5 / C++
  MSG_ORD_POSITION,                                                                      class=class="str">"cmt">// Position
  MSG_ORD_PENDING_ACTIVE,                                                                 class=class="str">"cmt">// Active pending order
  MSG_ORD_PENDING,                                                                        class=class="str">"cmt">// Pending order
  MSG_ORD_UNKNOWN_TYPE,                                                                   class=class="str">"cmt">// Unknown order type
  MSG_POS_UNKNOWN_TYPE,                                                                   class=class="str">"cmt">// Unknown position type
  MSG_POS_UNKNOWN_DEAL,                                                                   class=class="str">"cmt">// Unknown deal type
  class=class="str">"cmt">//---
  MSG_ORD_SL_ACTIVATED,                                                                   class=class="str">"cmt">// Due to StopLoss
  MSG_ORD_TP_ACTIVATED,                                                                   class=class="str">"cmt">// Due to TakeProfit
  MSG_ORD_PLACED_FROM_MQL4,                                                               class=class="str">"cmt">// Placed from mql4 program
  MSG_ORD_STATE_CANCELLED,                                                                class=class="str">"cmt">// Order cancelled
  MSG_ORD_STATE_CANCELLED_CLIENT,                                                         class=class="str">"cmt">// Order withdrawn by client
  MSG_ORD_STATE_STARTED,                                                                  class=class="str">"cmt">// Order verified but not yet accepted by broker
  MSG_ORD_STATE_PLACED,                                                                   class=class="str">"cmt">// Order accepted
  MSG_ORD_STATE_PARTIAL,                                                                  class=class="str">"cmt">// Order filled partially
  MSG_ORD_STATE_FILLED,                                                                   class=class="str">"cmt">// Order filled
  MSG_ORD_STATE_REJECTED,                                                                 class=class="str">"cmt">// Order rejected
  MSG_ORD_STATE_EXPIRED,                                                                  class=class="str">"cmt">// Order withdrawn upon expiration
  MSG_ORD_STATE_REQUEST_ADD,                                                              class=class="str">"cmt">// Order in the state of registration(placing in the trading system)
  MSG_ORD_STATE_REQUEST_MODIFY,                                                           class=class="str">"cmt">// Order in the state of modification
  MSG_ORD_STATE_REQUEST_CANCEL,                                                           class=class="str">"cmt">// Order in deletion state
  MSG_ORD_STATE_UNKNOWN,                                                                  class=class="str">"cmt">// Unknown state
  class=class="str">"cmt">//---
  MSG_ORD_REASON_CLIENT                                                                   class=class="str">"cmt">// Order set from desktop terminal

订单来源与属性的枚举常量

在 MT5 的订单事件通知体系里,系统用一组 MSG_ORD_REASON_* 常量区分订单是怎么来的:从桌面端、移动端、网页端手动下的,还是 EA/脚本自动发的,亦或是止损爆仓(Stop Out)触发的。 其中 MSG_ORD_REASON_MOBILE 到 MSG_ORD_REASON_EXPERT 描述的是挂单和下单动作的来源,而 MSG_ORD_REASON_DEAL_* 与 MSG_ORD_REASON_POS_* 则进一步把「成交」和「建仓」拆开标记,比如 MSG_ORD_REASON_DEAL_ROLLOVER 专门指代展期产生的成交,MSG_ORD_REASON_POS_EXPERT 则说明仓位由 EA 开启。 往下还有一批描述订单自身属性的 MSG_ORD_* 常量:MSG_ORD_MAGIC 是 EA 的魔术号,MSG_ORD_TICKET 是订单号,MSG_ORD_TICKET_FROM / MSG_ORD_TICKET_TO 用来追踪父子订单的继承关系,MSG_ORD_TIME_EXP 给出过期时间,MSG_ORD_TYPE 与 MSG_ORD_TYPE_BY_DIRECTION 则标明订单类型和方向。 开 MT5 按 F4 进 MetaEditor,在 TradeTransaction 相关头文件里搜 MSG_ORD_REASON 就能看到这整张表;写 EA 时靠这些常量过滤来源,可只处理自己魔术号或 EA 渠道的订单,避开手动单干扰。外汇与贵金属杠杆交易高风险,用来源过滤做风控逻辑时仍可能漏掉极端行情下的系统单。

MQL5 / C++
  MSG_ORD_REASON_MOBILE,                                              class=class="str">"cmt">// Order set from mobile app
  MSG_ORD_REASON_WEB,                                                 class=class="str">"cmt">// Order set from web platform
  MSG_ORD_REASON_EXPERT,                                              class=class="str">"cmt">// Order set from EA or script
  MSG_ORD_REASON_SO,                                                  class=class="str">"cmt">// Due to Stop Out
  MSG_ORD_REASON_DEAL_CLIENT,                                        class=class="str">"cmt">// Deal carried out from desktop terminal
  MSG_ORD_REASON_DEAL_MOBILE,                                        class=class="str">"cmt">// Deal carried out from mobile app
  MSG_ORD_REASON_DEAL_WEB,                                           class=class="str">"cmt">// Deal carried out from web platform
  MSG_ORD_REASON_DEAL_EXPERT,                                        class=class="str">"cmt">// Deal carried out from EA or script
  MSG_ORD_REASON_DEAL_STOPOUT,                                       class=class="str">"cmt">// Due to Stop Out
  MSG_ORD_REASON_DEAL_ROLLOVER,                                      class=class="str">"cmt">// Due to position rollover
  MSG_ORD_REASON_DEAL_VMARGIN,                                       class=class="str">"cmt">// Due to variation margin
  MSG_ORD_REASON_DEAL_SPLIT,                                         class=class="str">"cmt">// Due to split
  MSG_ORD_REASON_POS_CLIENT,                                         class=class="str">"cmt">// Position opened from desktop terminal
  MSG_ORD_REASON_POS_MOBILE,                                         class=class="str">"cmt">// Position opened from mobile app
  MSG_ORD_REASON_POS_WEB,                                            class=class="str">"cmt">// Position opened from web platform
  MSG_ORD_REASON_POS_EXPERT,                                         class=class="str">"cmt">// Position opened from EA or script
  class=class="str">"cmt">//---
  MSG_ORD_MAGIC,                                                     class=class="str">"cmt">// Magic number
  MSG_ORD_TICKET,                                                    class=class="str">"cmt">// Ticket
  MSG_ORD_TICKET_FROM,                                               class=class="str">"cmt">// Parent order ticket
  MSG_ORD_TICKET_TO,                                                 class=class="str">"cmt">// Inherited order ticket
  MSG_ORD_TIME_EXP,                                                  class=class="str">"cmt">// Expiration date
  MSG_ORD_TYPE,                                                      class=class="str">"cmt">// Type
  MSG_ORD_TYPE_BY_DIRECTION,                                         class=class="str">"cmt">// Direction

「订单推送消息枚举的字段映射」

在 MT5 的订单事件推送结构里,每一类订单状态变动都对应一组 MSG_ORD_* 枚举常量,用于向监听端传递具体字段。上面列出的 27 个常量覆盖了从开仓原因、持仓 ID 到盈亏点数、佣金库存费的完整链路。 比如 MSG_ORD_DEAL_IN 表示入場成交,MSG_ORD_DEAL_OUT 表示出场成交,而 MSG_ORD_DEAL_INOUT 特指反手(Reversal)这种同tick内平旧开新。MSG_ORD_TIME_OPEN / CLOSE / UPDATE 三者的注释都标了毫秒级时间戳,说明推送精度到 ms 而非秒。 做自定义盯盘面板时,直接按这些枚举捞字段即可,不用自己解析原始 JSON。外汇与贵金属杠杆高,推送里的 MSG_ORD_PROFIT_PT 只是点数浮盈,实盘可能因滑点偏离,仅作参考。

MQL5 / C++
  MSG_ORD_REASON,                                                                     class=class="str">"cmt">// Reason
  MSG_ORD_POSITION_ID,                                                                 class=class="str">"cmt">// Position ID
  MSG_ORD_DEAL_ORDER_TICKET,                                                           class=class="str">"cmt">// Deal by order ticket
  MSG_ORD_DEAL_ENTRY,                                                                  class=class="str">"cmt">// Deal direction
  MSG_ORD_DEAL_IN,                                                                     class=class="str">"cmt">// Entry to market
  MSG_ORD_DEAL_OUT,                                                                    class=class="str">"cmt">// Out from market
  MSG_ORD_DEAL_INOUT,                                                                  class=class="str">"cmt">// Reversal
  MSG_ORD_DEAL_OUT_BY,                                                                 class=class="str">"cmt">// Close by
  MSG_ORD_POSITION_BY_ID,                                                              class=class="str">"cmt">// Opposite position ID
  MSG_ORD_TIME_OPEN,                                                                   class=class="str">"cmt">// Open time in milliseconds
  MSG_ORD_TIME_CLOSE,                                                                  class=class="str">"cmt">// Close time in milliseconds
  MSG_ORD_TIME_UPDATE,                                                                 class=class="str">"cmt">// Position change time in milliseconds
  MSG_ORD_STATE,                                                                       class=class="str">"cmt">// State
  MSG_ORD_STATUS,                                                                      class=class="str">"cmt">// Status
  MSG_ORD_DISTANCE_PT,                                                                 class=class="str">"cmt">// Distance from price in points
  MSG_ORD_PROFIT_PT,                                                                   class=class="str">"cmt">// Profit in points
  MSG_ORD_GROUP_ID,                                                                    class=class="str">"cmt">// Group ID
  MSG_ORD_PRICE_OPEN,                                                                  class=class="str">"cmt">// Open price
  MSG_ORD_PRICE_CLOSE,                                                                 class=class="str">"cmt">// Close price
  MSG_ORD_PRICE_STOP_LIMIT,                                                            class=class="str">"cmt">// Limit order price when StopLimit order is activated
  MSG_ORD_COMMISSION,                                                                  class=class="str">"cmt">// Commission
  MSG_ORD_SWAP                                                                         class=class="str">"cmt">// Swap
让小布替你跑这套
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到消息分派与多语言切换的样板结构,你照着搬进自己的 EA 即可,不必从零写数组枚举。

常见问题

二维数组第一维放消息索引,第二维放各语言文本,新增语言只补一列,且同一条消息在多个对象间共享一份存储,编译后体积更小。
把错误码作为消息数组的索引,运行时取码直接查表显示对应语言文本,避免在每个调用点手写判断分支。
可封装邮件、移动推送、FTP 发文件、播声音等动作,统一用消息索引触发,调用方只传码不关心渠道。
小布盯盘品种页内置的 AIGC 片段含一套消息分派示例,支持中俄英切换,可借来改造成你函数库的基础类。
只需指定第二维的语言索引,类内部按索引取文本,业务代码无需变动,适合做运行时热切换。