如何正确关闭已打开的订单? (下单时不能传票号给"position")

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

我想开单,没问题,但是如果我想平单,我需要票号,ticket,我不能手动写,开单后会给出.

来自 documentation,我得到了这个:

但我不能将除 0 之外的任何其他内容传递给 "position": 0(第 20 行),否则它不会打开订单。

同时,如果 position = 0,它会开一个订单,我会从 result.order 得到一个 position ticket,然后我必须手动复制它并粘贴到 position from关闭订单功能,这样它会关闭订单。

那么,有没有办法不用在每次打开订单后手动复制票号并将其粘贴到关闭功能中?或者提前为打开和关闭订单写一张唯一的票?

提前致谢!

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

你的问题分为两个部分,我将分别解决。

为什么我不能传递位置值
您在 post 中提到您不能在初始请求中输入 "position": 0 以外的任何内容。正如您已经发现的那样,API 文档指出

Position ticket. Fill it when changing and closing a position for its clear identification. Usually, it is the same as the ticket of the order that opened the position.

这意味着,如果您已经有工单需要修改,则需要输入一个值。 API 文档在提供的示例中实际执行此操作。

我将在此处包含一些片段,但我建议您查看 order_send 文档页面上提供的示例。

request = {
    "action": mt5.TRADE_ACTION_DEAL,
    "symbol": symbol,
    "volume": lot,
    "type": mt5.ORDER_TYPE_BUY,
    "price": price,
    "sl": price - 100 * point,
    "tp": price + 100 * point,
    "deviation": deviation,
    "magic": 234000,
    "comment": "python script open",
    "type_time": mt5.ORDER_TIME_GTC,
    "type_filling": mt5.ORDER_FILLING_RETURN,
}

如您所见,position字段未填写。这是因为这是第一次请求,没有任何修改,因为还没有交易请求。

关闭请求dict如下所示

position_id = result.order

request={
    "action": mt5.TRADE_ACTION_DEAL,
    "symbol": symbol,
    "volume": lot,
    "type": mt5.ORDER_TYPE_SELL,
    "position": position_id,
    "price": price,
    "deviation": deviation,
    "magic": 234000,
    "comment": "python script close",
    "type_time": mt5.ORDER_TIME_GTC,
    "type_filling": mt5.ORDER_FILLING_RETURN,
}

在请求中,您可以看到两件事。第一个是填写 position 字段,因为我们现在正在对原始请求进行 修改 。您在这里可以看到的第二件事是 position_id 取自初始请求的响应。 position_id 是响应的 order 字段。此结构的文档可用 here.

如何在不手动复制订单号的情况下调整代码关闭它?
根据您的评论,我认为这就是您要找的。

例如,order_send 函数已经说明了如何完成此操作。

您需要做的最重要的事情是将 position_id 从 buy() 函数的响应传递给 close() 函数。

还注意到,在您的原始代码中,magic 字段针对购买请求设置为 234000,对于平仓请求设置为 0。在阅读文档时,它没有明确提到这需要相同。但是,由于在他们提供的示例中是相同的,因此我在下面的代码中也将其更改为相同。

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,
        "magic": 234000,
        "symbol": symbol,
        "volume": lot,
        "type": mt5.ORDER_TYPE_BUY,
        "price": price,
        "deviation": deviation,
        "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)
    position_id = result.order
    print(position_id)

    mt5.shutdown()
    return position_id


def close(position_id):
    close_request = {"action": mt5.TRADE_ACTION_DEAL,
                     "symbol": symbol,
                     "volume": lot,
                     "type": mt5.ORDER_TYPE_SELL,
                     "position": position_id,
                     "price": price,
                     "deviation": deviation,
                     "magic": 234000,
                     "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)


pos_id = buy()
close(pos_id)

我找到了一种方法(硬编码),可能有点不知所措,但这是我能想到的唯一方法。我会 post 回答;也许对某些人有用。

所以我想要买卖特定订单的功能;主要问题是票号,所以我为 buy/open 订单创建函数,关闭订单,获取票号(position/order 的唯一号码)和幻数(给定的确切号码EAs) 和一个函数来做我需要的事情(见上文),在这里我将我的幻数与所有打开的订单进行比较。如果有一个匹配,它将获取票号并用它来关闭订单。

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