DoEasy 函数库中的图形(第九十七部分):独立处理窗体对象移动·进阶篇
(2/3)· 想用鼠标拖动图表上的任意窗体,却总被其他工具的事件干扰?本篇收口移动处理逻辑。
10027–10038 这批交易报错码在说什么
在 MT5 的 Trade 相关返回码里,10027 到 10038 这一段集中暴露了客户端与交易服务器之间的「软性拒绝」。它们不是行情问题,而是下单动作本身被终端或券商规则拦下。 比如 10027 代表客户端禁用了自动交易,EA 再怎么发单也会被挡;10031 是无服务器连接,这时候任何下单函数都会直接返回失败。10033 和 10034 则是账户层面的限额:挂单总数触顶、或单一品种的开仓与挂单总体积触顶。 外汇与贵金属杠杆高,这类返回码频繁出现往往意味着风控参数或终端设置要先排查,而不是盲目重试。打开 MT5 的「工具→选项→EA交易」,确认允许算法交易勾选状态,能直接消掉 10027。 下面这段是这批码的原始中俄英对照定义,直接取自标准错误表结构,可粘进枚举做本地化:
{"Автотрейдинг запрещен клиентским терминалом","Autotrading disabled by client terminal"}, class=class="str">"cmt">// class="num">10027
{"Запрос заблокирован для обработки","Request locked for processing"}, class=class="str">"cmt">// class="num">10028
{"Ордер или позиция заморожены","Order or position frozen"}, class=class="str">"cmt">// class="num">10029
{"Указан неподдерживаемый тип исполнения ордера по остатку","Invalid order filling type"}, class=class="str">"cmt">// class="num">10030
{"Нет соединения с торговым сервером","No connection with trade server"}, class=class="str">"cmt">// class="num">10031
{"Операция разрешена только для реальных счетов","Operation allowed only for live accounts"}, class=class="str">"cmt">// class="num">10032
{"Достигнут лимит на количество отложенных ордеров","Number of pending orders reached limit"}, class=class="str">"cmt">// class="num">10033
{"Достигнут лимит на объем ордеров и позиций для данного символа","Volume of orders and positions for symbol reached limit"}, class=class="str">"cmt">// class="num">10034
{"Неверный или запрещённый тип ордера","Incorrect or prohibited order type"}, class=class="str">"cmt">// class="num">10035
{"Позиция с указанным идентификатором уже закрыта","Position with specified identifier already closed"}, class=class="str">"cmt">// class="num">10036
{"Неизвестный код возврата торгового сервера","Unknown trading server class="kw">return code"}, class=class="str">"cmt">// class="num">10037
{"Закрываемый объем превышает текущий объем позиции","Close volume exceeds the current position volume"} class=class="str">"cmt">// class="num">10038「交易请求被拒的底层错误码」
在 MT5 的 EA 或脚本里,交易函数返回的错误码能直接告诉你请求为什么没成交。下面这组 10039–10046 的常量,是仓位与账户规则层面的典型拒绝原因,做风控逻辑时绕不开。
- 表示指定仓位已经挂了关闭订单,再发平仓请求会被拒;10040 是持仓数触到账户上限。10041 则是挂单激活请求被驳、挂单直接取消,常见于流动性瞬间抽干时。
- 到 10044 都是品种级限制:分别只允许多、只允许空、只允许平。10045 是账户层 FIFO 平仓强制规则,10046 禁止同一品种开对向仓位。外汇与贵金属杠杆高,这类规则由经纪商动态设定,实盘前务必用 Print 把返回值打出来核对。
把这些码写进错误映射数组,EA 才能在拒绝时给出可读提示,而不是闷头重试。下面这段就是原文里的映射片段,逐行看:前两项是俄语与英语双语文本配错误码注释;10046 那组标明账户禁对向仓。
{"Для указанной позиции уже есть ордер на закрытие","Close order already exists for specified position"}, class=class="str">"cmt">// class="num">10039
{"Достигнут лимит на количество открытых позиций","Number of positions reached limit"}, class=class="str">"cmt">// class="num">10040
{
"Запрос на активацию отложенного ордера отклонен, а сам ордер отменен", class=class="str">"cmt">// class="num">10041
"The pending order activation request is rejected, the order is canceled"
},
{
"Запрос отклонен, так как на символе установлено правило \"Разрешены только длинные позиции\"", class=class="str">"cmt">// class="num">10042
"The request is rejected, because the \"Only class="type">long positions are allowed\" rule is set for the symbol"
},
{
"Запрос отклонен, так как на символе установлено правило \"Разрешены только короткие позиции\"", class=class="str">"cmt">// class="num">10043
"The request is rejected, because the \"Only class="type">class="kw">short positions are allowed\" rule is set for the symbol"
},
{
"Запрос отклонен, так как на символе установлено правило \"Разрешено только закрывать существующие позиции\"", class=class="str">"cmt">// class="num">10044
"The request is rejected, because the \"Only position closing is allowed\" rule is set for the symbol"
},
{
"Запрос отклонен, так как для торгового счета установлено правило \"Разрешено закрывать существующие позиции только по правилу FIFO\"", class=class="str">"cmt">// class="num">10045
"The request is rejected, because \"Position closing is allowed only by FIFO rule\" flag is set for the trading account"
},
{
"Запрос отклонен, так как для торгового счета установлено правило \"Запрещено открывать встречные позиции по одному символу\"", class=class="str">"cmt">// class="num">10046
"The request is rejected, because the \"Opposite positions on a single symbol are disabled\" rule is set for the trading account"
},◍ OpenCL 报错码 5100–5109 的本地化映射
在 MT5 终端里调用 OpenCL 做并行计算(比如多品种形态扫描)时,系统错误会以 5xxx 系列码返回。下面这段错误描述表把俄文与英文双语文本成对写死在数组里,方便 EA 在日志里直接吐出可读信息,而不是只留一个冷冰冰的数字。 从 5100 到 5109 覆盖了最常见的十类故障:本机不支持 OpenCL、运行内部错、句柄无效、上下文创建失败、执行队列创建失败、程序编译失败、内核名过长、内核创建失败、内核参数设置失败、程序运行时错误。 如果你在老核显或没装显卡驱动的 VPS 上跑 GPU 版指标,大概率先撞上 5100;而写了自定义 .cl 内核却编译不过,终端会抛 5105。开 MT5 按 F4 进 MetaEditor,把这段表贴进错误映射函数,断点跑一遍就能看到具体是哪一行卡住。
{"Функции OpenCL на данном компьютере не поддерживаются","OpenCL functions not supported on this computer"}, class=class="str">"cmt">// class="num">5100
{"Внутренняя ошибка при выполнении OpenCL","Internal error occurred when running OpenCL"}, class=class="str">"cmt">// class="num">5101
{"Неправильный хэндл OpenCL","Invalid OpenCL handle"}, class=class="str">"cmt">// class="num">5102
{"Ошибка при создании контекста OpenCL","Error creating the OpenCL context"}, class=class="str">"cmt">// class="num">5103
{"Ошибка создания очереди выполнения в OpenCL","Failed to create run queue in OpenCL"}, class=class="str">"cmt">// class="num">5104
{"Ошибка при компиляции программы OpenCL","Error occurred when compiling OpenCL program"}, class=class="str">"cmt">// class="num">5105
{"Слишком длинное имя точки входа (кернел OpenCL)","Too class="type">long kernel name(OpenCL kernel)"}, class=class="str">"cmt">// class="num">5106
{"Ошибка создания кернел - точки входа OpenCL","Error creating OpenCL kernel"}, class=class="str">"cmt">// class="num">5107
{
"Ошибка при установке параметров для кернел OpenCL(точки входа в программу OpenCL)", class=class="str">"cmt">// class="num">5108
"Error occurred when setting parameters for the OpenCL kernel"
},
{"Ошибка выполнения программы OpenCL","OpenCL program runtime error"}, class=class="str">"cmt">// class="num">5109OpenCL与数据库运行时报错码对照
在 MT5 的 EA 或指标里调用 OpenCL 做并行计算时,内核返回的错误码集中在 5110–5114 这一段。比如 5110 代表传入的缓冲区尺寸不合法,5111 是偏移量越界,5112 直接是缓冲区创建失败,这类错误往往出现在你用 BufferCreate 传了非 2 的幂尺寸、或总显存占用超过设备上限时。
紧接着 5120–5122 是数据库操作的执行期报错。DatabaseOpen 返回的句柄如果失效会抛 5121,而同进程内打开的 SQLite 连接数超过终端限制则触发 5122。实盘跑高频策略做本地 tick 落库时,这个上限很容易在多线程回测里踩到。
下面两段数组就是终端内部用的双语消息表,第一列俄语、第二列英文,直接嵌在你的错误打印模块里就能把数字码翻译成可读文本,省去查文档的功夫。
{"Неверный размер буфера OpenCL","Invalid size of OpenCL buffer"}, class=class="str">"cmt">// class="num">5110
{"Неверное смещение в буфере OpenCL","Invalid offset in OpenCL buffer"}, class=class="str">"cmt">// class="num">5111
{"Ошибка создания буфера OpenCL","Failed to create OpenCL buffer"}, class=class="str">"cmt">// class="num">5112
{"Превышено максимальное число OpenCL объектов","Too many OpenCL objects"}, class=class="str">"cmt">// class="num">5113
{"Ошибка выбора OpenCL устройства","OpenCL device selection error"}, class=class="str">"cmt">// class="num">5114
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Array of execution time error messages(class="num">5120 - class="num">5130) |
class=class="str">"cmt">//| (Working with databases) |
class=class="str">"cmt">//| (class="num">1) in user&class="macro">#x27;s country language |
class=class="str">"cmt">//| (class="num">2) in the international language |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string messages_runtime_database[][TOTAL_LANG]=
{
{"Внутренняя ошибка базы данных","Internal database error"}, class=class="str">"cmt">// class="num">5120
{"Невалидный хендл базы данных","Invalid database handle"}, class=class="str">"cmt">// class="num">5121
{"Превышено максимально допустимое количество объектов Database","Exceeded the maximum acceptable number of Database objects"}, class=class="str">"cmt">// class="num">5122「数据库与WebRequest报错码映射」
在 MQL5 里做本地数据库或外部 HTTP 接口调用时,报错不会直接给中文,而是落在一张双语消息数组里。上面这段就是数据库相关的一组:从 5123 到 5130,覆盖了连接失败、查询执行失败、结果未就绪、SQL 参数自动替换失败等非交易逻辑错误。
这些码和消息通常定义成 string messages_runtime_db[][2] 之类的二维数组,第一列是俄语等本地语种,第二列是英文。实战中如果你自己封装了 DatabaseOpen / WebRequest,建议直接复用这套枚举,别手搓字符串比对。
注意 5128「Data for reading request results are not ready yet」和 5130「Database query not read only」——前者常出现在异步读取没轮询完就取数,后者说明你跑的 SQL 带了写操作却被当成只读句柄。外汇与贵金属 EA 接数据库本就小众且高风险,参数错一处就可能静默丢信号。
{"Ошибка подключения к базе данных","Database connection error"}, class=class="str">"cmt">// class="num">5123
{"Ошибка выполнения запроса","Request execution error"}, class=class="str">"cmt">// class="num">5124
{"Ошибка создания запроса","Request generation error"}, class=class="str">"cmt">// class="num">5125
{"Данных для чтения больше нет","No more data to read"}, class=class="str">"cmt">// class="num">5126
{"Ошибка перехода к следующей записи запроса","Failed to move to the next request entry"}, class=class="str">"cmt">// class="num">5127
{"Данные для чтения результатов запроса еще не готовы","Data for reading request results are not ready yet"}, class=class="str">"cmt">// class="num">5128
{"Ошибка автоподстановки параметров в SQL-запрос","Failed to auto substitute parameters to an SQL request"}, class=class="str">"cmt">// class="num">5129
{"Запрос базы данных не только для чтения","Database query not read only"}, class=class="str">"cmt">// class="num">5130
};◍ 网络函数报错码的本地化对照
在 MT5 里做 HTTP 请求或 socket 通信时,错误会以双语文段形式返回:前一个是终端界面语言(如俄语),后一个是国际英语。上面这段数组覆盖了 5200–5203 与 5270–5272 两组网络相关错误码。
- 对应 URL 校验未过(Invalid URL),5201 是连不上指定地址,5202 为数据接收超时,5203 是 HTTP 请求执行失败;socket 侧 5270 表示传入了非法句柄,5271 提示打开的 socket 超过上限 128 个,5272 则是远端主机连接失败。
实盘接行情 API 或中继服务时,建议直接把这组 messages_runtime_netsocket 数组拷进 EA,用 GetLastError() 映射后打印英语项,排错效率比翻文档高。外汇与贵金属杠杆高,网络抖动可能触发 5272 造成信号延迟,仓位管理上需留余量。
{"URL не прошел проверку","Invalid URL"}, class=class="str">"cmt">// class="num">5200
{"Не удалось подключиться к указанному URL","Failed to connect to specified URL"}, class=class="str">"cmt">// class="num">5201
{"Превышен таймаут получения данных","Timeout exceeded"}, class=class="str">"cmt">// class="num">5202
{"Ошибка в результате выполнения HTTP запроса","HTTP request failed"}, class=class="str">"cmt">// class="num">5203
};
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Array of execution time error messages(class="num">5270 - class="num">5275) |
class=class="str">"cmt">//| (Working with network(sockets)) |
class=class="str">"cmt">//| (class="num">1) in user&class="macro">#x27;s country language |
class=class="str">"cmt">//| (class="num">2) in the international language |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string messages_runtime_netsocket[][TOTAL_LANG]=
{
{"В функцию передан неверный хэндл сокета","Invalid socket handle passed to function"}, class=class="str">"cmt">// class="num">5270
{"Открыто слишком много сокетов (максимум class="num">128)","Too many open sockets(max class="num">128)"}, class=class="str">"cmt">// class="num">5271
{"Ошибка соединения с удаленным хостом","Failed to connect to remote host"}, class=class="str">"cmt">// class="num">5272