Package: pymt5adapter
Introductionpymt5adapteris a drop-in replacement (wrapper) for theMetaTrader5python package by MetaQuotes.
The API functions simply pass through values from theMetaTrader5functions, but adds the following functionality
in addition to a more pythonic interface:Typing hinting has been added to all functions and return objects for linting and IDE integration.
Now intellisense will work no matter how nested objects are.Docstrings have been added to each function
(see official MQLdocumentation).
Docs can now be accessed on the fly in the IDE. For example:Ctrl+Qin pycharm.All params can now be called by keyword. No more positional only args.Testing included compliments ofpytestA new context manager has been added to provide a more pythonic interface to the setup and tear-down
of the terminal connection. The use of this context-manager can do the following:Ensures thatmt5.shutdown()is always called, even if the user code throws an uncaught exception.Modifies the global behavior of the API:Ensure the terminal has enabled auto-trading.Prevents running on real account by defaultAccepts a logger and automatically logs function API calls and order activity.Can raise the customMT5Errorexception wheneverlast_error()[0] != RES_S_OK(off by default)Installationpip install -U pymt5adapterTheMetaTrader5dependency sometimes has issues installing with thepipversion that automatically gets
packaged inside of thevirualenvenvironment. If cannot installMetaTrader5then you need to updatepipinside of the virtualenv. From the command line within the virual environment use:(inside virtualenv):easy_install -U pipImportThis should work with any existingMetaTrader5script by simply changing theimportstatement from:importMetaTrader5asmt5to:importpymt5adapterasmt5Context ManagerTheconnectedfunction returns a context manager which performs all API setup and tear-down and ensures
thatmt5.shutdown()is always called.Hello worldUsing the context manager can be easy as...importpymt5adapterasmt5withmt5.connected():print(mt5.version())and can be customized to modify the entire APIimportpymt5adapterasmt5importlogginglogger=mt5.get_logger(path_to_logfile='my_mt5_log.log',loglevel=logging.DEBUG,time_utc=True)mt5_connected=mt5.connected(path=r'C:\Users\user\Desktop\MT5\terminal64.exe',portable=True,server='MetaQuotes-Demo',login=1234567,password='password1',timeout=5000,logger=logger,# default is Noneensure_trade_enabled=True,# default is Falseenable_real_trading=False,# default is Falseraise_on_errors=True,# default is Falsereturn_as_dict=False,# default is Falsereturn_as_native_python_objects=False,# default is False)withmt5_connectedasconn:try:num_orders=mt5.history_orders_total("invalid","arguments")exceptmt5.MT5Errorase:print("We modified the API to throw exceptions for all functions.")print(f"Error ={e}")# change error handling behavior at runtimeconn.raise_on_errors=Falsetry:num_orders=mt5.history_orders_total("invalid","arguments")exceptmt5.MT5Error:passelse:print('We modified the API to silence Exceptions at runtime')Output:MT5 connection has been initialized.
[history_orders_total(invalid, arguments)][(-2, 'Invalid arguments')][None]
We modified the API to throw exceptions for all functions.
Error = (<ERROR_CODE.INVALID_PARAMS: -2>, "Invalid arguments('invalid', 'arguments'){}")
[history_orders_total(invalid, arguments)][(-2, 'Invalid arguments')][None]
We modified the API to silence Exceptions at runtime
[shutdown()][(1, 'Success')][True]
MT5 connection has been shutdown.Exception handlingTheMetaTrader5package does not raise exceptions and all errors fail silently
by default. This behavior forces the developer to check each object forNoneoremptystate and then calllast_error()to resolve any possible errors.
One of the primary features of the context manager is extend the ability
to toggle exceptions on/off globally. All raised exceptions are of typeMT5Error. TheMT5Errorexception has two properties which areerror_codeanddescription.withmt5.connected(raise_on_errors=True)asconn:try:invalid_args=mt5.history_deals_get('sdf','asdfa')print(invalid_args)exceptmt5.MT5Errorase:print(e.error_code,e.description)ife.error_codeismt5.ERROR_CODE.INVALID_PARAMS:print('You can use "is" to check identity since we use enums')conn.raise_on_errors=Falseprint('Errors will not raise exceptions and default behavior has bene restored at runtime')invalid_args=mt5.history_deals_get('sdf','asdfa')ifnotinvalid_args:print(mt5.last_error())OUTPUTERROR_CODE.INVALID_PARAMS Invalid arguments('sdf', 'asdfa'){}
You can use "is" to check identity since we use enums
Errors will not raise exceptions and default behavior has bene restored at runtime
(-2, 'Invalid arguments')LoggingLogging functionality has been added to the API and can be utilized by passing any logger that implements thelogging.Loggerinterface to theloggerparam inconnectedcontext manager. Messages generated from the API
functions are always tab deliminated and include two parts:A short human readable message.A JSON dump for easy log parsing and debugging.2020-07-22 18:54:10,399	INFO	Terminal Initialize Success	{"type": "terminal_connection_state", "state": true}For convenience, a preconfigured logger can be retrieved by callingget_loggerlogger=mt5.get_logger(path_to_logfile='my_mt5_log.log',loglevel=logging.DEBUG,time_utc=True)withmt5.connected(logger=logger):main()Note: The API will only automatically log if a logger is passed into the context manager. The intent was to provide
convenience but not force an opinionated logging schema.Additional features not included in theMetaTrader5packageFilter function callbacksThe following API functions can now except an optional callback for filtering using the named parameter,function:symbols_getorders_getpositions_gethistory_deals_gethistory_orders_getExample:visible_symbols=mt5.symbols_get(function=lambdas:s.visible)defout_deal(deal:mt5.TradeDeal):returndeal.entry==mt5.DEAL_ENTRY_OUTout_deals=mt5.history_deals_get(function=out_deal)