繁体   English   中英

Metatrader 5 绑定 ZeroMQ/Python

[英]Metatrader 5 binding ZeroMQ/Python

我的目标是:从 Metatrader 5 获取实时报价(买入/卖出值)并导出到 Python 中的变量。

到目前为止,我已经做了一些研究 - 并通过 ZeroMQ 4.2.3 和 dingmaotu 库成功地获得了服务器(MT5)/客户端(Python 3.6)的请求回复(“Hello / World”)。 ( https://github.com/dingmaotu/mql-zmq )

但是 - 我没有找到任何代码示例:启动 MT5 服务器并简单地在 Python 中获取报价。 (例如:IBM 收盘,GOOG 出价)。

我该怎么做?

我已经尝试过 Darwinex 模板 - 但在 MT5 中没有成功。 ( https://blog.darwinex.com/zeromq-interface-python-r-metatrader4/ )

上面 Darwinex 博客文章中引用的ZeroMQ <-> MetaTrader实现是最近完全重新编写的。

脚本和随附 MQL EA 的最新版本已得到显着扩展,并支持 Python 3。

具体来说

  1. 从 MetaTrader 到 Python 发送/接收历史价格,
  2. MetaTrader 终端连接到的任何可用符号的实时买卖报价流,
  3. .. 并实施了包括 OPEN/MODIFY/CLOSE/PARTIAL_CLOSE 在内的交易命令(Python 到 MetaTrader)。

此外,Python 和 MetaTrader 之间的所有交换现在都以 JSON 格式进行,从而可以更轻松地使用任何一端。

有关代码、示例和更多信息,请参见此处: https : //github.com/darwinex/DarwinexLabs/tree/master/tools/dwx_zeromq_connector

希望修改后的代码可以帮助您解决费率问题。

您面临的问题是什么?

向 0MQ 发送数据时,您需要确定格式,可能 json 可能是一个很好的解决方案。 将消息发送到 0MQ 的块是

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

而不是发送“世界”,您需要发送您的消息,让我们说 {"ticker":"GOOG","Bid":100,"Ask":101,"Time":1599000000}。 为了接收值,欢迎您使用

  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

最简单的方法是使用 metatrader5 的拖放集成,您只需安装 ea 和指标,您就可以轻松地将 qoutes 放入您的 Python 脚本中...

它是 Python 和 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

这个例子取自带有 Metatrader API 的Python

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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