MetaTrader 5 Python User Group - the summary - page 14

 

The copy_tick functions are not working now. last_error() returns (1, "success"), however the functions only return empty arrays. 

Terminal version: 2375

Python package version: 5.0.31

Test to reproduce:

def test_copy_ticks_range():
    from datetime import datetime, timedelta
    time_to = datetime.utcnow()
    time_from = time_to - timedelta(minutes=3)
    ticks = mt5.copy_ticks_range("EPM20", time_from, time_to, mt5.COPY_TICKS_ALL)
    assert mt5.last_error()[0] == mt5.RES_S_OK   #PASS
    assert len(ticks) > 0                        #FAIL
 

Have you seen CopyTicksRange ?

Note

The CopyTicks() function allows requesting and analyzing all received ticks. The first call of CopyTicks() initiates synchronization of the symbol's tick database stored on the hard disk. If the local database does not provide all the requested ticks, then missing ticks will be automatically downloaded from the trade server. Ticks beginning with the from date specified in CopyTicks() till the current moment will be synchronized. After that, all ticks arriving for this symbol will be added to the tick database thus keeping it in the synchronized state.


Try to call one more time later

Documentation on MQL5: Timeseries and Indicators Access / CopyTicksRange
Documentation on MQL5: Timeseries and Indicators Access / CopyTicksRange
  • www.mql5.com
[out] MqlTick static or dynamic array for receiving ticks. If the static array cannot hold all the ticks from the requested time interval, the maximum possible amount of ticks is received. In this case, the function generates the error ERR_HISTORY_SMALL_BUFFER (4407) . ERR_NOT_ENOUGH_MEMORY – insufficient memory for receiving a history from...
 
nicholi shen:

Bug report - package version 5.0.30


1. The functions [history_deals_get, history_deals_total, history_orders_get, history_orders_total, ...all of the copy_funcs] all have a fundamental flaw, and that is the parameter "from". From is a reserved keyword in python and cannot be used as a parameter name. This prevents the creation of pythonic adapter functions due to the naming conflict. The following will not even compile:


5. history_deals_get (and perhaps other functions) are inconsistent with their return type. Some functions return None when there is no data to return and other functions return an empty tuple. These functions all need to be consistent. They should all return the same object in the case of no data -- instead of some returning None and some returning an empty tuple. 

1. We don't have "from" named parameter in this functions, all range parameters are unnamed.

5. history_deals_get, history_orders_get are different from orders_get, positions_get, they don't have default parameters and they can't called with empty parameters. They fail in this situation and return Null.

 
Rashid Umarov:

Have you seen CopyTicksRange ?


Try to call one more time later

It's still not working for me. Any other suggestions?

Tested with:

def test_copy_ticks_range(connected):
    from datetime import datetime, timedelta
    import time
    time_to = datetime.utcnow()
    time_from = time_to - timedelta(minutes=3)
    with connected:
        for i in range(20):
            ticks = mt5.copy_ticks_range("EPM20", time_from, time_to, mt5.COPY_TICKS_ALL)
            if ticks:
                break
            time.sleep(1)
        assert mt5.last_error()[0] == mt5.RES_S_OK
        assert len(ticks) > 0
 
nicholi shen:

It's still not working for me. Any other suggestions?

Tested with:

What "EPM20" symbol? Does it have ticks in 3min?

We checked on standard symbols, all works normally:

import MetaTrader5 as mt5

def test_copy_ticks_range():
    from datetime import datetime, timedelta
    import time
    time_to = datetime.utcnow()
    time_from = time_to - timedelta(minutes=3)
    for i in range(20):
        ticks = mt5.copy_ticks_range("USDJPY", time_from, time_to, mt5.COPY_TICKS_ALL)
        if ticks is not None:
            break
        time.sleep(1)
    print(mt5.last_error())
    print(len(ticks))
    assert mt5.last_error()[0] == mt5.RES_S_OK
    assert len(ticks) > 0


mt5.initialize()
test_copy_ticks_range()
 

Ok. I found the reason it wasn't working, and I'm curious to see why.... 

The issue was actually with this line of code. 

time_to = datetime.utcnow()

Where my broker is on UTC time and I am on EST. The fix was to use 

time_to = datetime.now()

...but I'm really not sure how or why this works. Any ideas?


1. We don't have "from" named parameter in this functions, all range parameters are unnamed.

5. history_deals_gethistory_orders_get are different from orders_getpositions_get, they don't have default parameters and they can't called with empty parameters. They fail in this situation and return Null.


I realized that after looking at the package and realizing that it's a limitation of the C-functions. I am making a drop-in adapter package to make all the core API functions capable of handling keyword args. Have you considered including a stub file with type-hinting?

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                                                            |...
 

I made a pythonic wrapper to act as a drop-in replacement for the MetaTrader5 package. This runs python on top of the MetaTrader5 package and makes the API interface a bit more pythonic. 

Features include:

  • Type hinting on everything! Intellisence will work no matter how nested your objects are
  • Docstrings add to the functions themself so you can reference docs on the fly in the IDE
  • Testing
  • A new context manager to manage the API context and modify the API behavior.
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...
 

Is it too late to request that the API be modified to return dict objects instead of namedtuple objects? All of the namedtuple objects currently returned from the API cannot be pickled which breaks multi-processing. It is therefore necessary to run all data returned from the API through a recursive function that touches every point of data in order to ensure that all nested namedtuples are converted back to dictionaries which is highly inefficient. 

def as_dict_all(data: Any):
    """Convert all nested data returns to native python (pickleable) data structures. 
    Example: List[OrderSendResult] -> List[dict]

    :param data: Any API returned result from the MetaTrader5 API
    :return:
    """
    try:
        return as_dict_all(data._asdict())
    except AttributeError:
        T = type(data)
        if T is tuple or T is list:
            return T(as_dict_all(i) for i in data)
        if T is dict:
            return {k: as_dict_all(v) for k, v in data.items()}
        return data
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                                                            |...
 
Would it also be possible to pass the symbol name as a command-line arg when evoking a python script by dropping it on a chart? This way you can get the chart symbol from sys.argv[1]
 

Hello,


I could not install MetaTrader5 by:

  pip install MetaTrader5


I got the following error:

ERROR: Could not find a version that satisfies the requirement MetaTrader5 (from versions: none)

ERROR: No matching distribution found for MetaTrader5


Knowing that I am on MAC laptop and I have Python 3.7.6


Thanks in advance to provide me the solution

Reason: