Use MetaTrader with Python 3 on financial stock exchanges, Forex, CFD and Futures. From MetaTrader, you can get quotes in Python, but no complete connection between them. This post is one of the developers (RU).
This wrapper was created with changes in Python 3.7 Download ZIP from GitHub.
Python is now the standard for machine learning libraries (TensorFlow, PyTorch, etc.). Python itself is quite slow and therefore all machine learning library on C/C++ using it only for user interaction. It is not always possible to connect machine learning libraries directly to the C/C++ code without problems.
The main idea and the difference of this wrapper: a data exchange between the MQL and Python via pre-created function. This is the fastest and most reliable data exchange method. There is no time spent on parsing and compiling Python code that appears when using eval().
There is a class (the actual code here):
class MQL():
def getLong(self, magic: int, value: int, array: tuple) -> tuple or list:
raise NotImplementedError
def getULong(self, magic: int, value: int, array: tuple) -> tuple or list:
raise NotImplementedError
def getDouble(self, magic: int, value: float, array: tuple) -> tuple or list:
raise NotImplementedError
def getString(self, magic: int, value: str, array: bytes) -> str:
raise NotImplementedError
__mql__ = MQL()
The class name does not matter, because the reflection of the functions is via the variable __mql__
.
Also, the pyEval(..., override_class)
function has the argument override_class=true
when the variable __mql__
changes.
Example:
PythonDLL_Example.mq5 and
PythonDLL_Example.py
You can define the Python code execution environment:
if globals().get('__PythonDLL__'):
print('run in MetaTrader')
elif __name__ == '__main__':
print('run as script')
When testing is required “Allow DLL imports” at the global level.
The search for the necessary python3.dll occurs in the following order:
If python3.dll is not found:
Cannot load 'Roffild\PythonDLL\x64\Release\PythonDLL.dll' [126]
Cannot call 'pyInitialize', 'Roffild\PythonDLL\x64\Release\PythonDLL.dll' is not loaded
unresolved import function call
Python is not only python3.dll, but also its environment that needs to be configured. The most popular and simple solution is to install Anaconda. There is also Miniconda (minimum 200MB), if you clearly know which packages will be needed when running the script.
Python was created as a separate application, and with embeddability there are problems that are unlikely to ever be fixed:
With the active console, you can notice the output of Py_FatalError() until it disappears:
Fatal Python error: Py_Initialize: unable to load the file system codec
Compile errors and Python code execution errors are not automatically displayed on the active console. But when using the class CPythonDLL, errors are displayed in the terminal log.
There is always only one instance of Python to execute code. If several experts, indicators and scripts simultaneously use this Python wrapper without synchronization in one MetaTrader, then the result is not guaranteed. There is no such problem when testing.
Memory allocation is a long operation, but it doesn’t depend on the amount of memory requested. It will be faster to pre-allocate one megabyte per line and use this buffer several times rather than requesting the required amount of memory each time.
When using the multiprocessing module, you must specify the absolute path to the file in __file__
and sys.argv
. An example is here.
The wrapper was created with sub-interpreters, but I had to use a simple GIL.
Sub-interpreters are not compatible with the popular libraries for Python.
issue37186, issue10915.
But you can build this wrapper with PYTHONDLL_SUBINTERPRETERS
.
When you run in the terminal several independent experts, indicators and scripts that use this wrapper for each thread gets its own isolated interpreter using Py_NewInterpreter(). But there may be a delay in switching the thread, because Python does not have full multi-threaded execution, but a global interpreter lock (GIL) that blocks other threads when executing Python code.
When testing, there is always only one interpreter.
Official article on creating a DLL.
Addition to the article:
The int type in Python is infinite:
int("9999999999999999999999999999999999999999999999", 10).bit_length() == 153
Types in MQL:
long = 8 bytes (64 bits) = -9 223 372 036 854 775 808 ... 9 223 372 036 854 775 807
ulong = 8 bytes (64 bits) = 0 ... 18 446 744 073 709 551 615
CrashDumps:
%LOCALAPPDATA%\CrashDumps\