This commit is contained in:
lz_db
2025-11-30 11:19:39 +08:00
parent 6bb93a3968
commit a630c42ddd
4 changed files with 68 additions and 32 deletions

View File

@@ -766,6 +766,8 @@ class mt5(Exchange, ImplicitAPI):
timestamp = self.parse8601(self.safe_string(order, 'openTime')) timestamp = self.parse8601(self.safe_string(order, 'openTime'))
last_trade_timestamp = self.parse8601(self.safe_string(order, 'closeTime')) last_trade_timestamp = self.parse8601(self.safe_string(order, 'closeTime'))
if last_trade_timestamp is None:
last_trade_timestamp = timestamp
status = self.parse_order_status(self.safe_string(order, 'state')) status = self.parse_order_status(self.safe_string(order, 'state'))
side = self.parse_order_side(self.safe_string(order, 'orderType')) side = self.parse_order_side(self.safe_string(order, 'orderType'))
@@ -796,7 +798,7 @@ class mt5(Exchange, ImplicitAPI):
return self.safe_order({ return self.safe_order({
'id': id, 'id': id,
'clientOrderId': None, 'clientOrderId': self.safe_string(order, 'comment'),
'datetime': self.iso8601(timestamp), 'datetime': self.iso8601(timestamp),
'timestamp': timestamp, 'timestamp': timestamp,
'lastTradeTimestamp': last_trade_timestamp, 'lastTradeTimestamp': last_trade_timestamp,
@@ -836,13 +838,22 @@ class mt5(Exchange, ImplicitAPI):
def parse_order_status(self, status): def parse_order_status(self, status):
statuses = { statuses = {
'Started': 'open', # MT5 状态 -> CCXT 标准状态
'Placed': 'open', 'Started': 'open', # 订单已开始
'Cancelled': 'canceled', 'Placed': 'open', # 订单已放置
'Partial': 'open', 'RequestAdding': 'pending', # 请求添加订单(待处理)
'Filled': 'closed', 'RequestModifying': 'pending', # 请求修改订单(待处理)
'Rejected': 'rejected', 'RequestCancelling': 'pending', # 请求取消订单(待处理)
'Expired': 'expired', 'Partial': 'open', # 订单部分成交(仍可继续成交)
'Filled': 'closed', # 订单完全成交
'Cancelled': 'canceled', # 订单已取消
'Rejected': 'rejected', # 订单被拒绝
'Expired': 'expired', # 订单已过期
# 备用映射
'New': 'open',
'Active': 'open',
'Done': 'closed',
'Canceled': 'canceled',
} }
return self.safe_string(statuses, status, status) return self.safe_string(statuses, status, status)

View File

@@ -803,7 +803,7 @@ class mt5(Exchange, ImplicitAPI):
return self.safe_order({ return self.safe_order({
'id': id, 'id': id,
'clientOrderId': None, 'clientOrderId': self.safe_string(order, 'comment'),
'datetime': self.iso8601(timestamp), 'datetime': self.iso8601(timestamp),
'timestamp': timestamp, 'timestamp': timestamp,
'lastTradeTimestamp': last_trade_timestamp, 'lastTradeTimestamp': last_trade_timestamp,
@@ -835,13 +835,22 @@ class mt5(Exchange, ImplicitAPI):
def parse_order_status(self, status): def parse_order_status(self, status):
statuses = { statuses = {
'Started': 'open', # MT5 状态 -> CCXT 标准状态
'Placed': 'open', 'Started': 'open', # 订单已开始
'Cancelled': 'canceled', 'Placed': 'open', # 订单已放置
'Partial': 'open', 'RequestAdding': 'pending', # 请求添加订单(待处理)
'Filled': 'closed', 'RequestModifying': 'pending', # 请求修改订单(待处理)
'Rejected': 'rejected', 'RequestCancelling': 'pending', # 请求取消订单(待处理)
'Expired': 'expired', 'Partial': 'open', # 订单部分成交(仍可继续成交)
'Filled': 'closed', # 订单完全成交
'Cancelled': 'canceled', # 订单已取消
'Rejected': 'rejected', # 订单被拒绝
'Expired': 'expired', # 订单已过期
# 备用映射
'New': 'open',
'Active': 'open',
'Done': 'closed',
'Canceled': 'canceled',
} }
return self.safe_string(statuses, status, status) return self.safe_string(statuses, status, status)

View File

@@ -382,6 +382,7 @@ class mt5(mt5Parent):
update_data = self.safe_value(data, 'update', {}) update_data = self.safe_value(data, 'update', {})
order_data = self.safe_value(update_data, 'order') order_data = self.safe_value(update_data, 'order')
if order_data: if order_data:
order_data['update_type'] = self.safe_value(update_data, 'type', None) # 这个字段可以判断是开仓还是平仓
order = self.parse_ws_order(order_data) order = self.parse_ws_order(order_data)
if order: if order:
# 使用简单的列表而不是 ArrayCacheBySymbolById # 使用简单的列表而不是 ArrayCacheBySymbolById
@@ -601,7 +602,7 @@ class mt5(mt5Parent):
"""解析单个订单数据""" """解析单个订单数据"""
if not order_data: if not order_data:
return None return None
# print("++++++",order_data)
try: try:
symbol = self.safe_string(order_data, 'symbol') symbol = self.safe_string(order_data, 'symbol')
if symbol and len(symbol) >= 6: if symbol and len(symbol) >= 6:
@@ -621,17 +622,33 @@ class mt5(mt5Parent):
if timestamp is None: if timestamp is None:
timestamp = self.milliseconds() timestamp = self.milliseconds()
last_trade_timestamp = None last_trade_timestamp = timestamp
if is_closed: if is_closed:
last_trade_timestamp = self.parse8601(close_time) last_trade_timestamp = self.parse8601(close_time)
mt5_order_type = self.safe_string(order_data, 'update_type', None)
amount = self.safe_number(order_data, 'lots', 0) amount = self.safe_number(order_data, 'lots', 0)
filled = self.safe_number(order_data, 'closeLots', 0) filled = self.safe_number(order_data, 'closeLots', 0)
price = self.safe_number(order_data, 'openPrice')
side = self.parse_order_side(self.safe_string(order_data, 'orderType'))
if mt5_order_type == 'MarketOpen':
amount = self.safe_number(order_data, 'lots', 0)
filled = self.safe_number(order_data, 'lots', 0)
elif mt5_order_type == 'MarketClose':
amount = self.safe_number(self.safe_dict(order_data, 'dealInternalIn', {}), 'lots', 0)
filled = self.safe_number(order_data, 'closeLots', 0)
price = self.safe_number(order_data, 'closePrice')
if side == 'buy':
side = 'sell'
else:
side = 'buy'
remaining = max(amount - filled, 0) if amount is not None and filled is not None else None remaining = max(amount - filled, 0) if amount is not None and filled is not None else None
return { return {
'id': self.safe_string(order_data, 'ticket'), 'id': self.safe_string(order_data, 'ticket'),
'clientOrderId': None, 'clientOrderId': self.safe_string(order_data, 'comment'),
'datetime': self.iso8601(timestamp), 'datetime': self.iso8601(timestamp),
'timestamp': timestamp, 'timestamp': timestamp,
'lastTradeTimestamp': last_trade_timestamp, 'lastTradeTimestamp': last_trade_timestamp,
@@ -641,8 +658,8 @@ class mt5(mt5Parent):
'type': self.parse_order_type(self.safe_string(order_data, 'orderType')), 'type': self.parse_order_type(self.safe_string(order_data, 'orderType')),
'timeInForce': None, 'timeInForce': None,
'postOnly': None, 'postOnly': None,
'side': self.parse_order_side(self.safe_string(order_data, 'orderType')), 'side': side,
'price': self.safe_number(order_data, 'openPrice'), 'price': price,
'stopLossPrice': self.safe_number(order_data, 'stopLoss'), 'stopLossPrice': self.safe_number(order_data, 'stopLoss'),
'takeProfitPrice': self.safe_number(order_data, 'takeProfit'), 'takeProfitPrice': self.safe_number(order_data, 'takeProfit'),
'reduceOnly': None, 'reduceOnly': None,

View File

@@ -135,20 +135,19 @@ async def websocket_quick_test():
async def order_listener(): async def order_listener():
while True: while True:
# print("111111111") # print("111111111")
res = await exchange.watch_ticker(symbol='BTCUSD') res = await exchange.watch_orders()
logger.error("aaa")
logger.warning("bbb")
logger.debug("ccc")
print("===========================收到信息") print("===========================收到信息")
print(res) for order in res:
del order['info']
logger.info(f"📦 订单更新: {order}")
# for order in res: # for order in res:
# logger.info(f"📦 订单更新: {order}") # logger.info(f"📦 订单更新: {order}")
# 监听余额更新 # 监听余额更新
async def balance_listener(): # async def balance_listener():
balance = await exchange.watch_balance() # balance = await exchange.watch_balance()
total = sum([v for v in balance['total'].values() if v is not None]) # total = sum([v for v in balance['total'].values() if v is not None])
logger.info(f"💰 余额更新: 总余额 {total:.2f}") # logger.info(f"💰 余额更新: 总余额 {total:.2f}")
# 运行监听器 # 运行监听器
await asyncio.gather( await asyncio.gather(
@@ -166,5 +165,5 @@ async def websocket_quick_test():
if __name__ == "__main__": if __name__ == "__main__":
# 运行快速测试 # 运行快速测试
asyncio.run(quick_order_test()) # asyncio.run(quick_order_test())
# asyncio.run(websocket_quick_test()) asyncio.run(websocket_quick_test())