MetaTrader 5 + Python:socket 与 MetaTrader5

MetaTrader 5 + Python:socket 与 MetaTrader5

MetaTrader 5 通常可以通过两种方式连接到 Python:

  1. 在 MQL5 编写的 Expert Advisor 或脚本与 Python 进程之间使用 socket 桥接。
  2. 使用官方 MetaTrader5 Python 包与正在运行的 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 桥接能提供更多控制,但也需要围绕超时、重试和消息校验做更多防御性工程。

Leave a Reply