pythonalgorithmic-tradingtradingforexmetatrader5

got retcode=10021 in python with MT5


I'm trying to create a trading bot that makes orders instead of making them manually from the MetaTrader5 App, I make the function below

Note: BoS: Buy or Sell | sl: Stop Loss | tp: Take Profit | lot: Volume

def MetaTrader_Order(symbol, BoS, price, sl, tp, lot):

    # connect to MetaTrader 5
    if not mt5.initialize():
        print("initialize() failed")
        mt5.shutdown()

    

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

    
    # 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)


    
    deviation = 20


    if BoS == "SELL":    
        request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": symbol,
        "volume": lot,
        "type": mt5.ORDER_TYPE_SELL,
        "price": price,
        "sl": sl,
        "tp": tp,
        "deviation": deviation,
        "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_RETURN,
        }   

    elif BoS == "BUY":
        request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": symbol,
        "volume": lot,
        "type": mt5.ORDER_TYPE_BUY,
        "price": price,
        "sl": sl,
        "tp": tp,
        "deviation": deviation,
        "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_RETURN,
        } 


    else:
        request = None

    
    # send a trading request
    result = mt5.order_send(request)


    # check the execution result
    print("1. order_send(): {} {} at price {}, with lot {}, with deviation {}".format(BoS, symbol, price, lot, deviation))

    if result.retcode != mt5.TRADE_RETCODE_DONE:
        print("2. order_send failed, retcode={}".format(result.retcode))

        # 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]))

    

    else: 
        print("2. order_send done, ", result)

when I try to pass arguments to function like that:

MetaTrader_Order("GBPUSD", "SELL", 1.40001, 1.5, 1.3, 0.1)

it gives me an output like this:

1. order_send(): SELL GBPUSD at price 1.40001, with lot 0.01, with deviation 20
2. order_send failed, retcode=10021
   retcode=10021
   deal=0
   order=0
   volume=0.0
   price=0.0
   bid=0.0
   ask=0.0
   comment=No prices
   request_id=0
   retcode_external=0
   request=TradeRequest(action=1, magic=234000, order=0, symbol='GBPUSD', volume=0.01, price=1.40001, stoplimit=0.0, sl=1.5, tp=1.3, deviation=20, type=1, type_filling=2, type_time=0, expiration=0, comment='python script open', position=0, position_by=0)
       traderequest: action=1
       traderequest: magic=234000
       traderequest: order=0
       traderequest: symbol=GBPUSD
       traderequest: volume=0.01
       traderequest: price=1.40001
       traderequest: stoplimit=0.0
       traderequest: sl=1.5
       traderequest: tp=1.3
       traderequest: deviation=20
       traderequest: type=1
       traderequest: type_filling=2
       traderequest: type_time=0
       traderequest: expiration=0
       traderequest: comment=python script open
       traderequest: position=0
       traderequest: position_by=0 

if I try to put price automatically like this: price = mt5.symbol_info_tick(symbol).ask it works and sends the order to MetaTrader5 with no problems

but really I wont to send order with a specific price that I entered, not the market price

.
.
.
MT5 Documentation: https://www.mql5.com/en/docs/integration/python_metatrader5 MT5
order_send: https://www.mql5.com/en/docs/integration/python_metatrader5/mt5ordersend_py
MT5 Return Codes: https://www.mql5.com/en/docs/constants/errorswarnings/enum_trade_return_codes

also see TRADE_ACTION_PENDING on this page: https://www.mql5.com/en/docs/constants/structures/mqltraderequest (it's in another language)


Solution

  • I solved the problem by writing this part of the code like that:

    if BoS == "SELL": 
            if price < mt5.symbol_info_tick(symbol).bid:
                price = mt5.symbol_info_tick(symbol).bid
    
            request = {
            "action": mt5.TRADE_ACTION_PENDING,
            "symbol": symbol,
            "volume": lot,
            "type": mt5.ORDER_TYPE_SELL_LIMIT,
            "price": price,
            "sl": sl,
            "tp": tp,
            "deviation": deviation,
            "magic": 234000,
            "comment": "python script open",
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": mt5.ORDER_FILLING_RETURN,
            }   
    
        elif BoS == "BUY":
            if price > mt5.symbol_info_tick(symbol).ask:
                price = mt5.symbol_info_tick(symbol).ask
    
            request = {
            "action": mt5.TRADE_ACTION_PENDING,
            "symbol": symbol,
            "volume": lot,
            "type": mt5.ORDER_TYPE_BUY_LIMIT,
            "price": price,
            "sl": sl,
            "tp": tp,
            "deviation": deviation,
            "magic": 234000,
            "comment": "python script open",    ## may delete some items
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": mt5.ORDER_FILLING_RETURN,
            } 
    

    Notice: "action": mt5.TRADE_ACTION_PENDING,
    And: "type": mt5.ORDER_TYPE_SELL_LIMIT,