简体   繁体   中英

Metatrader 5 binding ZeroMQ/Python

I'm aiming to: get real-time quotes (bid/ask values) from Metatrader 5 and export to a variable in Python.

I've done some research so far - and got sucessfuly a request-reply ("Hello / World") with server (MT5) / client (Python 3.6) through ZeroMQ 4.2.3 and dingmaotu library. ( https://github.com/dingmaotu/mql-zmq )

However - I didn't find any code samples for: Launch a MT5 server and simply get a quote in Python. (Example: IBM close, GOOG bid).

How can I do that?

I've already tried Darwinex template - but without sucess in MT5. ( https://blog.darwinex.com/zeromq-interface-python-r-metatrader4/ )

The ZeroMQ <-> MetaTrader implementation referenced in the Darwinex blog post above was completely re-written from the ground up recently.

The latest versions of both the script and the accompanying MQL EA have been extended considerably, and support Python 3.

Specifically :

  1. Sending/receiving historical prices from MetaTrader to Python,
  2. Real-time bid/ask quote streaming for any symbol available in the MetaTrader terminal being connected to,
  3. .. and trading commands including OPEN/MODIFY/CLOSE/PARTIAL_CLOSE were implemented (Python to MetaTrader).

Furthermore, all exchange between Python and MetaTrader now happen in JSON format, allowing for easier consumption either end.

See here for code, examples and more information: https://github.com/darwinex/DarwinexLabs/tree/master/tools/dwx_zeromq_connector

Hope the revised code helps you solve the rates issue.

And what is the problem you are facing?

When sending data to 0MQ, you need to decide the format, probably json could be a good solution. The block sending the messages to 0MQ is

  ZmqMsg reply("World");
  // Send reply back to client
  socket.send(reply);

Instead of sending "World", you need to send your message, let us say {"ticker":"GOOG","Bid":100,"Ask":101,"Time":1599000000}. In order to receive the values, you are welcome to use

  SymbolInfoTick() structure, if you want to create a json automatically, you are welcome to use some library like jason.mqh available in Mql5.com/sources

easiest way to do it is with drag and drop integration for metatrader5, you just install the ea and indicator and you get qoutes into your python script easilly...

Its a great solution for python and metatrader:

import socket
import numpy as np
import pandas as pd
from datetime import datetime
import pytz

import io

TZ_SERVER = 'Europe/Tallinn' # EET
TZ_LOCAL  = 'Europe/Budapest'
TZ_UTC    = 'UTC'

class Pytrader_API:             
  
    def __init__(self):
        self.socket_error: int = 0
        self.socket_error_message: str = ''
        self.order_return_message: str = ''
        self.order_error: int = 0
        self.connected: bool = False
        self.timeout: bool = False
        self.command_OK: bool = False
        self.command_return_error: str = ''
        self.debug: bool = False
        self.version: str = '1.06'
        self.max_bars: int = 5000
        self.max_ticks: int = 5000
        self.timeout_value: int = 60
        self.instrument_conversion_list: dict = {}
        self.instrument_name_broker: str = ''
        self.instrument_name_universal: str = ''
        self.date_from: datetime = '2000/01/01, 00:00:00'
        self.date_to: datetime = datetime.now()
        self.instrument: str = ''

    def Set_timeout(self,
                    timeout_in_seconds: int = 60
                    ):
        """
        Set time out value for socket communication with MT4 or MT5 EA/Bot.
        Args:
            timeout_in_seconds: the time out value
        Returns:
            None
        """
        self.timeout_value = timeout_in_seconds
        self.sock.settimeout(self.timeout_value)
        self.sock.setblocking(1)
        return

    def Disconnect(self):
        """
        Closes the socket connection to a MT4 or MT5 EA bot.
        Args:
            None
        Returns:
            bool: True or False
        """

        self.sock.close()
        return True

    def Connect(self,
                server: str = '',
                port: int = 2345,
                instrument_lookup: dict = []) -> bool:
        """
        Connects to a MT4 or MT5 EA/Bot.
        Args:
            server: Server IP address, like -> '127.0.0.1', '192.168.5.1'
            port: port number
            instrument_lookup: dictionairy with general instrument names and broker intrument names
        Returns:
            bool: True or False
        """
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.setblocking(1)
        self.port = port
        self.server = server
        self.instrument_conversion_list = instrument_lookup

        if (len(self.instrument_conversion_list) == 0):
            print('Broker Instrument list not available or empty')
            self.socket_error_message = 'Broker Instrument list not available'
            return False

        try:
            self.sock.connect((self.server, self.port))
            try:
                data_received = self.sock.recv(1000000)
                self.connected = True
                self.socket_error = 0
                self.socket_error_message = ''
                return True
            except socket.error as msg:
                self.socket_error = 100
                self.socket_error_message = 'Could not connect to server.'
                self.connected = False
                return False
        except socket.error as msg:
            print(
                "Couldnt connect with the socket-server: %self.sock\n terminating program" %
                msg)
            self.connected = False
            self.socket_error = 101
            self.socket_error_message = 'Could not connect to server.'
            return False

    def Check_connection(self) -> bool:
        """
        Checks if connection with MT terminal/Ea bot is still active.
        Args:
            None
        Returns:
            bool: True or False
        """

        self.command = 'F000#0#'
        self.command_return_error = ''
        ok, dataString = self.send_command(self.command)

        try:
            if (ok == False):
                self.command_OK = False
                return False

            x = dataString.split('#')

            if x[1] == 'OK':
                self.timeout = True
                self.command_OK = True
                return True
            else:
                self.timeout = False
                self.command_OK = True
                return False
        except:
            self.command_return_error = 'Unexpected socket communication error'
            self.command_OK = False
            return False

    @property
    def IsConnected(self) -> bool:
        """Returns connection status.
        Returns:
            bool: True or False
        """
        return self.connected

    def Get_static_account_info(self) -> dict:
        """
        Retrieves static account information.
        Returns: Dictionary with:
            Account name,
            Account number,
            Account currency,
            Account type,
            Account leverage,
            Account trading allowed,
            Account maximum number of pending orders,
            Account margin call percentage,
            Account close open trades margin percentage
        """
        self.command_return_error = ''

        ok, dataString = self.send_command('F001#0#')
        if (ok == False):
            self.command_OK = False
            return None

        if self.debug:
            print(dataString)

        x = dataString.split('#')
        if x[0] != 'F001':
            self.command_return_error = str(x[2])
            self.command_OK = False
            return None

        returnDict = {}
        del x[0:2]
        x.pop(-1)

        returnDict['name'] = str(x[0])
        returnDict['login'] = str(x[1])
        returnDict['currency'] = str(x[2])
        returnDict['type'] = str(x[3])
        returnDict['leverage'] = int(x[4])
        returnDict['trade_allowed'] = bool(x[5])
        returnDict['limit_orders'] = int(x[6])
        returnDict['margin_call'] = float(x[7])
        returnDict['margin_close'] = float(x[8])

        self.command_OK = True
        return returnDict

    def Get_dynamic_account_info(self) -> dict:
        """
        Retrieves dynamic account information.
        Returns: Dictionary with:
            Account balance,
            Account equity,
            Account profit,
            Account margin,
            Account margin level,
            Account margin free
        """
        self.command_return_error = ''

        ok, dataString = self.send_command('F002#0#')
        if (ok == False):
            self.command_OK = False
            return None

        if self.debug:
            print(dataString)

        x = dataString.split('#')
        if x[0] != 'F002':
            self.command_return_error = str(x[2])
            self.command_OK = False
            return None

        returnDict = {}
        del x[0:2]
        x.pop(-1)

        returnDict['balance'] = float(x[0])
        returnDict['equity'] = float(x[1])
        returnDict['profit'] = float(x[2])
        returnDict['margin'] = float(x[3])
        returnDict['margin_level'] = float(x[4])
        returnDict['margin_free'] = float(x[5])

        self.command_OK = True
        return returnDict

    def Get_PnL(self,
                    date_from: datetime = datetime(2021, 3, 1, tzinfo = pytz.timezone("Etc/UTC")),
                    date_to: datetime = datetime.now()) -> pd.DataFrame:
        '''    
        Retrieves profit loss info.
        Args:
            date_from: start date
            date_to: end date
        Returns: Dictionary with:
            realized_profit             profit of all closed positions
            unrealized_profit           profit of all open positions
            buy_profit                  profit of closed buy positions
            sell_profit                 profit of closed sell positions
            positions_in_profit         number of profit positions
            positions in loss           number of loss positions
            volume_in_profit            total volume of positions in profit
            volume_in_loss              total volume of positions in loss
        
        total_profit = 0.0
        buy_profit = 0.0
        sell_profit = 0.0
        trades_in_loss = 0
        trades_in_profit = 0
        volume_in_loss = 0.0
        volume_in_profit = 0.0
        commission_in_loss = 0.0
        commission_in_profit = 0.0
        swap_in_loss = 0.0
        swap_in_profit = 0.0
        unrealized_profit = 0.0

this example taken from Python with Metatrader API

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM