MetaTrader 5 Python User Group - Come usare Python in Metatrader - pagina 60

 
È uscita la versione 5.0.30
 
MetaQuotes:
È uscita la versione 5.0.30

Grazie!

 
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...
 
È uscita la versione 5.0.31
 
MetaQuotes:
È uscita la versione 5.0.31
Qualche cambiamento 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:
Qualche cambiamento importante?

No, solo alcune correzioni per 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 :

Grazie, questo esempio che ho visto, funziona.

Sono un po' su qualcos'altro.


positions_get - la lista delle TradePosition mi sarà restituita. In linea di principio, si può buttare dentro i panda e lavorare bene.

Ma tutto non è limitato a un solo panda, e se avete bisogno di ottenere qualcosa come:

devi in qualche modo comporre, panda o per... in qualche modo un sacco di movimenti extra del corpo.

È diventato molto più conveniente con _asdict (), se chi scrive non è un prog MQL5, ma diciamo un pitonista... o un datasynetist, allora list / dict è

Gli elementi di base di python, molti stanno costruendo un trasferimento di dati su lista / dict.

Le tuple sono usate, troppo spesso e molto, ma solo se avete bisogno di controllare strettamente i tipi di dati che vi si muovono dentro.

e blocca anche un gestore di errori, se non utilizzato o assegnato correttamente. Beh, da qualche parte ... :) Potrei sbagliarmi.

Ok, sono completamente d'accordo con questo sentimento ora, e penso anche che restituire dati come namedtuples invece di dizionari sia troppo opinionistico per un'API. Recentemente ho avuto problemi con questo progetto perché è impossibile fare il pickle di namedtuples. Si consideri il seguente script di copiatore commerciale concorrente. Notate quanto sia una seccatura convertire tutte le namedtuples in dizionari per fare uso del 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()

terminale_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
    }
  ]
}

È particolarmente difficile quando ci sono namedtuple annidate dentro namedtuple, come nel caso di OrderSendResult.request. Quindi dovete creare funzioni di conversione uniche solo per convertirli di nuovo in tipi di dati decifrabili. Si potrebbe eseguire tutto attraverso una funzione ricorsiva per convertirlo di nuovo in tipi di dati nativi, ma questo è computazionalmente costoso.

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
 

Impossibile installare

----- Установка "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.

Motivazione: