nicholishen / pymt5adapter---DEPRECATED

A drop-in pythonic adapter for the MetaTrader5 package to enhance usability.
BSD 2-Clause "Simplified" License
86 stars 31 forks source link

Bug in the python api #3

Closed ViktorKnoben closed 4 years ago

ViktorKnoben commented 4 years ago

Hi,

I've found a bug in both your adapter as well as the python api (native). But given the lack of reactions I'm desperately hoping you know the solution:

I get the error that my filling mode is unsupported despite using their own example from ttps://www.mql5.com/en/docs/integration/python_metatrader5/mt5ordersend_py.

print("MetaTrader5 package author: ",mt5.__author__)
print("MetaTrader5 package version: ",mt5.__version__)

# establish connection to MetaTrader 5 terminal
mt5.initialize(login=<this has my login number>, server="XM.COM-MT5",password="<this has my pass>")

# get account currency
account_currency=mt5.account_info().currency
print("Account сurrency:",account_currency)

# prepare the request structure
symbol="USDJPY"
symbol_info = mt5.symbol_info(symbol)
if symbol_info is None:
    print(symbol, "not found, can not call order_check()")
    mt5.shutdown()
    quit()

# if the symbol is unavailable in MarketWatch, add it
if not symbol_info.visible:
    print(symbol, "is not visible, trying to switch on")
    if not mt5.symbol_select(symbol,True):
        print("symbol_select({}}) failed, exit",symbol)
        mt5.shutdown()
        quit()

# prepare the request
point=mt5.symbol_info(symbol).point
request = {
    "action": mt5.TRADE_ACTION_DEAL,
    "symbol": symbol,
    "volume": 1.0,
    "type": mt5.ORDER_TYPE_BUY,
    "price": mt5.symbol_info_tick(symbol).ask,
    "sl": mt5.symbol_info_tick(symbol).ask-100*point,
    "tp": mt5.symbol_info_tick(symbol).ask+100*point,
    "deviation": 10,
    "magic": 234000,
    "comment": "python script",
    "type_time": mt5.ORDER_TIME_GTC,
#    "type_filling": mt5.ORDER_FILLING_RETURN,
}

# perform the check and display the result 'as is'
result = mt5.order_check(request)
print(result);
# request the result as a dictionary and display it element by element
result_dict=result._asdict()
for field in result_dict.keys():
    print("   {}={}".format(field,result_dict[field]))
    # if this is a trading request structure, display it element by element as well
    if field=="request":
        traderequest_dict=result_dict[field]._asdict()
        for tradereq_filed in traderequest_dict:
            print("       traderequest: {}={}".format(tradereq_filed,traderequest_dict[tradereq_filed]))

# shut down connection to the MetaTrader 5 terminal
mt5.shutdown()

The result is:

MetaTrader5 package author:  MetaQuotes Software Corp.
MetaTrader5 package version:  5.0.33
Account сurrency: EUR
OrderCheckResult(retcode=10030, balance=0.0, equity=0.0, profit=0.0, margin=0.0, margin_free=0.0, margin_level=0.0, comment='Unsupported filling mode', request=TradeRequest(action=1, magic=234000, order=0, symbol='USDJPY', volume=1.0, price=107.155, stoplimit=0.0, sl=107.055, tp=107.255, deviation=10, type=0, type_filling=0, type_time=0, expiration=0, comment='python script', position=0, position_by=0))
   retcode=10030
   balance=0.0
   equity=0.0
   profit=0.0
   margin=0.0
   margin_free=0.0
   margin_level=0.0
   comment=Unsupported filling mode
   request=TradeRequest(action=1, magic=234000, order=0, symbol='USDJPY', volume=1.0, price=107.155, stoplimit=0.0, sl=107.055, tp=107.255, deviation=10, type=0, type_filling=0, type_time=0, expiration=0, comment='python script', position=0, position_by=0)
       traderequest: action=1
       traderequest: magic=234000
       traderequest: order=0
       traderequest: symbol=USDJPY
       traderequest: volume=1.0
       traderequest: price=107.155
       traderequest: stoplimit=0.0
       traderequest: sl=107.055
       traderequest: tp=107.255
       traderequest: deviation=10
       traderequest: type=0
       traderequest: type_filling=0
       traderequest: type_time=0
       traderequest: expiration=0
       traderequest: comment=python script
       traderequest: position=0
       traderequest: position_by=0
True

I find it very strange and makes me second guess the documentation or I've found a bug. Though to be honest I'm hoping I made a beginners mistake. This issue occurs for all combinations of type_filling,type_time,type and action. I know this as each represents an integer and by abusing loops I've tested all possible combinations, none worked.

Some additional information:

Algo trading is on No exceptions are listed The following is the result of mt5.account_info()

AccountInfo(login=XXXXXX, trade_mode=0, leverage=30, limit_orders=200, margin_so_mode=0, trade_allowed=True, trade_expert=True, margin_mode=2, currency_digits=2, fifo_close=False, balance=1001.61, credit=0.0, profit=0.0, equity=1001.61, margin=0.0, margin_free=1001.61, margin_level=0.0, margin_so_call=100.0, margin_so_so=50.0, margin_initial=0.0, margin_maintenance=0.0, assets=0.0, liabilities=0.0, commission_blocked=0.0, name='ViktorPython', server='XM.COM-MT5', currency='EUR', ...)

and the result of mt5.terminal_info()

TerminalInfo(community_account=False, community_connection=False, connected=True, dlls_allowed=False, trade_allowed=True, tradeapi_disabled=False, email_enabled=False, ftp_enabled=False, notifications_enabled=False, mqid=False, build=2489, maxbars=100000, codepage=1252, ping_last=23347, community_balance=0.0, retransmission=0.10604453870625664, company='Trading Point Of Financial Instruments Ltd', name='XM MT5', language='Dutch', path='C:\\Program Files\\XM MT5', ...)

And last but not least what an amazing initiative to improve their code. When I found out it worked without having to alter my own flow... Heaven!

I sincerely hope you can help me out,

Viktor

nicholishen commented 4 years ago

Hi Victor,

This is a bug on their end because they are sending the wrong filling mode in the symbol info. You can, however, find the correct filing mode by right clicking the symbol in the terminal and looking up its specifications. In the case of USDJPY on XM -- the filling mode is IOC. Switch to that and a smaller position size to fit within your margin and it will work. Also a couple more tips:

  1. Don't make repeated calls to the API for the same information, it will kill your performance. Your script calls the terminal three times for tick updates when you should only do it once.
  2. quit()and exit() are for use in the python REPL only. If you need to exit a script you should use sys.exit()
import pprint

import pymt5adapter as mta

def main():
    mysymbol = 'USDJPY'
    symbol = mta.symbol_info(mysymbol)
    tick = mta.symbol_info_tick(symbol.name)
    request = {
        "action"      : mta.TRADE_ACTION_DEAL,
        "symbol"      : symbol.name,
        "volume"      : 0.01,
        "type"        : mta.ORDER_TYPE_BUY,
        "price"       : tick.ask,
        "sl"          : tick.ask - 100 * symbol.point,
        "tp"          : tick.ask + 100 * symbol.point,
        "deviation"   : 10,
        "magic"       : 234000,
        "comment"     : "python script",
        "type_filling": mta.ORDER_FILLING_IOC,
    }
    res = mta.dictify(mta.order_send(request))
    pprint.pp(res)

if __name__ == '__main__':
    with mta.connected(raise_on_errors=True):
        main()