Update README.md

This commit is contained in:
Nikolai
2019-05-26 21:45:10 +03:00
+143
View File
@@ -18,16 +18,23 @@ Backtrader Python client located here: [Python Backtrader - Metaquotes MQL5 ](ht
In development:
* Historical data load speed
<<<<<<< HEAD
* Add error handling to docs
* Trades info
* Experation
* Devitation
* Netting/hedging mode switch
* Stop limit orders
=======
* Trades info
* Experation
* Devitation
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
## Installation
1. Install ZeroMQ for MQL5 [https://github.com/dingmaotu/mql-zmq](https://github.com/dingmaotu/mql-zmq)
<<<<<<< HEAD
2. Put `include/Json.mqh` from this repo to your MetaEditor `include` directoty.
3. Download and compile `experts/JsonAPI.mq5` script.
4. Check if Metatrader 5 automatic trading is allowed.
@@ -49,6 +56,29 @@ The script uses four ZeroMQ sockets:
The idea is to send requests via `System socket` and recieve results/errors via `Data socket`. For `Live socket` and `Streaming socket` event handlers should be created because server sends data to theese sockets automatically. See examples in [Usage](#usage) section.
`System socket` request uses default JSON dictionary:
=======
2. Put 'include/Json.mqh' from this repo to your MetaEditor 'include' directoty.
3. Download and compile JsonAPI script.
4. Check if automatic trading is allowed.
5. Attach the script to a chart in Metatrader 5.
6. Allow DLL import in dialog window.
7. Check if the ports are free to use. (default: 15555, 15556, 15557, 15558)
Tested on macOS Mojave and Windows 10 in Parallels Desktop container.
## Documentation
The script uses 4 ZeroMQ sockets:
1. System socket - recives requests from client and replies 'OK'
2. Data socket - pushes data to client depending on request via System socket.
3. Live socket - pushes last candle when it closes.
4. Streaming socket - pushes last transaction info when it happens.
Configure the script:
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
```
{
@@ -69,6 +99,7 @@ The idea is to send requests via `System socket` and recieve results/errors via
"comment": None
}
```
<<<<<<< HEAD
Check out the available combinations of `action` and `actionType`:
action | actionType | Description |
@@ -80,6 +111,18 @@ POSITIONS | None | Get current open positions |
ORDERS | None | Get current open orders |
HISTORY | DATA | Get data history |
HISTORY | TRADES | Get trades history |
=======
action | actionType | Description |
-----------|----------------------|----------------------------|
CONFIG | null | Set script configuration |
ACCOUNT | null | Get account settings |
BALANCE | null | Get current balance |
HISTORY | null | Get symbol history |
POSITIONS | null | Get current open positions |
ORDERS | null | Get current open orders |
-----------|----------------------|----------------------------|
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
TRADE | ORDER_TYPE_BUY | Buy market |
TRADE | ORDER_TYPE_SELL | Sell market |
TRADE | ORDER_TYPE_BUY_LIMIT | Buy limit |
@@ -88,17 +131,26 @@ TRADE | ORDER_TYPE_BUY_STOP | Buy stop |
TRADE | ORDER_TYPE_SELL_STOP | Sell stop |
TRADE | POSITION_MODIFY | Position modify |
TRADE | POSITION_PARTIAL | Position close partial |
<<<<<<< HEAD
TRADE | POSITION_CLOSE_ID | Position close by id |
TRADE | POSITION_CLOSE_SYMBOL| Positions close by symbol |
TRADE | ORDER_MODIFY | Order modify |
TRADE | ORDER_CANCEL | Order cancel |
Example Python API class:
=======
TRADE | POSITION_ID | Position close by id |
TRADE | POSITION_CLOSE | Position close |
TRADE | ORDER_MODIFY | Order modify |
TRADE | ORDER_CANCEL | Order cancel |
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
``` python
import zmq
class MTraderAPI:
<<<<<<< HEAD
def __init__(self, host=None):
self.HOST = host or 'localhost'
self.SYS_PORT = 15555 # REP/REQ port
@@ -124,6 +176,39 @@ class MTraderAPI:
self.data_socket.connect('tcp://{}:{}'.format(self.HOST, self.DATA_PORT))
except zmq.ZMQError:
raise zmq.ZMQBindError("Binding ports ERROR")
=======
HOST = 'localhost'
SYS_PORT = 15555 # REP/REQ port
DATA_PORT = 15556 # PUSH/PULL port
LIVE_PORT = 15557 # PUSH/PULL port
EVENTS_PORT = 15558 # PUSH/PULL port
# ZeroMQ timeout in seconds
sys_sock_tmout = 1
data_sock_tmout = 10
# initialise ZMQ context
context = zmq.Context()
# connect to server sockets
try:
sys_socket = context.socket(zmq.REQ)
sys_socket.RCVTIMEO = sys_sock_tmout * 1000
sys_socket.connect('tcp://{}:{}'.format(HOST, SYS_PORT))
data_socket = context.socket(zmq.PULL)
data_socket.RCVTIMEO = data_sock_tmout * 1000
data_socket.connect('tcp://{}:{}'.format(HOST, DATA_PORT))
live_socket = context.socket(zmq.PULL)
live_socket.connect('tcp://{}:{}'.format(HOST, LIVE_PORT))
events_socket = context.socket(zmq.PULL)
events_socket.connect('tcp://{}:{}'.format(HOST, EVENTS_PORT))
except zmq.ZMQError:
raise zmq.ZMQBindError("Binding ports ERROR")
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
def _send_request(self, data: dict) -> None:
""" Send request to server via ZeroMQ System socket """
@@ -145,6 +230,7 @@ class MTraderAPI:
raise zmq.NotDone('Data socket timeout ERROR')
return msg
<<<<<<< HEAD
def live_socket(self, context=None):
try:
context = context or zmq.Context.instance()
@@ -292,3 +378,60 @@ while True:
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See `LICENSE` for more information.
=======
def live_data(self):
""" Catch live data from server """
try:
candle = self.live_socket.recv_json()
except zmq.ZMQError:
raise zmq.NotDone("Live data ERROR")
return candle
def streaming_events(self):
""" Catch events from server """
try:
candle = self.events_socket.recv_json()
except zmq.ZMQError:
raise zmq.NotDone("Streaming events ERROR")
return candle
def construct_and_send(self, **kwargs) -> dict:
""" Construct request dictionary from default """
# default dictionary
request = {
"action": None,
"actionType": None,
"symbol": None,
"chartTF": None,
"fromDate": None,
"toDate": None,
"id": None,
"magic": None,
"volume": None,
"price": None,
"stoploss": None,
"takeprofit": None,
"expiration": None,
"deviation": None,
"comment": None
}
# update dict values if exist
for key, value in kwargs.items():
if key in request:
request[key] = value
else:
raise KeyError('Unknown key in **kwargs ERROR')
# send dict to server
self._send_request(request)
# return server reply
return self._pull_reply()
```
# License
Distributed under the GNU v3 License. See `LICENSE` for more information.
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19