Search code examples
pythonmql5metatrader5

How to properly close an opened order? (can't pass a ticket number to "position" when sending an order)


I want to open an order, no problem with that, but if I want to close this order, I need the ticket number, ticket that I can't write manually, it will be given after the order is opened.

From the documentation, I've got this: enter image description here

but I can't pass anything else than 0 to "position": 0 (line 20), otherwise it will not open the order.

Meantime, if position = 0, it will open an order, I'll get a position ticket from result.order, then I have to manually copy it and paste it in the position from the closing order function, like that it will close the order.

So, is there a way of not manually copying the ticket number after each opened order and paste it in the closing function? Or writing an unique ticket in advance for both, open and close, order?

Thank you in advance!

import MetaTrader5 as mt5

if not mt5.initialize():
    print("initialize() failed, error code =",mt5.last_error())
    quit()
    
symbol = "EURUSD"
lot = 0.1
point = mt5.symbol_info(symbol).point
price = mt5.symbol_info_tick(symbol).ask
deviation = 20

def buy():
    request = {
        "action": mt5.TRADE_ACTION_DEAL,
        "symbol": symbol,
        "volume": lot,
        "type": mt5.ORDER_TYPE_BUY,
        "price": price,
        "position": 0, # can't pass anything else than 0 here, otherwise it will not open the order!
        "deviation": deviation,
        "magic": 234000,
        "comment": "python script open",
        "type_time": mt5.ORDER_TIME_GTC,
        "type_filling": mt5.ORDER_FILLING_IOC,
    }
    # send a trading request
    result = mt5.order_send(request)
    
    # check the execution result
    print("2. order_send done, ", result)
    print(result.order)
    
    mt5.shutdown()
    quit()
    


def close():
    close_request={ "action": mt5.TRADE_ACTION_DEAL,
    "symbol": symbol,
    "volume": lot,
    "type": mt5.ORDER_TYPE_SELL,
    "position": 129950610,
    "price": price,
    "deviation": deviation,
    "magic": 0,
    "comment": "python script op",
    "type_time": mt5.ORDER_TIME_GTC,
    "type_filling": mt5.ORDER_FILLING_IOC,
    }
    # send a close request
    result=mt5.order_send(close_request)
    print(result)
    
    
# buy()
# close()

Solution

  • I found a way (hard code it), can be a little bit overwhelming, but it's the only way I can think about it. I'll post the answer; maybe it will be useful for somebody.

    So I want functions to buy and sell a specific order; the main issue is the ticket number, so I created functions to buy/open order, to close the order, to get the ticket number (an unique number for the position/order) and magic number (exact number given to EAs) and a function to do what I need (see above), where I compare my magic number with all opened orders. If there is one that will match, it will grab the ticket number and use it to close the order.

    import time
    import MetaTrader5 as mt5
    
    def init():
        if not mt5.initialize():
            print("initialize() failed, error code =",mt5.last_error())
            quit()
    
    
    # prepare the buy request structure
    lott = 0.15
    symboll = "EURUSD"
    
    deviation = 20
    magic = 987654321
    
    def buy():
        # establish connection to the MetaTrader 5 terminal
        init()
        
        symbol = symboll
        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()
    
        lot = lott
        point = mt5.symbol_info(symbol).point
        price = mt5.symbol_info_tick(symbol).ask
        
        request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": mt5.ORDER_TYPE_BUY,
            "price": price,
            "sl": price - 1000 * point,
            "tp": price + 1000 * point,
            "deviation": deviation,
            "magic": magic,
            "comment": "python script open",
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": mt5.ORDER_FILLING_IOC,
        }
        
        # send a trading request
        result = mt5.order_send(request)
        # check the execution result
        print("1. order_send(): by {} {} lots at {} with deviation={} points".format(symbol,lot,price,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]))
            print("shutdown() and quit")
            mt5.shutdown()
            quit()
     
        print("2. order_send done, ", result)
        print("   opened position with POSITION_TICKET={}".format(result.order))
        print("   sleep 2 seconds before closing position #{}".format(result.order))
    
    
    def close(ticket_no):
        init()
        symbol = symboll
        symbol_info = mt5.symbol_info(symbol)
        lot = lott
        # create a close request
        position_id=ticket_no
        price=mt5.symbol_info_tick(symbol).bid
        deviation=20
        request={
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": mt5.ORDER_TYPE_SELL,
            "position": position_id,
            "price": price,
            "deviation": deviation,
            "magic": magic,
            "comment": "python script close",
            "type_time": mt5.ORDER_TIME_GTC,
            "type_filling": mt5.ORDER_FILLING_IOC,
        }
        # send a trading request
        result=mt5.order_send(request)
        # check the execution result
        print("3. close position #{}: sell {} {} lots at {} with deviation={} points".format(position_id,symbol,lot,price,deviation));
        if result.retcode != mt5.TRADE_RETCODE_DONE:
            print("4. order_send failed, retcode={}".format(result.retcode))
            print("   result",result)
        else:
            print("4. position #{} closed, {}".format(position_id,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()
        quit()
    
    
    def get_ticket_no():
        init()
        symbol = symboll
        symbol_info = mt5.symbol_info(symbol)
        
        positions=mt5.positions_get(symbol=symbol)
        if positions==None:
            print("No positions on EURUSD, error code={}".format(mt5.last_error()))
        elif len(positions)>0:
            print("Total positions on EURUSD =",len(positions))
            # display all open positions
            for position in positions:
                print(position)
    
        # get the list of positions on symbols whose names contain "*EUR*"
        symmbol_positions=mt5.positions_get()
        if symmbol_positions==None:
            print("No positions with group=\"*EUR*\", error code={}".format(mt5.last_error()))    
        elif len(symmbol_positions)>0:
            lst = list(symmbol_positions)
            ticket_no = lst[0][0] # get the ticket number
            magic_no = lst[0][6] # get the magic number
            print(f'{ticket_no=}')
            print(f'{magic_no=}')
            return ticket_no
    
        # shut down connection to the MetaTrader 5 terminal
        mt5.shutdown()
        quit()
    
    
    def get_magic_no():
        init()
        symbol = symboll
        symbol_info = mt5.symbol_info(symbol)
        
        positions=mt5.positions_get(symbol=symbol)
        if positions==None:
            print("No positions on EURUSD, error code={}".format(mt5.last_error()))
        elif len(positions)>0:
            print("Total positions on EURUSD =",len(positions))
            # display all open positions
            for position in positions:
                print(position)
    
        # get the list of positions on symbols whose names contain "*EUR*"
        symmbol_positions=mt5.positions_get()
        if symmbol_positions==None:
            print("No positions with group=\"*EUR*\", error code={}".format(mt5.last_error()))    
        elif len(symmbol_positions)>0:
            lst = list(symmbol_positions)
            ticket_no = lst[0][0] # get the ticket number
            magic_no = lst[0][6] # get the magic number
            print(f'{ticket_no=}')
            print(f'{magic_no=}')
            return magic_no
    
        # shut down connection to the MetaTrader 5 terminal
        mt5.shutdown()
        quit()
        
    
    def close_order():
        if get_magic_no() == magic:
            close(get_ticket_no())
        else:
            print("Order not found!")
        
        
    buy()
    time.sleep(2)
    close_order()