MT5 订单、持仓、成交:三层模型与缓存陷阱
理解 Order / Position / Deal,邃开 MQL5 交易函数最常见的性能坑
要在 MT5 上写靠谱的 EA,第一道坎就是理解“订单、持仓、成交”三层模型,以及 MQL5 程序如何通过“缓存”访问它们。概念不清,轻则读不到数据,重则写出拖垮终端的“全量历史”循环。
一、三个核心概念
订单(Order)是交易服务器收到的操作请求,分为市价单与挂单,活动订单在 Trade 选项卡,执行/撤销后转入 History 且不可修改。成交(Deal)是订单执行的结果,一个订单可拆成多笔部分成交,只存于历史、不可改。持仓(Position)是某品种当前净头寸——同品种同时只能有一个,同向增仓、反向减仓,归零即平仓。
二、客户端与服务器的信息同步
客户端把交易历史存于本地加密资料库(密钥绑定本机),连服务器时只同步缺失部分以省流量。交易事件(出金、手续费、订单变动、成交、建/平仓)由服务器主动推送。Trade 选项卡显示活动订单/持仓,History 显示历史;调显示周期不改变本地存储深度,只会扩大范围时向服务器要更深数据。
三、MQL5 的缓存机制(最关键)
MQL5 程序不能直接访问客户端数据库,只能通过“填缓存”请求把数据拷进自身内存缓存,再从中读取。缓存不会自动同步,必须手动更新;任何填缓存请求都会先清空原缓存。
四、填缓存的函数
活动订单:OrderSelect(ticket) 按单证、OrderGetTicket(i) 配合 OrdersTotal() 遍历。持仓:PositionSelect(symbol) 按品种、PositionGetSymbol(i) 配合 PositionsTotal() 遍历。历史:HistorySelect(start,end) 按时间区间、HistorySelectByPosition(id) 按持仓标识符,以及 HistoryOrderSelect / HistoryDealSelect 按单证。
五、读缓存的函数
订单:OrderGetDouble/Integer/String;持仓:PositionGetDouble/Integer/String;历史订单与成交:HistoryOrderGet*/HistoryDealGet*(注意是从缓存取,不是数据库)。索引取单证用 HistoryOrderGetTicket(i) / HistoryDealGetTicket(i)。
六、最易踩的坑:历史全量加载
错误写法 HistorySelect(0, TimeCurrent()) 会从 1970 年至今全量载入,成千上万条记录严重拖慢程序。务必限定区间,如最近 3 天。
小结
- 订单=请求(活动/历史),成交=执行结果,持仓=净头寸
- 同品种同时只有一个持仓
- 程序经缓存读数据,不直接连库
- 缓存不自动同步,须手动更新
- 填缓存前会清空旧缓存
- HistorySelect 务必限定时间区间
- 用 HistorySelectByPosition 重构某持仓全生命周期