Использование MetaTrader с Python 3 на финансовых фондовых биржах, Forex, CFD и Futures. Из MetaTrader можно получать котировки в Python, но нет полноценной связи между ними. Пост одного из разработчиков.
Эта обертка создавалась с учетом изменений в Python 3.7 Скачать ZIP с GitHub.
Python сейчас является стандартом для библиотек машинного обучения (TensorFlow, PyTorch и т.п.). Сам Python довольно медленный и поэтому все библиотеки машинного обучения на C/C++ используют его только для взаимодействия с пользователем. Не всегда можно без проблем подключить библиотеки машинного обучения на прямую к коду C/C++.
Главная идея и отличие этой обертки от остальных: обмен данными между MQL и Python через заранее созданные функции. Это самый быстрый и надежный метод обмена данными. Нет затрат времени на синтаксический разбор и компиляцию кода Python, который появляется при использовании eval().
Имеется класс (актуальный код тут):
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()
Название класса неважно, потому что отражение функций идет через переменную __mql__
.
Также у функции pyEval(..., override_class)
аргумент override_class=true
, когда изменяется переменная __mql__
.
Пример:
PythonDLL_Example.mq5 и
PythonDLL_Example.py
Можно определить среду выполнения кода Python:
if globals().get('__PythonDLL__'):
print('run in MetaTrader')
elif __name__ == '__main__':
print('run as script')
При тестировании требуется “Разрешить импорт DLL” на глобальном уровне.
Поиск необходимой python3.dll происходит в следующем порядке:
Если ли python3.dll не найдена:
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 это не только python3.dll, но и его окружение, которое нужно настраивать. Самое популярное и простое решение это установить Anaconda. Есть еще Miniconda (минимум 200МБ), если четко знаешь, какие пакеты понадобятся при выполнении скрипта.
Python создавался как отдельное приложение и при встраемости есть проблемы, которые вряд ли когда-нибудь будут исправлены:
При активной консоли можно заметить вывод Py_FatalError(), пока она не исчезнет:
Fatal Python error: Py_Initialize: unable to load the file system codec
Ошибки компиляции и выполнения кода Python не отображаются автоматически на активной консоли. Но при использовании класса CPythonDLL ошибки отображаются в логе терминала.
Всегда есть только один экземпляр Питона для выполнения кода. Если несколько экспертов, индикаторов и скриптов будут одновременно использовать эту обертку Питона без синхронизации в одном MetaTrader, то результат не гарантируется. При тестировании такой проблемы нет.
Выделение памяти - долгая операция, но от объема запрошенной памяти это неслишком зависит. Быстрее будет заранее выделить один мегабайт под строку и использовать этот буффер несколько раз, нежели каждый раз запрашивать необходимый объем памяти.
При использовании модуля multiprocessing необходимо указывать абсолютный путь к файлу в __file__
и sys.argv
. Пример находится здесь.
Обертка создавалась с суб-интерпретаторами, но пришлось использовать простой GIL.
Суб-интерпретаторы не совместимы с популярными библиотеками для Питона.
issue37186, issue10915.
Но можно собрать эту обертку с PYTHONDLL_SUBINTERPRETERS
.
При запуске в терминале нескольких независимых экспертов, индикаторов и скриптов, использующих эту обертку, для каждого потока создается свой изолированный интерпретатор с помощью Py_NewInterpreter(). Но может возникнуть задержка при переключении потока, потому что в Python нет полноценного многопоточного выполнения, а есть global interpreter lock (GIL), который блокирует другие потоки при выполнении кода Python.
При тестировании всегда есть только один интерпретатор.
Официальная статья по созданию DLL.
Дополнение к статье:
Тип int в Python бесконечный:
int("9999999999999999999999999999999999999999999999", 10).bit_length() == 153
Типы в MQL:
long = 8 байт (64 бита) = -9 223 372 036 854 775 808 ... 9 223 372 036 854 775 807
ulong = 8 байт (64 бита) = 0 ... 18 446 744 073 709 551 615
CrashDumps:
%LOCALAPPDATA%\CrashDumps\