ZeroMQ – How To Interface Python/R with MetaTrader 4

Zero MQ - Distributed Messaging

ZeroMQ – Distributed Messaging

In this post, we present a technique employing ZeroMQ (an Open Source, Asynchronous Messaging Library and Concurrency Framework) for building a basic – but easily extensible – high performance bridge between external (non-MQL) programming languages and MetaTrader 4.


Reasons for writing this post:

  1. Lack of comprehensive, publicly available literature about this topic on the web.
  2. Traders have traditionally relied on Winsock/WinAPI based solutions that often require revision with both Microsoft™ and MetaQuotes™ updates.
  3. Alternatives to ZeroMQ include named pipes, and approaches where filesystem-dependent functionality forms the bridge between MetaTrader and external languages.

Click here to watch the Webinar Recording.

In this blog post, we lay the foundation for a distributed trading system that will:

  1. Consist of one or more trading strategies developed outside MetaTrader 4 (non-MQL),
  2. Use MetaTrader 4 for acquiring market data, trade execution and management,
  3. Support multiple non-MQL strategies interfacing with MetaTrader 4 simultaneously,
  4. Consider each trading strategy as an independent “Client”,
  5. Consider MetaTrader 4 as the “Server”, and medium to market,
  6. Permit both Server and Clients to communicate with each other on-demand.


Infographic: ZeroMQ-Enabled Distributed Trading Infrastructure (with MetaTrader 4)

Infographic: ZeroMQ-Enabled Distributed Trading Infrastructure (with MetaTrader 4)

Why ZeroMQ?

  1. Enables programmers to connect any code to any other code, in a number of ways.
  2. Eliminates a MetaTrader user’s dependency on just MetaTrader-supported technology (features, indicators, language constructs, libraries, etc.)
  3. Traders can develop indicators and strategies in C/C#/C++, Python, R and Java (to name a few), and deploy to market via MetaTrader 4.
  4. Leverage machine learning toolkits in Python and R for complex data analysis and strategy development, while interfacing with MetaTrader 4 for trade execution and management.
  5. ZeroMQ can be used as a high-performance transport layer in sophisticated, distributed trading systems otherwise difficult to implement in MQL.
  6. Different strategy components can be built in different languages if required, and seamlessly talk to each other over TCP, in-process, inter-process or multicast protocols.
  7. Multiple communication patterns and disconnected operation.

ZeroMQ: Supported Programming Languages

Though we focus on MQL interfaced with Python & R in this post, the basic process described here can be implemented easily in other ZeroMQ-supported languages.

A comprehensive list of ZeroMQ language bindings is available here:

Zero MQ Language Bindings

Who else is using ZeroMQ?

AT&T, Cisco, EA, Los Alamos Labs, NASA, Weta Digital, Zynga, Spotify, Samsung Electronics, Microsoft, CERN and Darwinex Labs.

ZeroMQ also powers at least 5 DARWINS on The DARWIN Exchange, where the underlying trading strategies were written in C++, Python and R.

Planning Flow Control

This post is not intended to be a detailed tutorial on ZeroMQ.

However, it is still important to understand a few things about ZeroMQ that make it particularly suited to the task of connecting external programming languages such as Python and R to MetaTrader 4.

  • It supports TCP, inter-process, in-process, PGM and EPGM enabled multicast networking. We will use the TCP transport type for the implementation in this post.
  • ZeroMQ enables servers and clients to connect “to each other” on demand, particularly useful for designing distributed trading infrastructure.
  • In addition to support for asynchronous communication and disconnected operation, ZeroMQ supports several communication patterns that permit higher-level data transfer, freeing programmers to focus more on the transfer logic rather than low-level mechanisms.
  • These patterns include: Request (REQ) / Reply (REP), Publish (PUB) / Subscribe (SUB) and Push (PUSH) / Pull (PULL).


For the implementation in this blog post, we will employ ZeroMQ’s REQ/REP and PUSH/PULL communication patterns. MetaTrader 4 will be our “Server”, and trading strategies will be “Clients”.

Please note that this (MT4=Server, Strategy=Client) is not a MUST – you will need to decide on whatever flow control suits your particular needs best.

For example, you might designate a machine independent of both the trading strategy as well as MetaTrader 4, as your Server, and have Strategies and MT4 both be Clients. There are a number of ways you could achieve the end goal; carefully planning flow control will lead to efficient functionality.


Request (REQ) / Reply (REP) Pattern

The Server (MetaTrader 4 EA) will employ a TCP socket of type REP, to receive requests and send responses. A REP socket MUST always initiate a pair of calls: first, a receive, followed by a send.

The Client (Trading Strategy, e.g. in Python) will employ a TCP socket of type REQ, to send requests and receive responses. A REQ socket MUST always initiate a pair of calls too: first, a send, followed by a receive.

For this implementation, the REQ/REP pattern will enable our Clients to send commands to the MetaTrader 4 Server and receive acknowledgements of the same (e.g. OPEN/MODIFY/CLOSE trades, GET BID/ASK RATES, GET HISTORICAL PRICES, etc.)


Push (PUSH) / Pull (PULL) Pattern

The Server (MetaTrader 4 EA) will also employ a second, PUSH socket, to send additional information to Clients (Trading Strategies). This is a one-way socket, and the server will only be able to send data to this socket, without being able to receive anything back through the same socket.

The Client (Trading Strategy) will also employ a second, PULL socket, to receive additional information from the Server. This too is a one-way socket, and the client will only be able to receive data from this socket, without being able to send anything through the same socket.

The PUSH/PULL pattern enables servers and clients to exchange data with each other on-demand, but in one direction without expecting a response. This could of course be swapped out for another REQ/REP pattern, depending on your application’s flow control requirements.


In summary, for this post’s basic implementation:

  1. The Server will employ two sockets, one REP and one PUSH.
  2. Each Client will employ two sockets, one REQ and one PULL.


Infographic: What this flow control plan looks like in practice.

Infographic: ZeroMQ Process Flow Control


MetaTrader 4 Expert Advisor – Components

As displayed in the infographic above, the MT4 EA will serve as our ZeroMQ-enabled Server, with three main modules:

  1. MESSAGE ROUTER – This allows the EA to receive commands and send acknowledgements back to connecting Clients (trading strategies) through the REP socket. The Router passes all messages on to the Parser. Note: For this example, the Router doesn’t serve much purpose, but it is good practice to have this intermediary where several strategies connect to the Server (MT4) and some manner of pre-parse actions may need to be performed.
  2. MESSAGE PARSER – Messages received by this module are decomposed into actions for the next module (Interpreter & Executor).
  3. INTERPRETER & EXECUTOR – This module literally “interprets” decomposed messages and performs requested actions accordingly. For example, if the Client is requesting market data, the module gathers it from the MetaTrader 4 History DB and sends it on to the Client via the PUSH socket. Alternatively, if the Client is requesting a BUY or SELL trade be opened on e.g. the EUR/USD, it sends the trade to market and a notification of success/failure/ticket-info to the Client via the PUSH socket.

Implementation Requirements

  1. ZeroMQ – MQL4 Bindings -> Download and install the required files as instructed here:
  2. For Python -> “pyzmq” library
  3. For R -> “rzmq” library

Sample Code

To give you a head start, we’ve published a functional MetaTrader 4 Expert Advisor with the full implementation discussed in this blog post.

The MQL sample code provided is quite extensible, and can be used as a template in your efforts.

GitHub Links:

  1. ZeroMQ-enabled MT4 Expert Advisor – GitHub
  2. Example ZeroMQ Client in R – GitHub
  3. Example ZeroMQ Client in Python – GitHub


  1. The Python and R samples demonstrate how communication patterns are implemented.
  2. It’s fairly simple to integrate this code in your existing Python/R trading strategies.


Webinar Recording: How to Interface Python/R Trading Strategies with MetaTrader 4

Do you have what it takes? – Join the Darwinex Trader Movement!

Darwinex - The Open Trader Exchange

13 replies
  1. Victor
    Victor says:

    Hola!! Estoy intentando conectar R con Metatrader siguiendo los pasos marcados, pero luego el código de ejemplo no sé realmente lo que hace, ya que se me queda todo el rato ejecutando y no hace nada. Alguien que ya lo hay instalado me podría ayudar, yo no soy programador ni informático y la verdad estoy ya un poco perdido para realizar la conexión. Tengo las estrategias en R y me gustaría poder operar desde R con metatrader. Gracias

    • The Market Bull
      The Market Bull says:

      Hola Victor,

      Gracias por su interés en el código!

      Si ya tiene estrategias en R, debe hacer dos cosas:

      Por ejemplo,

      Si su estrategia hace una señal para “BUY STOP EUR/USD” con “open price” 1.2000, “stop loss” 1.1950 y “take profit” 1.2050.

      Primero, defina un texto para esta señal. Por ejemplo, “O: 1.2000, SL: 1.1950, TP: 1.2050, C: EURUSD, D: BUYSTOP”

      A continuación,

      1) Modifique el código de “OnTimer()” en para aceptar y procesar esta señal en forma de texto. Puedes hacer esto con “repSocket.recv()”.

      2) Modifique el código de “remote.send()” en para enviar esta señal a MetaTrader 4 en forma de texto.

      Por ejemplo,

      Su estrategia hace una señal a “BUY STOP EUR/USD” con “open price” 1.2000, “stop loss” 1.1950 y “take profit” 1.2050.

      R debe hacer:
      remote.send (reqSocket, “O: 1.2000, SL: 1.1950, TP: 1.2050, C: EURUSD, D: BUYSTOP”)

      Su código de “OnTimer()” debe recibir esto con:
      repSocket.recv(request, true)

      Ahora debe modificar el código de “InterpretZmqMessage (Socket & pSocket, string & compArray [])” para procesar y ejecutar esta señal en MetaTrader 4.

      Publicaremos una nueva publicación de blog en el futuro con ejemplos más detallados.


      • Victor
        Victor says:

        Sí, tengo las estrategias en R, donde al final obtengo la cantidad que debo introducir en metatader, por ejemplo, 0.5 EURUSD y 0.3 en AUDCAD. La cuestión es como decirle yo que haga la operación en MT4.
        ¿En el primer paso tendría que poner cambiar el código de OnTimer donde pone
        // Get client’s response, but don’t wait.

        // Get client’s response, but don’t wait.
        repSocket.recv(“O: 1.2000, SL: 1.1950, TP: 1.2050, C: EURUSD, D: BUYSTOP”);
        No sé si es eso lo que tendría que cambiar.
        Luego en el paso 2 sería en R en la función que pone
        # Function to send commands to ZeroMQ MT4 EA
        remote.send <- function(rSocket,data) {
        send.raw.string(rSocket, data)
        msg <- receive.string(rSocket)


        cambiarlo por :
        remote.send (reqSocket, "O: 1.2000, SL: 1.1950, TP: 1.2050, C: EURUSD, D: BUYSTOP")

        Vaya en mi caso las operaciones serían a mercado, igualmente, ¿ Sería así el cambio? Muchas gracias por vuestro tiempo

        • The Market Bull
          The Market Bull says:

          Hola Victor,

          Sin problema, estamos para ayudar! Con respecto a tu pregunta sobre repSocket.recv() y remote.send():

          1) “request” es el parametro global en el archivo “ZeroMQ_MT4_EA_Template.mq4” que se actualiza cada vez que se ejecuta “OnTimer()”.

          2) Este variable recibe el señal desde tu código en R.

          Por ejemplo, en su caso para “market orders”:

          Debes modificar esto como tal en R:
          remote.send (reqSocket, “SL: 1.1950, TP: 1.2050, C: EURUSD, D: MARKET”)

          Entonces, MetaTrader lo recibe con repSocket.recv():
          repSocket.recv(request, true)

          3) Ahora el parámetro “request” tiene el texto “SL: 1.1950, TP: 1.2050, C: EURUSD, D: MARKET”.

          4) Ahora, en el archivo “ZeroMQ_MT4_EA_Template.mq4”, debes modificar “ParseZmqMessage()”, “MessageHandler()” y “InterpretZmqMessage()” para interpretar esta señal en consecuencia.

          Finalmente, debes implementar la lógica de ejecución con las funciones de MetaTrader 4, por ejemplo como las funciones aquí:


  2. Domingo
    Domingo says:


    Primero felicitarlos por su excelente artículo. He estado haciendo varias pruebas con el código python, pero cuando intento traer datos históricos, utilizando ‘get_data = “DATA|GOLD|5|0|1000″‘ como comando, obtengo erráticamente el siguiente error en la respuesta:

    File “”, line 62, in remote_send
    msg = socket.recv_string()
    File “/usr/lib/python2.7/dist-packages/zmq/sugar/”, line 345, in recv_string
    return b.decode(encoding)
    File “/usr/lib/python2.7/encodings/”, line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
    UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0xf3 in position 5: invalid continuation byte

    Al parecer es un problema con el encoding de string.

    Nota: En el servidor MT4 cambié el comando CopyClose a:
    price_count = CopyClose(compArray[1], StrToInteger(compArray[2]),
    StrToInteger(compArray[3]), StrToInteger(compArray[4]),
    porque con fechas no logré que me respondiera.

    • The Market Bull
      The Market Bull says:

      Hola Domingo,

      Muchas gracias por tu interés y comentario en nuestro blog.

      Hemos tratado de reproducir tu error en nuestro entorno y te podemos confirmar que ha funcionado sin problema.

      Tienes toda la razón sobre la codificación. Vamos a intentar algo sencillo a ver si funciona:

      Por favor, cambia “|” por “,” y modifica el codigo MQL de “|” a “,” y haznos saber si se ha resuelto.

      Un saludo

  3. pepelu linfosite
    pepelu linfosite says:

    hola, muchas gracias por el artículo, es sumamente interesante, pero… ¿para cuando el tercer artículo de la serie…¿?, Según adelantabais…
    “En el siguiente artículo veremos cómo implementar la obtención de información sobre la cuenta y las operaciones vía ZeroMQ”

  4. Joan
    Joan says:

    Hola, antes de nada daros las gracias por el artículo y por proporcionar las herramientas para poder conectar estrategias de inversión implementadas en Python con una herrmienta para operar en el mercado como Metatrader 4.

    Desgraciadamente estoy teniendo algunos problemas para poner a funcionar el DWX_ZeroMQ_Server 2.0.1 en mi plataforma de Metatrader 4.

    He seguido los pasos que se detallan en:

    y finalmente he consigo ver las publicaciones de las cotizaciones de los pares de divisas en la pestaña “Expertos”. Para ello tuve que habilitar todas las opciones de Seguridad en la pestaña “Común” del Asesor Experto.

    Sin embargo, pienso que aun así no se ha cargado correctamente el Servidor, ya que en la esquina superior derecha, junto al nombre del Asesor Experto (DWX_ZeroMQ_Server), aparece una carita triste 🙁

    Además desde mi terminal de Python, después de cargar DWX_ZeroMQ_Connector_v2_0_1_RC8, no consigo ver las operaciones que tengo abiertas ni tampoco lanzar operaciones siguiendo los pasos del webinario:

    _zmq = zeromq_Connector.DWX_ZeroMQ_Connector()
    _zmq._DWX_MTX_GET_ALL_OPEN_TRADES_()–> (Vacio)

    Tampoco consigo suscribirme a las cotizaciones para ver las en el terminal de Python:

    _zmq._Market_Data_DB.keys() –> (Vacio)
    _zmq._Market_Data_DB –> (Vacio)

    Puede ser que me falte configurar algo de las Opciones de Metatarder 4 que no se menciona en el tutorial?

    Cómo debo de tener configuradas las opciones en las Pestañas “Servidor”, “Asesores Expertos”, “Notificaciones” del Metatrader 4?


    • The Market Owl
      The Market Owl says:

      Gracias por tu interés Joan. ¡Genial que estés encontrando el código útil!

      Para que Python reciba las respuestas de MetaTrader, debe haber una “cara feliz” en la esquina superior derecha del gráfico en MetaTrader.

      Aquí hay dos pasos para asegurarse de que aparezca la “cara feliz”:

      1) Asegúrate de que las opciones Tools -> Options -> Expert Advisors -> “Allow DLL imports” y “Allow automated trading” estén seleccionadas.

      2) Dentro de las “Properties” de la EA (clic con el botón derecho en el gráfico -> Expert Advisors -> Properties), también se deben seleccionar “Allow live trading” y “Allow DLL imports”.

      Estos pasos asegurarán que aparezca la “cara feliz”, que se requiere para que MetaTrader y Python se comuniquen entre sí correctamente.

      Esperamos que esto te ayude a resolver el problema.

      • Joan
        Joan says:

        Genial! ya me aparece la “cara feliz” en la esquina superior derecha y me funcionan los comandos del ZeroMQ_Connector desde la consola de Python 🙂

        Muchas gracias por la aclaración!

      • Joan
        Joan says:

        Hola de nuevo, creo que canté victoria demasiado pronto. A pesar de que me aparece la “cara feliz” en la esquina superior derecha, parece que la comunicación Python – Metatrader sólo funciona en un sentido.

        De momento puedo ver que Metatrader recibe y procesa casi todas las órdenes desde Python correctamente, pero sin embargo en la consola de Python no consigo ver las respuestas que debería enviar Metatrader.

        De esta manera cuando envio la orden _zmq._DWX_MTX_GET_ALL_OPEN_TRADES_() desde la consola de Python, no se recibe ninguna respuesta, ni tampoco se recibe ninguna respuesta cuando abro una orden nueva(_zmq._DWX_MTX_NEW_TRADE_()) o cierro una orden por ticket (_zmq._DWX_MTX_CLOSE_TRADE_BY_TICKET_(149031419)), a pesar de que estas ordenes se ejecutan correctamente:

        >>> import DWX_ZeroMQ_Connector_v2_0_1_RC8 as zeromq_Connector
        >>> _zmq = zeromq_Connector.DWX_ZeroMQ_Connector()
        [INIT] Ready to send commands to METATRADER (PUSH): 32768
        [INIT] Listening for responses from METATRADER (PULL): 32769
        >>> _zmq._DWX_MTX_NEW_TRADE_()
        >>> _zmq._DWX_MTX_GET_ALL_OPEN_TRADES_()
        >>> _zmq._DWX_MTX_CLOSE_TRADE_BY_TICKET_(149031419)

        Me parece muy extraño ya que cuando creo el objeto “_zmq” aparece un mensaje como que los sockets están listos para enviar y recibir mensajes.

        También se observa en la pestaña “Expertos” los mensajes cuando se abren o se cierran operaciones correctamente, aunque por la parte de Python no se recibe feedback desde Metatrader.

        Alguna idea de lo que puede estar pasando?


Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Campos obligatorios *