QuoteDislikedHere's an example using MetaTrader5 (C) and TA-lib (C) to get rates and calculate BBands using pymt5adapter as the glue (pythonic interface).
..
1
Python Trader code and skills sharing 59 replies
embedding python 19 replies
Monty python and the holy grail 4 replies
Upcoming MetaTrader5 with MQL5 3 replies
Python or Perl? 17 replies
QuoteDislikedHere's an example using MetaTrader5 (C) and TA-lib (C) to get rates and calculate BBands using pymt5adapter as the glue (pythonic interface).
Disliked{quote} No, no, it is not polling. See the constant "INFINITE"? It means that execution is halted and only resumes after the wait-object(s) is signalled (it is an OS function - I know not how the OS internally manages wait objects, however) - CPU usage is "zero". Now, to wait again for another event, the execution has to return into the wait function, but this is not the same as polling - the function can be used in pollling mode also, if zero or any other time span value (ms) is supplied instead of INFINITE. {quote} Ok.Ignored
DislikedHow are you handling events in your application on the other end? I assume that it is polling then?Ignored
Disliked{quote} Both ends can use synchronization objects. In my case, I post a window message into the window's message queue i.e., from an indicator or ea when they register an event (i.e. tick, book etc). There is a window message wm_copydata, which creates on demand a shared memory space between two processes to pass data but I use a static (predefined) shared memory to read/write data between the processes.Ignored
Disliked{quote} Nick, are there any insights about the API the Python connector uses? Does MT5 expose an OLE or COM interface? Or communicates Python with the terminal via TCP or shared memory? If so, is there anything known about the protocol the API uses? Background: I'm interested in accessing order data from a pure Windows application. Thanks.Ignored
import argparse import asyncio import json import pymt5adapter as mta API_FUNCS = mta.get_function_dispatch() async def handle_api(reader, writer): data = await reader.read(1000) message = data.decode() try: req = json.loads(message) func = API_FUNCS[req['function']] args = req.get('args', []) kwargs = req.get('kwargs', {}) response = func(*args, **kwargs) res = dict(error=mta.mt5_last_error(), response=response) except Exception as e: res = dict(error=[-1, f'{type(e).__name__} {e.args[0]}'], response=None) res = json.dumps(res) writer.write(res.encode()) await writer.drain() writer.close() async def main(): server = await asyncio.start_server(handle_api, '127.0.0.1', 8888) addr = server.sockets[0].getsockname() print('Serving on {}:{}'.format(*addr)) async with server: await server.serve_forever() if __name__ == '__main__': parser = argparse.ArgumentParser(description='Socket server for MT5 API') parser.add_argument('--path', type=str, help='Absolute path to the terminal64.exe') parser.add_argument('--login', type=int, help='Account number') parser.add_argument('--password', type=str, help='Account password') parser.add_argument('--server', type=str, help='Name of the trade server eg. "MetaQuotes-Demo"') parser.add_argument('--portable', action='store_true', default=None, help='Will launch the terminal in portable mode if this flag is set') ns = parser.parse_args() kw = vars(ns) val_states = [v is not None for v in kw.values()] if any(val_states) and not all(val_states): print(ns) raise Exception('Missing commandline arguments.') mt5_connected = mta.connected( ensure_trade_enabled=True, native_python_objects=True, raise_on_errors=True, **kw ) with mt5_connected: asyncio.run(main())
import asyncio import json async def socket_client(message): reader, writer = await asyncio.open_connection('127.0.0.1', 8888) print(f'Send: {message!r}') writer.write(message.encode()) data = await reader.read() data = data.decode() writer.close() return json.loads(data) if __name__ == '__main__': req = json.dumps({ 'function': 'copy_rates_from_pos', 'kwargs' : { 'symbol' : 'EURUSD', 'timeframe': 1, 'start_pos': 1, 'count' : 1000 }, }) res = asyncio.run(socket_client(req)) print(str(res)[:100]) errno, strerr = res['error'] if errno == 1: rates = res['response'] print(len(rates))
Disliked{quote} Thank you. Does the MetaQuotes Python package (not your adapter) talk to an existing running terminal process, or does it launch it's own separate terminal process?Ignored
DislikedSo, ever since i discovered TA-Lib and saw @nicholisen's endorsements, I'm exploring using python to build WORA trading robots. Now, in the short term, I would still use MT5 and/or MT4, but I am ready to get on the python train and be rid of MQL. Like, Forever. With that said, I hear that if i were looking to adopt Python, MT backtesting may not be as straightforward, or not possible. Is there a way around that? I'd imagine it should be possible to write a shell EA in MQL, whose sole purpose is to take inputs and send them over TCP/IP to a python...Ignored
Disliked{quote} Interesting. Would you mind sharing the code for the MQL side? I'm wondering if it might be better to use this pattern instead of polling the terminal API...Ignored
import pymt5adapter as mta import logging logger = mta.get_logger(path_to_logfile='example_mt5_log.log', loglevel=logging.DEBUG) with mta.connected(raise_on_errors=True, logger=logger) as conn: # custom log logger.info(mta.LogJson('My custom message', dict(type='custom', ping=conn.ping()))) raise Exception('Error!')
2020-07-24 00:33:08,398 INFO Terminal Initialize Success {"type": "terminal_connection_state", "state": true} 2020-07-24 00:33:08,400 INFO Init TerminalInfo {"type": "init_terminal_info", "terminal_info": {"community_account": false, "community_connection": false, "connected": true, "dlls_allowed": false, "trade_allowed": true, "tradeapi_disabled": false, "email_enabled": false, "ftp_enabled": false, "notifications_enabled": false, "mqid": false, "build": 2539, "maxbars": 100000000, "codepage": 0, "ping_last": 45665, "community_balance": 0.0, "retransmission": 0.0, "company": "MetaQuotes Software Corp.", "name": "MetaTrader 5", "language": "English", "path": "C:\\Users\\User\\Desktop\\MetaTrader\\Terminal1", "data_path": "C:\\Users\\User\\Desktop\\MetaTrader\\Terminal1", "commondata_path": "C:\\Users\\User\\AppData\\Roaming\\MetaQuotes\\Terminal\\Common"}} 2020-07-24 00:33:08,400 INFO Init AccountInfo {"type": "init_account_info", "account_info": {"login": 8217648, "trade_mode": 0, "leverage": 100, "limit_orders": 0, "margin_so_mode": 0, "trade_allowed": true, "trade_expert": true, "margin_mode": 0, "currency_digits": 2, "fifo_close": false, "balance": 1001438.9, "credit": 0.0, "profit": 0.0, "equity": 1001438.9, "margin": 0.0, "margin_free": 1001438.9, "margin_level": 0.0, "margin_so_call": 50.0, "margin_so_so": 30.0, "margin_initial": 0.0, "margin_maintenance": 0.0, "assets": 0.0, "liabilities": 0.0, "commission_blocked": 0.0, "name": "Nicholishen", "server": "AMPGlobalUSA-Demo", "currency": "USD", "company": "AMP Global Clearing LLC"}} 2020-07-24 00:33:08,408 INFO My custom message {"type": "custom", "ping": [45665, 7]} 2020-07-24 00:33:08,408 CRITICAL UNCAUGHT EXCEPTION: Error! {"type": "exception", "last_error": [1, "Success"], "exception": {"type": "Exception", "message": "Error!"}} 2020-07-24 00:33:08,408 INFO Terminal Shutdown {"type": "terminal_connection_state", "state": false}
pip install --update pymt5adapter
DislikedDang what an awesome thread. Thanks Nicholishen!! It’s a bummer there isn’t a way to use the back tester. I’m currently getting some crude stats just using pandas. But I’m thinking if I get trade entry/tp/sl data for a 5min chart, then I can loop through a 1min data frame to get a better look at performance. If anyone has any clever ideas for backtesting please let me know Normalized swing ratings and liquidity zones: https://prnt.sc/tmvmc7Ignored
With that said, i'll probably end up just doing it all in python, haha. Here are some links to backtesting options i found, that I shared in another thread.
!pip install plotly>=4.7.1 !wget https://github.com/plotly/orca/releases/download/v1.2.1/orca-1.2.1-x86_64.AppImage -O /usr/local/bin/orca !chmod +x /usr/local/bin/orca !apt-get install xvfb libgtk2.0-0 libgconf-2-4
fig.write_image('{}.png'.format(i)) files.download('{}.png'.format(i))