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

 
nicholi shen:

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

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

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

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

pytest

это должно быть написано в главном потоке... я скопировал

 
Дмитрий Прокопьев:

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

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

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

Неправильно. К одному терминалу (скорее к брокеру/счету) может быть много подключений. Или я неправильно понял?

 
Documentation on MQL5: Integration / MetaTrader for Python / order_calc_margin
Documentation on MQL5: Integration / MetaTrader for Python / order_calc_margin
  • www.mql5.com
The function allows estimating the margin necessary for a specified order type on the current account and in the current market environment without considering the current pending orders and open positions. The function is similar to OrderCalcMargin...
 
alkam_ai:
pip install MetaTrader5 не работает даже после обновления до python 3.8

Работает. Я использую 3.82, и python и дополнительные пакеты работают нормально.

Я не уверен, что вы занимаетесь разработкой, если да, то, пожалуйста, не обращайте внимания на мою неосведомленность о вас. Если нет, то посмотрите на https://www.mql5.com/en/docs/integration/python_metatrader5 и https://datatofish.com/upgrade-pip/.

Обратите внимание, что вы должны использовать CMD от имени администратора. Вы должны найти приложение CMD и щелкнуть правой кнопкой мыши >Запустить от имени администратора.

Pip является обязательным условием перед продолжением всех шагов. Вы же не хотите собирать whl с устаревшим Pip.

Все эти шаги необходимо выполнять каждый раз, когда вы обновляете Python.


Я бы рекомендовал использовать PyCharm в качестве IDE для Python вне MT5.


Ничего не установится, если вы не запустите CMD от имени администратора.

1. Установите последние пакеты разработчика в MT5 MetaEditor в разделе опций.

2. Убедитесь, что каталог Python - это фактический путь к 3.8, а не путь к MT5 python. (возможно, вам придется скопировать и вставить путь).

3. Убедитесь, что при установке 3.8 были установлены все флажки?

4. Вам потребуется несколько гигабайт памяти на жестком диске для всех инструментов разработчика.


Приведенный ниже тестовый скрипт модифицирован из ссылки python_metatrader5. Он будет запущен, если вы выполните все шаги по установке разработчика


# Copyright 2019, MetaQuotes Software Corp.

# https://www.mql5.com


from datetime import datetime

import matplotlib.pyplot as plt

import pandas as pd

from pandas.plotting import register_matplotlib_converters

register_matplotlib_converters()

import MetaTrader5 as mt5

# ваш код здесь


# подключаемся к MetaTrader 5

if not mt5.initialize():

print("initialize() failed")

mt5.shutdown()

# запросить статус и параметры соединения

print(mt5.terminal_info())

# получить данные о версии MetaTrader 5

print(mt5.version())


# выключить соединение с MetaTrader 5

mt5.shutdown()

Documentation on MQL5: Integration / MetaTrader for Python
Documentation on MQL5: Integration / MetaTrader for Python
  • www.mql5.com
Python is a modern high-level programming language for developing scripts and applications. It contains multiple libraries for machine learning, process automation, as well as data analysis and visualization. MetaTrader package for Python is designed...
 
Azeem Hussein:

Можно ли отправить запрос на установку стоп-лосса по существующему ордеру?

У меня есть код, который работает в моей python ea, которая может устанавливать и открывать сделки. однако мне нужно знать синтаксис для mt5.Buy(), mt5.Sell(), и какие значения они принимают. например, как я могу установить стоп-лосс и значение тейк-профита при отправке покупки? или продажи?

Buy(), Sell(), Close() - это просто обертки для oreder_send() в модуле __init__.py:

#  internal order send
def _RawOrder(order_type, symbol, volume, price, comment=None, ticket=None):
    order = {
      "action":    TRADE_ACTION_DEAL,
      "symbol":    symbol,
      "volume":    volume,
      "type":      order_type,
      "price":     price,
      "deviation": 10,
    }
    if comment != None:
        order["comment"] = comment
    if ticket != None:
        order["position"] = ticket
    r = order_send(order)
    return r

#  Close all specific orders
def Close(symbol, *, comment=None, ticket=None):
    if ticket != None:
        positions = positions_get(ticket=ticket)
    else:
        positions = positions_get(symbol=symbol)

    tried = 0
    done = 0

    for pos in positions:
        #  process only simple buy, sell
        if pos.type == ORDER_TYPE_BUY or pos.type == ORDER_TYPE_SELL:
            tried += 1
            for tries in range(10):
                info = symbol_info_tick(symbol)
                if pos.type == ORDER_TYPE_BUY:
                    r = _RawOrder(ORDER_TYPE_SELL, symbol, pos.volume, info.bid, comment, pos.ticket)
                else:
                    r = _RawOrder(ORDER_TYPE_BUY, symbol, pos.volume, info.ask, comment, pos.ticket)
                #  check results
                if r.retcode != TRADE_RETCODE_REQUOTE and r.retcode != TRADE_RETCODE_PRICE_OFF:
                    if r.retcode == TRADE_RETCODE_DONE:
                        done += 1
                    break
    
    if done > 0:
        if done == tried:
            return True
        else:
            return "Partially"
    return False

#  Buy order                
def Buy(symbol, volume, price=None, *, comment=None, ticket=None):
    #  with direct call
    if price != None:
        return _RawOrder(ORDER_TYPE_BUY, symbol, volume, price, comment, ticket)
    #  no price, we try several times with current price
    for tries in range(10):
        info = symbol_info_tick(symbol)
        r = _RawOrder(ORDER_TYPE_BUY, symbol, volume, info.ask, comment, ticket)
        if r.retcode != TRADE_RETCODE_REQUOTE and r.retcode != TRADE_RETCODE_PRICE_OFF:
            break
    return r

#  Sell order
def Sell(symbol, volume, price=None, *, comment=None, ticket=None):
    #  with direct call
    if price != None:
        return _RawOrder(ORDER_TYPE_SELL, symbol, volume, price, comment, ticket)
    #  no price, we try several times with current price
    for tries in range(10):
        info = symbol_info_tick(symbol)
        r = _RawOrder(ORDER_TYPE_SELL, symbol, volume, info.bid, comment, ticket)
        if r.retcode != TRADE_RETCODE_REQUOTE and r.retcode != TRADE_RETCODE_PRICE_OFF:
            break
    return r
 
Vladimir Perervenko:

Неверно. К одному терминалу (скорее к брокеру/счету) может быть много подключений. Или я неправильно понял?

MT5 можно использовать в портативном режиме

https://www.metatrader5.com/en/terminal/help/start_advanced/start

2 экземпляра MT5 - 2 брокера/счета, но 1 библиотека MetaTrader5, 1 подключение за раз ...

Platform Start - For Advanced Users - MetaTrader 5 Help
Platform Start - For Advanced Users - MetaTrader 5 Help
  • www.metatrader5.com
After installation, a group of programs of the trading platform is added to the Start menu, and the program shortcut is created on the desktop. Use them to run the platform. Two copies of the platform cannot run from the same directory. If you need to run multiple copies at the same time, install the appropriate number of programs in different...
 

Сообщение об ошибке - версия пакета 5.0.30


1. Функции[history_deals_get, history_deals_total, history_orders_get, history_orders_total, ... все copy_funcs] имеют фундаментальный недостаток, и это параметр "from". From является зарезервированным ключевым словом в python и не может быть использован в качестве имени параметра. Это препятствует созданию питоновских функций-адаптеров из-за конфликта имен. Следующие функции даже не будут компилироваться:

def my_history_orders_total(from:datetime, to:datetime):
    return mt5.history_orders_total(from=from, to=to)

Имена параметров должны быть изменены на те, которые не конфликтуют с python и являются более описательными. Пример:

def my_history_orders_total(datetime_from:datetime, datetime_to:datetime, **kwargs):
    return mt5.history_orders_total(datetime_from=datetime_from, datetime_to=datetime_to)

2. Константы mt5.RES_* заданы как кортежи вместо <int>. Кто-то забыл убрать запятые после выражений в модуле MetaTrader5.__init__.py. Вот как исправить ошибку:

RES_S_OK                            =1, # <-- REMOVE COMMA
RES_E_FAIL                          =-1,# <-- REMOVE COMMA
...					# etc

Тест

def test_last_error_res_codes():
    defined_error_codes = [getattr(mt5, name) for name in dir(mt5) if name.startswith('RES_')]
    for code in defined_error_codes:
        assert isinstance(code, int)


3. last_error() должна возвращать кортеж, а не список, чтобы оставаться совместимой с API.

Тест

def test_last_error():
    defined_error_codes = [getattr(mt5, name) for name in dir(mt5) if name.startswith('RES_')]
    error = mt5.last_error()
    assert isinstance(error, tuple)
    assert len(error) == 2
    code, description = error
    assert code in defined_error_codes
    assert isinstance(code, int)
    assert isinstance(description, str)

4. В документации к version() нужно изменить тип для "build-number" с "string" на "int".


5. history_deals_get (и, возможно, другие функции) не согласуются со своим типом возврата. Некоторые функции возвращают None, когда нет данных для возврата, а другие возвращают пустой кортеж. Все эти функции должны быть последовательными. Все они должны возвращать один и тот же объект в случае отсутствия данных - вместо того, чтобы одни возвращали None , а другие - пустой кортеж.

Тест

def test_consistency_for_empty_data_returns():
    def all_same_return_types(results):
        g = itertools.groupby(results, key=lambda v: type(v))
        return next(g, True) and not next(g, False)

    funcs = (mt5.positions_get, mt5.orders_get, mt5.history_orders_get, mt5.history_deals_get,)
    results = [f(ticket=0) for f in funcs]
    assert all_same_return_types(results)


Пожалуйста, посмотрите все приложенные pytest unittests.

Файлы:
 
Выпущена версия 5.0.31
 
Дмитрий Прокопьев:
Выпущена версия 5.0.31

Спасибо за быстрый ответ! Все тесты пройдены, за исключением того, который проверяет различные типы возврата. Есть идеи по поводу изменения ключевого слова "from" в C-функциях?

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