MetaTrader 5 Python User Group - como usar o Python no Metatrader - página 60

 
A versão 5.0.30 foi lançada
 
MetaQuotes:
A versão 5.0.30 foi lançada

Obrigado!

 
MetaTrader 5 Python User Group - the summary
MetaTrader 5 Python User Group - the summary
  • 2020.03.30
  • www.mql5.com
The Main Study MetaTrader Python online documentation Python Releases for Windows - website MetaTrader5 : Python Package - website...
 
A versão 5.0.31 foi lançada
 
MetaQuotes:
A versão 5.0.31 foi lançada
Alguma mudança importante?
 
MetaTrader 5 Python User Group - the summary
MetaTrader 5 Python User Group - the summary
  • 2020.04.02
  • www.mql5.com
The Main Study MetaTrader Python online documentation Python Releases for Windows - website MetaTrader5 : Python Package - website...
 
Kiran Sawant:
Alguma mudança importante?

Não, apenas algumas correcções para https://www.mql5.com/en/forum/306742/page13#comment_15699363

MetaTrader 5 Python User Group - the summary
MetaTrader 5 Python User Group - the summary
  • 2020.03.30
  • www.mql5.com
The Main Study MetaTrader Python online documentation Python Releases for Windows - website MetaTrader5 : Python Package - website...
 
pymt5adapter
pymt5adapter
  • 2020.04.02
  • pypi.org
is a wrapper and drop-in replacement for the python package by MetaQuotes. The API functions return the same values from the functions, but adds the following functionality: Typing hinting has been added to all functions and return objects for linting and IDE integration. Intellisense will now work now matter how nested the objects are...
 
Dmitry Prokopyev :

Obrigado, este exemplo que eu vi, funciona.

Estou um pouco mais a pensar noutra coisa.


posições_get - a lista de TradePosition ser-me-á devolvida. Em princípio, é possível introduzir pandas e trabalhar bem.

Mas tudo não está limitado a um pandas, e se precisar de obter algo do género:

tem de compor de alguma forma, pandas ou para... de alguma forma, muitos movimentos extra do corpo.

Tornou-se muito mais conveniente com _asdict (), se aquele que escreve não é um programa MQL5, mas digamos um pythonist ... ou um dataynetist, então a lista / ditado é

Os elementos básicos de python, muitos estão a construir uma transferência de dados em lista / ditado.

Os tuplos são usados com demasiada frequência e muito, mas apenas se for necessário controlar rigorosamente os tipos de dados que se movem nele.

e também pendurar um manipulador de erros, se não for utilizado ou atribuído correctamente. Bem, em algum lugar ... :) Posso estar enganado.

Ok, concordo completamente com este sentimento agora, e também penso que a devolução de dados como túbulos nomeados em vez de dicionários é demasiado opinante para um API. Tive recentemente problemas com este desenho, porque é impossível fazer picles com os nomes dos picles. Considere o seguinte guião de copiadora de comércio concorrente. Notar o incómodo de converter todos os túbulos nomeados em dicionários para fazer uso do ProcessPoolExectutor?


trade_copier.py

import json
import time
from concurrent.futures.process import ProcessPoolExecutor
from typing import List

import pymt5adapter as mt5
from pymt5adapter.order import Order
from pymt5adapter.symbol import Symbol


def result_to_dict(result):
    res = result._asdict()
    res['request'] = res['request']._asdict()
    return res


def p2d(positions):
    return [p._asdict() for p in positions]


def get_position_map(positions: List[dict]):
    position_map = {}
    for p in positions:
        position_map.setdefault(p['symbol'], {}).setdefault('positions', []).append(p)
        v = -p['volume'] if p['type'] else p['volume']
        inner = position_map[p['symbol']]
        inner['net_volume'] = inner.get('net_volume', 0.0) + v
    return position_map


def match_positions(terminal, positions):
    result_positions = []
    incoming = get_position_map(positions)
    with mt5.connected(**terminal):
        my_pos_map = get_position_map(p2d(mt5.positions_get()))
        for symbol, d in incoming.items():
            if symbol not in my_pos_map:
                volume = d['net_volume']
            else:
                volume = d['net_volume'] - my_pos_map[symbol]['net_volume']
            if volume == 0.0:
                continue
            symbol = Symbol(symbol)
            order = Order.as_buy() if volume > 0.0 else Order.as_sell()
            order(volume=abs(volume), symbol=symbol.name)
            for _ in range(5):
                symbol.refresh_rates()
                price = symbol.ask if volume > 0.0 else symbol.bid
                res = order(price=price).send()
                if res.retcode == mt5.TRADE_RETCODE_DONE:
                    result_positions.append(result_to_dict(res))
                    break
    return result_positions


def main():
    with open('terminal_config.json') as f:
        terminals = json.load(f)
    master = terminals['master']
    slaves = terminals['slaves']
    with mt5.connected(**master), ProcessPoolExecutor() as pool:
        while True:
            positions = [p2d(mt5.positions_get())] * len(slaves)
            results = list(pool.map(match_positions, slaves, positions))
            for result in results:
                for sub in result:
                    if sub:
                        print(sub)
            time.sleep(0.01)


if __name__ == "__main__":
    main()

terminal_config.json

{
  "master": {
    "path":"C:\\Users\\nicho\\Desktop\\terminal1\\terminal64.exe",
    "portable": true
  },
  "slaves": [
    {
      "path": "C:\\Users\\nicho\\Desktop\\terminal2\\terminal64.exe",
      "portable": true
    },{
      "path": "C:\\Users\\nicho\\Desktop\\terminal3\\terminal64.exe",
      "portable": true
    }
  ]
}

É especialmente difícil quando existem túbulos nomeados dentro de um túple nomeado, como é o caso com OrderSendResult.request. Assim, é necessário criar funções de conversão únicas apenas para as converter de volta a tipos de dados picleáveis. Poderia correr tudo através de uma função recursiva para a converter de volta a tipos de dados nativos, mas isto é computacionalmente caro.

def as_dict(data: Any):
    try:
        return as_dict(data._asdict())
    except AttributeError:
        T = type(data)
        if T is list or T is tuple:
            return T(as_dict(i) for i in data)
        if T is dict:
            return {k: as_dict(v) for k, v in data.items()}
        return data
 

Falha na instalação

----- Установка "pymt5adapter" -----
ERROR: Could not find a version that satisfies the requirement pymt5adapter (from versions: none)
ERROR: No matching distribution found for pymt5adapter
----- Не удалось установить "pymt5adapter". -----

----- Установка "pymt5adapter==0.1.11" -----
ERROR: Could not find a version that satisfies the requirement pymt5adapter==0.1.11 (from versions: none)
ERROR: No matching distribution found for pymt5adapter==0.1.11
----- Не удалось установить "pymt5adapter==0.1.11". -----

----- Установка "pymt5adapter" -----
ERROR: Could not find a version that satisfies the requirement pymt5adapter (from versions: none)
ERROR: No matching distribution found for pymt5adapter
----- Не удалось установить "pymt5adapter". -----

Win10, Py3.6.10 e WinPy3.7.7.