Manual de CCXT Pro
CCXT Pro es una parte gratuita de CCXT que añade soporte para streaming WebSocket: https://github.com/ccxt/ccxt/issues/15171
Manual
CCXT Pro es una parte gratuita de CCXT que añade soporte para streaming WebSocket: https://github.com/ccxt/ccxt/issues/15171
La pila de CCXT Pro está construida sobre CCXT y extiende las clases principales de CCXT, utilizando:
- Mixins a nivel de prototipo en JavaScript
- Herencia múltiple en Python
- Traits en PHP
- Herencia de clases en Java (las clases de exchange pro extienden las clases base de exchange)
CCXT Pro depende en gran medida del transpilador de CCXT para el soporte multilenguaje.
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
La biblioteca CCXT Pro actualmente soporta los siguientes 74 mercados de criptomonedas y APIs de trading 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 es la lista de exchanges en CCXT Pro con soporte para APIs WebSockets. Esta lista se actualizará con nuevos exchanges de forma periódica.
Lista completa de exchanges disponibles en CCXT vía REST: Mercados de intercambio de criptomonedas compatibles.
Uso
- 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 appreciatedRequisitos previos
La mejor manera de entender CCXT Pro es asegurarse de comprender todo el Manual de CCXT y practicar primero con CCXT estándar. CCXT Pro toma prestado de CCXT. Ambas bibliotecas comparten muchos puntos en común, entre ellos:
- los conceptos de API pública y API privada autenticada
- mercados, símbolos, códigos e identificadores de divisas
- estructuras y formatos de datos unificados, libros de órdenes, operaciones, órdenes, velas, marcos temporales, ...
- excepciones y mapeos de errores
- autenticación y claves de API (para feeds y llamadas privadas)
- opciones de configuración
El público objetivo de CCXT Pro está compuesto principalmente por traders algorítmicos profesionales y desarrolladores. Para trabajar de manera eficiente con esta biblioteca, el usuario debe estar bien familiarizado con los conceptos de streaming. Es necesario comprender las diferencias subyacentes entre las APIs de streaming basadas en conexión (WebSocket, CCXT Pro) y las APIs basadas en solicitud-respuesta (REST, CCXT).
El flujo general de estilo asíncrono para una aplicación CCXT es el siguiente:
// 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
}
}En CCXT Pro, cada método RESTful unificado público y privado que tiene un prefijo fetch* también tiene un método homólogo basado en streams con el prefijo watch*, como se muestra a continuación:
- 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 (detiene la suscripción en segundo plano para los métodos con
watch)unWatchOrderBookunWatchOrderBooksForSymbolsunWatchTradesunWatchTradesForSymbolsunWatchOHLCVForSymbolsunWatchOrderBookForSymbolsunWatchPositionsunWatchTickersunWatchMyTradesunWatchTickerunWatchOHLCVunWatchOrders
La API de Streaming Unificada de CCXT Pro hereda los patrones de uso de CCXT para facilitar la migración.
El flujo general de estilo asíncrono para una aplicación CCXT Pro (en contraposición a una aplicación CCXT descrita anteriormente) se muestra a continuación:
// 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
}
}Ese patrón de uso generalmente se encapsula en un método de lógica de negocio central llamado "función tick()", ya que reitera una reacción a los eventos entrantes (también conocidos como ticks). De los dos ejemplos anteriores es evidente que el patrón de uso genérico en CCXT Pro y CCXT es idéntico.
Muchas de las reglas y conceptos de CCXT también se aplican a CCXT Pro:
- CCXT Pro cargará los mercados y los almacenará en caché en la primera llamada a un método de API unificado
- CCXT Pro llamará a los métodos RESTful de CCXT de forma interna cuando sea necesario
- CCXT Pro lanzará las excepciones estándar de CCXT cuando sea necesario
- ...
Especificidades del Streaming
A pesar de las numerosas similitudes, las APIs basadas en streaming tienen sus propias particularidades debido a su naturaleza orientada a conexiones.
Contar con una interfaz basada en conexión implica mecanismos de gestión de conexiones. CCXT Pro gestiona las conexiones de forma transparente para el usuario. Cada instancia de exchange gestiona su propio conjunto de conexiones.
En la primera llamada a cualquier método watch*(), la biblioteca establecerá una conexión a un stream/recurso específico del exchange y la mantendrá. Si la conexión ya existe, se reutiliza. La biblioteca gestionará las secuencias de mensajes de solicitud/respuesta de suscripción, así como la autenticación/firma si el stream solicitado es privado.
La biblioteca también monitorizará el estado del enlace y mantendrá la conexión activa. Ante una excepción crítica, una desconexión o un tiempo de espera/fallo de conexión, la siguiente iteración de la función tick llamará al método watch, que activará una reconexión. De este modo, la biblioteca gestiona las desconexiones y reconexiones para el usuario de forma transparente. CCXT Pro aplica la limitación de velocidad necesaria y los retrasos de reconexión con retroceso exponencial. Toda esa funcionalidad está habilitada por defecto y puede configurarse a través de las propiedades del exchange, como de costumbre.
La mayoría de los exchanges solo tienen una URL base única para las APIs de streaming (habitualmente WebSocket, que comienza con ws:// o wss://). Algunos pueden tener más de una URL por cada stream, dependiendo del feed en cuestión.
Las APIs de Streaming de los exchanges pueden clasificarse en dos categorías diferentes:
- sub o subscribe permite solo recibir datos
- pub o publish permite enviar y recibir datos
Sub
Una interfaz sub generalmente permite suscribirse a un flujo de datos y escucharlo. La mayoría de los exchanges que soportan WebSockets solo ofrecerán una API de tipo sub. El tipo sub incluye el streaming de datos públicos de mercado. A veces los exchanges también permiten suscribirse a datos privados del usuario. Una vez que el usuario se suscribe a un feed de datos, el canal comienza a funcionar de forma unidireccional, enviando actualizaciones del exchange al usuario de manera continua.
Tipos de streams de datos públicos más habituales:
- libro de órdenes (el más común) - actualizaciones sobre órdenes añadidas, editadas y eliminadas (también conocidas como deltas de cambio)
- actualizaciones del ticker al cambiar las estadísticas de 24 horas
- feed de ejecuciones (también común) - un stream en tiempo real de operaciones públicas
- feed de velas ohlcv
- heartbeat
- chat/trollbox del exchange
Tipos menos comunes de streams de datos privados del usuario:
- el stream de operaciones privadas del usuario
- actualizaciones de órdenes en tiempo real
- actualizaciones de saldo
- streams personalizados
- streams específicos del exchange y otros
Pub
Una interfaz pub generalmente permite a los usuarios enviar solicitudes de datos al servidor. Esto normalmente incluye acciones comunes del usuario, como:
- colocar órdenes
- cancelar órdenes
- realizar solicitudes de retiro
- publicar mensajes en el chat/trollbox
- etc
Algunos exchanges no ofrecen una API WS de tipo pub, solo ofrecerán una API WS de tipo sub. Sin embargo, existen exchanges que también disponen de una API de Streaming completa. En la mayoría de los casos, un usuario no puede operar de forma efectiva disponiendo únicamente de la API de Streaming. Los exchanges transmitirán datos públicos de mercado mediante sub, y la API REST sigue siendo necesaria para la parte pub cuando esta falta.
unWatch
Cada método watchX establece una suscripción con un stream y recibirá actualizaciones continuas del exchange. Aunque dejes de obtener el valor de retorno del método watchX, el stream seguirá enviando datos, los cuales son gestionados y almacenados en segundo plano. Para detener esas suscripciones en segundo plano, debes usar el método unWatch (p. ej. watchTrades -> unWatchTrades).
Estructuras de Datos Incrementales
En muchos casos, debido a la naturaleza unidireccional de los feeds de datos subyacentes, la aplicación que escucha en el lado del cliente debe mantener una instantánea local de los datos en memoria y combinar las actualizaciones recibidas del servidor del exchange con la instantánea local. Las actualizaciones que provienen del exchange también se denominan frecuentemente deltas, porque en la mayoría de los casos solo contendrán los cambios entre dos estados de los datos y no incluirán los datos que no han cambiado, lo que hace necesario almacenar el estado actual S en caché localmente de todos los objetos de datos relevantes.
Toda esa funcionalidad es gestionada por CCXT Pro para el usuario. Para trabajar con CCXT Pro, el usuario no tiene que rastrear ni gestionar suscripciones ni los datos relacionados. CCXT Pro mantendrá una caché de estructuras en memoria para gestionar la complejidad subyacente.
Cada actualización entrante indica qué partes de los datos han cambiado y el lado receptor "incrementa" el estado local S combinando la actualización sobre el estado actual S y pasando al siguiente estado local S'. En términos de CCXT Pro, esto se denomina "estado incremental" y las estructuras involucradas en el proceso de almacenamiento y actualización del estado en caché se denominan "estructuras incrementales". CCXT Pro introduce varias nuevas clases base para gestionar el estado incremental cuando es necesario.
Las estructuras incrementales devueltas por los métodos unificados de CCXT Pro son generalmente de uno de dos tipos:
- Objeto decodificado en JSON (
objecten JavaScript,dicten Python,array()en PHP). Este tipo puede devolverse desde métodos públicos y privados comowatchOrderBook,watchTicker,watchBalance,watchOrder, etc. - Un array/lista de objetos (generalmente ordenados cronológicamente). Este tipo puede devolverse desde métodos como
watchOHLCV,watchTrades,watchMyTrades,watchOrders, etc.
Los métodos unificados que devuelven arrays como watchOHLCV, watchTrades, watchMyTrades, watchOrders, se basan en la capa de caché. El usuario debe comprender el funcionamiento interno de la capa de caché para trabajar con ella de manera eficiente.
La caché es una cola de doble extremo de tamaño fijo, también conocida como array/lista. La biblioteca CCXT Pro tiene un límite razonable en el número de objetos almacenados en memoria. Por defecto, las estructuras de array en caché almacenarán hasta 1000 entradas de cada tipo (las 1000 operaciones más recientes, las 1000 velas más recientes, las 1000 órdenes más recientes). El número máximo permitido puede ser configurado por el usuario en el momento de la instanciación o posteriormente:
ccxtpro.binance({
'options': {
'tradesLimit': 1000,
'OHLCVLimit': 1000,
'ordersLimit': 1000,
},
})
# or
exchange.options['tradesLimit'] = 1000
exchange.options['OHLCVLimit'] = 1000
exchange.options['ordersLimit'] = 1000Los límites de caché deben establecerse antes de llamar a cualquier método watch y no pueden cambiar durante la ejecución del programa.
Cuando hay espacio disponible en la caché, los nuevos elementos se añaden simplemente al final. Si no hay suficiente espacio para un nuevo elemento, el elemento más antiguo se elimina del principio de la caché para liberar espacio. Así, por ejemplo, la caché crece de 0 a 1000 operaciones más recientes y luego se mantiene en un máximo de 1000 operaciones más recientes, renovando constantemente los datos almacenados con cada nueva actualización que llega del exchange. Se asemeja a una ventana deslizante o una puerta corredera, que se muestra a continuación:
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 frameEl usuario puede configurar los límites de caché usando exchange.options como se mostró anteriormente. No confundas los límites de caché con el límite de paginación.
Ten en cuenta que los parámetros since y limit de paginación basada en fechas tienen un significado diferente y siempre se aplican dentro de la ventana en caché. Si el usuario especifica un argumento since en la llamada a watchTrades(), CCXT Pro devolverá todas las operaciones en caché con timestamp >= since. Si el usuario no especifica un argumento since, CCXT Pro devolverá las operaciones en caché desde el principio de la ventana deslizante. Si el usuario especifica un argumento limit, la biblioteca devolverá hasta limit velas comenzando desde since o desde el inicio de la caché. Por ese motivo, el usuario no puede paginar más allá del marco en caché debido a las especificidades en tiempo real de WebSocket.
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
Si desea obtener siempre solo la operación más reciente, debe instanciar el exchange con la bandera newUpdates establecida en true.
exchange = ccxtpro.binance({'newUpdates': True})
while True:
trades = await exchange.watchTrades (symbol)
print(trades)El modo newUpdates sigue utilizando la caché deslizante en segundo plano, pero el usuario solo recibirá las nuevas actualizaciones. Esto se debe a que algunos exchanges utilizan estructuras incrementales, por lo que necesitamos mantener una caché de objetos ya que el exchange puede proporcionar únicamente información parcial, como actualizaciones de estado.
El resultado del modo newUpdates será una o más actualizaciones que hayan ocurrido desde la última vez que exchange.watchMethod se resolvió. CCXT Pro puede devolver una o más órdenes que se actualizaron desde la llamada anterior. El resultado de llamar a exchange.watchOrders tendrá el aspecto que se muestra a continuación:
[
order, // see /docs/manual#order-structure
order,
order,
...
]Aviso de obsolescencia: en el futuro newUpdates: true será el modo predeterminado y tendrá que establecer newUpdates en false para obtener la caché deslizante.
const ccxtpro = require ('ccxt').pro
console.log ('CCXT version', ccxtpro.version)
console.log ('Supported exchanges:', ccxtpro.exchanges)El módulo CCXT Pro importado envuelve a CCXT dentro de sí mismo: cada exchange instanciado a través de CCXT Pro tiene todos los métodos de CCXT además de la funcionalidad adicional.
Instanciación
CCXT Pro está diseñado para la sintaxis async/await y depende en gran medida de primitivas asíncronas como las promesas y los futuros.
Crear una instancia de exchange de CCXT Pro es prácticamente idéntico a crear una instancia de exchange de CCXT.
const ccxt = require ('ccxt').pro
const exchange = new ccxtpro.binance ({ newUpdates: false })Python
La implementación en Python de CCXT Pro se basa en el módulo integrado asyncio y en particular en el Event Loop. En Python es posible suministrar una instancia del bucle de eventos de asyncio en los argumentos del constructor como se muestra a continuación (idéntico a 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
En PHP las primitivas asíncronas se toman prestadas de ReactPHP. La implementación en PHP de CCXT Pro se basa en Promise y en EventLoop en particular. En PHP el usuario debe suministrar una instancia del bucle de eventos de ReactPHP en los argumentos del constructor como se muestra a continuación:
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));
}
}Propiedades del Exchange
Cada instancia de CCXT Pro contiene todas las propiedades de la instancia CCXT subyacente. Además de las propiedades estándar de CCXT, la instancia de CCXT Pro incluye las siguientes:
{
'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
La API Unificada de CCXT Pro fomenta el flujo de control directo para lograr un mejor estilo de código, más legible y arquitectónicamente superior en comparación con el uso de EventEmitters y callbacks. Este último enfoque se considera obsoleto hoy en día, ya que requiere inversión del control (la gente no está acostumbrada al pensamiento invertido).
CCXT Pro adopta el enfoque moderno y está diseñado para la sintaxis asíncrona. Internamente, CCXT Pro aún tendrá que usar flujo de control invertido en ocasiones debido a las dependencias y las librerías WebSocket que no pueden hacer otra cosa.
Lo mismo aplica no solo para JS/ES6 sino también para el código asíncrono de Python 3. En PHP las primitivas asíncronas se toman prestadas de ReactPHP.
La sintaxis asíncrona moderna permite combinar y dividir la ejecución en caminos paralelos para luego fusionarlos, agruparlos, priorizarlos y mucho más. Con las promesas se puede convertir fácilmente de un flujo de control de estilo asíncrono directo a un flujo de control de estilo callback invertido, y viceversa.
Tiempo Real vs Limitación de Frecuencia
CCXT Pro admite dos modos de bucles de funciones de tick: el modo en tiempo real y el modo de limitación de frecuencia. Ambos se muestran a continuación en 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
}En el modo en tiempo real, CCXT Pro devolverá el resultado tan pronto como llegue cada nuevo delta desde el exchange. La lógica general de una llamada unificada en un bucle en tiempo real consiste en esperar el siguiente delta y devolver inmediatamente la estructura de resultado unificada al usuario, una y otra vez. Esto es útil cuando el tiempo de reacción es crítico o debe ser lo más rápido posible.
Sin embargo, el modo en tiempo real requiere experiencia en programación con flujos asíncronos a la hora de sincronizar múltiples bucles de tick en paralelo. Además, los exchanges pueden transmitir un número muy elevado de actualizaciones durante períodos de alta actividad o alta volatilidad. Por ello, el usuario que desarrolla un algoritmo en tiempo real debe asegurarse de que el código en espacio de usuario sea capaz de consumir datos a esa velocidad. Trabajar en modo en tiempo real puede ser a veces más exigente en cuanto a recursos.
En el modo de limitación de frecuencia, CCXT Pro recibirá y gestionará los datos en segundo plano. El usuario es responsable de consultar los resultados de vez en cuando cuando sea necesario. La lógica general del bucle de limitación consiste en dormir la mayor parte del tiempo y despertar ocasionalmente para comprobar los resultados. Esto se hace normalmente a una frecuencia fija o, en otras palabras, a una "tasa de fotogramas". El código dentro de un bucle de limitación suele ser más fácil de sincronizar entre múltiples exchanges. El racionamiento del tiempo invertido en un bucle con limitación también ayuda a reducir el uso de recursos al mínimo. Esto es práctico cuando su algoritmo es pesado y desea controlar la ejecución con precisión para evitar ejecutarlo con demasiada frecuencia.
La desventaja obvia del modo de limitación de frecuencia es ser menos reactivo o sensible a las actualizaciones. Cuando un algoritmo de trading tiene que esperar cierta cantidad de milisegundos antes de ejecutarse, puede llegar una o dos actualizaciones antes de que ese tiempo expire. En el modo de limitación, el usuario solo comprobará esas actualizaciones en el siguiente despertar (iteración del bucle), por lo que el retardo de reacción puede variar dentro de cierta cantidad de milisegundos a lo largo del tiempo.
Métodos Públicos
watchOrderBook
La interfaz de watchOrderBook es idéntica a la de fetchOrderBook. Acepta tres argumentos:
symbol– cadena de texto, un símbolo CCXT unificado, obligatoriolimit– entero, el número máximo de ofertas de compra/venta devueltas, opcionalparams– diccionario asociativo, sobreescrituras opcionales como se describe en Sobreescritura de Parámetros de la API Unificada
En general, los exchanges se pueden dividir en dos categorías:
- los exchanges que admiten libros de órdenes limitados (transmitiendo solo la parte superior de la pila de órdenes)
- los exchanges que transmiten solo libros de órdenes completos
Si el exchange acepta un argumento de limitación, el argumento limit se envía al exchange al suscribirse al flujo del libro de órdenes a través de una conexión WebSocket. El exchange enviará entonces solo la cantidad de órdenes especificada, lo que ayuda a reducir el tráfico. Algunos exchanges solo pueden aceptar ciertos valores de limit, como 10, 25, 50, 100, etc.
Si el exchange subyacente no acepta un argumento de limitación, la limitación se realiza en el lado del cliente.
El argumento limit no garantiza que el número de ofertas de compra o de venta sea siempre igual a limit. Designa el límite superior o el máximo, por lo que en algún momento puede haber menos de limit ofertas de compra o de venta, pero nunca más de limit. Este es el caso cuando el exchange no tiene suficientes órdenes en el libro de órdenes, o cuando una de las órdenes superiores del libro de órdenes se empareja y se elimina del libro de órdenes, dejando menos de limit entradas en el lado de las ofertas de compra o en el lado de las ofertas de venta. El espacio libre en el libro de órdenes generalmente se llena rápidamente con nuevos datos.
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 a watchOrderBook pero acepta un array de símbolos para que pueda suscribirse a múltiples libros de órdenes en un solo mensaje.
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
Algunos exchanges permiten diferentes temas para escuchar tickers (por ejemplo: bookTicker). Puede configurar esto en 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
Un error muy común sobre los WebSockets es creer que los flujos OHLCV de WS pueden de algún modo acelerar una estrategia de trading. Si el propósito de su aplicación es implementar trading basado en OHLCV o una estrategia algorítmica especulativa, considere lo siguiente cuidadosamente.
En general, existen dos tipos de datos de trading utilizados en los algoritmos:
- datos en tiempo real de primer orden como libros de órdenes y operaciones
- datos de segundo orden no en tiempo real como tickers, ohlcvs, etc.
Cuando los desarrolladores dicen "tiempo real", generalmente se refieren a pseudo tiempo real, o, dicho simplemente, "tan rápido y tan cerca del tiempo real como sea posible".
Los datos de segundo orden se calculan siempre a partir de los datos de primer orden. Los OHLCVs se calculan a partir de operaciones agregadas. Los tickers se calculan a partir de operaciones y libros de órdenes.
Algunos exchanges realizan el cálculo de OHLCVs (datos de segundo orden) por usted en el lado del exchange y le envían actualizaciones a través de WS (Binance). Otros exchanges no consideran que esto sea necesario, con razón.
Obviamente, lleva tiempo calcular las velas OHLCV de segundo orden a partir de las operaciones. Además, enviar la vela calculada de vuelta a todos los usuarios conectados también lleva tiempo. Pueden producirse retrasos adicionales durante períodos de alta volatilidad si un exchange opera muy activamente bajo alta carga.
No existe una garantía estricta sobre cuánto tiempo tardará el exchange en calcular los datos de segundo orden y transmitirlos a usted a través de WS. Los retrasos y desfases en las velas OHLCV pueden variar significativamente de un exchange a otro. Por ejemplo, un exchange puede enviar una actualización OHLCV aproximadamente 30 segundos después del cierre real del período correspondiente. Otros exchanges pueden enviar las actualizaciones OHLCV actuales a intervalos regulares (digamos, una vez cada 100ms), mientras que en realidad las operaciones pueden ocurrir con mucha más frecuencia.
La mayoría de las personas usan WS para evitar cualquier tipo de retrasos y tener datos en tiempo real. Por lo tanto, en la mayoría de los casos es mucho mejor no esperar al exchange. Recalcular los datos de segundo orden a partir de los datos de primer orden por cuenta propia puede ser mucho más rápido y puede reducir los retrasos innecesarios. Por ello, no tiene mucho sentido usar WS únicamente para observar las velas OHLCV del exchange. Los desarrolladores preferirían usar watch_trades() y recalcular las velas OHLCV usando los métodos integrados de 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 eEso explica por qué algunos exchanges razonablemente consideran que los OHLCVs no son necesarios en el contexto de WS, ya que los usuarios pueden calcular esa información en el espacio de usuario mucho más rápido teniendo solo un flujo WS de operaciones en tiempo real de primer orden.
Si su aplicación no es muy crítica en tiempo, puede seguir suscribiéndose a flujos OHLCV, con fines de representación gráfica. Si el exchange subyacente tiene exchange.has['watchOHLCV'], puede usar watchOHLCV()/watch_ohlcv() como se muestra a continuación:
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 a watchOHLCV pero permite múltiples suscripciones de símbolos y marcos temporales
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 a watchTrades pero permite suscribirse a múltiples símbolos en una sola llamada.
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
En la mayoría de los casos la lógica de autenticación se toma prestada de CCXT, ya que los exchanges utilizan los mismos pares de claves y algoritmos de firma para las APIs REST y las APIs WebSocket. Consulte Configuración de Claves API para más detalles.
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 las posiciones abiertas y devuelve una lista de estructura de posición
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)Manejador personalizado
Si deseas tener acceso a los mensajes entrantes sin procesar y usar tus propios manejadores personalizados, puedes sobreescribir el método handleMessage/handle_message del exchange, de la siguiente manera:
A) Por herencia:
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) sobreescribiendo el 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');Manejo de errores
En caso de error, CCXT Pro lanzará una excepción estándar de CCXT; consulta Manejo de errores para más detalles.

























