Manual do CCXT Pro
CCXT Pro é uma parte gratuita do CCXT que adiciona suporte a streaming via WebSocket: https://github.com/ccxt/ccxt/issues/15171
Manual
CCXT Pro é uma parte gratuita do CCXT que adiciona suporte a streaming via WebSocket: https://github.com/ccxt/ccxt/issues/15171
A pilha do CCXT Pro é construída sobre o CCXT e estende as classes principais do CCXT, usando:
- Mixins em nível de protótipo JavaScript
- Herança múltipla em Python
- Traits em PHP
- Herança de classe em Java (as classes de exchange pro estendem as classes de exchange base)
O CCXT Pro depende fortemente do transpilador do CCXT para suporte a múltiplos idiomas.
User
+-------------------------------------------------------------+
| CCXT Pro |
+------------------------------+------------------------------+
| Public . Private |
+=============================================================+
│ . |
│ The Unified CCXT Pro API |
| . |
| loadMarkets . watchBalance |
| watchTicker . watchOrders |
| watchTickers . watchMyTrades |
| watchOrderBook . watchPositions |
| watchOHLCV . createOrderWs |
| watchStatus . editOrderWs |
| watchTrades . cancelOrderWs |
│ watchOHLCVForSymbols . cancelOrdersWs |
│ watchTradesForSymbols . cancelAllOrdersWs |
│ watchOrderBookForSymbols . |
│ . |
+=============================================================+
│ unWatch |
│ (to stop **watch** method) |
+=============================================================+
│ . |
| The Underlying Exchange-Specific APIs |
| (Derived Classes And Their Implementations) |
│ . |
+=============================================================+
│ . |
| CCXT Pro Base Exchange Class |
│ . |
+=============================================================+
+-------------------------------------------------------------+
| |
| CCXT |
| |
+=============================================================+Exchanges
A biblioteca CCXT Pro suporta atualmente os seguintes 74 mercados de criptomoedas e APIs de negociação via WebSocket:| logo | id | name | ver | type | certified | pro |
|---|---|---|---|---|---|---|
| aftermath | AftermathFinance | |||||
| alpaca | Alpaca | |||||
| apex | Apex | |||||
| arkham | ARKHAM | |||||
| ascendex | AscendEX | |||||
| aster | Aster | |||||
| backpack | Backpack | |||||
| bequant | Bequant | |||||
| binance | Binance | |||||
| binancecoinm | Binance COIN-M | |||||
| binanceus | Binance US | |||||
| binanceusdm | Binance USDⓈ-M | |||||
![]() | bingx | BingX | ||||
| bitfinex | Bitfinex | |||||
| bitget | Bitget | |||||
| bithumb | Bithumb | |||||
| bitmart | BitMart | |||||
| bitmex | BitMEX | |||||
| bitopro | BitoPro | |||||
| bitrue | Bitrue | |||||
| bitstamp | Bitstamp | |||||
![]() | bittrade | BitTrade | ||||
| bitvavo | Bitvavo | |||||
| blockchaincom | Blockchain.com | |||||
| blofin | BloFin | |||||
| bullish | Bullish | |||||
| bybit | Bybit | |||||
| bybiteu | Bybit EU | |||||
| bydfi | BYDFi | |||||
![]() | cex | CEX.IO | ||||
![]() | coinbase | Coinbase Advanced | ||||
| coinbaseexchange | Coinbase Exchange | |||||
| coinbaseinternational | Coinbase International | |||||
![]() | coinex | CoinEx | ||||
![]() | cryptocom | Crypto.com | ||||
| deepcoin | DeepCoin | |||||
![]() | deribit | Deribit | ||||
| derive | derive | |||||
| dydx | dYdX | |||||
| gate | Gate | |||||
![]() | gemini | Gemini | ||||
| grvt | GRVT | |||||
| hashkey | HashKey Global | |||||
![]() | hollaex | HollaEx | ||||
![]() | htx | HTX | ||||
| hyperliquid | Hyperliquid | |||||
![]() | independentreserve | Independent Reserve | ||||
![]() | kraken | Kraken | ||||
![]() | krakenfutures | Kraken Futures | ||||
![]() | kucoin | KuCoin | ||||
![]() | kucoinfutures | KuCoin Futures | ||||
![]() | lbank | LBank | ||||
| lighter | Lighter | |||||
![]() | luno | luno | ||||
![]() | mexc | MEXC Global | ||||
| modetrade | Mode Trade | |||||
![]() | myokx | MyOKX (EEA) | ||||
![]() | ndax | NDAX | ||||
![]() | okx | OKX | ||||
![]() | okxus | OKX (US) | ||||
| onetrading | One Trading | |||||
| oxfun | OXFUN | |||||
| p2b | p2b | |||||
| pacifica | Pacifica | |||||
| paradex | Paradex | |||||
![]() | phemex | Phemex | ||||
![]() | poloniex | Poloniex | ||||
| toobit | Toobit | |||||
![]() | upbit | Upbit | ||||
| weex | Weex | |||||
![]() | whitebit | WhiteBit | ||||
![]() | woo | WOO X | ||||
| woofipro | WOOFI PRO | |||||
![]() | xt | XT |
Esta é a lista de exchanges no CCXT Pro com suporte a APIs WebSockets. Esta lista será atualizada com novas exchanges regularmente.
Lista completa de exchanges disponíveis no CCXT via REST: Mercados de Exchange de Criptomoedas Suportados.
Utilização
- this part of the doc is under heavy development right now
- there may be some typos, mistakes and missing info here and there
- contributions, pull requests and feedback appreciatedPré-requisitos
A melhor forma de compreender o CCXT Pro é garantir que você domina todo o Manual do CCXT e pratica o CCXT padrão primeiro. O CCXT Pro se apoia no CCXT. As duas bibliotecas compartilham muitas características em comum, incluindo:
- os conceitos de API pública e API privada autenticada
- mercados, símbolos, códigos de moeda e ids
- estruturas e formatos de dados unificados, livros de ordens, negociações, ordens, velas, timeframes, ...
- exceções e mapeamentos de erros
- autenticação e chaves de API (para feeds e chamadas privadas)
- opções de configuração
O público do CCXT Pro é composto principalmente por traders algorítmicos profissionais e desenvolvedores. Para trabalhar de forma eficiente com esta biblioteca, o utilizador deve estar bem familiarizado com os conceitos de streaming. É necessário compreender as diferenças subjacentes entre APIs de streaming baseadas em conexão (WebSocket, CCXT Pro) e APIs baseadas em requisição-resposta (REST, CCXT).
O fluxo geral de estilo assíncrono para uma aplicação CCXT é o seguinte:
// a RESTful orderbook polling request-response loop
while (condition) {
try {
// fetch some of the public data
orderbook = await exchange.fetchOrderBook (symbol, limit)
// do something or react somehow based on that data
// ...
} catch (e) {
// handle errors
}
}No CCXT Pro, cada método RESTful unificado público e privado com prefixo fetch* também possui um método correspondente baseado em stream com prefixo watch*, como segue:
- API Pública
fetchStatus→watchStatusfetchOrderBook→watchOrderBookfetchOrderBookForSymbols→watchOrderBookForSymbolsfetchTicker→watchTickerfetchTickers→watchTickersfetchOHLCV→watchOHLCVfetchOHLCVForSymbols→watchOHLCVForSymbolsfetchTrades→watchTradesfetchTradesForSymbols→watchTradesForSymbolsfetchBidsAsks→watchBidsAsksfetchLiquidations→watchLiquidationsfetchLiquidationsForSymbols→watchLiquidationsForSymbols
- API Privada
fetchBalance→watchBalancefetchOrders→watchOrdersfetchOrdersForSymbols→watchOrdersForSymbolsfetchMyTrades→watchMyTradesfetchPosition→watchPositionfetchPositions→watchPositionsfetchLiquidations→watchLiquidationsfetchMyLiquidations→watchMyLiquidationsfetchMyLiquidationsForSymbols→watchMyLiquidationsForSymbolsfetchFundingRates→watchFundingRates
- Alternativas REST
fetchTrades→fetchTradesWscreateOrder→createOrderWseditOrder→editOrderWscancelOrder→cancelOrderWscancelOrders→cancelOrdersWscancelAllOrders→cancelAllOrdersWs- etc ...
- unWatch (interrompe a subscrição em segundo plano para os métodos
watch)unWatchOrderBookunWatchOrderBooksForSymbolsunWatchTradesunWatchTradesForSymbolsunWatchOHLCVForSymbolsunWatchOrderBookForSymbolsunWatchPositionsunWatchTickersunWatchMyTradesunWatchTickerunWatchOHLCVunWatchOrders
A API de Streaming Unificada do CCXT Pro herda os padrões de uso do CCXT para facilitar a migração.
O fluxo geral de estilo assíncrono para uma aplicação CCXT Pro (em oposição a uma aplicação CCXT acima) é apresentado abaixo:
// a stream-based (WebSocket) orderbook feed loop
while (condition) {
try {
// watch some of the public data
orderbook = await exchange.watchOrderBook (symbol, limit)
// do something or react somehow based on that data
// ...
} catch (e) {
// handle errors
}
}Esse padrão de uso normalmente é encapsulado em um método de lógica de negócio central chamado "função tick()", uma vez que reitera uma reação aos eventos recebidos (também conhecidos como ticks). Pelos dois exemplos acima, fica evidente que o padrão de uso genérico no CCXT Pro e no CCXT é idêntico.
Muitas das regras e conceitos do CCXT também se aplicam ao CCXT Pro:
- O CCXT Pro carregará mercados e os armazenará em cache na primeira chamada a um método de API unificada
- O CCXT Pro chamará métodos RESTful do CCXT internamente, se necessário
- O CCXT Pro lançará exceções padrão do CCXT quando necessário
- ...
Especificidades do Streaming
Apesar das numerosas características em comum, as APIs baseadas em streaming possuem suas próprias especificidades, devido à sua natureza orientada a conexão.
Ter uma interface baseada em conexão implica mecanismos de gestão de conexão. As conexões são gerenciadas pelo CCXT Pro de forma transparente para o utilizador. Cada instância de exchange gerencia seu próprio conjunto de conexões.
Na sua primeira chamada a qualquer método watch*(), a biblioteca estabelecerá uma conexão com um stream/recurso específico da exchange e a manterá. Se a conexão já existir, ela será reutilizada. A biblioteca tratará as sequências de mensagens de requisição/resposta de subscrição, bem como a autenticação/assinatura caso o stream solicitado seja privado.
A biblioteca também monitorará o estado do uplink e manterá a conexão ativa. Diante de uma exceção crítica, desconexão ou timeout/falha de conexão, a próxima iteração da função tick chamará o método watch, que acionará uma reconexão. Desta forma, a biblioteca trata as desconexões e reconexões para o utilizador de forma transparente. O CCXT Pro aplica os limites de taxa necessários e atrasos de reconexão com backoff exponencial. Toda essa funcionalidade está habilitada por padrão e pode ser configurada através das propriedades da exchange, como de costume.
A maioria das exchanges possui apenas uma URL base para APIs de streaming (geralmente WebSocket, iniciando com ws:// ou wss://). Algumas podem ter mais de uma URL para cada stream, dependendo do feed em questão.
As APIs de Streaming das exchanges podem ser classificadas em duas categorias diferentes:
- sub ou subscribe permite apenas receber
- pub ou publish permite enviar e receber
Sub
Uma interface sub geralmente permite subscrever a um stream de dados e escutá-lo. A maioria das exchanges que suportam WebSockets oferecerá apenas uma API do tipo sub. O tipo sub inclui o streaming de dados públicos de mercado. Às vezes, as exchanges também permitem subscrever dados privados do utilizador. Após o utilizador subscrever a um feed de dados, o canal começa a funcionar de forma unidirecional, enviando atualizações da exchange para o utilizador continuamente.
Tipos comuns de streams de dados públicos:
- livro de ordens (mais comum) - atualizações sobre ordens adicionadas, editadas e eliminadas (também conhecidas como deltas de mudança)
- atualizações de ticker com mudança das estatísticas de 24 horas
- feed de execuções (também comum) - um stream ao vivo de negociações públicas
- feed de velas ohlcv
- heartbeat
- chat/trollbox da exchange
Tipos menos comuns de streams de dados privados do utilizador:
- o stream de negociações privadas do utilizador
- atualizações de ordens ao vivo
- atualizações de saldo
- streams personalizados
- streams específicos da exchange e outros
Pub
Uma interface pub geralmente permite que os utilizadores enviem requisições de dados para o servidor. Isso normalmente inclui ações comuns do utilizador, como:
- colocação de ordens
- cancelamento de ordens
- colocação de requisições de saque
- publicação de mensagens no chat/trollbox
- etc
Algumas exchanges não oferecem uma API WS do tipo pub, oferecendo apenas a API WS do tipo sub. No entanto, existem exchanges que possuem uma API de Streaming completa. Na maioria dos casos, um utilizador não consegue operar de forma eficaz apenas com a API de Streaming. As exchanges farão streaming de dados públicos de mercado via sub, e a API REST ainda é necessária para a parte pub quando ausente.
unWatch
Cada método watchX estabelece uma subscrição com um stream e continuará recebendo atualizações da exchange. Mesmo que você pare de obter o valor de retorno do método watchX, o stream continuará enviando dados, que são tratados e armazenados em segundo plano. Para interromper essas subscrições em segundo plano, você deve usar o método unWatch (ex.: watchTrades -> unWatchTrades).
Estruturas de Dados Incrementais
Em muitos casos, devido à natureza unidirecional dos feeds de dados subjacentes, a aplicação que escuta no lado do cliente precisa manter um snapshot local dos dados na memória e mesclar as atualizações recebidas do servidor da exchange no snapshot local. As atualizações provenientes da exchange também são frequentemente chamadas de deltas, porque na maioria dos casos essas atualizações conterão apenas as mudanças entre dois estados dos dados e não incluirão os dados que não mudaram, tornando necessário armazenar o estado atual S em cache local de todos os objetos de dados relevantes.
Toda essa funcionalidade é tratada pelo CCXT Pro para o utilizador. Para trabalhar com o CCXT Pro, o utilizador não precisa rastrear ou gerenciar subscrições e dados relacionados. O CCXT Pro manterá um cache de estruturas na memória para lidar com a complexidade subjacente.
Cada atualização recebida indica quais partes dos dados mudaram, e o lado receptor "incrementa" o estado local S mesclando a atualização sobre o estado atual S, movendo para o próximo estado local S'. Em termos de CCXT Pro, isso é chamado de "estado incremental" e as estruturas envolvidas no processo de armazenamento e atualização do estado em cache são chamadas de "estruturas incrementais". O CCXT Pro introduz várias novas classes base para tratar o estado incremental quando necessário.
As estruturas incrementais retornadas pelos métodos unificados do CCXT Pro são geralmente de um dos dois tipos:
- Objeto decodificado em JSON (
objectem JavaScript,dictem Python,array()em PHP). Este tipo pode ser retornado por métodos públicos e privados comowatchOrderBook,watchTicker,watchBalance,watchOrder, etc. - Um array/lista de objetos (geralmente ordenados em ordem cronológica). Este tipo pode ser retornado por métodos como
watchOHLCV,watchTrades,watchMyTrades,watchOrders, etc.
Os métodos unificados que retornam arrays como watchOHLCV, watchTrades, watchMyTrades, watchOrders, são baseados na camada de cache. O utilizador precisa compreender o funcionamento interno da camada de cache para trabalhar com ela de forma eficiente.
O cache é uma deque de tamanho fixo, também conhecida como array/lista com duas extremidades. A biblioteca CCXT Pro tem um limite razoável no número de objetos armazenados na memória. Por padrão, as estruturas de array em cache armazenarão até 1000 entradas de cada tipo (1000 negociações mais recentes, 1000 velas mais recentes, 1000 ordens mais recentes). O número máximo permitido pode ser configurado pelo utilizador na instanciação ou posteriormente:
ccxtpro.binance({
'options': {
'tradesLimit': 1000,
'OHLCVLimit': 1000,
'ordersLimit': 1000,
},
})
# or
exchange.options['tradesLimit'] = 1000
exchange.options['OHLCVLimit'] = 1000
exchange.options['ordersLimit'] = 1000Os limites do cache devem ser definidos antes de chamar qualquer método watch e não podem ser alterados durante a execução do programa.
Quando há espaço disponível no cache, novos elementos são simplesmente adicionados ao final. Se não houver espaço suficiente para um novo elemento, o elemento mais antigo é excluído do início do cache para liberar espaço. Assim, por exemplo, o cache cresce de 0 até 1000 negociações mais recentes e depois permanece no máximo de 1000 negociações mais recentes, renovando constantemente os dados armazenados a cada nova atualização recebida da exchange. Isso lembra uma janela deslizante ou uma porta deslizante, que se parece com o mostrado abaixo:
past > ------------------ > time > - - - - - - - - > future
sliding frame
of 1000 most
recent trades
+-----------------+
| |
|===========+=====|
+----------------+------| | | - - - - - + - - - - - - - - + - - -
| | | | | | |
0 1000 | 2000 | 3000 4000 ...
| | | | | | |
+----------------+------| | | - - - - - + - - - - - - - - + - - -
|===========+=====|
| |
+---+---------+---+
| |
since ^ ^ limit
date-based pagination arguments
are always applied
within the cached frameO utilizador pode configurar os limites do cache usando exchange.options conforme mostrado acima. Não confunda os limites do cache com o limite de paginação.
Observe que os parâmetros since e limit de paginação baseada em data têm um significado diferente e são sempre aplicados dentro da janela em cache! Se o utilizador especificar um argumento since na chamada watchTrades(), o CCXT Pro retornará todas as negociações em cache com timestamp >= since. Se o utilizador não especificar um argumento since, o CCXT Pro retornará as negociações em cache desde o início da janela deslizante. Se o utilizador especificar um argumento limit, a biblioteca retornará até limit velas a partir de since ou desde o início do cache. Por essa razão, o utilizador não pode paginar além do frame em cache devido às especificidades do WebSocket em tempo real.
exchange.options['tradesLimit'] = 5 # set the size of the cache to 5
# this call will return up to 5 cached trades
await exchange.watchTrades (symbol)
# the following call will return the first 2 of up to 5 cached trades
await exchange.watchTrades (symbol, since=None, limit=2)
# this call will first filter cached trades by trade['timestamp'] >= since
# and will return the first 2 of up to 5 cached trades that pass the filter
since = exchange.iso8601('2020-01-01T00:00:00Z')
limit = 2
await exchange.watchTrades (symbol, since, limit)Modo newUpdates
Se você quiser sempre obter apenas a negociação mais recente, deve instanciar a exchange com o sinalizador newUpdates definido como true.
exchange = ccxtpro.binance({'newUpdates': True})
while True:
trades = await exchange.watchTrades (symbol)
print(trades)O modo newUpdates continua a utilizar o cache deslizante em segundo plano, mas o usuário receberá apenas as novas atualizações. Isso ocorre porque algumas exchanges usam estruturas incrementais, portanto precisamos manter um cache de objetos, já que a exchange pode fornecer apenas informações parciais, como atualizações de status.
O resultado do modo newUpdates será uma ou mais atualizações ocorridas desde a última vez que exchange.watchMethod foi resolvido. O CCXT Pro pode retornar uma ou mais ordens que foram atualizadas desde a chamada anterior. O resultado de chamar exchange.watchOrders será como mostrado abaixo:
[
order, // see /docs/manual#order-structure
order,
order,
...
]Aviso de Depreciação: no futuro, newUpdates: true será o modo padrão e você precisará definir newUpdates como false para obter o cache deslizante.
const ccxtpro = require ('ccxt').pro
console.log ('CCXT version', ccxtpro.version)
console.log ('Supported exchanges:', ccxtpro.exchanges)O módulo CCXT Pro importado envolve o CCXT dentro de si mesmo – toda exchange instanciada via CCXT Pro possui todos os métodos do CCXT, bem como a funcionalidade adicional.
Instanciação
O CCXT Pro foi projetado para a sintaxe async/await e depende fortemente de primitivos assíncronos como promises e futures.
Criar uma instância de exchange no CCXT Pro é praticamente idêntico a criar uma instância de exchange no CCXT.
const ccxt = require ('ccxt').pro
const exchange = new ccxtpro.binance ({ newUpdates: false })Python
A implementação Python do CCXT Pro depende do asyncio integrado e, em particular, do Event Loop. Em Python é possível fornecer uma instância do event loop do asyncio nos argumentos do construtor, como mostrado abaixo (idêntico ao ccxt.async support):
import ccxt.pro as ccxtpro
from asyncio import run
async def main():
exchange = ccxtpro.kraken({'newUpdates': False})
while True:
orderbook = await exchange.watch_order_book('BTC/USD')
print(orderbook['asks'][0], orderbook['bids'][0])
await exchange.close()
run(main())PHP
Em PHP, os primitivos assíncronos são emprestados do ReactPHP. A implementação PHP do CCXT Pro depende do Promise e do EventLoop em particular. Em PHP, o usuário é obrigado a fornecer uma instância do event loop do ReactPHP nos argumentos do construtor, como mostrado abaixo:
error_reporting(E_ALL);
date_default_timezone_set('UTC');
require_once 'vendor/autoload.php';
$exchange = new \ccxt\pro\kucoin(array( 'newUpdates' => false ));using ccxt.pro;
public async static Task Watch()
{
var exchange = new binance();
while (true)
{
var trades = await exchange.WatchTrades("BTC/USDT");
Console.WriteLine("Trades: " + JsonConvert.SerializeObject(trades, Formatting.Indented));
}
}Propriedades da Exchange
Toda instância do CCXT Pro contém todas as propriedades da instância CCXT subjacente. Além das propriedades padrão do CCXT, a instância do CCXT Pro inclui o seguinte:
{
'has': { // an associative array of extended exchange capabilities
'ws': true, // only available in CCXT Pro
'watchOrderBook': true,
'watchTicker': true,
'watchTickers': true,
'watchTrades': true,
'watchMyTrades': true,
'watchOHLCV': true,
'watchBalance': true,
'watchPositions': true,
'createOrderWs': true,
'editOrderWs': true,
'cancelOrderWs': true,
'cancelOrdersWs': false,
'cancelAllOrdersWs': true,
'fetchOrderWs': true,
'fetchOrdersWs': true,
'fetchBalanceWs': true,
'fetchMyTradesWs': true,
...
},
'urls': {
'api': { // will contain a streaming API base URL, depending on the underlying protocol
'ws': 'wss://ws.exchange.com', // https://en.wikipedia.org/wiki/WebSocket
'signalr': 'https://signalr.exchange.com' // https://en.wikipedia.org/wiki/SignalR
'socketio': 'wss://socket.exchange.io' // https://socket.io
},
},
'version': '1.21',
'streaming': {
'keepAlive': 30000, // integer keep-alive rate in milliseconds
'maxPingPongMisses': 2.0, // how many ping pong misses to drop and reconnect
... // other streaming options
},
// incremental data structures
'orderbooks': {}, // incremental order books indexed by symbol
'ohlcvs': {}, // standard CCXT OHLCVs indexed by symbol by timeframe
'balance': {}, // a standard CCXT balance structure, accounts indexed by currency code
'orders': {}, // standard CCXT order structures indexed by order id
'trades': {}, // arrays of CCXT trades indexed by symbol
'tickers': {}, // standard CCXT tickers indexed by symbol
'transactions': {}, // standard CCXT deposits and withdrawals indexed by id or txid
...
}API Unificada
A API Unificada do CCXT Pro incentiva o controle direto de fluxo para um estilo de código melhor, mais legível e arquiteturalmente superior em comparação ao uso de EventEmitters e callbacks. Esta última é considerada uma abordagem desatualizada atualmente, pois requer inversão de controle (as pessoas não estão acostumadas com o pensamento invertido).
O CCXT Pro segue a abordagem moderna e foi projetado para a sintaxe assíncrona. Por baixo dos panos, o CCXT Pro ainda precisará usar fluxo de controle invertido às vezes, por causa das dependências e das bibliotecas WebSocket que não conseguem fazer de outra forma.
O mesmo vale não apenas para JS/ES6, mas também para código assíncrono Python 3. Em PHP, os primitivos assíncronos são emprestados do ReactPHP.
A sintaxe assíncrona moderna permite combinar e dividir a execução em caminhos paralelos e depois mesclá-los, agrupá-los, priorizá-los e muito mais. Com promises, é possível converter facilmente de fluxo de controle direto em estilo assíncrono para fluxo de controle invertido em estilo callback, e vice-versa.
Tempo Real vs Throttling
O CCXT Pro suporta dois modos de loops de função tick – o modo em tempo real e o modo de throttling. Ambos são mostrados abaixo em pseudocódigo:
// real-time mode
const limit = 5 // optional
while (true) {
try {
const orderbook = await exchange.watchOrderBook (symbol, limit)
// your reaction to the update takes place here
// you arrive here after receiving the update from the exchange in real time
console.log (orderbook) // every update
} catch (e) {
console.log (e)
// throw e // uncomment to stop the loop on exceptions
}
}// throttling mode
const limit = 5 // optional
// await is optional, alternatively you can launch it in bg without await
await exchange.watchOrderBook (symbol, limit)
while (true) {
// your reaction takes place here
// you arrive here every 100 ms regardless of whether there was an update or not
// in throttling mode offloading the orderbook with .limit () is required
console.log (exchange.orderbooks[symbol].limit (limit))
await exchange.sleep (100) // every 100 ms
}No modo em tempo real, o CCXT Pro retornará o resultado assim que cada novo delta chegar da exchange. A lógica geral de uma chamada unificada em um loop em tempo real é aguardar o próximo delta e imediatamente retornar a estrutura de resultado unificada ao usuário, repetidamente. Isso é útil quando o tempo de reação é crítico ou precisa ser o mais rápido possível.
No entanto, o modo em tempo real requer experiência em programação com fluxos assíncronos quando se trata de sincronizar múltiplos loops tick paralelos. Além disso, as exchanges podem transmitir um número muito grande de atualizações durante períodos de alta atividade ou alta volatilidade. Portanto, o usuário que desenvolve um algoritmo em tempo real deve garantir que o código do lado do usuário seja capaz de consumir dados nessa velocidade. Trabalhar no modo em tempo real pode ser mais exigente em termos de recursos às vezes.
No modo de throttling, o CCXT Pro receberá e gerenciará os dados em segundo plano. O usuário é responsável por consultar os resultados de tempos em tempos, quando necessário. A lógica geral do loop de throttling é dormir na maior parte do tempo e acordar para verificar os resultados ocasionalmente. Isso geralmente é feito em alguma frequência fixa, ou "taxa de quadros". O código dentro de um loop de throttling é frequentemente mais fácil de sincronizar entre múltiplas exchanges. O racionamento do tempo gasto em um loop com throttling também ajuda a reduzir o uso de recursos ao mínimo. Isso é conveniente quando seu algoritmo é pesado e você deseja controlar a execução com precisão para evitar executá-lo com muita frequência.
A desvantagem óbvia do modo de throttling é ser menos reativo ou responsivo a atualizações. Quando um algoritmo de trading precisa aguardar alguns milissegundos antes de ser executado – uma ou duas atualizações podem chegar antes que esse tempo expire. No modo de throttling, o usuário só verificará essas atualizações na próxima vez que o loop acordar (iteração do loop), portanto, o atraso de reação pode variar dentro de alguns milissegundos ao longo do tempo.
Métodos Públicos
watchOrderBook
A interface do watchOrderBook é idêntica à do fetchOrderBook. Aceita três argumentos:
symbol– string, um símbolo CCXT unificado, obrigatóriolimit– inteiro, o número máximo de bids/asks retornados, opcionalparams– dicionário associativo, substituições opcionais conforme descrito em Substituindo Parâmetros da API Unificada
Em geral, as exchanges podem ser divididas em duas categorias:
- as exchanges que suportam orderbooks limitados (transmitindo apenas a parte superior da pilha de ordens)
- as exchanges que transmitem apenas orderbooks completos
Se a exchange aceita um argumento de limitação, o argumento limit é enviado para a exchange ao assinar o stream do orderbook por uma conexão WebSocket. A exchange então enviará apenas a quantidade especificada de ordens, o que ajuda a reduzir o tráfego. Algumas exchanges podem aceitar apenas determinados valores de limit, como 10, 25, 50, 100 e assim por diante.
Se a exchange subjacente não aceitar um argumento de limitação, a limitação é feita no lado do cliente.
O argumento limit não garante que o número de bids ou asks sempre será igual a limit. Ele designa o limite superior ou o máximo, portanto, em algum momento pode haver menos do que limit bids ou asks, mas nunca mais do que limit bids ou asks. Esse é o caso quando a exchange não tem ordens suficientes no orderbook, ou quando uma das ordens do topo do orderbook é correspondida e removida do orderbook, deixando menos de limit entradas no lado dos bids ou no lado dos asks. O espaço livre no orderbook geralmente é rapidamente preenchido com novos dados.
if (exchange.has['watchOrderBook']) {
while (true) {
try {
const orderbook = await exchange.watchOrderBook (symbol, limit, params)
console.log (new Date (), symbol, orderbook['asks'][0], orderbook['bids'][0])
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchOrderBookForSymbols
Similar ao watchOrderBook, mas aceita um array de símbolos para que você possa assinar múltiplos orderbooks em uma única mensagem.
if (exchange.has['watchOrderBookForSymbols']) {
while (true) {
try {
const orderbook = await exchange.watchOrderBookForSymbols (['BTC/USDT', 'LTC/USDT'], limit, params)
console.log (new Date (), symbol, orderbook['asks'][0], orderbook['bids'][0])
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchTicker
Algumas exchanges permitem diferentes tópicos para ouvir tickers (ex.: bookTicker). Você pode definir isso em exchange.options['watchTicker']['name']
// JavaScript
if (exchange.has['watchTicker']) {
while (true) {
try {
const ticker = await exchange.watchTicker (symbol, params)
console.log (new Date (), ticker)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}# Python
if exchange.has['watchTicker']:
while True:
try:
ticker = await exchange.watch_ticker(symbol, params)
print(exchange.iso8601(exchange.milliseconds()), ticker)
except Exception as e:
print(e)
# stop the loop on exception or leave it commented to retry
# raise eif ($exchange->has['watchTicker']) {
$exchange::execute_and_run(function() use ($exchange, $symbol, $params) {
while (true) {
try {
$ticker = yield $exchange->watch_ticker($symbol, $params);
echo date('c'), ' ', json_encode($ticker), "\n";
} catch (Exception $e) {
echo get_class($e), ' ', $e->getMessage(), "\n";
}
}
});
}watchTickers
if (exchange.has['watchTickers']) {
while (true) {
try {
const tickers = await exchange.watchTickers (symbols, params)
console.log (new Date (), tickers)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchOHLCV
Um equívoco muito comum sobre WebSockets é que streams WS de OHLCV podem de alguma forma acelerar uma estratégia de trading. Se o objetivo do seu aplicativo é implementar trading baseado em OHLCV ou uma estratégia algorítmica especulativa, considere o seguinte cuidadosamente.
Em geral, há dois tipos de dados de trading usados nos algoritmos:
- dados em tempo real de 1ª ordem, como orderbooks e negociações
- dados não em tempo real de 2ª ordem, como tickers, ohlcvs, etc
Quando os desenvolvedores dizem "tempo real", geralmente significa pseudo tempo real, ou, simplificando, "tão rápido e tão próximo do tempo real quanto possível".
Os dados de 2ª ordem são sempre calculados a partir dos dados de 1ª ordem. OHLCVs são calculados a partir de negociações agregadas. Tickers são calculados a partir de negociações e orderbooks.
Algumas exchanges fazem o cálculo de OHLCVs (dados de 2ª ordem) para você no lado da exchange e enviam atualizações via WS (Binance). Outras exchanges realmente não acham isso necessário, por uma razão.
Obviamente, leva tempo para calcular candles OHLCV de 2ª ordem a partir de negociações. Além disso, enviar o candle calculado de volta a todos os usuários conectados também leva tempo. Atrasos adicionais podem ocorrer durante períodos de alta volatilidade, se uma exchange for negociada muito ativamente sob alta carga.
Não há garantia estrita de quanto tempo levará para a exchange calcular os dados de 2ª ordem e transmiti-los para você via WS. Os atrasos e defasagens nos candles OHLCV podem variar significativamente de exchange para exchange. Por exemplo, uma exchange pode enviar uma atualização de OHLCV aproximadamente 30 segundos após o fechamento real de um período correspondente. Outras exchanges podem enviar as atualizações de OHLCV atuais em intervalos regulares (digamos, uma vez a cada 100ms), enquanto na realidade as negociações podem ocorrer com muito mais frequência.
A maioria das pessoas usa WS para evitar qualquer tipo de atraso e ter dados em tempo real. Portanto, na maioria dos casos é muito melhor não esperar pela exchange. Recalcular os dados de 2ª ordem a partir dos dados de 1ª ordem por conta própria pode ser muito mais rápido e isso pode reduzir os atrasos desnecessários. Portanto, não faz muito sentido usar WS apenas para assistir candles OHLCV da exchange. Os desenvolvedores preferem usar watch_trades() e recalcular os candles OHLCV usando os métodos integrados do CCXT, como build_ohlcvc().
# Python
exchange = ccxtpro.binance()
if not exchange.has['watchOHLCV']:
while True:
try:
trades = await exchange.watch_trades(symbol)
ohlcvc = exchange.build_ohlcvc(trades, '1m')
print(ohlcvc)
except Exception as e:
print(e)
# stop the loop on exception or leave it commented to retry
# raise eIsso explica por que algumas exchanges razoavelmente acham que OHLCVs não são necessários no contexto WS, pois os usuários podem calcular essas informações no lado do usuário muito mais rapidamente tendo apenas um stream WS de negociações de 1ª ordem em tempo real.
Se o seu aplicativo não for muito crítico em termos de tempo, você ainda pode assinar streams de OHLCV, para fins de gráficos. Se a exchange subjacente tiver exchange.has['watchOHLCV'], você pode usar watchOHLCV()/watch_ohlcv() conforme mostrado abaixo:
if (exchange.has['watchOHLCV']) {
while (true) {
try {
const candles = await exchange.watchOHLCV (symbol, timeframe, since, limit, params)
console.log (new Date (), candles)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchOHLCVForSymbols
Similar ao watchOHLCV, mas permite múltiplas assinaturas de símbolos e timeframes
if (exchange.has['watchOHLCVForSymbols']) {
while (true) {
try {
const subscriptions = [[
['BTC/USDT', '1d'],
['LTC/USDT', '5m'],
['ETH/USDT', '1h']
]]
const candles = await exchange.watchOHLCVForSymbols (subscriptions, since, limit, params)
console.log (new Date (), candles)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchTrades
// JavaScript
if (exchange.has['watchTrades']) {
while (true) {
try {
const trades = await exchange.watchTrades (symbol, since, limit, params)
console.log (new Date (), trades)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchTradesForSymbols
Similar ao watchTrades, mas permite assinar múltiplos símbolos em uma única chamada.
if (exchange.has['watchTradesForSymbols']) {
while (true) {
try {
const trades = await exchange.watchTradesForSymbols (['LTC/USDT', 'BTC/USDT'], since, limit, params)
console.log (new Date (), trades)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}Métodos Privados
Na maioria dos casos, a lógica de autenticação é emprestada do CCXT, já que as exchanges usam os mesmos pares de chaves e algoritmos de assinatura para APIs REST e APIs WebSocket. Consulte Configuração de Chaves de API para mais detalhes.
watchBalance
if (exchange.has['watchBalance']) {
while (true) {
try {
const balance = await exchange.watchBalance (params)
console.log (new Date (), balance)
} catch (e) {
console.log (e)
// stop the loop on exception or leave it commented to retry
// throw e
}
}
}watchOrders
watchOrders (symbol = undefined, since = undefined, limit = undefined, params = {})watchMyTrades
watchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {})watchPositions
observa todas as posições abertas e retorna uma lista de estrutura de posição
watchPositions (symbols = undefined, since = undefined, limit = undefined, params = {}) createOrderWs
createOrderWs (symbol: string, type: OrderType, side: OrderSide, amount: number, price: number = undefined, params = {})editOrderWs
// JavaScript
editOrderWs (id, symbol: string, type: OrderType, side: OrderSide, amount: number, price: number = undefined, params = {})cancelOrderWs
cancelOrderWs(id: string, symbol: string = undefined, params = {})cancelOrdersWs
cancelOrdersWs(ids: string[], symbol: string = undefined, params = {})cancelAllOrdersWs
cancelAllOrdersWs(symbol: string = undefined, params = {})watchTransactions
- this method is a work in progress now (may be unavailable)Manipulador personalizado
Se você quiser ter acesso às mensagens recebidas brutas e usar seus próprios manipuladores personalizados, pode sobrescrever o método handleMessage/handle_message da exchange, da seguinte forma:
A) Por herança:
class myExchange extends ccxt.pro.coinbase {
handleMessage (wsClient, data) {
console.log("Raw incoming message:", message) // this is the raw update
super.handleMessage(wsClient, data);
// your extra logic here
}
}
const ex = new myExchange();
ex.watchTicker('BTC/USDT');B) sobrescrevendo o método:
function myHandler(ws, data, orignal_handler){
orignal_handler(ws, data); // trigger original `handleMessage`
if (your_condition) {
// execute your additional code
}
}
const ex = new ccxt.pro.binance();
const original_handler = ex.handleMessage.bind(ex);
ex.handleMessage = (ws, data) => myHandler(ws, data, original_handler);
ex.watchTicker('BTC/USDT');Tratamento de Erros
Em caso de erro, o CCXT Pro lançará uma exceção padrão do CCXT. Consulte Tratamento de Erros para mais detalhes.

























