如何通过ZeroMQ从Metatrader 5获取实时报价至Python变量?
Great to hear you’ve already got the basic request-reply flow working with ZeroMQ and the mql-zmq library! Let’s walk through how to extend that setup to pull real-time bid/ask prices (and other quote data) from MT5 into your Python variables.
Step 1: Update the MT5 MQL5 Script to Handle Price Requests
First, we’ll modify the MT5 side to listen for symbol-specific requests and return the corresponding bid/ask prices. This replaces your "Hello World" logic with quote-fetching functionality.
//+------------------------------------------------------------------+ //| MT5_ZMQ_Quotes.mq5 | //+------------------------------------------------------------------+ #include <zmq/zmq.mqh> input string ZMQ_LISTEN_ADDRESS = "tcp://*:5555"; // Match this with your Python client void OnStart() { void *zmq_context = zmq_ctx_new(); void *responder_socket = zmq_socket(zmq_context, ZMQ_REP); // Bind the socket to the specified address int bind_result = zmq_bind(responder_socket, ZMQ_LISTEN_ADDRESS); if(bind_result != 0) { Print("Failed to bind ZMQ socket: ", zmq_strerror(errno)); return; } Print("MT5 Quote Server running on ", ZMQ_LISTEN_ADDRESS); // Keep running until the script is stopped in MT5 while(!IsStopped()) { // Receive the symbol request from Python char request_buffer[256]; int bytes_received = zmq_recv(responder_socket, request_buffer, sizeof(request_buffer), 0); if(bytes_received == -1) { Print("ZMQ receive error: ", zmq_strerror(errno)); continue; } request_buffer[bytes_received] = '\0'; // Ensure valid string termination string target_symbol = string(request_buffer); // Validate the symbol exists in MT5 if(!SymbolSelect(target_symbol, true)) { string error_response = "Error: Symbol '" + target_symbol + "' not found in MT5"; zmq_send(responder_socket, error_response, StringLen(error_response), 0); continue; } // Fetch bid and ask prices (add SYMBOL_LAST for closing price if needed) double bid_price = SymbolInfoDouble(target_symbol, SYMBOL_BID); double ask_price = SymbolInfoDouble(target_symbol, SYMBOL_ASK); // Package data into JSON for easy Python parsing string quote_response = StringFormat( "{\"symbol\":\"%s\", \"bid\":%.5f, \"ask\":%.5f}", target_symbol, bid_price, ask_price ); zmq_send(responder_socket, quote_response, StringLen(quote_response), 0); Print("Sent quote for ", target_symbol, ": Bid=", bid_price, ", Ask=", ask_price); Sleep(100); // Prevent excessive loop frequency } // Cleanup resources when stopped zmq_close(responder_socket); zmq_ctx_destroy(zmq_context); }
- Key Details:
SymbolSelect(target_symbol, true)ensures the symbol is loaded in MT5 (critical for fetching valid prices).- We use JSON to serialize the response because it’s straightforward to parse in Python.
- The script runs continuously until you manually stop it in MT5 (look for the running script icon in the bottom-right corner).
Step 2: Python Client Code to Request and Parse Quotes
Now, write a Python script to send symbol requests to MT5 and convert the response into usable variables.
import zmq import json def fetch_mt5_quote(target_symbol): # Initialize ZMQ context and request socket zmq_context = zmq.Context() client_socket = zmq_context.socket(zmq.REQ) client_socket.connect("tcp://localhost:5555") # Match MT5's listen address # Send the symbol request client_socket.send_string(target_symbol) # Receive and parse the response raw_response = client_socket.recv_string() client_socket.close() zmq_context.term() try: quote_data = json.loads(raw_response) return quote_data except json.JSONDecodeError: # Handle error messages from MT5 return {"error": raw_response} # Test the function with your target symbols if __name__ == "__main__": ibm_quote = fetch_mt5_quote("IBM") print("IBM Quote:", ibm_quote) # Extract individual variables if needed if "bid" in ibm_quote: ibm_bid = ibm_quote["bid"] ibm_ask = ibm_quote["ask"] print(f"IBM Bid: {ibm_bid}, Ask: {ibm_ask}") goog_quote = fetch_mt5_quote("GOOG") print("GOOG Quote:", goog_quote)
- Key Details:
- The
zmq.REQsocket pairs perfectly with MT5’sZMQ_REPsocket for request-reply communication. - We parse the JSON response into a dictionary, making it easy to access
bid,ask, andsymbolas Python variables. - Error handling catches cases where MT5 returns a non-JSON error message (like an invalid symbol).
- The
Step 3: Real-Time Quote Updates (Optional)
If you want continuous real-time updates instead of one-off requests, switch to a publish-subscribe (PUB/SUB) pattern:
MT5 Publisher Script
//+------------------------------------------------------------------+ //| MT5_ZMQ_PubQuotes.mq5 | //+------------------------------------------------------------------+ #include <zmq/zmq.mqh> input string ZMQ_PUB_ADDRESS = "tcp://*:5556"; input string PUBLISH_SYMBOL = "IBM"; input int UPDATE_INTERVAL_MS = 1000; // Update every 1 second void OnStart() { void *zmq_context = zmq_ctx_new(); void *publisher_socket = zmq_socket(zmq_context, ZMQ_PUB); int bind_result = zmq_bind(publisher_socket, ZMQ_PUB_ADDRESS); if(bind_result != 0) { Print("Failed to bind PUB socket: ", zmq_strerror(errno)); return; } Print("MT5 Quote Publisher running on ", ZMQ_PUB_ADDRESS); while(!IsStopped()) { if(!SymbolSelect(PUBLISH_SYMBOL, true)) { Print("Symbol ", PUBLISH_SYMBOL, " not found"); Sleep(UPDATE_INTERVAL_MS); continue; } double bid = SymbolInfoDouble(PUBLISH_SYMBOL, SYMBOL_BID); double ask = SymbolInfoDouble(PUBLISH_SYMBOL, SYMBOL_ASK); string publish_msg = StringFormat( "{\"symbol\":\"%s\", \"bid\":%.5f, \"ask\":%.5f}", PUBLISH_SYMBOL, bid, ask ); zmq_send(publisher_socket, publish_msg, StringLen(publish_msg), 0); Print("Published: ", publish_msg); Sleep(UPDATE_INTERVAL_MS); } zmq_close(publisher_socket); zmq_ctx_destroy(zmq_context); }
Python Subscriber Script
import zmq import json def subscribe_to_real_time_quotes(): zmq_context = zmq.Context() subscriber_socket = zmq_context.socket(zmq.SUB) subscriber_socket.connect("tcp://localhost:5556") subscriber_socket.setsockopt_string(zmq.SUBSCRIBE, "") # Subscribe to all messages print("Listening for real-time MT5 quotes...") while True: raw_msg = subscriber_socket.recv_string() quote_data = json.loads(raw_msg) print(f"Real-Time Update: {quote_data['symbol']} | Bid: {quote_data['bid']} | Ask: {quote_data['ask']}") if __name__ == "__main__": subscribe_to_real_time_quotes()
Critical Notes
- Symbol Names: Ensure the symbol you request matches exactly what’s in your MT5 instance (e.g.,
IBMvs.IBMUSD— check the MT5 Market Watch window). - Firewall/Network: Make sure port 5555 (or 5556 for pub/sub) is open on your machine so Python can connect to MT5.
- MT5 Script State: The MT5 script must be running (execute it in MT5) for Python to receive any responses.
内容的提问来源于stack exchange,提问作者Safrinha

