Files
ccxt_with_mt5/ccxt/async_support/mt5_bak.py
lz_db 0fab423a18 add
2025-11-16 12:31:03 +08:00

317 lines
11 KiB
Python

# -*- coding: utf-8 -*-
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
from ccxt.async_support.base.exchange import Exchange
from ccxt.abstract.mt5 import ImplicitAPI
import asyncio
import hashlib
from ccxt.base.types import Any, Balances, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, OrderBooks, Trade, TradingFees, Transaction
from typing import List
from ccxt.base.errors import ExchangeError
from ccxt.base.errors import AuthenticationError
from ccxt.base.errors import ArgumentsRequired
from ccxt.base.errors import InsufficientFunds
from ccxt.base.errors import InvalidOrder
from ccxt.base.errors import OrderNotFound
from ccxt.base.errors import DDoSProtection
from ccxt.base.errors import RateLimitExceeded
from ccxt.base.errors import ExchangeNotAvailable
from ccxt.base.errors import InvalidNonce
from ccxt.base.decimal_to_precision import TICK_SIZE
from ccxt.base.precise import Precise
class mt5(Exchange, ImplicitAPI):
def describe(self) -> Any:
return self.deep_extend(super(mt5, self).describe(), {
'id': 'mt5',
'name': 'MT5',
'countries': ['US'],
'version': 'v2025.02.05-05.23',
'rateLimit': 1000,
'hostname': '43.167.188.220:5000',
'pro': True,
'options': {
'host': '18.163.85.196',
'port': 443,
},
'has': {
'CORS': True,
'spot': True,
'margin': True,
'swap': True,
'future': True,
'option': True,
'borrowCrossMargin': True,
'cancelAllOrders': True,
'cancelAllOrdersAfter': True,
'cancelOrder': True,
'cancelOrders': True,
'cancelOrdersForSymbols': True,
'closeAllPositions': False,
'closePosition': False,
'createConvertTrade': True,
'createMarketBuyOrderWithCost': True,
'createMarketSellOrderWithCost': True,
'createOrder': True,
'createOrders': True,
'createOrderWithTakeProfitAndStopLoss': True,
'createPostOnlyOrder': True,
'createReduceOnlyOrder': True,
'createStopLimitOrder': True,
'createStopLossOrder': True,
'createStopMarketOrder': True,
'createStopOrder': True,
'createTakeProfitOrder': True,
'createTrailingAmountOrder': True,
'createTriggerOrder': True,
'editOrder': True,
'editOrders': True,
'fetchAllGreeks': True,
'fetchBalance': True,
'fetchBidsAsks': 'emulated',
'fetchBorrowInterest': False, # temporarily disabled, doesn't work
'fetchBorrowRateHistories': False,
'fetchBorrowRateHistory': False,
'fetchCanceledAndClosedOrders': True,
'fetchCanceledOrders': True,
'fetchClosedOrder': True,
'fetchClosedOrders': True,
'fetchConvertCurrencies': True,
'fetchConvertQuote': True,
'fetchConvertTrade': True,
'fetchConvertTradeHistory': True,
'fetchCrossBorrowRate': True,
'fetchCrossBorrowRates': False,
'fetchCurrencies': True,
'fetchDeposit': False,
'fetchDepositAddress': True,
'fetchDepositAddresses': False,
'fetchDepositAddressesByNetwork': True,
'fetchDeposits': True,
'fetchDepositWithdrawFee': 'emulated',
'fetchDepositWithdrawFees': True,
'fetchFundingHistory': True,
'fetchFundingRate': 'emulated', # emulated in exchange
'fetchFundingRateHistory': True,
'fetchFundingRates': True,
'fetchGreeks': True,
'fetchIndexOHLCV': True,
'fetchIsolatedBorrowRate': False,
'fetchIsolatedBorrowRates': False,
'fetchLedger': True,
'fetchLeverage': True,
'fetchLeverageTiers': True,
'fetchLongShortRatio': False,
'fetchLongShortRatioHistory': True,
'fetchMarginAdjustmentHistory': False,
'fetchMarketLeverageTiers': True,
'fetchMarkets': True,
'fetchMarkOHLCV': True,
'fetchMyLiquidations': True,
'fetchMySettlementHistory': True,
'fetchMyTrades': True,
'fetchOHLCV': True,
'fetchOpenInterest': True,
'fetchOpenInterestHistory': True,
'fetchOpenOrder': True,
'fetchOpenOrders': True,
'fetchOption': True,
'fetchOptionChain': True,
'fetchOrder': True,
'fetchOrderBook': True,
'fetchOrders': False,
'fetchOrderTrades': True,
'fetchPosition': True,
'fetchPositionHistory': 'emulated',
'fetchPositions': True,
'fetchPositionsHistory': True,
'fetchPremiumIndexOHLCV': True,
'fetchSettlementHistory': True,
'fetchTicker': True,
'fetchTickers': True,
'fetchTime': True,
'fetchTrades': True,
'fetchTradingFee': True,
'fetchTradingFees': True,
'fetchTransactions': False,
'fetchTransfers': True,
'fetchUnderlyingAssets': False,
'fetchVolatilityHistory': True,
'fetchWithdrawals': True,
'repayCrossMargin': True,
'sandbox': True,
'setLeverage': True,
'setMarginMode': True,
'setPositionMode': True,
'transfer': True,
'withdraw': True,
},
'timeframes': {
'1m': 1,
'5m': 5,
'15m': 15,
'30m': 30,
'1h': 60,
'4h': 240,
'1d': 1440,
'1w': 10080,
'1M': 43200,
},
'urls': {
'logo': '',
'api': {
'public': 'http://{hostname}',
'private': 'http://{hostname}',
},
'www': 'http://{hostname}',
'doc': ['http://{hostname}/index.html'],
},
'api': {
'public': {
'get': {
'Ping': 1
},
},
'private': {
'get': {
'Connect': 10,
'CheckConnect': 1,
'Disconnect': 1,
'Symbols': 1,
'ServerTimezone':1,
'AccountSummary': 1,
'AccountDetails': 1,
'SymbolList': 1,
'GetQuote': 1,
'GetQuoteMany': 1,
'MarketWatchMany': 1,
'OpenedOrders': 1,
'ClosedOrders': 1,
'OpenedOrder': 1,
'OrderHistory': 1,
'PriceHistory': 1,
'OrderSend': 1,
'OrderModify': 1,
'OrderClose': 1,
},
},
'wsEndpoint': {
'order': "OnOrderUpdate",
'quote': "OnQuote",
'orderbook': "OnOrderBook",
}
},
'requiredCredentials': {
'apiKey': True,
'secret': True,
'hostname': True,
},
'commonCurrencies': {},
'exceptions': {
'exact': {
'Invalid token': AuthenticationError,
'Connection failed': ExchangeError,
'Invalid symbol': ExchangeError,
'Invalid order': InvalidOrder,
'Order not found': OrderNotFound,
},
},
})
async def get_token(self):
"""获取或刷新 token - 异步版本"""
if self.token and self.token_checked:
try:
await self.check_connect()
return self.token
except Exception:
# Token 无效,重新连接
pass
# 重新连接获取 token
return await self.connect()
async def connect(self):
"""连接到 MT5 账户并获取 token - 异步版本"""
request = {
'user': self.apiKey,
'password': self.secret,
'host': self.options['host'],
'port': self.options['port'],
'connectTimeoutSeconds': 30,
}
print(f"🔧 Debug: Connect request params: {request}")
response = await self.private_get_connect(request)
print(f"🔧 Debug: Connect response: {response}")
self.token = response
self.token_checked = True
return self.token
async def check_connect(self):
"""检查连接状态 - 异步版本"""
request = {
'id': await self.get_token(),
}
return await self.private_get_check_connect(request)
async def fetch_markets(self, params={}):
"""获取交易对列表"""
if not self.token:
await self.get_token()
request = {
'id': self.token,
}
response = await self.private_get_symbols(self.deep_extend(request, params))
markets = []
if isinstance(response, dict):
for symbol, info in response.items():
market = self.parse_market(info)
if market:
markets.append(market)
return markets
def parse_market(self, info):
"""解析市场信息 - 根据 SymbolInfo 结构修正"""
symbol = info.get('currency', '').upper()
if not symbol:
return None
return {
'id': symbol,
'symbol': symbol,
'base': symbol[:3] if len(symbol) >= 6 else symbol,
'quote': symbol[3:] if len(symbol) >= 6 else 'USD',
'active': True,
'precision': {
'price': info.get('digits', 5),
'amount': 2,
},
'limits': {
'amount': {
'min': 0.01,
'max': None,
},
'price': {
'min': None,
'max': None,
},
'cost': {
'min': None,
'max': None,
},
},
'info': info,
}