Skip to content

Commit ad5c808

Browse files
committed
Update README.md
2 parents 413c6e4 + f5db7b1 commit ad5c808

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

README.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,23 @@ Backtrader Python client located here: [Python Backtrader - Metaquotes MQL5 ](ht
1818

1919
In development:
2020
* Historical data load speed
21+
<<<<<<< HEAD
2122
* Add error handling to docs
2223
* Trades info
2324
* Experation
2425
* Devitation
2526
* Netting/hedging mode switch
2627
* Stop limit orders
28+
=======
29+
* Trades info
30+
* Experation
31+
* Devitation
32+
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
2733
2834
## Installation
2935

3036
1. Install ZeroMQ for MQL5 [https://github.com/dingmaotu/mql-zmq](https://github.com/dingmaotu/mql-zmq)
37+
<<<<<<< HEAD
3138
2. Put `include/Json.mqh` from this repo to your MetaEditor `include` directoty.
3239
3. Download and compile `experts/JsonAPI.mq5` script.
3340
4. Check if Metatrader 5 automatic trading is allowed.
@@ -49,6 +56,29 @@ The script uses four ZeroMQ sockets:
4956
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.
5057

5158
`System socket` request uses default JSON dictionary:
59+
=======
60+
2. Put 'include/Json.mqh' from this repo to your MetaEditor 'include' directoty.
61+
3. Download and compile JsonAPI script.
62+
4. Check if automatic trading is allowed.
63+
5. Attach the script to a chart in Metatrader 5.
64+
6. Allow DLL import in dialog window.
65+
7. Check if the ports are free to use. (default: 15555, 15556, 15557, 15558)
66+
67+
Tested on macOS Mojave and Windows 10 in Parallels Desktop container.
68+
69+
## Documentation
70+
71+
The script uses 4 ZeroMQ sockets:
72+
73+
1. System socket - recives requests from client and replies 'OK'
74+
2. Data socket - pushes data to client depending on request via System socket.
75+
3. Live socket - pushes last candle when it closes.
76+
4. Streaming socket - pushes last transaction info when it happens.
77+
78+
79+
80+
Configure the script:
81+
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
5282
5383
```
5484
{
@@ -69,6 +99,7 @@ The idea is to send requests via `System socket` and recieve results/errors via
6999
"comment": None
70100
}
71101
```
102+
<<<<<<< HEAD
72103
Check out the available combinations of `action` and `actionType`:
73104

74105
action | actionType | Description |
@@ -80,6 +111,18 @@ POSITIONS | None | Get current open positions |
80111
ORDERS | None | Get current open orders |
81112
HISTORY | DATA | Get data history |
82113
HISTORY | TRADES | Get trades history |
114+
=======
115+
116+
action | actionType | Description |
117+
-----------|----------------------|----------------------------|
118+
CONFIG | null | Set script configuration |
119+
ACCOUNT | null | Get account settings |
120+
BALANCE | null | Get current balance |
121+
HISTORY | null | Get symbol history |
122+
POSITIONS | null | Get current open positions |
123+
ORDERS | null | Get current open orders |
124+
-----------|----------------------|----------------------------|
125+
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
83126
TRADE | ORDER_TYPE_BUY | Buy market |
84127
TRADE | ORDER_TYPE_SELL | Sell market |
85128
TRADE | ORDER_TYPE_BUY_LIMIT | Buy limit |
@@ -88,17 +131,26 @@ TRADE | ORDER_TYPE_BUY_STOP | Buy stop |
88131
TRADE | ORDER_TYPE_SELL_STOP | Sell stop |
89132
TRADE | POSITION_MODIFY | Position modify |
90133
TRADE | POSITION_PARTIAL | Position close partial |
134+
<<<<<<< HEAD
91135
TRADE | POSITION_CLOSE_ID | Position close by id |
92136
TRADE | POSITION_CLOSE_SYMBOL| Positions close by symbol |
93137
TRADE | ORDER_MODIFY | Order modify |
94138
TRADE | ORDER_CANCEL | Order cancel |
95139

96140
Example Python API class:
141+
=======
142+
TRADE | POSITION_ID | Position close by id |
143+
TRADE | POSITION_CLOSE | Position close |
144+
TRADE | ORDER_MODIFY | Order modify |
145+
TRADE | ORDER_CANCEL | Order cancel |
146+
147+
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
97148
98149
``` python
99150
import zmq
100151

101152
class MTraderAPI:
153+
<<<<<<< HEAD
102154
def __init__(self, host=None):
103155
self.HOST = host or 'localhost'
104156
self.SYS_PORT = 15555 # REP/REQ port
@@ -124,6 +176,39 @@ class MTraderAPI:
124176
self.data_socket.connect('tcp://{}:{}'.format(self.HOST, self.DATA_PORT))
125177
except zmq.ZMQError:
126178
raise zmq.ZMQBindError("Binding ports ERROR")
179+
=======
180+
181+
HOST = 'localhost'
182+
SYS_PORT = 15555 # REP/REQ port
183+
DATA_PORT = 15556 # PUSH/PULL port
184+
LIVE_PORT = 15557 # PUSH/PULL port
185+
EVENTS_PORT = 15558 # PUSH/PULL port
186+
187+
# ZeroMQ timeout in seconds
188+
sys_sock_tmout = 1
189+
data_sock_tmout = 10
190+
191+
# initialise ZMQ context
192+
context = zmq.Context()
193+
194+
# connect to server sockets
195+
try:
196+
sys_socket = context.socket(zmq.REQ)
197+
sys_socket.RCVTIMEO = sys_sock_tmout * 1000
198+
sys_socket.connect('tcp://{}:{}'.format(HOST, SYS_PORT))
199+
200+
data_socket = context.socket(zmq.PULL)
201+
data_socket.RCVTIMEO = data_sock_tmout * 1000
202+
data_socket.connect('tcp://{}:{}'.format(HOST, DATA_PORT))
203+
204+
live_socket = context.socket(zmq.PULL)
205+
live_socket.connect('tcp://{}:{}'.format(HOST, LIVE_PORT))
206+
207+
events_socket = context.socket(zmq.PULL)
208+
events_socket.connect('tcp://{}:{}'.format(HOST, EVENTS_PORT))
209+
except zmq.ZMQError:
210+
raise zmq.ZMQBindError("Binding ports ERROR")
211+
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19
127212

128213
def _send_request(self, data: dict) -> None:
129214
""" Send request to server via ZeroMQ System socket """
@@ -145,6 +230,7 @@ class MTraderAPI:
145230
raise zmq.NotDone('Data socket timeout ERROR')
146231
return msg
147232

233+
<<<<<<< HEAD
148234
def live_socket(self, context=None):
149235
try:
150236
context = context or zmq.Context.instance()
@@ -292,3 +378,60 @@ while True:
292378
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.
293379

294380
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.
381+
=======
382+
def live_data(self):
383+
""" Catch live data from server """
384+
try:
385+
candle = self.live_socket.recv_json()
386+
except zmq.ZMQError:
387+
raise zmq.NotDone("Live data ERROR")
388+
return candle
389+
390+
def streaming_events(self):
391+
""" Catch events from server """
392+
try:
393+
candle = self.events_socket.recv_json()
394+
except zmq.ZMQError:
395+
raise zmq.NotDone("Streaming events ERROR")
396+
return candle
397+
398+
def construct_and_send(self, **kwargs) -> dict:
399+
""" Construct request dictionary from default """
400+
401+
# default dictionary
402+
request = {
403+
"action": None,
404+
"actionType": None,
405+
"symbol": None,
406+
"chartTF": None,
407+
"fromDate": None,
408+
"toDate": None,
409+
"id": None,
410+
"magic": None,
411+
"volume": None,
412+
"price": None,
413+
"stoploss": None,
414+
"takeprofit": None,
415+
"expiration": None,
416+
"deviation": None,
417+
"comment": None
418+
}
419+
420+
# update dict values if exist
421+
for key, value in kwargs.items():
422+
if key in request:
423+
request[key] = value
424+
else:
425+
raise KeyError('Unknown key in **kwargs ERROR')
426+
427+
# send dict to server
428+
self._send_request(request)
429+
430+
# return server reply
431+
return self._pull_reply()
432+
433+
```
434+
435+
# License
436+
Distributed under the GNU v3 License. See `LICENSE` for more information.
437+
>>>>>>> f5db7b13fe223453c6b2950ab4e5cddea7a80e19

0 commit comments

Comments
 (0)