This commit is contained in:
lz_db
2025-11-16 12:31:03 +08:00
commit 0fab423a18
1451 changed files with 743213 additions and 0 deletions

312
ccxt/pro/mt5_bak.py Normal file
View File

@@ -0,0 +1,312 @@
# -*- coding: utf-8 -*-
from ccxt.async_support.mt5 import mt5 as mt5Parent
from ccxt.base.errors import ExchangeError, ArgumentsRequired
from ccxt.async_support.base.ws.client import Client
import asyncio
from typing import Optional, Dict, Any, List
class mt5(mt5Parent):
def describe(self):
return self.deep_extend(super(mt5, self).describe(), {
'platinum': True,
'hostname': '43.167.188.220:5000',
'has': {
# 专业版特有功能
'watchPosition': True,
'watchOrder': True,
'watchLeverage': True,
'watchMargin': True,
'advancedAPI': True,
'batchOrders': True,
'modifyOrder': True,
'closePosition': True,
'setLeverage': True,
'setMargin': True,
},
'urls': {
'api': {
'ws': 'ws://{hostname}',
},
},
'options': {
'defaultType': 'spot',
'watchOrder': {
'symbol': None,
'orderId': None,
},
'watchPosition': {
'symbol': None,
},
},
})
# 专业版特有方法
async def watch_order(self, params={}):
"""
监听特定订单的更新(专业版特有)
"""
if not self.token:
await self.get_token()
try:
await self.load_markets()
except Exception as e:
print(f"错误: {e}")
# await self.fetch_markets()
# return
request: dict = {
'id': self.token,
}
endpoint = self.api['wsEndpoint']['order']
url = self.implode_hostname(self.urls['api']['ws']) + '/' + endpoint
url += '?' + self.urlencode(request)
return await self.watch(url,'order_position')
def handle_message(self, client: Client, message):
# print(message)
errorCode = self.safe_string(message, 'errorCode')
if errorCode is not None:
self.handle_error_message(client, message)
return
# 处理 MT5 特定的消息
message_type = self.safe_string(message, 'type')
if message_type == 'OpenedOrders':
print("111111111111111")
self.handle_opened_orders(client, message)
elif message_type == self.api['wsEndpoint']['orderbook']:
self.handle_orderbook(client, message)
elif message_type == self.api['wsEndpoint']['quote']:
self.handle_ticker(client, message)
def handle_opened_orders(self, client, message):
"""
处理 OpenedOrders 消息
"""
orders_data = self.safe_value(message, 'data', [])
message_id = self.safe_string(message, 'id')
timestamp = self.safe_integer(message, 'timestampUTC')
parsed_orders = []
for order_data in orders_data:
# 解析每个订单
order = self.parse_ws_order(order_data)
parsed_orders.append(order)
# 分发到不同的消息流
order_id = order['id']
symbol = order['symbol']
# 更新特定订单
client.resolve(order, 'order:' + order_id)
# 更新符号特定的订单列表
client.resolve([order], 'orders:' + symbol)
print('-------------parsed_orders:',parsed_orders)
# 更新所有订单列表
client.resolve(parsed_orders, 'orders')
# 如果有请求ID也解析到该请求
if message_id:
client.resolve(parsed_orders, 'request:' + message_id)
def handle_orderbook(self, client, message):
"""处理深度数据"""
orderbook = self.parse_ws_order_book(message)
symbol = orderbook['symbol']
message_hash = 'orderbook:' + symbol
client.resolve(orderbook, message_hash)
def parse_ws_order(self, order, market=None):
"""
解析 MT5 WebSocket 订单数据为 CCXT 标准格式
"""
# 提取订单基本信息
ticket = self.safe_integer(order, 'ticket')
symbol = self.safe_string(order, 'symbol')
order_type = self.safe_string(order, 'orderType')
deal_type = self.safe_string(order, 'dealType')
state = self.safe_string(order, 'state')
lots = self.safe_number(order, 'lots')
contract_size = self.safe_number(order, 'contractSize', 1.0)
open_price = self.safe_number(order, 'openPrice')
close_price = self.safe_number(order, 'closePrice')
profit = self.safe_number(order, 'profit')
print("ggeggegge========")
# 获取市场信息
market = self.market(symbol) if market is None else market
# 解析时间戳
open_time_str = self.safe_string(order, 'openTime')
open_timestamp = self.safe_integer(order, 'openTimestampUTC')
# 如果 openTimestampUTC 不存在,尝试解析 openTime 字符串
if open_timestamp is None and open_time_str:
try:
# 解析格式: "2025-11-15T04:06:06.994"
open_timestamp = self.parse8601(open_time_str)
except:
open_timestamp = None
# 解析订单状态
status = self.parse_order_status(state)
# 解析订单方向
side = self.parse_order_side(order_type, deal_type)
# 解析订单类型
order_type_parsed = self.parse_order_type(order_type)
# 计算数量 (lots * contractSize)
amount = lots * contract_size if (lots is not None and contract_size is not None) else None
# 解析成交数量
volume = self.safe_integer(order, 'volume', 0)
close_volume = self.safe_integer(order, 'closeVolume', 0)
# 对于已成交订单filled 应该是 volume
filled = volume
remaining = 0 # MT5 中订单要么完全成交,要么没有
# 解析止盈止损
stop_loss = self.safe_number(order, 'stopLoss')
take_profit = self.safe_number(order, 'takeProfit')
# 构建标准订单对象
result = {
'id': str(ticket),
'clientOrderId': None,
'datetime': self.iso8601(open_timestamp) if open_timestamp else None,
'timestamp': open_timestamp,
'lastTradeTimestamp': None,
'status': status,
'symbol': market['symbol'] if market else symbol,
'type': order_type_parsed,
'side': side,
'price': open_price,
'amount': amount,
'filled': filled,
'remaining': remaining,
'cost': None, # 可以计算: amount * price
'average': None,
'fee': {
'currency': market['quote'] if market else 'USD',
'cost': self.safe_number(order, 'fee', 0),
},
'trades': None,
'info': order,
}
# 计算成本
if amount is not None and open_price is not None:
result['cost'] = amount * open_price
# 添加 MT5 特定字段
result['stopLoss'] = stop_loss
result['takeProfit'] = take_profit
result['profit'] = profit
result['commission'] = self.safe_number(order, 'commission', 0)
result['swap'] = self.safe_number(order, 'swap', 0)
result['comment'] = self.safe_string(order, 'comment', '')
print("-----------result:",result)
return result
def parse_order_status(self, status):
"""
解析 MT5 订单状态
"""
statuses = {
'Filled': 'closed', # 已成交
'PartialFilled': 'open', # 部分成交
'Pending': 'open', # 挂单中
'Cancelled': 'canceled', # 已取消
'Rejected': 'rejected', # 已拒绝
'Expired': 'expired', # 已过期
# 根据您的数据添加更多状态映射
'Active': 'open',
'Closed': 'closed',
}
return self.safe_string(statuses, status, status.lower() if status else 'unknown')
def parse_order_side(self, order_type, deal_type):
"""
解析订单方向
"""
# 优先使用 deal_type因为它更准确
if deal_type:
if 'Buy' in deal_type:
return 'buy'
elif 'Sell' in deal_type:
return 'sell'
# 其次使用 order_type
if order_type:
if order_type == 'Buy':
return 'buy'
elif order_type == 'Sell':
return 'sell'
elif 'Buy' in order_type:
return 'buy'
elif 'Sell' in order_type:
return 'sell'
return 'unknown'
def parse_order_type(self, order_type):
"""
解析订单类型
"""
if not order_type:
return 'market' # 默认类型
order_type_lower = order_type.lower()
if 'limit' in order_type_lower:
return 'limit'
elif 'stop' in order_type_lower:
return 'stop'
elif 'market' in order_type_lower:
return 'market'
else:
# 根据 dealType 判断
return 'market' # 默认为市价单
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
"""签名请求 URL 构建"""
endpoint = '/' + self.implode_params(path, params)
url = self.implode_hostname(self.urls['api'][api]) + endpoint
headers = headers if (headers is not None) else {}
# 对于 GET 请求,将参数添加到查询字符串
if method == 'GET' and params:
# 特殊处理数组参数
query_params = {}
for key, value in params.items():
if isinstance(value, list):
# 对于数组参数,可能需要特殊编码
query_params[key] = ','.join(value)
else:
query_params[key] = value
url += '?' + self.urlencode(query_params)
elif method == 'GET' and params:
url += '?' + self.urlencode(params)
# print(f"🔧 Debug: Final URL: {url}")
return {
'url': url,
'method': method,
'body': body,
'headers': headers
}