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

1167 lines
47 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
import ccxt.async_support
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
from ccxt.base.types import Any, Int, Market, Order, OrderBook, Position, Str, Strings, Ticker, Trade
from ccxt.async_support.base.ws.client import Client
from typing import List
from ccxt.base.errors import ExchangeError
from ccxt.base.errors import BadRequest
class deepcoin(ccxt.async_support.deepcoin):
def describe(self) -> Any:
return self.deep_extend(super(deepcoin, self).describe(), {
'has': {
'ws': True,
'watchTicker': True,
'watchMarkPrice': False,
'watchMarkPrices': False,
'watchTickers': False,
'watchBidsAsks': False,
'watchOrderBook': True,
'watchTrades': True,
'watchTradesForSymbols': False,
'watchOrderBookForSymbols': False,
'watchBalance': False,
'watchLiquidations': False,
'watchLiquidationsForSymbols': False,
'watchMyLiquidations': False,
'watchMyLiquidationsForSymbols': False,
'watchOHLCV': True,
'watchOHLCVForSymbols': False,
'watchOrders': True,
'watchMyTrades': True,
'watchPositions': True,
'watchFundingRate': False,
'watchFundingRates': False,
'createOrderWs': False,
'editOrderWs': False,
'cancelOrderWs': False,
'cancelOrdersWs': False,
'cancelAllOrdersWs': False,
'unWatchTicker': True,
'unWatchTrades': True,
'unWatchOHLCV': True,
'unWatchOrderBook': True,
},
'urls': {
'api': {
'ws': {
'public': {
'spot': 'wss://stream.deepcoin.com/streamlet/trade/public/spot?platform=api',
'swap': 'wss://stream.deepcoin.com/streamlet/trade/public/swap?platform=api',
},
'private': 'wss://stream.deepcoin.com/v1/private',
},
},
},
'options': {
'lastRequestId': None,
'listenKey': None,
'listenKeyExpiryTimestamp': None,
'authenticate': {
'method': 'privateGetDeepcoinListenkeyExtend', # refresh existing listen key or 'privateGetDeepcoinListenkeyAcquire' - get a new one
},
'timeframes': {
'1m': '1m',
'5m': '5m',
'15m': '15m',
'30m': '30m',
'1h': '1h',
'4h': '4h',
'12h': '12h',
'1d': '1d',
'1w': '1w',
'1M': '1o',
'1y': '1y',
},
},
'streaming': {
'ping': self.ping,
},
})
def ping(self, client: Client):
url = client.url
if url.find('private') >= 0:
client.lastPong = self.milliseconds()
# prevent automatic disconnects on private channel
return 'ping'
def handle_pong(self, client: Client, message):
client.lastPong = self.milliseconds()
return message
def request_id(self):
previousValue = self.safe_integer(self.options, 'lastRequestId', 0)
newValue = self.sum(previousValue, 1)
self.options['lastRequestId'] = newValue
return newValue
def create_public_request(self, market: Market, requestId: float, topicID: str, suffix: str = '', unWatch: bool = False):
marketId = market['symbol'] # spot markets use symbol with slash
if market['type'] == 'swap':
marketId = market['baseId'] + market['quoteId'] # swap markets use symbol without slash
action = '1' # subscribe
if unWatch:
action = '0' # unsubscribe
request = {
'sendTopicAction': {
'Action': action,
'FilterValue': 'DeepCoin_' + marketId + suffix,
'LocalNo': requestId,
'ResumeNo': -1, # -1 from the end, 0 from the beginning
'TopicID': topicID,
},
}
return request
async def watch_public(self, market: Market, messageHash: str, topicID: str, params: dict = {}, suffix: str = '') -> Any:
url = self.urls['api']['ws']['public'][market['type']]
requestId = self.request_id()
request = self.create_public_request(market, requestId, topicID, suffix)
subscription = {
'subHash': messageHash,
'id': requestId,
}
return await self.watch(url, messageHash, self.deep_extend(request, params), messageHash, subscription)
async def un_watch_public(self, market: Market, messageHash: str, topicID: str, params: dict = {}, subscription: dict = {}, suffix: str = '') -> Any:
url = self.urls['api']['ws']['public'][market['type']]
requestId = self.request_id()
client = self.client(url)
existingSubscription = self.safe_dict(client.subscriptions, messageHash)
if existingSubscription is None:
raise BadRequest(self.id + ' no subscription for ' + messageHash)
subId = self.safe_integer(existingSubscription, 'id')
request = self.create_public_request(market, subId, topicID, suffix, True) # unsubscribe message uses the same id original subscribe message
unsubHash = 'unsubscribe::' + messageHash
subscription = self.extend(subscription, {
'subHash': messageHash,
'unsubHash': unsubHash,
'symbols': [market['symbol']],
'id': requestId,
})
return await self.watch(url, unsubHash, self.deep_extend(request, params), unsubHash, subscription)
async def watch_private(self, messageHash: str, params: dict = {}) -> Any:
listenKey = await self.authenticate()
url = self.urls['api']['ws']['private'] + '?listenKey=' + listenKey
return await self.watch(url, messageHash, None, 'private', params)
async def authenticate(self, params={}):
self.check_required_credentials()
time = self.milliseconds()
listenKeyExpiryTimestamp = self.safe_integer(self.options, 'listenKeyExpiryTimestamp', time)
expired = (time - listenKeyExpiryTimestamp) > 60000 # 1 minute before expiry
listenKey = self.safe_string(self.options, 'listenKey')
response = None
if listenKey is None:
response = await self.privateGetDeepcoinListenkeyAcquire(params)
elif expired:
method = self.safe_string(self.options, 'method', 'privateGetDeepcoinListenkeyExtend')
getNewKey = (method == 'privateGetDeepcoinListenkeyAcquire')
if getNewKey:
response = await self.privateGetDeepcoinListenkeyAcquire(params)
else:
request: dict = {
'listenkey': listenKey,
}
response = await self.privateGetDeepcoinListenkeyExtend(self.extend(request, params))
if response is not None:
data = self.safe_dict(response, 'data', {})
listenKey = self.safe_string(data, 'listenkey')
listenKeyExpiryTimestamp = self.safe_timestamp(data, 'expire_time')
self.options['listenKey'] = listenKey
self.options['listenKeyExpiryTimestamp'] = listenKeyExpiryTimestamp
return listenKey
async def watch_ticker(self, symbol: str, params={}) -> Ticker:
"""
watches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
https://www.deepcoin.com/docs/publicWS/latestMarketData
:param str symbol: unified symbol of the market to fetch the ticker for
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
"""
await self.load_markets()
market = self.market(symbol)
messageHash = 'ticker' + '::' + market['symbol']
return await self.watch_public(market, messageHash, '7', params)
async def un_watch_ticker(self, symbol: str, params={}) -> Any:
"""
unWatches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
https://www.deepcoin.com/docs/publicWS/latestMarketData
:param str symbol: unified symbol of the market to fetch the ticker for
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
"""
await self.load_markets()
market = self.market(symbol)
messageHash = 'ticker' + '::' + market['symbol']
subscription = {
'topic': 'ticker',
}
return await self.un_watch_public(market, messageHash, '7', params, subscription)
def handle_ticker(self, client: Client, message):
#
# a: 'PO',
# m: 'Success',
# tt: 1760913034780,
# mt: 1760913034780,
# r: [
# {
# d: {
# I: 'BTC/USDT',
# U: 1760913034742,
# PF: 0,
# E: 0,
# O: 108479.9,
# H: 109449.9,
# L: 108238,
# V: 789.3424915,
# T: 43003872.3705223,
# N: 109345,
# M: 87294.7,
# D: 0,
# V2: 3086.4496105,
# T2: 332811624.339836,
# F: 0,
# C: 0,
# BP1: 109344.9,
# AP1: 109345.2
# }
# }
# ]
#
response = self.safe_list(message, 'r', [])
first = self.safe_dict(response, 0, {})
data = self.safe_dict(first, 'd', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
parsedTicker = self.parse_ws_ticker(data, market)
messageHash = 'ticker' + '::' + symbol
self.tickers[symbol] = parsedTicker
client.resolve(parsedTicker, messageHash)
def parse_ws_ticker(self, ticker: dict, market: Market = None) -> Ticker:
#
# {
# I: 'BTC/USDT',
# U: 1760913034742,
# PF: 0,
# E: 0,
# O: 108479.9,
# H: 109449.9,
# L: 108238,
# V: 789.3424915,
# T: 43003872.3705223,
# N: 109345,
# M: 87294.7,
# D: 0,
# V2: 3086.4496105,
# T2: 332811624.339836,
# F: 0,
# C: 0,
# BP1: 109344.9,
# AP1: 109345.2
# }
#
timestamp = self.safe_integer(ticker, 'U')
high = self.safe_number(ticker, 'H')
low = self.safe_number(ticker, 'L')
open = self.safe_number(ticker, 'O')
last = self.safe_number(ticker, 'N')
bid = self.safe_number(ticker, 'BP1')
ask = self.safe_number(ticker, 'AP1')
baseVolume = self.safe_number(ticker, 'V')
quoteVolume = self.safe_number(ticker, 'T')
if market['inverse']:
temp = baseVolume
baseVolume = quoteVolume
quoteVolume = temp
return self.safe_ticker({
'symbol': market['symbol'],
'timestamp': timestamp,
'datetime': self.iso8601(timestamp),
'high': high,
'low': low,
'bid': bid,
'bidVolume': None,
'ask': ask,
'askVolume': None,
'vwap': None,
'open': open,
'close': last,
'last': last,
'previousClose': None,
'change': None,
'percentage': None,
'average': None,
'baseVolume': baseVolume,
'quoteVolume': quoteVolume,
'info': ticker,
}, market)
async def watch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
"""
watches information on multiple trades made in a market
https://www.deepcoin.com/docs/publicWS/lastTransactions
:param str symbol: unified market symbol of the market trades were made in
:param int [since]: the earliest time in ms to fetch orders for
:param int [limit]: the maximum number of trade structures to retrieve
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
"""
await self.load_markets()
market = self.market(symbol)
messageHash = 'trades' + '::' + market['symbol']
trades = await self.watch_public(market, messageHash, '2', params)
if self.newUpdates:
limit = trades.getLimit(symbol, limit)
return self.filter_by_since_limit(trades, since, limit, 'timestamp', True)
async def un_watch_trades(self, symbol: str, params={}):
"""
unWatches the list of most recent trades for a particular symbol
https://www.deepcoin.com/docs/publicWS/lastTransactions
:param str symbol: unified symbol of the market to fetch trades for
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=public-trades>`
"""
await self.load_markets()
market = self.market(symbol)
messageHash = 'trades' + '::' + market['symbol']
subscription = {
'topic': 'trades',
}
return await self.un_watch_public(market, messageHash, '2', params, subscription)
def handle_trades(self, client: Client, message):
#
# {
# "a": "PMT",
# "b": 0,
# "tt": 1760968672380,
# "mt": 1760968672380,
# "r": [
# {
# "d": {
# "TradeID": "1001056452325378",
# "I": "BTC/USDT",
# "D": "1",
# "P": 111061,
# "V": 0.00137,
# "T": 1760968672
# }
# }
# ]
# }
#
response = self.safe_list(message, 'r', [])
first = self.safe_dict(response, 0, {})
data = self.safe_dict(first, 'd', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
if not (symbol in self.trades):
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
self.trades[symbol] = ArrayCache(limit)
strored = self.trades[symbol]
if data is not None:
trade = self.parse_ws_trade(data, market)
strored.append(trade)
messageHash = 'trades' + '::' + symbol
client.resolve(strored, messageHash)
def parse_ws_trade(self, trade: dict, market: Market = None) -> Trade:
#
# watchTrades
# {
# "TradeID": "1001056452325378",
# "I": "BTC/USDT",
# "D": "1",
# "P": 111061,
# "V": 0.00137,
# "T": 1760968672
# }
#
# watchMyTrades
# {
# "A": "9256245",
# "CC": "USDT",
# "CP": 0,
# "D": "0",
# "F": 0.152,
# "I": "DOGE/USDT",
# "IT": 1761048103,
# "M": "9256245",
# "OS": "1001437462198486",
# "P": 0.19443,
# "T": 14.77668,
# "TI": "1001056459096708",
# "TT": 1761048103,
# "V": 76,
# "f": "DOGE",
# "l": 1,
# "m": "1",
# "o": "0"
# }
#
direction = self.safe_string(trade, 'D')
timestamp = self.safe_timestamp_2(trade, 'TT', 'T')
matchRole = self.safe_string(trade, 'm')
fee = None
feeCost = self.safe_string(trade, 'F')
if feeCost is not None:
fee = {
'cost': feeCost,
'currency': self.safe_currency_code(self.safe_string(trade, 'f')),
}
return self.safe_trade({
'info': trade,
'timestamp': timestamp,
'datetime': self.iso8601(timestamp),
'symbol': market['symbol'],
'id': self.safe_string_2(trade, 'TradeID', 'TI'),
'order': self.safe_string(trade, 'OS'),
'type': None,
'takerOrMaker': self.handle_taker_or_maker(matchRole),
'side': self.parse_trade_side(direction),
'price': self.safe_string(trade, 'P'),
'amount': self.safe_string(trade, 'V'),
'cost': self.safe_string(trade, 'T'),
'fee': fee,
}, market)
def parse_trade_side(self, direction: Str) -> Str:
sides = {
'0': 'buy',
'1': 'sell',
}
return self.safe_string(sides, direction, direction)
def handle_taker_or_maker(self, matchRole: Str) -> Str:
roles = {
'0': 'maker',
'1': 'taker',
}
return self.safe_string(roles, matchRole, matchRole)
async def watch_ohlcv(self, symbol: str, timeframe: str = '1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
"""
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
https://www.deepcoin.com/docs/publicWS/KLines
:param str symbol: unified symbol of the market to fetch OHLCV data for
:param str [timeframe]: the length of time each candle represents
:param int [since]: timestamp in ms of the earliest candle to fetch
:param int [limit]: the maximum amount of candles to fetch
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns int[][]: A list of candles ordered, open, high, low, close, volume
"""
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
timeframes = self.safe_dict(self.options, 'timeframes', {})
interval = self.safe_string(timeframes, timeframe, timeframe)
messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe
suffix = '_' + interval
ohlcv = await self.watch_public(market, messageHash, '11', params, suffix)
if self.newUpdates:
limit = ohlcv.getLimit(symbol, limit)
return self.filter_by_since_limit(ohlcv, since, limit, 0, True)
async def un_watch_ohlcv(self, symbol: str, timeframe: str = '1m', params={}) -> Any:
"""
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
https://docs.backpack.exchange/#tag/Streams/Public/K-Line
:param str symbol: unified symbol of the market to fetch OHLCV data for
:param str [timeframe]: the length of time each candle represents
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns int[][]: A list of candles ordered, open, high, low, close, volume
"""
await self.load_markets()
market = self.market(symbol)
symbol = market['symbol']
timeframes = self.safe_dict(self.options, 'timeframes', {})
interval = self.safe_string(timeframes, timeframe, timeframe)
messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe
suffix = '_' + interval
subscription = {
'topic': 'ohlcv',
'symbolsAndTimeframes': [[symbol, timeframe]],
}
return await self.un_watch_public(market, messageHash, '11', params, subscription, suffix)
def handle_ohlcv(self, client: Client, message):
#
# {
# "a": "PK",
# "tt": 1760972831580,
# "mt": 1760972831580,
# "r": [
# {
# "d": {
# "I": "BTC/USDT",
# "P": "1m",
# "B": 1760972820,
# "O": 111373,
# "C": 111382.9,
# "H": 111382.9,
# "L": 111373,
# "V": 0.2414172,
# "M": 26888.19693324
# },
# "t": "LK"
# }
# ]
# }
#
response = self.safe_list(message, 'r', [])
first = self.safe_dict(response, 0, {})
data = self.safe_dict(first, 'd', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
interval = self.safe_string(data, 'P')
timeframe = self.find_timeframe(interval)
if not (symbol in self.ohlcvs):
self.ohlcvs[symbol] = {}
if not (timeframe in self.ohlcvs[symbol]):
limit = self.safe_integer(self.options, 'OHLCVLimit', 1000)
self.ohlcvs[symbol][timeframe] = ArrayCacheByTimestamp(limit)
stored = self.ohlcvs[symbol][timeframe]
if data is not None:
ohlcv = self.parse_ws_ohlcv(data, market)
stored.append(ohlcv)
messageHash = 'ohlcv' + '::' + symbol + '::' + timeframe
client.resolve(stored, messageHash)
def parse_ws_ohlcv(self, ohlcv, market: Market = None) -> list:
#
# {
# "I": "BTC/USDT",
# "P": "1m",
# "B": 1760972820,
# "O": 111373,
# "C": 111382.9,
# "H": 111382.9,
# "L": 111373,
# "V": 0.2414172,
# "M": 26888.19693324
# }
#
return [
self.safe_timestamp(ohlcv, 'B'),
self.safe_number(ohlcv, 'O'),
self.safe_number(ohlcv, 'H'),
self.safe_number(ohlcv, 'L'),
self.safe_number(ohlcv, 'C'),
self.safe_number(ohlcv, 'V'),
]
async def watch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
"""
watches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData
:param str symbol: unified symbol of the market to fetch the order book for
:param int [limit]: the maximum amount of order book entries to return.
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
"""
await self.load_markets()
market = self.market(symbol)
messageHash = 'orderbook' + '::' + market['symbol']
suffix = '_0.1'
orderbook = await self.watch_public(market, messageHash, '25', params, suffix)
return orderbook.limit()
async def un_watch_order_book(self, symbol: str, params={}) -> Any:
"""
unWatches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
https://www.deepcoin.com/docs/publicWS/25LevelIncrementalMarketData
:param str symbol: unified array of symbols
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
"""
await self.load_markets()
market = self.market(symbol)
messageHash = 'orderbook' + '::' + market['symbol']
suffix = '_0.1'
subscription = {
'topic': 'orderbook',
}
return await self.un_watch_public(market, messageHash, '25', params, subscription, suffix)
def handle_order_book(self, client: Client, message):
#
# {
# "a": "PMO",
# "t": "i", # i - update, f - snapshot
# "r": [
# {
# "d": {"I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979}
# },
# {
# "d": {"I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724}
# }
# ],
# "tt": 1760975816446,
# "mt": 1760975816446
# }
#
response = self.safe_list(message, 'r', [])
first = self.safe_dict(response, 0, {})
data = self.safe_dict(first, 'd', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
if not (symbol in self.orderbooks):
self.orderbooks[symbol] = self.order_book()
orderbook = self.orderbooks[symbol]
type = self.safe_string(message, 't')
if orderbook['timestamp'] is None:
if type == 'f':
# snapshot
self.handle_order_book_snapshot(client, message)
else:
# cache the updates until the snapshot is received
orderbook.cache.append(message)
else:
self.handle_order_book_message(client, message, orderbook)
messageHash = 'orderbook' + '::' + symbol
client.resolve(orderbook, messageHash)
def handle_order_book_snapshot(self, client: Client, message):
entries = self.safe_list(message, 'r', [])
first = self.safe_dict(entries, 0, {})
data = self.safe_dict(first, 'd', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
orderbook = self.orderbooks[symbol]
orderedEntries: dict = {
'bids': [],
'asks': [],
}
for i in range(0, len(entries)):
entry = entries[i]
entryData = self.safe_dict(entry, 'd', {})
side = self.safe_string(entryData, 'D')
price = self.safe_number(entryData, 'P')
volume = self.safe_number(entryData, 'V')
if side == '0':
# bid
orderedEntries['bids'].append([price, volume])
elif side == '1':
# ask
orderedEntries['asks'].append([price, volume])
timestamp = self.safe_integer(message, 'mt')
snapshot = self.parse_order_book(orderedEntries, symbol, timestamp)
orderbook.reset(snapshot)
cachedMessages = orderbook.cache
for j in range(0, len(cachedMessages)):
cachedMessage = cachedMessages[j]
self.handle_order_book_message(client, cachedMessage, orderbook)
orderbook.cache = []
messageHash = 'orderbook' + '::' + symbol
client.resolve(orderbook, messageHash)
def handle_order_book_message(self, client: Client, message, orderbook):
# {
# "a": "PMO",
# "t": "i", # i - update, f - snapshot
# "r": [
# {
# "d": {"I": "ETH/USDT", "D": "1", "P": 4021, "V": 54.39979}
# },
# {
# "d": {"I": "ETH/USDT", "D": "0", "P": 4021.1, "V": 49.56724}
# }
# ],
# "tt": 1760975816446,
# "mt": 1760975816446
# }
#
timestamp = self.safe_integer(message, 'mt')
if timestamp > orderbook['timestamp']:
response = self.safe_list(message, 'r', [])
self.handle_deltas(orderbook, response)
orderbook['timestamp'] = timestamp
orderbook['datetime'] = self.iso8601(timestamp)
def handle_delta(self, orderbook, entry):
data = self.safe_dict(entry, 'd', {})
bids = orderbook['bids']
asks = orderbook['asks']
side = self.safe_string(data, 'D')
price = self.safe_number(data, 'P')
volume = self.safe_number(data, 'V')
if side == '0':
# bid
bids.store(price, volume)
elif side == '1':
# ask
asks.store(price, volume)
async def watch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
"""
watches information on multiple trades made by the user
https://www.deepcoin.com/docs/privateWS/Trade
:param str symbol: unified market symbol of the market orders were made in
:param int [since]: the earliest time in ms to fetch orders for
:param int [limit]: the maximum number of order structures to retrieve
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
"""
messageHash = 'myTrades'
await self.load_markets()
if symbol is not None:
symbol = self.symbol(symbol)
messageHash += '::' + symbol
trades = await self.watch_private(messageHash, params)
if self.newUpdates:
limit = trades.getLimit(symbol, limit)
return self.filter_by_symbol_since_limit(trades, symbol, since, limit, True)
def handle_my_trade(self, client: Client, message):
#
# {
# "action": "PushTrade",
# "result": [
# {
# "table": "Trade",
# "data": {
# "A": "9256245",
# "CC": "USDT",
# "CP": 0,
# "D": "0",
# "F": 0.152,
# "I": "DOGE/USDT",
# "IT": 1761048103,
# "M": "9256245",
# "OS": "1001437462198486",
# "P": 0.19443,
# "T": 14.77668,
# "TI": "1001056459096708",
# "TT": 1761048103,
# "V": 76,
# "f": "DOGE",
# "l": 1,
# "m": "1",
# "o": "0"
# }
# }
# ]
# }
#
result = self.safe_list(message, 'result', [])
first = self.safe_dict(result, 0, {})
data = self.safe_dict(first, 'data', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
messageHash = 'myTrades'
symbolMessageHash = messageHash + '::' + symbol
if (messageHash in client.futures) or (symbolMessageHash in client.futures):
if self.myTrades is None:
limit = self.safe_integer(self.options, 'tradesLimit', 1000)
self.myTrades = ArrayCacheBySymbolById(limit)
stored = self.myTrades
parsed = self.parse_ws_trade(data, market)
stored.append(parsed)
client.resolve(stored, messageHash)
client.resolve(stored, symbolMessageHash)
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
"""
watches information on multiple orders made by the user
https://www.deepcoin.com/docs/privateWS/order
:param str symbol: unified market symbol of the market orders were made in
:param int [since]: the earliest time in ms to fetch orders for
:param int [limit]: the maximum number of order structures to retrieve
:param dict [params]: extra parameters specific to the exchange API endpoint
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
"""
messageHash = 'orders'
await self.load_markets()
if symbol is not None:
symbol = self.symbol(symbol)
messageHash += '::' + symbol
orders = await self.watch_private(messageHash, params)
if self.newUpdates:
limit = orders.getLimit(symbol, limit)
return self.filter_by_symbol_since_limit(orders, symbol, since, limit, True)
def handle_order(self, client: Client, message):
#
# {
# "action": "PushOrder",
# "result": [
# {
# "table": "Order",
# "data": {
# "D": "0",
# "I": "DOGE/USDT",
# "IT": 1761051006,
# "L": "1001437480817468",
# "OPT": "4",
# "OS": "1001437480817468",
# "OT": "0",
# "Or": "1",
# "P": 0.19537,
# "T": 14.84128,
# "U": 1761051006,
# "V": 76,
# "VT": 76,
# "i": 1,
# "l": 1,
# "o": "0",
# "p": "0",
# "t": 0.19528
# }
# }
# ]
# }
#
result = self.safe_list(message, 'result', [])
first = self.safe_dict(result, 0, {})
data = self.safe_dict(first, 'data', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
messageHash = 'orders'
symbolMessageHash = messageHash + '::' + symbol
if (messageHash in client.futures) or (symbolMessageHash in client.futures):
if self.orders is None:
limit = self.safe_integer(self.options, 'ordersLimit', 1000)
self.orders = ArrayCacheBySymbolById(limit)
parsed = self.parse_ws_order(data, market)
self.orders.append(parsed)
client.resolve(self.orders, messageHash)
client.resolve(self.orders, symbolMessageHash)
def parse_ws_order(self, order, market: Market = None) -> Order:
#
# {
# "D": "0",
# "I": "DOGE/USDT",
# "IT": 1761051006,
# "L": "1001437480817468",
# "OPT": "4",
# "OS": "1001437480817468",
# "OT": "0",
# "Or": "1",
# "P": 0.19537,
# "T": 14.84128,
# "U": 1761051006,
# "V": 76,
# "VT": 76,
# "i": 1,
# "l": 1,
# "o": "0",
# "p": "0",
# "t": 0.19528
# }
#
state = self.safe_string(order, 'Or')
timestamp = self.safe_timestamp(order, 'IT')
direction = self.safe_string(order, 'D')
return self.safe_order({
'id': self.safe_string(order, 'OS'),
'clientOrderId': None,
'datetime': self.iso8601(timestamp),
'timestamp': timestamp,
'lastTradeTimestamp': None,
'lastUpdateTimestamp': self.safe_timestamp(order, 'U'),
'status': self.parse_ws_order_status(state),
'symbol': market['symbol'],
'type': None,
'timeInForce': None,
'side': self.parse_trade_side(direction),
'price': self.safe_string(order, 'P'),
'average': self.safe_string(order, 't'),
'amount': self.safe_string(order, 'V'),
'filled': self.safe_string(order, 'VT'),
'remaining': None,
'triggerPrice': None,
'takeProfitPrice': self.safe_string(order, 'TPT'),
'stopLossPrice': self.safe_string(order, 'SLT'),
'cost': self.safe_string(order, 'T'),
'trades': None,
'fee': None,
'reduceOnly': None,
'postOnly': None,
'info': order,
}, market)
def parse_ws_order_status(self, status: Str) -> Str:
statuses = {
'1': 'closed',
'4': 'open',
'6': 'canceled',
}
return self.safe_string(statuses, status, status)
async def watch_positions(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
"""
watch all open positions
https://www.deepcoin.com/docs/privateWS/Position
:param str[] [symbols]: list of unified market symbols to watch positions for
:param int [since]: the earliest time in ms to fetch positions for
:param int [limit]: the maximum number of positions to retrieve
:param dict params: extra parameters specific to the exchange API endpoint
:returns dict[]: a list of `position structure <https://docs.ccxt.com/en/latest/manual.html#position-structure>`
"""
await self.load_markets()
listenKey = await self.authenticate()
symbols = self.market_symbols(symbols)
messageHash = 'positions'
messageHashes = []
if symbols is not None:
for i in range(0, len(symbols)):
symbol = symbols[i]
symbolMessageHash = messageHash + '::' + symbol
messageHashes.append(symbolMessageHash)
else:
messageHashes.append(messageHash)
url = self.urls['api']['ws']['private'] + '?listenKey=' + listenKey
positions = await self.watch_multiple(url, messageHashes, params, ['private'])
if self.newUpdates:
return positions
return self.filter_by_symbols_since_limit(self.positions, symbols, since, limit, True)
def handle_position(self, client: Client, message):
#
# {
# "action": "PushPosition",
# "result": [
# {
# "table": "Position",
# "data": {
# "A": "9256245",
# "CP": 0,
# "I": "DOGE/USDT",
# "M": "9256245",
# "OP": 0.198845,
# "Po": 151.696,
# "U": 1761058213,
# "i": 1,
# "l": 1,
# "p": "0",
# "u": 0
# }
# }
# ]
# }
#
result = self.safe_list(message, 'result', [])
first = self.safe_dict(result, 0, {})
data = self.safe_dict(first, 'data', {})
marketId = self.safe_string(data, 'I')
market = self.safe_market(marketId, None, '/')
symbol = self.safe_symbol(marketId, market)
messageHash = 'positions'
symbolMessageHash = messageHash + '::' + symbol
if (messageHash in client.futures) or (symbolMessageHash in client.futures):
if self.positions is None:
self.positions = ArrayCacheBySymbolBySide()
parsed = self.parse_ws_position(data, market)
self.positions.append(parsed)
client.resolve(self.positions, messageHash)
client.resolve(self.positions, symbolMessageHash)
def parse_ws_position(self, position, market: Market = None) -> Position:
#
# {
# "A": "9256245",
# "CP": 0,
# "I": "DOGE/USDT",
# "M": "9256245",
# "OP": 0.198845,
# "Po": 151.696,
# "U": 1761058213,
# "i": 1,
# "l": 1,
# "p": "0",
# "u": 0
# }
#
timestamp = self.safe_integer(position, 'U')
direction = self.safe_string(position, 'p')
marginMode = self.safe_string(position, 'i')
return self.safe_position({
'symbol': market['symbol'],
'id': None,
'timestamp': timestamp,
'datetime': self.iso8601(timestamp),
'contracts': self.safe_string(position, 'Po'),
'contractSize': None,
'side': self.parse_position_side(direction),
'notional': None,
'leverage': self.omit_zero(self.safe_string(position, 'l')),
'unrealizedPnl': None,
'realizedPnl': None,
'collateral': None,
'entryPrice': self.safe_string(position, 'OP'),
'markPrice': None,
'liquidationPrice': None,
'marginMode': self.parse_ws_margin_mode(marginMode),
'hedged': True,
'maintenanceMargin': self.safe_string(position, 'u'),
'maintenanceMarginPercentage': None,
'initialMargin': None,
'initialMarginPercentage': None,
'marginRatio': None,
'lastUpdateTimestamp': None,
'lastPrice': None,
'stopLossPrice': None,
'takeProfitPrice': None,
'percentage': None,
'info': position,
})
def parse_position_side(self, direction: Str) -> Str:
if direction is None:
return direction
directions = {
'0': 'long',
'1': 'short',
}
return self.safe_string(directions, direction, direction)
def parse_ws_margin_mode(self, marginMode: Str) -> Str:
if marginMode is None:
return marginMode
modes = {
'0': 'isolated',
'1': 'cross',
}
return self.safe_string(modes, marginMode, marginMode)
def handle_message(self, client: Client, message):
if message == 'pong':
self.handle_pong(client, message)
else:
m = self.safe_string(message, 'm')
if (m is not None) and (m != 'Success'):
self.handle_error_message(client, message)
action = self.safe_string_2(message, 'a', 'action')
if action == 'RecvTopicAction':
self.handle_subscription_status(client, message)
elif action == 'PO':
self.handle_ticker(client, message)
elif action == 'PMT':
self.handle_trades(client, message)
elif action == 'PK':
self.handle_ohlcv(client, message)
elif action == 'PMO':
self.handle_order_book(client, message)
elif action == 'PushTrade':
self.handle_my_trade(client, message)
elif action == 'PushOrder':
self.handle_order(client, message)
elif action == 'PushPosition':
self.handle_position(client, message)
def handle_subscription_status(self, client: Client, message):
#
# {
# "a": "RecvTopicAction",
# "m": "Success",
# "r": [
# {
# "d": {
# "A": "0",
# "L": 1,
# "T": "7",
# "F": "DeepCoin_BTC/USDT",
# "R": -1
# }
# }
# ]
# }
#
response = self.safe_list(message, 'r', [])
first = self.safe_dict(response, 0, {})
data = self.safe_dict(first, 'd', {})
action = self.safe_string(data, 'A') # 1 = subscribe, 0 = unsubscribe
if action == '0':
subscriptionsById = self.index_by(client.subscriptions, 'id')
subId = self.safe_integer(data, 'L')
subscription = self.safe_dict(subscriptionsById, subId, {}) # original watch subscription
subHash = self.safe_string(subscription, 'subHash')
unsubHash = 'unsubscribe::' + subHash
unsubsciption = self.safe_dict(client.subscriptions, unsubHash, {}) # unWatch subscription
self.handle_un_subscription(client, unsubsciption)
def handle_un_subscription(self, client: Client, subscription: dict):
subHash = self.safe_string(subscription, 'subHash')
unsubHash = self.safe_string(subscription, 'unsubHash')
self.clean_unsubscription(client, subHash, unsubHash)
self.clean_cache(subscription)
def handle_error_message(self, client: Client, message):
#
# {
# "a": "RecvTopicAction",
# "m": "subscription cluster does not "exist": BTC/USD",
# "r": [
# {
# "d": {
# "A": "1",
# "L": 1,
# "T": "7",
# "F": "DeepCoin_BTC/USD",
# "R": -1
# }
# }
# ]
# }
#
messageText = self.safe_string(message, 'm', '')
response = self.safe_list(message, 'r', [])
first = self.safe_dict(response, 0, {})
data = self.safe_dict(first, 'd', {})
requestId = self.safe_integer(data, 'L')
subscriptionsById = self.index_by(client.subscriptions, 'id')
subscription = self.safe_dict(subscriptionsById, requestId, {})
messageHash = self.safe_string(subscription, 'subHash')
feedback = self.id + ' ' + self.json(message)
try:
self.throw_exactly_matched_exception(self.exceptions['exact'], messageText, feedback)
self.throw_broadly_matched_exception(self.exceptions['broad'], messageText, feedback)
raise ExchangeError(feedback)
except Exception as e:
client.reject(e, messageHash)