diff --git a/ccxt/async_support/mt5.py b/ccxt/async_support/mt5.py index a6f5432..97fd4ef 100644 --- a/ccxt/async_support/mt5.py +++ b/ccxt/async_support/mt5.py @@ -772,11 +772,14 @@ class mt5(Exchange, ImplicitAPI): else: # 如果无法解析,使用原始 market_id symbol = market_id - - timestamp = self.parse8601(self.safe_string(order, 'openTime')) - self.diff_milliseconds - last_trade_timestamp = self.parse8601(self.safe_string(order, 'closeTime')) - self.diff_milliseconds - if last_trade_timestamp is None: + + timestamp = self.safe_integer(order, 'openTimestampUTC') - self.diff_milliseconds + last_trade_timestamp = self.safe_integer(order, 'closeTimestampUTC') + + if last_trade_timestamp is None or last_trade_timestamp <= 0: last_trade_timestamp = timestamp + else: + last_trade_timestamp = last_trade_timestamp - self.diff_milliseconds status = self.parse_order_status(self.safe_string(order, 'state')) side = self.parse_order_side(self.safe_string(order, 'orderType')) diff --git a/ccxt/mt5.py b/ccxt/mt5.py index 9df2124..36683aa 100644 --- a/ccxt/mt5.py +++ b/ccxt/mt5.py @@ -782,9 +782,14 @@ class mt5(Exchange, ImplicitAPI): else: symbol = market_id - timestamp = self.parse8601(self.safe_string(order, 'openTime')) - self.diff_milliseconds - last_trade_timestamp = self.parse8601(self.safe_string(order, 'closeTime')) - self.diff_milliseconds - + timestamp = self.safe_integer(order, 'openTimestampUTC') - self.diff_milliseconds + last_trade_timestamp = self.safe_integer(order, 'closeTimestampUTC') + + if last_trade_timestamp is None or last_trade_timestamp <= 0: + last_trade_timestamp = timestamp + else: + last_trade_timestamp = last_trade_timestamp - self.diff_milliseconds + status = self.parse_order_status(self.safe_string(order, 'state')) side = self.parse_order_side(self.safe_string(order, 'orderType')) type = self.parse_order_type(self.safe_string(order, 'orderType')) diff --git a/ccxt/pro/mt5.py b/ccxt/pro/mt5.py index 385cf7c..d5227df 100644 --- a/ccxt/pro/mt5.py +++ b/ccxt/pro/mt5.py @@ -620,13 +620,13 @@ class mt5(mt5Parent): close_time = self.safe_string(order_data, 'closeTime') is_closed = close_time and close_time != "0001-01-01T00:00:00" - timestamp = self.parse8601(self.safe_string(order_data, 'openTime')) - self.diff_milliseconds - if timestamp is None: - timestamp = self.milliseconds() - - last_trade_timestamp = timestamp - if is_closed: - last_trade_timestamp = self.parse8601(close_time) - - self.diff_milliseconds + timestamp = self.safe_integer(order_data, 'openTimestampUTC') - self.diff_milliseconds + last_trade_timestamp = self.safe_integer(order_data, 'closeTimestampUTC') + + if last_trade_timestamp is None or last_trade_timestamp <= 0: + last_trade_timestamp = timestamp + else: + last_trade_timestamp = last_trade_timestamp - self.diff_milliseconds mt5_order_type = self.safe_string(order_data, 'update_type', None) @@ -717,7 +717,7 @@ class mt5(mt5Parent): quote = symbol[3:] symbol = base + '/' + quote - timestamp = self.parse8601(self.safe_string(order_data, 'openTime')) - self.diff_milliseconds + timestamp = self.safe_integer(order_data, 'openTimestampUTC') - self.diff_milliseconds contracts = self.safe_number(order_data, 'lots') entry_price = self.safe_number(order_data, 'openPrice') diff --git a/test/data.md b/test/data.md index 447e424..81fd691 100644 --- a/test/data.md +++ b/test/data.md @@ -4717,4 +4717,356 @@ "internalOrders": [], "action": 1, "partialResponse": false +} + + +websocket 订单推送 + +{ + "id": "947437118", + "clientOrderId": None, + "datetime": "2025-12-01T08:58:55.299Z", + "timestamp": 1764579535299, + "lastTradeTimestamp": 1764579773698, + "lastUpdateTimestamp": 1764579773698, + "status": "closed", + "symbol": "BTC/USD", + "type": "market", + "timeInForce": None, + "postOnly": None, + "side": "buy", + "price": 86900.31000000001, + "stopLossPrice": 0.0, + "takeProfitPrice": 0.0, + "reduceOnly": None, + "triggerPrice": None, + "amount": 0.01, + "filled": 0.01, + "remaining": 0.0, + "cost": None, + "trades": None, + "fee": { + "cost": 0.0, + "currency": None + }, + "average": None, + "info": { + "ticket": 947437118, + "profit": -0.59, + "swap": 0.0, + "commission": 0.0, + "fee": 0.0, + "closePrice": 86900.31000000001, + "closeTime": "2025-12-01T09:02:53.698", + "closeLots": 0.01, + "closeComment": None, + "openPrice": 86840.87, + "openTime": "2025-12-01T08:58:55.299", + "lots": 0.0, + "contractSize": 1.0, + "expertId": 0, + "placedType": "Manually", + "orderType": "Sell", + "dealType": "DealSell", + "symbol": "BTCUSD", + "comment": "", + "state": "Filled", + "stopLoss": 0.0, + "takeProfit": 0.0, + "requestId": 773064901, + "digits": 2, + "profitRate": 1.0, + "stopLimitPrice": 0.0, + "dealInternalIn": { + "ticketNumber": 680256931, + "id": "", + "login": 76888962, + "historyTime": 134090531352999600, + "orderTicket": 947437118, + "openTime": 1764579535, + "symbol": "BTCUSD", + "type": "DealSell", + "direction": "In", + "openPrice": 86840.87, + "price": 0.0, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 1000000, + "profit": 0.0, + "profitRate": 1.0, + "volumeRate": 86840.87, + "commission": 0.0, + "fee": 0.0, + "swap": 0.0, + "expertId": 0, + "positionTicket": 947437118, + "comment": "", + "contractSize": 1.0, + "digits": 2, + "moneyDigits": 2, + "freeProfit": 0.0, + "trailRounder": 0.0, + "openTimeMs": 1764579535299, + "placedType": "Manually", + "openTimeAsDateTime": "2025-12-01T08:58:55", + "lots": 0.01 + }, + "dealInternalOut": { + "ticketNumber": 680278258, + "id": "", + "login": 76888962, + "historyTime": 134090533736980208, + "orderTicket": 947455680, + "openTime": 1764579773, + "symbol": "BTCUSD", + "type": "DealBuy", + "direction": "Out", + "openPrice": 86900.31000000001, + "price": 86840.87, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 1000000, + "profit": -0.59, + "profitRate": 1.0, + "volumeRate": 86900.31000000001, + "commission": 0.0, + "fee": 0.0, + "swap": 0.0, + "expertId": 0, + "positionTicket": 947437118, + "comment": "", + "contractSize": 1.0, + "digits": 2, + "moneyDigits": 2, + "freeProfit": -0.59, + "trailRounder": 0.0, + "openTimeMs": 1764579773698, + "placedType": "Manually", + "openTimeAsDateTime": "2025-12-01T09:02:53", + "lots": 0.01 + }, + "orderInternal": None, + "partialCloseDeals": [], + "closeVolume": 1000000, + "volume": 0, + "expirationType": "GTC", + "expirationTime": "0001-01-01T00:00:00", + "fillPolicy": "FillOrKill", + "openTimestampUTC": 1764579535299, + "closeTimestampUTC": 1764579773698, + "update_type": "MarketClose" + } +} + +websocket 订单成交推送(原始数据) + +{ + "type": "OrderUpdate", + "id": "33ecbfc8-30cd-4691-88e9-b36442b5d8eb", + "data": { + "openedOrders": [], + "update": { + "trans": { + "updateId": 3173214, + "action": 0, + "ticketNumber": 31244190572937316, + "currency": "\\ME\\Classic-USD", + "id": 0, + "s58": "Buy", + "orderState": "Started", + "expirationType": "GTC", + "expirationTime": 0, + "openPrice": 0.0, + "orderPrice": 0.0, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 0 + }, + "orderInternal": None, + "deal": { + "ticketNumber": 680304242, + "id": "", + "login": 76888962, + "historyTime": 134090542933641351, + "orderTicket": 947486966, + "openTime": 1764580693, + "symbol": "BTCUSD", + "type": "DealBuy", + "direction": "Out", + "openPrice": 86695.37000000001, + "price": 86640.68000000001, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 1000000, + "profit": -0.54, + "profitRate": 1.0, + "volumeRate": 86695.37000000001, + "commission": 0.0, + "fee": 0.0, + "swap": 0.0, + "expertId": 0, + "positionTicket": 947482106, + "comment": "", + "contractSize": 1.0, + "digits": 2, + "moneyDigits": 2, + "freeProfit": -0.54, + "trailRounder": 0.0, + "openTimeMs": 1764580693364, + "placedType": "Manually", + "openTimeAsDateTime": "2025-12-01T09:18:13", + "lots": 0.01 + }, + "oppositeDeal": { + "ticketNumber": 947482106, + "id": "", + "login": 76888962, + "historyTime": 134089609933137354, + "orderTicket": 0, + "openTime": 0, + "symbol": "BTCUSD", + "type": "DealSell", + "direction": "In", + "openPrice": 0.0, + "price": 0.0, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 0, + "profit": 0.0, + "profitRate": 0.0, + "volumeRate": 0.0, + "commission": 0.0, + "fee": 0.0, + "swap": 0.0, + "expertId": 0, + "positionTicket": 0, + "comment": "", + "contractSize": 0.0, + "digits": 2, + "moneyDigits": 2, + "freeProfit": 0.0, + "trailRounder": 0.0, + "openTimeMs": 0, + "placedType": "Manually", + "openTimeAsDateTime": "1970-01-01T00:00:00", + "lots": 0.0 + }, + "order": { + "ticket": 947482106, + "profit": -0.54, + "swap": 0.0, + "commission": 0.0, + "fee": 0.0, + "closePrice": 86695.37000000001, + "closeTime": "2025-12-01T09:18:13.364", + "closeLots": 0.01, + "closeComment": None, + "openPrice": 86640.68000000001, + "openTime": "2025-12-01T09:15:12.615", + "lots": 0.0, + "contractSize": 1.0, + "expertId": 0, + "placedType": "Manually", + "orderType": "Sell", + "dealType": "DealSell", + "symbol": "BTCUSD", + "comment": "", + "state": "Filled", + "stopLoss": 0.0, + "takeProfit": 0.0, + "requestId": 773064905, + "digits": 2, + "profitRate": 1.0, + "stopLimitPrice": 0.0, + "dealInternalIn": { + "ticketNumber": 680300404, + "id": "", + "login": 76888962, + "historyTime": 134090541126158513, + "orderTicket": 947482106, + "openTime": 1764580512, + "symbol": "BTCUSD", + "type": "DealSell", + "direction": "In", + "openPrice": 86640.68000000001, + "price": 0.0, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 1000000, + "profit": 0.0, + "profitRate": 1.0, + "volumeRate": 86640.68000000001, + "commission": 0.0, + "fee": 0.0, + "swap": 0.0, + "expertId": 0, + "positionTicket": 947482106, + "comment": "", + "contractSize": 1.0, + "digits": 2, + "moneyDigits": 2, + "freeProfit": 0.0, + "trailRounder": 0.0, + "openTimeMs": 1764580512615, + "placedType": "Manually", + "openTimeAsDateTime": "2025-12-01T09:15:12", + "lots": 0.01 + }, + "dealInternalOut": { + "ticketNumber": 680304242, + "id": "", + "login": 76888962, + "historyTime": 134090542933641351, + "orderTicket": 947486966, + "openTime": 1764580693, + "symbol": "BTCUSD", + "type": "DealBuy", + "direction": "Out", + "openPrice": 86695.37000000001, + "price": 86640.68000000001, + "stopLoss": 0.0, + "takeProfit": 0.0, + "volume": 1000000, + "profit": -0.54, + "profitRate": 1.0, + "volumeRate": 86695.37000000001, + "commission": 0.0, + "fee": 0.0, + "swap": 0.0, + "expertId": 0, + "positionTicket": 947482106, + "comment": "", + "contractSize": 1.0, + "digits": 2, + "moneyDigits": 2, + "freeProfit": -0.54, + "trailRounder": 0.0, + "openTimeMs": 1764580693364, + "placedType": "Manually", + "openTimeAsDateTime": "2025-12-01T09:18:13", + "lots": 0.01 + }, + "orderInternal": None, + "partialCloseDeals": [], + "closeVolume": 1000000, + "volume": 0, + "expirationType": "GTC", + "expirationTime": "0001-01-01T00:00:00", + "fillPolicy": "FillOrKill", + "openTimestampUTC": 1764580512615, + "closeTimestampUTC": 1764580693364 + }, + "type": "MarketClose", + "closeByTicket": 0 + }, + "balance": 9369.719999999998, + "equity": 9369.719999999998, + "margin": 0.0, + "freeMargin": 9369.719999999998, + "profit": 0.0, + "marginLevel": 0.0, + "credit": 0.0, + "user": 0 + }, + "timestampUTC": 1764580693411 } \ No newline at end of file diff --git a/test/test_mt5_tools.py b/test/test_mt5_tools.py index 5680986..b47e248 100644 --- a/test/test_mt5_tools.py +++ b/test/test_mt5_tools.py @@ -65,7 +65,7 @@ async def quick_order_test(): 'apiKey': '76888962', 'secret': 'LZ-trade666888', 'verbose': False, # 启用详细日志 - 'hostname': '43.133.206.185:5000', + 'hostname': '43.133.21.145:5000', 'options': { # 'server': '147.160.254.81:443', # 使用服务器名称 # 或者 @@ -124,7 +124,7 @@ async def websocket_quick_test(): 'apiKey': '76888962', 'secret': 'LZ-trade666888', 'verbose': False, # 启用详细日志 - 'hostname': '43.133.206.185:5000', + 'hostname': '43.133.21.145:5000', 'options': { # 'server': '147.160.254.81:443', # 使用服务器名称 # 或者 @@ -134,15 +134,24 @@ async def websocket_quick_test(): }) try: + + # 监听all + async def all_listener(): + while True: + print("111111111") + res = await exchange.watch_all() + print("==========================收到信息") + print(f"收到数据:{res}") # 监听订单更新 async def order_listener(): while True: - # print("111111111") + print("111111111") res = await exchange.watch_orders() print("===========================收到信息") for order in res: - del order['info'] + # del order['info'] logger.info(f"📦 订单更新: {order}") + print(order) # 监听持仓更新 async def positions_listener(): @@ -161,8 +170,9 @@ async def websocket_quick_test(): # 运行监听器 await asyncio.gather( - # order_listener(), - positions_listener(), + # all_listener(), + order_listener(), + # positions_listener(), # balance_listener(), return_exceptions=True )