MetaTrader 5 + Python:socket 与 MetaTrader5
MetaTrader 5 通常可以通过两种方式连接到 Python:
- 在 MQL5 编写的 Expert Advisor 或脚本与 Python 进程之间使用 socket 桥接。
- 使用官方
MetaTrader5Python 包与正在运行的 MetaTrader 5 终端通信。
两种方法都很有用,但解决的问题略有不同。socket 桥接更灵活,适合交易逻辑必须保留在 MetaTrader 内部,而 Python 负责计算、数据处理或机器学习的场景。若希望 Python 直接请求市场数据、检查账户状态,或通过终端发送订单,MetaTrader5 包会更简单。
方案 1:Socket 桥接
socket 桥接通常包含两部分:
- 一个用于发送请求并接收响应的 MQL5 Expert Advisor;
- 一个监听本地端口并处理这些请求的 Python 服务器。
最安全的部署方式是让 socket 服务器运行在 127.0.0.1,这样它只能被同一台机器访问。
一个最小化的 Python TCP 服务器如下:
import socket
HOST = "127.0.0.1"
PORT = 9090
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((HOST, PORT))
server.listen(1)
print(f"Listening on {HOST}:{PORT}")
while True:
conn, addr = server.accept()
with conn:
data = conn.recv(4096)
if not data:
continue
message = data.decode("utf-8").strip()
print("received:", message)
response = "okn"
conn.sendall(response.encode("utf-8"))
在 MQL5 端,使用平台的 socket 函数连接本地服务器、发送消息并读取回复。刚开始协议应保持简单:每个请求一行 UTF-8 文本,并以 n 结尾。连接跑通后,再迁移到 JSON,让消息字段更加明确。
请求载荷示例:
{"symbol":"EURUSD","timeframe":"M1","action":"signal","bid":1.1284,"ask":1.1286}
使用 socket 做交易决策时,要谨慎处理失败情况:
- Python 进程未运行;
- 端口已被占用;
- 等待响应时超时;
- 响应格式错误;
- 重连后请求重复;
- 终端或账户禁止交易。
不要让 Expert Advisor 在等待 Python 时无限期阻塞。使用超时机制,并在通信失败时回退到安全的不交易决策。
方案 2:MetaTrader5 Python 包
官方 Python 包通常是最快的入门方式。使用 pip 安装:
python -m pip install MetaTrader5
MetaTrader 5 必须安装在同一台机器上,并且已经登录。Python 包会与终端通信,因此脚本启动前终端应处于运行状态。
最小化连接检查:
import MetaTrader5 as mt5
if not mt5.initialize():
print("initialize() failed:", mt5.last_error())
raise SystemExit(1)
print(mt5.version())
print(mt5.account_info())
mt5.shutdown()
请求近期 K 线:
from datetime import datetime, timezone
import MetaTrader5 as mt5
symbol = "EURUSD"
timeframe = mt5.TIMEFRAME_M1
count = 100
if not mt5.initialize():
print("initialize() failed:", mt5.last_error())
raise SystemExit(1)
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, count)
if rates is None:
print("copy_rates_from_pos() failed:", mt5.last_error())
else:
for row in rates[:5]:
ts = datetime.fromtimestamp(row["time"], tz=timezone.utc)
print(ts, row["open"], row["high"], row["low"], row["close"])
mt5.shutdown()
从 Python 发送订单前,应在本地验证终端、经纪商、交易品种和账户权限。具体字段和允许的订单参数可能因经纪商和账户类型而异,因此应检查 mt5.symbol_info(symbol)、mt5.account_info() 以及 mt5.order_send() 的返回值,而不是假设固定配置。
如何选择
适合使用 socket 桥接的情况:
- Expert Advisor 已经负责交易循环;
- Python 只是计算或信号服务;
- 需要在 MQL5 与 Python 之间使用自定义协议;
- 希望由 EA 在 MetaTrader 内部控制订单提交。
适合使用 MetaTrader5 包的情况:
- Python 应作为主程序;
- 需要快速访问账户信息、交易品种、tick、K 线或订单;
- 希望减少 MQL5 代码;
- 所有工作都运行在 MetaTrader 5 终端所在的同一台机器上。
对于研究和自动化,建议从 MetaTrader5 开始,因为它更容易验证。对于需要调用外部分析的生产级 Expert Advisor,本地 socket 桥接能提供更多控制,但也需要围绕超时、重试和消息校验做更多防御性工程。
