DoEasy 函数库中的其他类(第六十六部分):MQL5.com 信号集合类(基础篇)
◍ 给信号对象造一个集合容器
在 DoEasy 函数库里,信号对象原本是零散存在的,要把它们当一组来管理,就得单独做一个集合类。这个类专门收纳 MQL5 信号对象,方便后续统一遍历、查找和释放。 做集合类时,核心是把每个信号对象封装成可索引的节点,外层用动态数组或哈希结构持有指针。这样在 EA 里调用时,不用反复向终端请求信号列表,本地就能直接拿到已缓存的对象引用。 实际落地时,建议先在脚本里打印集合的 Size() 和首个信号名,确认装载逻辑没问题再接进策略。外汇与贵金属信号波动受杠杆和流动性影响,高杠杆品类风险显著,信号历史表现不代表未来概率。
「信号集合与DOM快照的对象化封装」
上一节只解决了单个信号对象的建模,这一节把视角拉到信号数据库整体:用一个集合类把服务里广播的所有信号塞进同一张列表,之后按索引调 SignalBaseSelect() 就能直接取到目标信号。 集合类落地后,筛选逻辑可以完全参数化。比如只拉免费或付费信号、按盈利能力排序,或者一步返回参数等于、大于、小于某阈值的信号索引——搜索和排序都在对象内部完成,外层不用再写循环。 顺带把市场深度(DOM)快照类也补了属性:建对象时直接算好买卖盘总成交量。做贵金属或外汇 DOM 策略时,你不必再临时遍历挂单求和,开 MT5 调 CMarketDepth 构造就能拿到即时买卖量。 外汇与贵金属杠杆高、滑点跳空频繁,DOM 成交量只是概率参考,不能直接当成交保证。
给 DoEasy 库补上快照量与信号检索的底层接口
做图形化操控前,先把库里的消息与对象属性接口铺平。Data.mqh 里新增了 DOM 快照买卖量、快照序列、以及 MQL5 信号服务相关的一批消息索引,这些索引后续由 Message 类统一往日志抛,不再散用 Print()。 Message.mqh 中给 ToLog() 做了重载:新变体多接收一个“来源方法/函数名”参数,日志输出时把这个来源写在消息前面。调试时你能直接看到是哪段逻辑吐的线,不用再手动拼前缀。 MarketBookSnapshot 类的私密区加了总买量、总卖量两个成员变量。参数型构造函数里遍历 DOM 订单时,按订单方向把交易量分别累加进这两个变量——对象建完,总买卖量就已经就绪,不用事后另算。 返回说明的两个新方法会做阈值判断:交易量大于 0 才返回“标题+实数交易量”,否则返回整数型占位。这条规则让日志里的 DOM 简报更干净。 MQLSignal 类补了带连字符标志的 PrintShort(),并新增按描述执行信号订阅的方法;构造函数里订阅状态不再写死 false,而是用信号对象 ID 与“当前已订阅”有效 ID 比对的结果初始化。相等即视为已激活订阅。 Select.mqh 的 CSelect 类声明了操控信号对象集合的搜索/排序方法,逻辑与第三篇文章里其他对象类一致。Defines.mqh 则加了信号集合的自定义 ID,为后面独立集合类铺路。 下面这段是本次新增消息索引的原文片段,直接贴进对应头文件即可编译:
class=class="str">"cmt">//--- CMarketBookSnapshot MSG_MBOOK_SNAP_TEXT_SNAPSHOT, class=class="str">"cmt">// DOM snapshot MSG_MBOOK_SNAP_VOLUME_BUY, class=class="str">"cmt">// Buy volume MSG_MBOOK_SNAP_VOLUME_SELL, class=class="str">"cmt">// Sell volume class=class="str">"cmt">//--- CMBookSeries MSG_MBOOK_SERIES_TEXT_MBOOKSERIES, class=class="str">"cmt">// DOM snapshot series MSG_MBOOK_SERIES_ERR_ADD_TO_LIST, class=class="str">"cmt">// Error. Failed to add DOM snapshot series to the list class=class="str">"cmt">//--- CMQLSignal MSG_SIGNAL_MQL5_TEXT_SIGNAL, class=class="str">"cmt">// Signal MSG_SIGNAL_MQL5_TEXT_SIGNAL_MQL5, class=class="str">"cmt">// MQL5.com Signals service signal MSG_SIGNAL_MQL5_TRADE_MODE, class=class="str">"cmt">// Account type MSG_SIGNAL_MQL5_DATE_PUBLISHED, class=class="str">"cmt">// Publication date MSG_SIGNAL_MQL5_DATE_STARTED, class=class="str">"cmt">// Monitoring start date MSG_SIGNAL_MQL5_DATE_UPDATED, class=class="str">"cmt">// Date of the latest update of the trading statistics MSG_SIGNAL_MQL5_ID, class=class="str">"cmt">// ID MSG_SIGNAL_MQL5_LEVERAGE, class=class="str">"cmt">// Trading account leverage MSG_SIGNAL_MQL5_PIPS, class=class="str">"cmt">// Trading result in pips MSG_SIGNAL_MQL5_RATING, class=class="str">"cmt">// Position in the signal rating
◍ 信号元数据枚举里藏着的订阅参数
在 MQL5 的信号接口里,一组 MSG_SIGNAL_MQL5_* 枚举直接对应信号展示与订阅时的核心字段。从订阅人数、交易笔数到账户权益、最大回撤、ROI 百分比,这些常量决定了你在终端里能看到哪些信号指标。 下面这段枚举清单是直接从标准头文件截出的,逐行看就能明白每个 ID 管什么: MSG_SIGNAL_MQL5_SUBSCRIBERS, // 订阅者数量 MSG_SIGNAL_MQL5_TRADES, // 交易笔数 MSG_SIGNAL_MQL5_SUBSCRIPTION_STATUS, // 账户对该信号的订阅状态 MSG_SIGNAL_MQL5_EQUITY, // 账户权益 MSG_SIGNAL_MQL5_GAIN, // 账户增长百分比 MSG_SIGNAL_MQL5_MAX_DRAWDOWN, // 最大回撤 MSG_SIGNAL_MQL5_PRICE, // 信号订阅价格 MSG_SIGNAL_MQL5_ROI, // 信号投资回报率百分比 MSG_SIGNAL_MQL5_AUTHOR_LOGIN, // 作者登录名 MSG_SIGNAL_MQL5_BROKER, // 经纪商公司名 MSG_SIGNAL_MQL5_BROKER_SERVER, // 经纪商服务器 MSG_SIGNAL_MQL5_NAME, // 名称 MSG_SIGNAL_MQL5_CURRENCY, // 账户货币 MSG_SIGNAL_MQL5_TEXT_GAIN, // 增长文本 MSG_SIGNAL_MQL5_TEXT_DRAWDOWN, // 回撤文本 MSG_SIGNAL_MQL5_TEXT_SUBSCRIBERS, // 订阅者文本 CMQLSignalsCollection 这组则管信号集合本身:付费/免费信号分类、新信号入列、拉取失败报错都在里面。 MSG_MQLSIG_COLLECTION_TEXT_MQL5_SIGNAL_COLLECTION, // MQL5信号服务信号集合 MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_PAID, // 付费信号 MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_FREE, // 免费信号 MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_NEW, // 新加入集合的信号 MSG_MQLSIG_COLLECTION_ERR_FAILED_GET_SIGNAL, // 从集合接收信号失败 订阅复制端的参数也暴露了风控点:MSG_SIGNAL_INFO_EQUITY_LIMIT 是仓位体积转换的百分比,MSG_SIGNAL_INFO_SLIPPAGE 是同步持仓时的市价单滑点,MSG_SIGNAL_INFO_VOLUME_PERCENT 限制信号权益。外汇和贵金属信号订阅自带高杠杆风险,复制前建议先在 MT5 策略测试器里用历史数据核验最大回撤与 ROI 是否匹配你的账户权益上限。
MSG_SIGNAL_MQL5_SUBSCRIBERS, class=class="str">"cmt">// Number of subscribers MSG_SIGNAL_MQL5_TRADES, class=class="str">"cmt">// Number of trades MSG_SIGNAL_MQL5_SUBSCRIPTION_STATUS, class=class="str">"cmt">// Status of account subscription to a signal MSG_SIGNAL_MQL5_EQUITY, class=class="str">"cmt">// Account equity MSG_SIGNAL_MQL5_GAIN, class=class="str">"cmt">// Account growth in % MSG_SIGNAL_MQL5_MAX_DRAWDOWN, class=class="str">"cmt">// Maximum drawdown MSG_SIGNAL_MQL5_PRICE, class=class="str">"cmt">// Signal subscription price MSG_SIGNAL_MQL5_ROI, class=class="str">"cmt">// Signal ROI(Return on Investment) in % MSG_SIGNAL_MQL5_AUTHOR_LOGIN, class=class="str">"cmt">// Author login MSG_SIGNAL_MQL5_BROKER, class=class="str">"cmt">// Broker(company) name MSG_SIGNAL_MQL5_BROKER_SERVER, class=class="str">"cmt">// Broker server MSG_SIGNAL_MQL5_NAME, class=class="str">"cmt">// Name MSG_SIGNAL_MQL5_CURRENCY, class=class="str">"cmt">// Account currency MSG_SIGNAL_MQL5_TEXT_GAIN, class=class="str">"cmt">// Growth MSG_SIGNAL_MQL5_TEXT_DRAWDOWN, class=class="str">"cmt">// Drawdown MSG_SIGNAL_MQL5_TEXT_SUBSCRIBERS, class=class="str">"cmt">// Subscribers class=class="str">"cmt">//--- CMQLSignalsCollection MSG_MQLSIG_COLLECTION_TEXT_MQL5_SIGNAL_COLLECTION, class=class="str">"cmt">// Collection of MQL5.com Signals service signals MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_PAID, class=class="str">"cmt">// Paid signals MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_FREE, class=class="str">"cmt">// Free signals MSG_MQLSIG_COLLECTION_TEXT_SIGNALS_NEW, class=class="str">"cmt">// New signal added to collection MSG_MQLSIG_COLLECTION_ERR_FAILED_GET_SIGNAL, class=class="str">"cmt">// Failed to receive signal from collection MSG_SIGNAL_INFO_PARAMETERS, class=class="str">"cmt">// Signal copying parameters MSG_SIGNAL_INFO_EQUITY_LIMIT, class=class="str">"cmt">// Percentage for converting deal volume MSG_SIGNAL_INFO_SLIPPAGE, class=class="str">"cmt">// Market order slippage when synchronizing positions and copying deals MSG_SIGNAL_INFO_VOLUME_PERCENT, class=class="str">"cmt">// Limitation on signal equity MSG_SIGNAL_INFO_CONFIRMATIONS_DISABLED class=class="str">"cmt">// Enable synchronization without confirmation dialog
「信号订阅与行情快照的本地化字段映射」
在 MT5 的 EA 或指标源码里,信号服务与深度行情快照的类对象通常带一套俄英双语文案常量,编译后用于界面提示和多语言切换。上面这段枚举/结构体初始化列出了 MSG_SIGNAL_INFO_* 系列,覆盖复制止损止盈、按保证金限制、信号 ID、订阅开关、服务条款同意等 12 个关键状态位。 其中 MSG_SIGNAL_INFO_ERR_SIGNAL_NOT_ALLOWED 对应的提示是「Signal service disabled for program」,意味着在程序属性 Common 页没勾选 Allow modification of Signals settings 时,EA 内部调用信号接口会直接返回该错误,而不是静默失败。 紧跟着的 CMarketBookSnapshot、CMBookSeries 等类把「Снимок стакана цен」映射为 Depth of Market Snapshot,「Объём на покупку / продажу」分别映射为 Buy Volume / Sell Volume,这是本地化 DOM 面板数据的底层键值。CMQLSignal 类则暴露了信号账号杠杆、盈利点数、订阅人数、最大回撤、ROI(%) 等 20 余个可读属性——接信号前先读 Number of subscribers 和 Account maximum drawdown,外汇与贵金属信号自带高杠杆风险,订阅复制可能放大本金亏损。 开 MT5 按 F4 进 MetaEditor,搜 MSG_SIGNAL_INFO_TEXT_CHECK_SETTINGS 就能定位到这段映射,改双语常量即可做私有化提示,不必动逻辑层。
MSG_SIGNAL_INFO_COPY_SLTP, class=class="str">"cmt">// Copy Stop Loss and Take Profit MSG_SIGNAL_INFO_DEPOSIT_PERCENT, class=class="str">"cmt">// Limit by deposit MSG_SIGNAL_INFO_ID, class=class="str">"cmt">// Signal ID MSG_SIGNAL_INFO_SUBSCRIPTION_ENABLED, class=class="str">"cmt">// Enable copying deals by subscription MSG_SIGNAL_INFO_TERMS_AGREE, class=class="str">"cmt">// Agree to the terms of use of the Signals service MSG_SIGNAL_INFO_NAME, class=class="str">"cmt">// Signal name MSG_SIGNAL_INFO_SIGNALS_PERMISSION, class=class="str">"cmt">// Allow using signals for program MSG_SIGNAL_INFO_TEXT_SIGNAL_SUBSCRIBED, class=class="str">"cmt">// Subscribed to signal MSG_SIGNAL_INFO_TEXT_SIGNAL_UNSUBSCRIBED, class=class="str">"cmt">// Unsubscribed from signal MSG_SIGNAL_INFO_ERR_SIGNAL_NOT_ALLOWED, class=class="str">"cmt">// Signal service disabled for program MSG_SIGNAL_INFO_TEXT_CHECK_SETTINGS, class=class="str">"cmt">// Please check program settings(Common-->Allow modification of Signals settings) }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//--- CMarketBookSnapshot {"Снимок стакана цен","Depth of Market Snapshot"}, {"Объём на покупку","Buy Volume"}, {"Объём на продажу","Sell Volume"}, class=class="str">"cmt">//--- CMBookSeries {"Серия снимков стакана цен","Series of shots of the Depth of Market"}, {"Ошибка. Не удалось добавить серию снимков стакана цен в список","Error. Failed to add a shots series of the Depth of Market to the list"}, class=class="str">"cmt">//--- CMBookSeriesCollection {"Коллекция серий снимков стакана цен","Collection of series of the Depth of Market shot"}, class=class="str">"cmt">//--- CMQLSignal {"Сигнал","Signal"}, {"Сигнал сервиса сигналов mql5.com","Signal from mql5.com signal service"}, {"Тип счета","Account type"}, {"Дата публикации","Publication date"}, {"Дата начала мониторинга","Monitoring starting date"}, {"Дата последнего обновления торговой статистики","The date of the last update of the signal&class="macro">#x27;s trading statistics"}, {"ID","ID"}, {"Плечо торгового счета","Account leverage"}, {"Результат торговли в пипсах","Profit in pips"}, {"Позиция в рейтинге сигналов","Position in rating"}, {"Количество подписчиков","Number of subscribers"}, {"Количество трейдов","Number of trades"}, {"Состояние подписки счёта на этот сигнал","Account subscription status for this signal"}, {"Средства на счете","Account equity"}, {"Прирост счета в процентах","Account gain"}, {"Максимальная просадка","Account maximum drawdown"}, {"Цена подписки на сигнал","Signal subscription price"}, {"Значение ROI(Return on Investment) сигнала в %","Return on Investment(%)"}, {"Логин автора","Author login"}
信号服务多语言映射与日志投递接口
这段结构体初始化把信号服务里的中文/俄文字段逐个映射到英文字符串,覆盖券商名、服务器、账户币种、增益、回撤、订阅人数等基础项,也包含 CMQLSignalsCollection 下的信号集合、付费/免费信号数、复制参数(如 Equity limit 对应成交量转换百分比、Slippage 用于同步持仓与跟单时的滑点容差)。 跟单权限相关字段值得在 MT5 里实测:'Allow synchronization without confirmation dialog' 控制是否跳过确认框直接同步,'Maximum percent of deposit used' 限制信号占用保证金比例,'Copy Stop Loss and Take Profit' 决定止损止盈是否跟随。外汇与贵金属杠杆高,跟单前应先在策略测试器用极小资金验证这些参数实际行为。 日志类静态方法提供了三种出口:ToLog 按 msg_id 往专家日志打消息,重载版可带 source 前缀;ToMail 发邮件,Push 推送到移动端。下面这段声明直接可见接口形态。 调用 ToLog 时若传入 code=true,日志会附带错误码,便于在小布盯盘后台按 ID 过滤信号异常。实际跟单中断多半能在 journal 里用 Signal ID 反查是哪条订阅出了界。
{"Наименование брокера (компании)","Broker name(company)"},
{"Сервер брокера","Broker server"},
{"Имя","Name"},
{"Валюта счета","Base currency"},
{"Прирост","Gain"},
{"Просадка","Drawdown"},
{"Подписчиков","Subscribers"},
class=class="str">"cmt">//--- CMQLSignalsCollection
{"Коллекция сигналов сервиса сигналов mql5.com","Collection of signals from the mql5.com signal service"},
{"Платных сигналов","Paid signals"},
{"Бесплатных сигналов","Free signals"},
{"Новый сигнал добавлен в коллекцию","New signal added to collection"},
{"Не удалось получить сигнал из коллекции","Failed to get signal from collection"},
{"Параметры копирования сигнала","Signal copying parameters"},
{"Процент для конвертации объема сделки","Equity limit"},
{"Проскальзывание, с которым выставляются рыночные ордера при синхронизации позиций и копировании сделок","Slippage(used when placing market orders in synchronization of positions and copying of trades)"},
{"Ограничение по средствам для сигнала","Maximum percent of deposit used"},
{"Разрешение синхронизации без показа диалога подтверждения","Allow synchronization without confirmation dialog"},
{"Копирование Stop Loss и Take Profit","Copy Stop Loss and Take Profit"},
{"Ограничение по депозиту","Deposit percent"},
{"Идентификатор сигнала","Signal ID"},
{"Разрешение на копирование сделок по подписке","Permission to copy trades by subscription"},
{"Согласие с условиями использования сервиса \"Сигналы\"","Agree to the terms of use of the \"Signals\" service"},
{"Имя сигнала","Signal name"},
{"Разрешение на работу с сигналами для программы","Permission to work with signals for the program"},
{"Осуществлена подписка на сигнал","Signal subscribed"},
{"Осуществлена отписка от сигнала","Signal unsubscribed"},
{"Работа с сервисом сигналов для программы не разрешена","Work with the \"Signals\" service is not allowed for the program"},
{
"Пожалуйста, проверьте настройки программы (Общие --> Разрешить изменение настроек Сигналов)",
"Please check the program settings(Common --> Allow modification of Signals settings)"
},
};
class=class="str">"cmt">//+---------------------------------------------------------------------+
class=class="str">"cmt">//--- (class="num">1,class="num">2) display a message in the journal by ID, (class="num">3) to e-mail, (class="num">4) to a mobile device
class="kw">static class="type">void ToLog(const class="type">int msg_id,const class="type">bool code=false);
class="kw">static class="type">void ToLog(const class="type">class="kw">string source,const class="type">int msg_id,const class="type">bool code=false);
class="kw">static class="type">bool ToMail(const class="type">class="kw">string message,const class="type">class="kw">string subject=NULL);
class="kw">static class="type">bool Push(const class="type">class="kw">string message);
class=class="str">"cmt">//--- (class="num">1) send a file to FTP, (class="num">2) class="kw">return an error code