Группа пользователей MetaTrader 5 Python - краткое содержание - страница 12

 

Форум о трейдинге, автоматизированных торговых системах и тестировании торговых стратегий

MetaTrader 5 Python User Group - как использовать Python в Metatrader

Рашид Умаров, 2020.03.28 09:11

В справку добавлены описания 3 новых функций:

Кроме того, внесены изменения в описания многих функций по мере их доработки. Почти все примеры были переписаны с учетом новой функциональности. Однако примеры для следующих функций на сайте еще не обновлены, это произойдет чуть позже:


 

Насколько важно вызывать mt5.shutdown()?

Я полагаю, что это довольно важно, иначе это не было бы частью общепринятой практики. Но тогда почему он никогда не представлен в блоке try/finally? Если пользовательский код вызовет исключение, то mt5.shutdown не будет вызван. Другой проблемой является отсутствие пользовательских исключений в MT5 python. Я хотел бы предложить добавить контекстный менеджер в официальную библиотеку MT5, а также уникальное исключение, которое можно было бы перехватывать в блоке try. Пример:


Этот код устанавливает контекстный менеджер MT5-соединений и инициализирует MT5 connect при входе и выключает его при выходе, гарантируя, что функция mt5.shutdown() всегда вызывается.

if __name__ == "__main__":
    mt5_connection = mt5_connection_context(
        path=r"C:\Users\user\Desktop\MT5\terminal64.exe",
        portable=True,
        server="MetaQuotes-Demo",
        login=112878789,
        password="d183SD8",
        timeout=7_000,
        ensure_trade_enabled=True,
        logger=print,
    )

    with mt5_connection:
        x = 1 / 0  #  raises exception
        print(x)

Получается следующий результат:

Python <-> MT5 init: success
Traceback (most recent call last):
  File "C:/Users/user/AppData/Scripts/mt5py.py", line 69, in <module>
    x = 1 / 0  # raises exception
ZeroDivisionError: division by zero
Python <-> MT5 shutdown: success

Вот код менеджера контекста:

import MetaTrader5 as mt5
from contextlib import contextmanager


class Mt5Error(Exception):
    pass


@contextmanager
def mt5_connection_context(*,
    path: str = None,
    portable: bool = None,
    server: str = None,
    login: int = None,
    password: str = None,
    timeout: int = None,
    ensure_trade_enabled: bool = False,
    logger: callable = None,
    message: callable = None
):
    logger = logger or (lambda m: None)
    message = message or (lambda m: "Python <-> MT5 {}: {}".format(*m.split()))
    try:
        mt5_keys = "path portable server login password timeout".split()
        mt5_kwargs = {k: v for k, v in locals().items() if v is not None and k in mt5_keys}
        if not mt5.initialize(**mt5_kwargs):
            reason = message("init failed") + " ({}) {}".format(*mt5.last_error())
            logger(reason)
            raise Mt5Error(reason)
        else:
            logger(message("init success"))
        if ensure_trade_enabled and not mt5.terminal_info().trade_allowed:
            logger(reason:="Terminal auto-trade is disabled")
            raise Mt5Error(reason)
        yield
    finally:
        mt5.shutdown()
        logger(message("shutdown success"))
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
  • www.mql5.com
//| Expert initialization function                                   | //| Expert deinitialization function                                 | //| Expert tick function                                             | //| test1                                                            |...
 
nicholi shen:


Этот код устанавливает менеджер контекста соединения MT5, инициализирует его при входе и выключает при выходе, обеспечивая постоянный вызов функции mt5.shutdown().

Это приводит к следующему результату:

Вот код менеджера контекста:

Хороший пример, я бы посоветовал devops включить его в документацию.

 
nicholi shen:

Насколько важно вызывать mt5.shutdown()?

MetaTrader5 - в условиях реализации ограниченный ресурс.

На хосте может быть запущено несколько терминалов. Чтобы указать, какой именно запущен - используется path-переменная.

initialize(
   path                      // path to the MetaTrader 5 terminal EXE file
   timeout=TIMEOUT,          // timeout
   login=LOGIN,              // account number
   password="PASSWORD",      // password
   server="SERVER"           // server name as it is specified in the terminal
   )

Точнее, первый, неименованный параметр.

Если вам нужно переподключиться - сменить счет или терминал, необходимо выполнить mt5.shutdown()

 
nicholi shen:


Вот код менеджера контекста:

import MetaTrader5 as mt5
from contextlib import contextmanager


class Mt5Error(Exception):
    pass

MetaTrader5 - Исключение не обрабатывается в классической концепции python, необходимо использовать last_error()

https://www.mql5.com/en/docs/integration/python_metatrader5/mt5lasterror_py

Documentation on MQL5: Integration / MetaTrader for Python / last_error
Documentation on MQL5: Integration / MetaTrader for Python / last_error
  • www.mql5.com
allows obtaining an error code in case of a failed execution of a MetaTrader 5 library function. It is similar to GetLastError(). However, it applies its own error codes. Possible values:
 
Дмитрий Прокопьев:

MetaTrader5 - в условиях реализации ограниченный ресурс.

На хосте может быть запущено несколько терминалов. Чтобы указать, какой из них запущен - используется переменная path.

Точнее, первый, безымянный параметр.

Если вам нужно переподключиться - сменить учетную запись или терминал, необходимо выполнить mt5.shutdown()

То есть, если я правильно вас понял, нельзя иметь более одного одновременного терминального подключения?

 

Я обнаружил проблему с обработкой **kwargs в некоторых функциях, которые могут вызываться как с аргументами, так и без них. Пожалуйста, обратитесь к этим модульным тестам pytest.

Ожидаемое поведение:

Все функции должны быть способны исключать **kwargs и возвращать эквивалент вызова без аргументов:

all_positions = mt5.positions_get()
#should return the same as
all_positions = mt5.positions_get(**{})

Это нежелательное обходное решение

positions_get = lambda **kwargs: mt5.positions_get(**kwargs) if kwargs else mt5.positions_get()

pytest

import MetaTrader5 as mt5
import pytest


@pytest.fixture(autouse=True)
def mt5_init_shutdown():
    try:
        mt5.initialize()
        yield
    finally:
        mt5.shutdown()


def make_kwargs_func(func):
    return lambda **kwargs: func(**kwargs)


def test_initialize(): #PASSED
    initialize = make_kwargs_func(mt5.initialize)
    assert isinstance(mt5.initialize(), bool)
    assert isinstance(initialize(), bool)


def test_symbols_get_without_args(): #PASSED
    symbols_get = make_kwargs_func(mt5.symbols_get)
    assert mt5.symbols_get() is not None
    assert symbols_get() is not None


def test_orders_get_without_args(): #FAILED
    orders_get = make_kwargs_func(mt5.orders_get)
    assert mt5.orders_get() is not None #PASSED
    assert orders_get() is not None #FAILED


def test_positions_get_without_args(): #FAILED
    positions_get = make_kwargs_func(mt5.positions_get)
    assert mt5.positions_get() is not None #PASSED
    assert positions_get() is not None #FAILED


if __name__ == "__main__":
    pass
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
Documentation on MQL5: Constants, Enumerations and Structures / Named Constants / Predefined Macro Substitutions
  • www.mql5.com
//| Expert initialization function                                   | //| Expert deinitialization function                                 | //| Expert tick function                                             | //| test1                                                            |...
 

Привет,

Я новичок в MetaTrader5. Я решил начать программировать в этой области и ищу способ интегрировать Python3 в него, чтобы я мог извлекать исторические данные в качестве первой программы HelloWorld.

Я также использую Debian 10 Buster. Я подготовил все пакеты в соответствии с инструкцией здесь, но, к сожалению, я не могу импортировать MetaTrader5 и сталкиваюсь с этой ошибкой:

In [1]: import MetaTrader5 as mt5
Error:

----> 1 import MetaTrader5

~/mt5/env/lib/python3.7/site-packages/MetaTrader5/__init__.py in <module>
    250
    251 # import C methods to our module
--> 252 from ._core import *
    253
    254 # internal order send

ModuleNotFoundError: No module named 'MetaTrader5._core'

Кто-нибудь знает, как преодолеть эту ошибку?

Я также успешно установил пакет:

(env) [mt5] pip3 install MetaTrader5                                           
Requirement already satisfied: MetaTrader5 in ./env/lib/python3.7/site-packages (5.0.29)
Requirement already satisfied: numpy>=1.7 in ./env/lib/python3.7/site-packages (from MetaTrader5) (1.18.2

Я установил MetaTrader5 через pip3, но эта ошибка заставила меня удалить его и переустановить с помощью самого файла колеса MetaTrader5, но та же ошибка. Я проверил файл MetaTrader5 .whl на pypi.org и обнаружил, что в имени файла присутствует название win_amd64 или win32. Это заставило меня переименовать файл в соответствии с архитектурой моей системы, но после успешной установки (как и раньше) снова появляется та же ошибка. Неужели этот пакет был разработан только для Windows? Если да, то есть ли другой способ развернуть этот пакет в GNU/Linux.

Спасибо
 
jeanjacques88:

Этот пакет был разработан только для Windows?


Да. Для его работы требуется запущенный терминал MT5, который работает только под Windows.

 
nicholi shen:

Итак, если я правильно вас понял, невозможно иметь более одного одновременного терминального соединения?

Да, 1 терминал - 1 соединение.

В моей задаче требовалось использовать более 1 терминального соединения, и в коде я использовал threading.RLock() в качестве семафора :)

Ничего лучше я не придумал...

Причина обращения: