使用 MetaTrader 5 Python 构建类似 MQL5 的交易类(基础篇)
📘

使用 MetaTrader 5 Python 构建类似 MQL5 的交易类(基础篇)

第 1/3 篇

「用 Python 在 MT5 里搭一套交易信息类」

想在 MT5 外部用 Python 做策略监控或回测预处理,第一步是把 MQL5 里那套内置信息类搬过来。官方 Python 包 metaquotes.metatrader5 只给底层函数,不直接提供 CAccountInfo、CSymbolInfo 这类封装,得自己按字段对齐写类。 原文列了 9 个核心类:账户、品种、当前订单、历史订单、持仓、成交、终端、交易执行。实际工程里最常先写 CAccountInfo 和 CSymbolInfo,因为开仓前必查杠杆与 Tick 精度。 这套结构在 2026 年 1 月发布的示例里被归为「交易系统」分类,原始讨论帖显示有 559 次浏览、2 条跟帖,说明社区对跨语言复用 MQL5 对象模型有真实需求。外汇与贵金属杠杆高,任何账户或品种参数读取错误都可能触发异常下单,实盘前务必在策略测试器用历史数据跑通。

裸写下单与 CTrade 的差距

在 MT5 的 MQL5 环境里,标准库把算法交易系统的搭建门槛压低了一大截。开仓、校验、平仓这些动作,官方已经封装成现成函数和类,直接调用就能跑。 如果不依赖这些模块,连「脚本里开一个买入仓」这种最基础的需求都会变得笨重。下面两段代码都可以在 MetaTrader 5 里发出买入指令,但第一段走的是原生 MqlTradeRequest 结构,第二段用 CTrade 类。 原生写法要手动填 15 个以上的请求字段,从 action、symbol 到 deviation、type_filling 一个都不能漏;CTrade 版本只需 Set 几个参数再调 Buy(),代码行数少了一半多。字段越多,手误概率越高,对 MT5 下单全流程的理解要求也更强。 Python 侧有个 MetaTrader 5 包,能取行情、查持仓、发交易指令,能力上接近 MQL5。但它没有等效的内置交易类,写个简单程序也得堆不少行;更麻烦的是和 VS Code 等 IDE 的 Intellisense 兼容差,写着写着就得切去翻文档,开发体验明显打折。本文后续会基于这个包在 Python 里造一个交易类,把效率拉到接近 MQL5 的水平。外汇与贵金属杠杆高,任何下单封装都只是降低编码成本,不降低持仓风险。

MQL5 / C++
class="type">void OnStart()
  {
  class="type">MqlTradeRequest request;
  class="type">MqlTradeResult result;
  
  class="type">MqlTick ticks;
  SymbolInfoTick(Symbol(), ticks);
  
class=class="str">"cmt">//--- setting a trade request
  
  ZeroMemory(request);
  request.action   =TRADE_ACTION_DEAL;
  request.symbol   =Symbol();
  request.magic    =class="num">2025;
  request.volume   =class="num">0.01;
  request.type     =ORDER_TYPE_BUY;
  request.price    =ticks.ask;
  request.sl       =class="num">0;
  request.tp       =class="num">0;
  request.deviation = class="num">10;   class=class="str">"cmt">// Max price slippage in points
  request.magic        = class="num">2025;
  request.comment     = "Buy Order";
  request.type_filling= ORDER_FILLING_IOC;   class=class="str">"cmt">// or ORDER_FILLING_IOC, ORDER_FILLING_RETURN
  request.type_time   = ORDER_TIME_GTC;       class=class="str">"cmt">// Good till canceled
  
class=class="str">"cmt">//--- action and class="kw">return the result
  if(!OrderSend(request, result))
    {
      Print("OrderSend failed retcode: ", result.retcode);
    }
  }
class="macro">#include <Trade\Trade.mqh>
CTrade m_trade;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Script program start function                                    |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart()
  {
class=class="str">"cmt">//---
    class="type">MqlTick ticks;
    SymbolInfoTick(Symbol(), ticks);
    
    m_trade.SetTypeFillingBySymbol(Symbol());
    m_trade.SetExpertMagicNumber(class="num">2025);
    m_trade.SetDeviationInPoints(class="num">10); class=class="str">"cmt">//Slippage 
    
    m_trade.Buy(class="num">0.01, Symbol(), ticks.ask,class="num">0,class="num">0,"Buy Order");
  }

◍ 用 Python 接管 MT5 账户属性读取

MQL5 里的 CAccountInfo 类把经纪商账户的所有属性封装成方法,开 MT5 做风控或仓位计算时经常要调。把它在 Python 端重写一遍,配合 MetaTrader5 包,就能在本地脚本里随时抓账户状态,不必依赖 EA 内部逻辑。 这个类覆盖三类属性:整数与字符串类(如 login、leverage、trade_mode_description)、双精度类(balance、equity、margin_level 等)、文本类(server、company、currency)。额外还有 margin_check、max_lot_check 这类方法,能在下单前算 Required Margin 和最大可开手数。 下面这段是可直接跑的调用示例,初始化时填你自己的 terminal64.exe 路径。Demo 账户回测跑出来一组真实值:杠杆 400、余额 928.42、净值 926.21、保证金水平 32961.21%、Margin Call 线 90.0、StopOut 线 20.0。外汇和贵金属杠杆高,保证金水平掉到 StopOut 附近时平台会强平,用这类接口做实时预警比肉眼看终端更稳。 代码逐行拆解: import MetaTrader5 as mt5 —— 引入 MT5 官方 Python 接口 from Trade.AccountInfo import CAccountInfo —— 引入自写的账户信息类 if not mt5.initialize(r"c:\Users\...\terminal64.exe"): —— 按指定客户端路径初始化,失败则打印错误并退出 acc = CAccountInfo() —— 实例化账户对象 print(f"""...{acc.login()}...""") —— 用 f-string 把各方法返回值填进报告模板 mt5.shutdown() —— 断开 MT5 连接释放资源

MQL5 / C++
class="kw">import MetaTrader5 as mt5
from Trade.AccountInfo class="kw">import CAccountInfo
if not mt5.initialize(r"c:\Users\Omega Joctan\AppData\Roaming\Pepperstone MetaTrader class="num">5\terminal64.exe"):
    print("Failed to initialize Metatrader5 Error = ",mt5.last_error())
    quit()
acc = CAccountInfo()
print(f"""
Account Information
-------------------
Login: {acc.login()}
Name: {acc.name()}
Server: {acc.server()}
Company: {acc.company()}
Currency: {acc.currency()}
Trade Mode: {acc.trade_mode()} ({acc.trade_mode_description()})
Leverage: {acc.leverage()}
Stopout Mode: {acc.stopout_mode()} ({acc.stopout_mode_description()})
Margin Mode: {acc.margin_mode()} ({acc.margin_mode_description()})
Trade Allowed: {acc.trade_allowed()}
Trade Expert: {acc.trade_expert()}
Limit Orders: {acc.limit_orders()}
-------------------
Balance: {acc.balance()}
Credit: {acc.credit()}
Profit: {acc.profit()}
Equity: {acc.equity()}
Margin: {acc.margin()}
Free Margin: {acc.free_margin()}
Margin Level: {acc.margin_level()}
Margin Call: {acc.margin_call()}
Margin StopOut: {acc.margin_stopout()}
-------------------
""")
mt5.shutdown()

「用 CSymbolInfo 把品种属性一次拉全」

在 MT5 的 Python 环境里,CSymbolInfo 类把交易品种的属性访问封装成了一套方法,覆盖报价、成交量、点差、合约规模、库存费、时段数据等维度。比起逐个调 mt5.symbol_info(),这个类把 Bid/Ask/Last 的当日高低、StopsLevel、FreezeLevel、SwapLong/Short 这些容易漏掉的项都归到了一处。 外汇与贵金属品种的属性差异很大,例如 EURUSD 的 digits 通常是 5,point 为 1e-5,而 XAUUSD 常见 digits 为 2、point 为 0.01;不先读这些字段,止损距离和保证金计算都可能算错。开 MT5 终端后,用下面这段代码可以直接把 EURUSD 的核心属性打印出来验证。 别把 select 和 is_synchronized 当摆设 很多脚本一上来就读 bid,却没确认品种是否已加入市场报价且完成服务器同步。select(True) 保证品种在终端可见,is_synchronized() 返回 False 时读到的可能是陈旧数据,下单请求会被拒。 完整方法列表在 SymbolInfo.py 中,上面代码里的调用只是常用子集;想做分笔深度或时段持仓摘要,再去翻 session_* 那一组。

MQL5 / C++
class="kw">import MetaTrader5 as mt5
from Trade.SymbolInfo class="kw">import CSymbolInfo
if not mt5.initialize(r"c:\Users\Omega Joctan\AppData\Roaming\Pepperstone MetaTrader class="num">5\terminal64.exe"):
    print("Failed to initialize Metatrader5 Error = ",mt5.last_error())
    quit()
    
m_symbol = CSymbolInfo("EURUSD")
print(f"""
Symbol Information
---------------------
Name: {m_symbol.name()}
Selected: {m_symbol.select()}
Synchronized: {m_symbol.is_synchronized()}
--- Volumes ---
Volume: {m_symbol.volume()}
Volume High: {m_symbol.volume_high()}
Volume Low: {m_symbol.volume_low()}
--- Time & Spread ---
Time: {m_symbol.time()}
Spread: {m_symbol.spread()}
Spread Float: {m_symbol.spread_float()}
Ticks Book Depth: {m_symbol.ticks_book_depth()}
--- Trade Levels ---
Stops Level: {m_symbol.stops_level()}
Freeze Level: {m_symbol.freeze_level()}
--- Bid Parameters ---
Bid: {m_symbol.bid()}
Bid High: {m_symbol.bid_high()}
Bid Low: {m_symbol.bid_low()}
--- Ask Parameters ---
Ask: {m_symbol.ask()}
Ask High: {m_symbol.ask_high()}
Ask Low: {m_symbol.ask_low()}
--- Last Parameters ---
Last: {m_symbol.last()}
Last High: {m_symbol.last_high()}
Last Low: {m_symbol.last_low()}
--- Order & Trade Modes ---
Trade Calc Mode: {m_symbol.trade_calc_mode()} ({m_symbol.trade_calc_mode_description()})
Trade Mode: {m_symbol.trade_mode()} ({m_symbol.trade_mode_description()})
Trade Execution Mode: {m_symbol.trade_execution()}  ({m_symbol.trade_execution_description()})
--- Swap Terms ---
Swap Mode: {m_symbol.swap_mode()} ({m_symbol.swap_mode_description()})
Swap Rollover class="num">3 Days: {m_symbol.swap_rollover_3days()} ({m_symbol.swap_rollover_3days_description()})
--- Futures Dates ---
Start Time: {m_symbol.start_time()}

从 EURUSD 实例看品种属性怎么读

在 MT5 的 Python 接口里,symbol_info() 返回的是一整张品种参数表,但真要做风控和仓位计算,只有其中几行是天天要盯的。上面这份 EURUSD 实时快照(2025-05-21 20:30:36 取数)能直接当模板对照。 Digits=5、Point=1e-05 说明这是五位数报价,最小价格变动就是 0.00001;Contract Size=100000 代表标准手每手 10 万基础货币,Lots Step=0.01 意味着你最小能下 0.01 手(微仓)。这些数不核对,EA 里的手数算法可能直接越界报错。 保证金和掉期是隐性成本大头:Initial Margin=100000.0 表示开 1 标准手要冻结 10 万保证金(账户货币 EUR),Swap Long=-8.99 点、Swap Short=4.5 点,周三 rollover 3 天——拿隔夜多单会被收 8.99 点,空单反而返 4.5 点。外汇和贵金属杠杆高,掉期在震荡市会吃掉不少利润,下单前务必在终端「规格」里复算一遍。 Trade Execution Mode=2 是市价执行,Stops Level=0 和 Freeze Level=0 代表止损挂单没有最小距离限制;但 Spread 显示 0 只是取样时刻流动性重叠的瞬像,实盘欧美点差常态在 0.5~1.5 点浮动,不能拿这个当交易成本假设。

◍ 从盘后会话字段读 EURUSD 多空失衡

一段交易会话结束,MT5 后台吐出的统计字段比图表上的影线更直白。上面这组样本里,Session Sell Orders 只有 2 笔,但 Session Sell Volume 干到 13.0,Session Buy Volume 才 3.0——卖单少、卖量重,是少数账户在集中倒货。 价格端 Session Open 1.12817、Session Close 1.12842,收盘比开盘高 2.5 点,看似多头收尾;但买量仅为卖量的约 23%,这种量价背离在外汇 EURUSD 上往往暗示上行缺乏广度,后续回吐概率偏高。贵金属与外汇均属高杠杆品种,此类会话数据只作微观结构参考,不构成方向定论。 Session Interest、AW、Price Settlement 及 Limit Min/Max 全为 0.0,说明该会话无隔夜利息累积、无加权偏移、也未触发限价边界——纯日内脉冲。开 MT5 用自定义脚本抓这几项,连跑一周就能看出你常做的时段里谁在控盘。

常见问题

Python 裸写下单要自己处理返回码和重试,自带交易类已封装好下单、改仓、撤单流程,少写很多容错代码。
建一个品种信息类,把属性接口集中封装,调用时传品种名就能一次拉全,不用每条单独查。
可以,小布能接管账户与品种属性读取,并在盘后自动汇总 EURUSD 等品种的会话字段和多空失衡,打开对应页就能看。
对比盘后买盘量与卖盘量字段,差值明显偏向一方时,该方向短期概率上更占优,但外汇高风险需结合其他信号。
先实现账户连接与品种属性读取,跑通 EURUSD 实例,再补下单封装,避免一上来就陷在订单逻辑里。