manual

Skip to content

Type / to search

Manual

Travis CI User edited this page yesterday · 1606 revisions

Overview

The ccxt library is a collection of available crypto exchanges or exchange classes. Each class implements the public and private API for a particular crypto exchange. All exchanges are derived from the base Exchange class and share a set of common methods. To access a particular exchange from ccxt library you need to create an instance of corresponding exchange class. Supported exchanges are updated frequently and new exchanges are added regularly.

The structure of the library can be outlined as follows:

                                 User
    +-------------------------------------------------------------+
    |                            CCXT                             |
    +------------------------------+------------------------------+
    |            Public            |           Private            |
    +=============================================================+
    │                              .                              |
    │                    The Unified CCXT API                     |
    │                              .                              |
    |       loadMarkets            .           fetchBalance       |
    |       fetchMarkets           .            createOrder       |
    |       fetchCurrencies        .            cancelOrder       |
    |       fetchTicker            .             fetchOrder       |
    |       fetchTickers           .            fetchOrders       |
    |       fetchOrderBook         .        fetchOpenOrders       |
    |       fetchOHLCV             .      fetchClosedOrders       |
    |       fetchStatus            .          fetchMyTrades       |
    |       fetchTrades            .                deposit       |
    |                              .               withdraw       |
    │                              .                              |
    +=============================================================+
    │                              .                              |
    |                     Custom Exchange API                     |
    |         (Derived Classes And Their Implicit Methods)        |
    │                              .                              |
    |       publicGet...           .          privateGet...       |
    |       publicPost...          .         privatePost...       |
    |                              .          privatePut...       |
    |                              .       privateDelete...       |
    |                              .                   sign       |
    │                              .                              |
    +=============================================================+
    │                              .                              |
    |                      Base Exchange Class                    |
    │                              .                              |
    +=============================================================+

Full public and private HTTP REST APIs for all exchanges are implemented. WebSocket implementations in JavaScript, PHP, Python are available in CCXT Pro, which is a professional addon to CCXT with support for WebSocket streams.

Social

Exchanges

The CCXT library currently supports the following 97 cryptocurrency exchange markets and trading APIs:

Besides making basic market and limit orders, some exchanges offer margin trading (leverage), various derivatives (like futures contracts and options) and also have dark pools, OTC (over-the-counter trading), merchant APIs and much more.

Instantiation

To connect to an exchange and start trading you need to instantiate an exchange class from ccxt library.

To get the full list of ids of supported exchanges programmatically:

Javascript

const ccxt = require ('ccxt')
console.log (ccxt.exchanges)

Python

import ccxt
print (ccxt.exchanges)

PHP

include 'ccxt.php';
var_dump (\ccxt\Exchange::$exchanges);

An exchange can be instantiated like shown in the examples below:

Javascript

const ccxt = require ('ccxt')
let exchange = new ccxt.kraken () // default id
let kraken1 = new ccxt.kraken ({ id: 'kraken1' })
let kraken2 = new ccxt.kraken ({ id: 'kraken2' })
let id = 'coinbasepro'
let coinbasepro = new ccxt[id] ();

// from variable id
const exchangeId = 'binance'
    , exchangeClass = ccxt[exchangeId]
    , exchange = new exchangeClass ({
        'apiKey': 'YOUR_API_KEY',
        'secret': 'YOUR_SECRET',
    })

Python

import ccxt
exchange = ccxt.okcoin () # default id
okcoin1 = ccxt.okcoin ({ 'id': 'okcoin1' })
okcoin2 = ccxt.okcoin ({ 'id': 'okcoin2' })
id = 'btcchina'
btcchina = eval ('ccxt.%s ()' % id)
coinbasepro = getattr (ccxt, 'coinbasepro') ()

# from variable id
exchange_id = 'binance'
exchange_class = getattr(ccxt, exchange_id)
exchange = exchange_class({
    'apiKey': 'YOUR_API_KEY',
    'secret': 'YOUR_SECRET',
})

PHP

The ccxt library in PHP uses builtin UTC/GMT time functions, therefore you are required to set date.timezone in your php.ini or call date_default_timezone_set() function before using the PHP version of the library. The recommended timezone setting is "UTC".

// PHP
date_default_timezone_set('UTC');
include 'ccxt.php';
$bitfinex = new \ccxt\bitfinex(); // default id
$bitfinex1 = new \ccxt\bitfinex(array('id' => 'bitfinex1'));
$bitfinex2 = new \ccxt\bitfinex(array('id' => 'bitfinex2'));
$id = 'kraken';
$exchange = '\\ccxt\\' . $id;
$kraken = new $exchange();

// from variable id
$exchange_id = 'binance';
$exchange_class = "\\ccxt\\$exchange_id";
$exchange = new $exchange_class(array(
    'apiKey' => 'YOUR_API_KEY',
    'secret' => 'YOUR_SECRET',
));

Overriding Exchange Properties Upon Instantiation

Most of exchange properties as well as specific options can be overrided upon exchange class instantiation or afterwards, like shown below:

Javascript

const exchange = new ccxt.binance ({
    'rateLimit': 10000, // unified exchange property
    'headers': {
        'YOUR_CUSTOM_HTTP_HEADER': 'YOUR_CUSTOM_VALUE',
    },
    'options': {
        'adjustForTimeDifference': true, // exchange-specific option
    }
})
exchange.options['adjustForTimeDifference'] = false

Python

exchange = ccxt.binance ({
    'rateLimit': 10000,  # unified exchange property
    'headers': {
        'YOUR_CUSTOM_HTTP_HEADER': 'YOUR_CUSTOM_VALUE',
    },
    'options': {
        'adjustForTimeDifference': True,  # exchange-specific option
    }
})
exchange.options['adjustForTimeDifference'] = False

PHP

$exchange_id = 'binance';
$exchange_class = "\\ccxt\\$exchange_id";
$exchange = new $exchange_class(array(
    'rateLimit' => 10000, // unified exchange property
    'headers' => array(
        'YOUR_CUSTOM_HTTP_HEADER' => 'YOUR_CUSTOM_VALUE',
    ),
    'options' => array(
        'adjustForTimeDifference' => true, // exchange-specific option
    ),
));
$exchange->options['adjustForTimeDifference'] = false;

Overriding Exchange Methods

In all CCXT-supported languages, you can override instance methods during runtime:

Javascript

const ex = new ccxt.binance ();
ex.fetch_ticker = function (symbol, params = {}) {
    // your codes go here
};
console.log (ex.fetch_ticker('BTC/USDT'));

Python

ex = ccxt.binance()
def my_overload(symbol, params = {}):
    # your codes go here

ex.fetch_ticker = my_overload
print(ex.fetch_ticker('BTC/USDT'))

PHP

$ex = new \ccxt\binance();
$ex->add_method('fetch_ticker', function($symbol, $params = []) {
    // your codes go here
});
var_dump($ex->call_method('fetch_ticker', ['BTC/USDT']));

Testnets And Sandbox Environments

Some exchanges also offer separate APIs for testing purposes that allows developers to trade virtual money for free and test out their ideas. Those APIs are called "testnets", "sandboxes" or "staging environments" (with virtual testing assets) as opposed to "mainnets" and "production environments" (with real assets). Most often a sandboxed API is a clone of a production API, so, it's literally the same API, except for the URL to the exchange server.

CCXT unifies that aspect and allows the user to switch to the exchange's sandbox (if supported by the underlying exchange). To switch to the sandbox one has to call the exchange.setSandboxMode (true) or exchange.set_sandbox_mode(true) immediately after creating the exchange before any other call!

Javascript

const exchange = new ccxt.binance (config)
exchange.setSandboxMode (true) // enable sandbox mode

Python

exchange = ccxt.binance(config)
exchange.set_sandbox_mode(True)  # enable sandbox mode

PHP

$exchange = new \ccxt\binance($config);
$exchange->set_sandbox_mode(true); // enable sandbox mode
  • The exchange.setSandboxMode (true) / exchange.set_sandbox_mode (True) has to be your first call immediately after creating the exchange (before any other calls)

  • To obtain the API keys to the sandbox the user has to register with the sandbox website of the exchange in question and create a sandbox keypair

  • Sandbox keys are not interchangeable with production keys!

Exchange Structure

Every exchange has a set of properties and methods, most of which you can override by passing an associative array of params to an exchange constructor. You can also make a subclass and override everything.

Here's an overview of generic exchange properties with values added for example:

{
    'id':   'exchange'                   // lowercase string exchange id
    'name': 'Exchange'                   // human-readable string
    'countries': [ 'US', 'CN', 'EU' ],   // array of ISO country codes
    'urls': {
        'api': 'https://api.example.com/data',  // string or dictionary of base API URLs
        'www': 'https://www.example.com'        // string website URL
        'doc': 'https://docs.example.com/api',  // string URL or array of URLs
    },
    'version':         'v1',             // string ending with digits
    'api':             { ... },          // dictionary of api endpoints
    'has': {                             // exchange capabilities
        'CORS': false,
        'cancelOrder': true,
        'createDepositAddress': false,
        'createOrder': true,
        'fetchBalance': true,
        'fetchCanceledOrders': false,
        'fetchClosedOrder': false,
        'fetchClosedOrders': false,
        'fetchCurrencies': false,
        'fetchDepositAddress': false,
        'fetchMarkets': true,
        'fetchMyTrades': false,
        'fetchOHLCV': false,
        'fetchOpenOrder': false,
        'fetchOpenOrders': false,
        'fetchOrder': false,
        'fetchOrderBook': true,
        'fetchOrders': false,
        'fetchStatus': 'emulated',
        'fetchTicker': true,
        'fetchTickers': false,
        'fetchBidsAsks': false,
        'fetchTrades': true,
        'withdraw': false,
    },
    'timeframes': {                      // empty if the exchange.has['fetchOHLCV'] !== true
        '1m': '1minute',
        '1h': '1hour',
        '1d': '1day',
        '1M': '1month',
        '1y': '1year',
    },
    'timeout':           10000,          // number in milliseconds
    'rateLimit':         2000,           // number in milliseconds
    'userAgent':        'ccxt/1.1.1 ...' // string, HTTP User-Agent header
    'verbose':           false,          // boolean, output error details
    'markets':          { ... }          // dictionary of markets/pairs by symbol
    'symbols':          [ ... ]          // sorted list of string symbols (traded pairs)
    'currencies':       { ... }          // dictionary of currencies by currency code
    'markets_by_id':    { ... },         // dictionary of array of dictionaries (markets) by id
    'currencies_by_id': { ... },         // dictionary of dictionaries (markets) by id
    'apiKey':   '92560ffae9b8a0421...',  // string public apiKey (ASCII, hex, Base64, ...)
    'secret':   '9aHjPmW+EtRRKN/Oi...'   // string private secret key
    'password': '6kszf4aci8r',           // string password
    'uid':      '123456',                // string user id
    'options':          { ... },         // exchange-specific options
    // ... other properties here ...
}

Exchange Properties

Below is a detailed description of each of the base exchange properties:

  • id: Each exchange has a default id. The id is not used for anything, it's a string literal for user-land exchange instance identification purposes. You can have multiple links to the same exchange and differentiate them by ids. Default ids are all lowercase and correspond to exchange names.

  • name: This is a string literal containing the human-readable exchange name.

  • countries: An array of string literals of 2-symbol ISO country codes, where the exchange is operating from.

  • urls['api']: The single string literal base URL for API calls or an associative array of separate URLs for private and public APIs.

  • urls['www']: The main HTTP website URL.

  • urls['doc']: A single string URL link to original documentation for exchange API on their website or an array of links to docs.

  • version: A string literal containing version identifier for current exchange API. The ccxt library will append this version string to the API Base URL upon each request. You don't have to modify it, unless you are implementing a new exchange API. The version identifier is a usually a numeric string starting with a letter 'v' in some cases, like v1.1. Do not override it unless you are implementing your own new crypto exchange class.

  • api: An associative array containing a definition of all API endpoints exposed by a crypto exchange. The API definition is used by ccxt to automatically construct callable instance methods for each available endpoint.

  • has: This is an associative array of exchange capabilities (e.g fetchTickers, fetchOHLCV or CORS).

  • timeframes: An associative array of timeframes, supported by the fetchOHLCV method of the exchange. This is only populated when has['fetchOHLCV'] property is true.

  • timeout: A timeout in milliseconds for a request-response roundtrip (default timeout is 10000 ms = 10 seconds). If the response is not received in that time, the library will throw an RequestTimeout exception. You can leave the default timeout value or set it to a reasonable value. Hanging forever with no timeout is not your option, for sure. You don't have to override this option in general case.

  • rateLimit: A request rate limit in milliseconds. Specifies the required minimal delay between two consequent HTTP requests to the same exchange. The built-in rate-limiter is enabled by default and can be turned off by setting the enableRateLimit property to false.

  • enableRateLimit: A boolean (true/false) value that enables the built-in rate limiter and throttles consecutive requests. This setting is true (enabled) by default. The user is required to implement own rate limiting or leave the built-in rate limiter enabled to avoid being banned from the exchange.

  • userAgent: An object to set HTTP User-Agent header to. The ccxt library will set its User-Agent by default. Some exchanges may not like it. If you are having difficulties getting a reply from an exchange and want to turn User-Agent off or use the default one, set this value to false, undefined, or an empty string. The value of userAgent may be overrided by HTTP headers property below.

  • headers: An associative array of HTTP headers and their values. Default value is empty {}. All headers will be prepended to all requests. If the User-Agent header is set within headers, it will override whatever value is set in the userAgent property above.

  • verbose: A boolean flag indicating whether to log HTTP requests to stdout (verbose flag is false by default). Python people have an alternative way of DEBUG logging with a standard pythonic logger, which is enabled by adding these two lines to the beginning of their code:

    import logging
    logging.basicConfig(level=logging.DEBUG)
  • markets: An associative array of markets indexed by common trading pairs or symbols. Markets should be loaded prior to accessing this property. Markets are unavailable until you call the loadMarkets() / load_markets() method on exchange instance.

  • symbols: A non-associative array (a list) of symbols available with an exchange, sorted in alphabetical order. These are the keys of the markets property. Symbols are loaded and reloaded from markets. This property is a convenient shorthand for all market keys.

  • currencies: An associative array (a dict) of currencies by codes (usually 3 or 4 letters) available with an exchange. Currencies are loaded and reloaded from markets.

  • markets_by_id: An associative array of arrays of markets indexed by exchange-specific ids. Typically a length one array unless there are multiple markets with the same marketId. Markets should be loaded prior to accessing this property.

  • apiKey: This is your public API key string literal. Most exchanges require API keys setup.

  • secret: Your private secret API key string literal. Most exchanges require this as well together with the apiKey.

  • password: A string literal with your password/phrase. Some exchanges require this parameter for trading, but most of them don't.

  • uid: A unique id of your account. This can be a string literal or a number. Some exchanges also require this for trading, but most of them don't.

  • requiredCredentials: A unified associative dictionary that shows which of the above API credentials are required for sending private API calls to the underlying exchange (an exchange may require a specific set of keys).

  • options: An exchange-specific associative dictionary containing special keys and options that are accepted by the underlying exchange and supported in CCXT.

  • precisionMode: The exchange decimal precision counting mode, read more about Precision And Limits

  • For proxies - proxyUrl, httpUrl, httpsUrl, socksProxy, wsProxy, wssProxy, wsSocksProxy : An url of specific proxy. Read details in Proxy section.

See this section on Overriding exchange properties.

Exchange Metadata

  • has: An assoc-array containing flags for exchange capabilities, including the following:

    'has': {
    
        'CORS': false,  // has Cross-Origin Resource Sharing enabled (works from browser) or not
    
        // unified methods availability flags (can be true, false, or 'emulated'):
    
        'cancelOrder': true,
        'createDepositAddress': false,
        'createOrder': true,
        'fetchBalance': true,
        'fetchCanceledOrders': false,
        'fetchClosedOrder': false,
        'fetchClosedOrders': false,
        'fetchCurrencies': false,
        'fetchDepositAddress': false,
        'fetchMarkets': true,
        'fetchMyTrades': false,
        'fetchOHLCV': false,
        'fetchOpenOrder': false,
        'fetchOpenOrders': false,
        'fetchOrder': false,
        'fetchOrderBook': true,
        'fetchOrders': false,
        'fetchStatus': 'emulated',
        'fetchTicker': true,
        'fetchTickers': false,
        'fetchBidsAsks': false,
        'fetchTrades': true,
        'withdraw': false,
        ...
    }

    The meaning of each flag showing availability of this or that method is:

    • a value of undefined / None / null means the method is not currently implemented in ccxt (either ccxt has not unified it yet or the method isn't natively available from the exchange API)

    • boolean false specifically means that the endpoint isn't natively available from the exchange API

    • boolean true means the endpoint is natively available from the exchange API and unified in the ccxt library

    • 'emulated' string means the endpoint isn't natively available from the exchange API but reconstructed (as much as possible) by the ccxt library from other available true-methods

    For a complete list of all exchages and their supported methods, please, refer to this example: https://github.com/ccxt/ccxt/blob/master/examples/js/exchange-capabilities.js

Rate Limit

Exchanges usually impose what is called a rate limit. Exchanges will remember and track your user credentials and your IP address and will not allow you to query the API too frequently. They balance their load and control traffic congestion to protect API servers from (D)DoS and misuse.

WARNING: Stay under the rate limit to avoid ban!

Most exchanges allow up to 1 or 2 requests per second. Exchanges may temporarily restrict your access to their API or ban you for some period of time if you are too aggressive with your requests.

The exchange.rateLimit property is set to a safe default which is sub-optimal. Some exchanges may have varying rate limits for different endpoints. It is up to the user to tweak rateLimit according to application-specific purposes.

The CCXT library has a built-in experimental rate-limiter that will do the necessary throttling in background transparently to the user. WARNING: users are responsible for at least some type of rate-limiting: either by implementing a custom algorithm or by doing it with the built-in rate-limiter..

You can turn on/off the built-in rate-limiter with .enableRateLimit property, like so:

Javascript

// enable built-in rate limiting upon instantiation of the exchange
const exchange = new ccxt.bitfinex ({
    // 'enableRateLimit': true, // enabled by default
})

// or switch the built-in rate-limiter on or off later after instantiation
exchange.enableRateLimit = true // enable
exchange.enableRateLimit = false // disable

Python

# enable built-in rate limiting upon instantiation of the exchange
exchange = ccxt.bitfinex({
    # 'enableRateLimit': True,  # enabled by default
})

# or switch the built-in rate-limiter on or off later after instantiation
exchange.enableRateLimit = True  # enable
exchange.enableRateLimit = False  # disable

PHP

// enable built-in rate limiting upon instantiation of the exchange
$exchange = new \ccxt\bitfinex (array (
    // 'enableRateLimit' => true, // enabled by default
));

// or switch the built-in rate-limiter on or off later after instantiation
$exchange->enableRateLimit = true; // enable
$exchange->enableRateLimit = false; // disable

In case your calls hit a rate limit or get nonce errors, the ccxt library will throw an InvalidNonce exception, or, in some cases, one of the following types:

  • DDoSProtection

  • ExchangeNotAvailable

  • ExchangeError

  • InvalidNonce

A later retry is usually enough to handle that.

Notes On Rate Limiter

One Rate Limiter Per Each Exchange Instance

The rate limiter is a property of the exchange instance, in other words, each exchange instance has its own rate limiter that is not aware of the other instances. In many cases the user should reuse the same exchange instance throughout the program. Do not use multiple instances of the same exchange with the same API keypair from the same IP address.

// DO NOT DO THIS!

const binance1 = new ccxt.binance ()
const binance2 = new ccxt.binance ()
const binance3 = new ccxt.binance ()

while (true) {
    const result = await Promise.all ([
        binance1.fetchOrderBook ('BTC/USDT'),
        binance2.fetchOrderBook ('ETH/USDT'),
        binance3.fetchOrderBook ('ETH/BTC'),
    ])
    console.log (result)
}

Reuse the exchange instance as much as possible as shown below:

// DO THIS INSTEAD:

const binance = new ccxt.binance ()

while (true) {
    const result = await Promise.all ([
        binance.fetchOrderBook ('BTC/USDT'),
        binance.fetchOrderBook ('ETH/USDT'),
        binance.fetchOrderBook ('ETH/BTC'),
    ])
    console.log (result)
}

Since the rate limiter belongs to the exchange instance, destroying the exchange instance will destroy the rate limiter as well. Among the most common pitfalls with the rate limiting is creating and dropping the exchange instance over and over again. If in your program you are creating and destroying the exchange instance (say, inside a function that is called multiple times), then you are effectively resetting the rate limiter over and over and that will eventually break the rate limits. If you are recreating the exchange instance every time instead of reusing it, CCXT will try to load the markets every time. Therefore, you will force-load the markets over and over as explained in the Loading Markets section. Abusing the markets endpoint will eventually break the rate limiter as well.

// DO NOT DO THIS!

async function tick () {
    const exchange = new ccxt.binance ()
    const response = await exchange.fetchOrderBook ('BTC/USDT')
    // ... some processing here ...
    return response
}

while (true) {
    const result = await tick ()
    console.log (result)
}

Do not break this rule unless you really understand the inner workings of the rate-limiter and you are 100% sure you know what you're doing. In order to stay safe always reuse the exchange instance throughout your functions and methods callchain like shown below:

// DO THIS INSTEAD:

async function tick (exchange) {
    const response = await exchange.fetchOrderBook ('BTC/USDT')
    // ... some processing here ...
    return response
}

const exchange = new ccxt.binance ()
while (true) {
    const result = await tick (exchange)
    console.log (result)
}

DDoS Protection By Cloudflare / Incapsula

Some exchanges are DDoS-protected by Cloudflare or Incapsula. Your IP can get temporarily blocked during periods of high load. Sometimes they even restrict whole countries and regions. In that case their servers usually return a page that states a HTTP 40x error or runs an AJAX test of your browser / captcha test and delays the reload of the page for several seconds. Then your browser/fingerprint is granted access temporarily and gets added to a whitelist or receives a HTTP cookie for further use.

The most common symptoms for a DDoS protection problem, rate-limiting problem or for a location-based filtering issue:

  • Getting RequestTimeout exceptions with all types of exchange methods

  • Catching ExchangeError or ExchangeNotAvailable with HTTP error codes 400, 403, 404, 429, 500, 501, 503, etc..

  • Having DNS resolving issues, SSL certificate issues and low-level connectivity issues

  • Getting a template HTML page instead of JSON from the exchange

If you encounter DDoS protection errors and cannot reach a particular exchange then:

  • use a proxy (this is less responsive, though)

  • ask the exchange support to add you to a whitelist

  • try an alternative IP within a different geographic region

  • run your software in a distributed network of servers

  • run your software in close proximity to the exchange (same country, same city, same datacenter, same server rack, same server)

  • ...

Markets

Each exchange is a place for trading some kinds of valuables. The exchanges may use differing terms to call them: "a currency", "an asset", "a coin", "a token", "stock", "commodity", "crypto", "fiat", etc. A place for trading one asset for another is usually called "a market", "a symbol", "a trading pair", "a contract", etc.

In terms of the ccxt library, every exchange offers multiple markets within itself. Each market is defined by two or more currencies. The set of markets differs from exchange to exchange opening possibilities for cross-exchange and cross-market arbitrage.

Currency Structure

{
    'id':       'btc',       // string literal for referencing within an exchange
    'code':     'BTC',       // uppercase unified string literal code the currency
    'name':     'Bitcoin',   // string, human-readable name, if specified
    'active':    true,       // boolean, currency status (tradeable and withdrawable)
    'fee':       0.123,      // withdrawal fee, flat
    'precision': 8,          // number of decimal digits "after the dot" (depends on exchange.precisionMode)
    'deposit':   true        // boolean, deposits are available
    'withdraw':  true        // boolean, withdraws are available
    'limits': {              // value limits when placing orders on this market
        'amount': {
            'min': 0.01,     // order amount should be > min
            'max': 1000,     // order amount should be < max
        },
        'withdraw': { ... }, // withdrawal limits
        'deposit': {...},
    },
    'networks': {...}        // network structures indexed by unified network identifiers (ERC20, TRC20, BSC, etc)
    'info': { ... },         // the original unparsed currency info from the exchange
}

Each currency is an associative array (aka dictionary) with the following keys:

  • id. The string or numeric ID of the currency within the exchange. Currency ids are used inside exchanges internally to identify coins during the request/response process.

  • code. An uppercase string code representation of a particular currency. Currency codes are used to reference currencies within the ccxt library (explained below).

  • name. A human-readable name of the currency (can be a mix of uppercase & lowercase characters).

  • fee. The withdrawal fee value as specified by the exchange. In most cases it means a flat fixed amount paid in the same currency. If the exchnange does not specify it via public endpoints, the fee can be undefined/None/null or missing.

  • active. A boolean indicating whether trading or funding (depositing or withdrawing) for this currency is currently possible, more about it here: active status.

  • info. An associative array of non-common market properties, including fees, rates, limits and other general market information. The internal info array is different for each particular market, its contents depend on the exchange.

  • precision. Precision accepted in values by exchanges upon referencing this currency. The value of this property depends on exchange.precisionMode.

  • limits. The minimums and maximums for amounts (volumes), withdrawals and deposits.

Network Structure

{
    'id':       'tron',         // string literal for referencing within an exchange
    'network':  'TRC20'         // unified network
    'name':     'Tron Network', // string, human-readable name, if specified
    'active':    true,          // boolean, currency status (tradeable and withdrawable)
    'fee':       0.123,         // withdrawal fee, flat
    'precision': 8,             // number of decimal digits "after the dot" (depends on exchange.precisionMode)
    'deposit':   true           // boolean, deposits are available
    'withdraw':  true           // boolean, withdraws are available
    'limits': {                 // value limits when placing orders on this market
        'amount': {
            'min': 0.01,        // order amount should be > min
            'max': 1000,        // order amount should be < max
        },
        'withdraw': { ... },    // withdrawal limits
        'deposit': {...},       // deposit limits
    },
    'info': { ... },            // the original unparsed currency info from the exchange
}

Each network is an associative array (aka dictionary) with the following keys:

  • id. The string or numeric ID of the network within the exchange. Network ids are used inside exchanges internally to identify networks during the request/response process.

  • network. An uppercase string representation of a particular network. Networks are used to reference networks within the ccxt library.

  • name. A human-readable name of the network (can be a mix of uppercase & lowercase characters).

  • fee. The withdrawal fee value as specified by the exchange. In most cases it means a flat fixed amount paid in the same currency. If the exchnange does not specify it via public endpoints, the fee can be undefined/None/null or missing.

  • active. A boolean indicating whether trading or funding (depositing or withdrawing) for this currency is currently possible, more about it here: active status.

  • info. An associative array of non-common market properties, including fees, rates, limits and other general market information. The internal info array is different for each particular market, its contents depend on the exchange.

  • precision. Precision accepted in values by exchanges upon referencing this currency. The value of this property depends on exchange.precisionMode.

  • limits. The minimums and maximums for amounts (volumes), withdrawals and deposits.

Market Structure

{
    'id':      'btcusd',      // string literal for referencing within an exchange
    'symbol':  'BTC/USD',     // uppercase string literal of a pair of currencies
    'base':    'BTC',         // uppercase string, unified base currency code, 3 or more letters
    'quote':   'USD',         // uppercase string, unified quote currency code, 3 or more letters
    'baseId':  'btc',         // any string, exchange-specific base currency id
    'quoteId': 'usd',         // any string, exchange-specific quote currency id
    'active':   true,         // boolean, market status
    'type':    'spot',        // spot for spot, future for expiry futures, swap for perpetual swaps, 'option' for options
    'spot':     true,         // whether the market is a spot market
    'margin':   true,         // whether the market is a margin market
    'future':   false,        // whether the market is a expiring future
    'swap':     false,        // whether the market is a perpetual swap
    'option':   false,        // whether the market is an option contract
    'contract': false,        // whether the market is a future, a perpetual swap, or an option
    'settle':   'USDT',       // the unified currency code that the contract will settle in, only set if `contract` is true
    'settleId': 'usdt',       // the currencyId of that the contract will settle in, only set if `contract` is true
    'contractSize': 1,        // the size of one contract, only used if `contract` is true
    'linear':   true,         // the contract is a linear contract (settled in quote currency)
    'inverse':  false,        // the contract is an inverse contract (settled in base currency)
    'expiry':  1641370465121, // the unix expiry timestamp in milliseconds, undefined for everything except market['type'] `future`
    'expiryDatetime': '2022-03-26T00:00:00.000Z', // The datetime contract will in iso8601 format
    'strike': 4000,           // price at which a put or call option can be exercised
    'optionType': 'call',     // call or put string, call option represents an option with the right to buy and put an option with the right to sell
    'taker':    0.002,        // taker fee rate, 0.002 = 0.2%
    'maker':    0.0016,       // maker fee rate, 0.0016 = 0.16%
    'percentage': true,       // whether the taker and maker fee rate is a multiplier or a fixed flat amount
    'tierBased': false,       // whether the fee depends on your trading tier (your trading volume)
    'feeSide': 'get',         // string literal can be 'get', 'give', 'base', 'quote', 'other'
    'precision': {            // number of decimal digits "after the dot"
        'price': 8,           // integer or float for TICK_SIZE roundingMode, might be missing if not supplied by the exchange
        'amount': 8,          // integer, might be missing if not supplied by the exchange
        'cost': 8,            // integer, very few exchanges actually have it
    },
    'limits': {               // value limits when placing orders on this market
        'amount': {
            'min': 0.01,      // order amount should be > min
            'max': 1000,      // order amount should be < max
        },
        'price': { ... },     // same min/max limits for the price of the order
        'cost':  { ... },     // same limits for order cost = price * amount
        'leverage': { ... },  // same min/max limits for the leverage of the order
    },
    'info':      { ... },     // the original unparsed market info from the exchange
}

Each market is an associative array (aka dictionary) with the following keys:

  • id. The string or numeric ID of the market or trade instrument within the exchange. Market ids are used inside exchanges internally to identify trading pairs during the request/response process.

  • symbol. An uppercase string code representation of a particular trading pair or instrument. This is usually written as BaseCurrency/QuoteCurrency with a slash as in BTC/USD, LTC/CNY or ETH/EUR, etc. Symbols are used to reference markets within the ccxt library (explained below).

  • base. A unified uppercase string code of base fiat or crypto currency. This is the standardized currency code that is used to refer to that currency or token throughout CCXT and throughout the Unified CCXT API, it's the language that CCXT understands.

  • quote. A unified uppercase string code of quoted fiat or crypto currency.

  • baseId. An exchange-specific id of the base currency for this market, not unified. Can be any string, literally. This is communicated to the exchange using the language the exchange understands.

  • quoteId. An exchange-specific id of the quote currency, not unified.

  • active. A boolean indicating whether or not trading this market is currently possible, more about it here: active status.

  • maker. Float, 0.0015 = 0.15%. Maker fees are paid when you provide liquidity to the exchange i.e. you market-make an order and someone else fills it. Maker fees are usually lower than taker fees. Fees can be negative, this is very common amongst derivative exchanges. A negative fee means the exchange will pay a rebate (reward) to the user for trading this market.

  • taker. Float, 0.002 = 0.2%. Taker fees are paid when you take liquidity from the exchange and fill someone else's order.

  • percentage. A boolean true/false value indicating whether taker and maker are multipliers or fixed flat amounts.

  • tierBased. A boolean true/false value indicating whether the fee depends on your trading tier (usually, your traded volume over a period of time).

  • info. An associative array of non-common market properties, including fees, rates, limits and other general market information. The internal info array is different for each particular market, its contents depend on the exchange.

  • precision. Precision accepted in order values by exchanges upon order placement for price, amount and cost. (The value inside this property depend on the exchange.precisionMode).

  • limits. The minimums and maximums for prices, amounts (volumes) and costs (where cost = price * amount).

  • optionType. The type of the option, call option represents an option with the right to buy and put an option with the right to sell.

  • strike. Price at which an option can be bought or sold when it is exercised.

Active Status

The active flag is typically used in currencies and markets. The exchanges might put a slightly different meaning into it. If a currency is inactive, most of the time all corresponding tickers, orderbooks and other related endpoints return empty responses, all zeroes, no data or outdated information. The user should check if the currency is active and reload markets periodically.

Note: the false value for the active property doesn't always guarantee that all of the possible features like trading, withdrawing or depositing are disabled on the exchange. Likewise, neither the true value guarantees that all those features are enabled on the exchange. Check the underlying exchanges' documentation and the code in CCXT for the exact meaning of the active flag for this or that exchange. This flag is not yet supported or implemented by all markets and may be missing.

WARNING! The information about the fee is experimental, unstable and may be partial or not available at all.

Precision And Limits

Do not confuse limits with precision! Precision has nothing to do with min limits. A precision of 8 digits does not necessarily mean a min limit of 0.00000001. The opposite is also true: a min limit of 0.0001 does not necessarily mean a precision of 4.

Examples:

  1. (market['limits']['amount']['min'] == 0.05) && (market['precision']['amount'] == 4)

In this example the amount of any order placed on the market must satisfy both conditions:

  • The amount value should be >= 0.05:

    + good: 0.05, 0.051, 0.0501, 0.0502, ..., 0.0599, 0.06, 0.0601, ...
    - bad: 0.04, 0.049, 0.0499
  • Precision of the amount should be up to 4 decimal digits:

    + good: 0.05, 0.051, 0.052, ..., 0.0531, ..., 0.06, ... 0.0719, ...
    - bad: 0.05001, 0.05000, 0.06001
  1. (market['limits']['price']['min'] == 0.019) && (market['precision']['price'] == 5)

In this example the price of any order placed on the market must satisfy both conditions:

  • The price value should be >= 0.019:

    + good: 0.019, ... 0.0191, ... 0.01911, 0.01912, ...
    - bad: 0.016, ..., 0.01699
  • Precision of price should be 5 decimal digits or less:

    + good: 0.02, 0.021, 0.0212, 0.02123, 0.02124, 0.02125, ...
    - bad: 0.017000, 0.017001, ...
  1. (market['limits']['amount']['min'] == 50) && (market['precision']['amount'] == -1)

In this example both conditions must be satisfied:

  • The amount value should be greater than or equal to 50:

    + good: 50, 60, 70, 80, 90, 100, ... 2000, ...
    - bad: 1, 2, 3, ..., 9
  • A negative amount precision means that the amount should be an integer multiple of 10 (to the absolute power specified):

    + good: 50, ..., 110, ... 1230, ..., 1000000, ..., 1234560, ...
    - bad: 9.5, ... 10.1, ..., 11, ... 200.71, ...

The precision and limits params are currently under heavy development, some of these fields may be missing here and there until the unification process is complete. This does not influence most of the orders but can be significant in extreme cases of very large or very small orders.

Notes On Precision And Limits

The user is required to stay within all limits and precision! The values of the order should satisfy the following conditions:

  • Order amount >= limits['amount']['min']

  • Order amount <= limits['amount']['max']

  • Order price >= limits['price']['min']

  • Order price <= limits['price']['max']

  • Order cost (amount * price) >= limits['cost']['min']

  • Order cost (amount * price) <= limits['cost']['max']

  • Precision of amount must be <= precision['amount']

  • Precision of price must be <= precision['price']

The above values can be missing with some exchanges that don't provide info on limits from their API or don't have it implemented yet.

Methods For Formatting Decimals

Each exchange has its own rounding, counting and padding modes.

Supported rounding modes are:

  • ROUND – will round the last decimal digits to precision

  • TRUNCATE– will cut off the digits after certain precision

The decimal precision counting mode is available in the exchange.precisionMode property.

Precision Mode

Supported precision modes in exchange['precisionMode'] are:

  • DECIMAL_PLACES – counts all digits, 99% of exchanges use this counting mode. With this mode of precision, the numbers in market_or_currency['precision'] designate the number of decimal digits after the dot for further rounding or truncation.

  • SIGNIFICANT_DIGITS – counts non-zero digits only, some exchanges (bitfinex and maybe a few other) implement this mode of counting decimals. With this mode of precision, the numbers in market_or_currency['precision'] designate the Nth place of the last significant (non-zero) decimal digit after the dot.

  • TICK_SIZE – some exchanges only allow a multiple of a specific value (bitmex uses this mode, for example). In this mode, the numbers in market_or_currency['precision'] designate the minimal precision fractions (floats) for rounding or truncating.

Padding Mode

Supported padding modes are:

  • NO_PADDING – default for most cases

  • PAD_WITH_ZERO – appends zero characters up to precision

Formatting To Precision

Most of the time the user does not have to take care of precision formatting, since CCXT will handle that for the user when the user places orders or sends withdrawal requests, if the user follows the rules as described on Precision And Limits. However, in some cases precision-formatting details may be important, so the following methods may be useful in the userland.

The exchange base class contains the decimalToPrecision method to help format values to the required decimal precision with support for different rounding, counting and padding modes.

Javascript

function decimalToPrecision (x, roundingMode, numPrecisionDigits, countingMode = DECIMAL_PLACES, paddingMode = NO_PADDING)

Python

# WARNING! The `decimal_to_precision` method is susceptible to getcontext().prec!
def decimal_to_precision(n, rounding_mode=ROUND, precision=None, counting_mode=DECIMAL_PLACES, padding_mode=NO_PADDING):

PHP

function decimalToPrecision ($x, $roundingMode = ROUND, $numPrecisionDigits = null, $countingMode = DECIMAL_PLACES, $paddingMode = NO_PADDING)

For examples of how to use the decimalToPrecision to format strings and floats, please, see the following files:

Python WARNING! The decimal_to_precision method is susceptible to getcontext().prec!

For users' convenience CCXT base exchange class also implements the following methods:

Javascript

function amountToPrecision (symbol, amount)
function priceToPrecision (symbol, price)
function costToPrecision (symbol, cost)
function currencyToPrecision (code, amount)

Python

def amount_to_precision (symbol, amount):
def price_to_precision (symbol, price):
def cost_to_precision (symbol, cost):
def currency_to_precision (code, amount):

PHP

function amount_to_precision($symbol, $amount)
function price_to_precision($symbol, $price)
function cost_to_precision($symbol, $cost)
function currency_to_precision($code, $amount)

Every exchange has its own precision settings, the above methods will help format those values according to exchange-specific precision rules, in a way that is portable and agnostic of the underlying exchange. In order to make that possible, markets and currencies have to be loaded prior to formatting any values.

Make sure to load the markets with exchange.loadMarkets() before calling these methods!

For example:

Javascript

await exchange.loadMarkets ()
const symbol = 'BTC/USDT'
const amount = 1.2345678 // amount in base currency BTC
const price = 87654.321 // price in quote currency USDT
const formattedAmount = exchange.amountToPrecision (symbol, amount)
const formattedPrice = exchange.priceToPrecision (symbol, price)
console.log (formattedAmount, formattedPrice)

Python

exchange.load_markets()
symbol = 'BTC/USDT'
amount = 1.2345678  # amount in base currency BTC
price = 87654.321  # price in quote currency USDT
formatted_amount = exchange.amount_to_precision(symbol, amount)
formatted_price = exchange.price_to_precision(symbol, price)
print(formatted_amount, formatted_price)

PHP

$exchange->load_markets();
$symbol = 'BTC/USDT';
$amount = 1.2345678;  // amount in base currency BTC
$price = 87654.321; // price in quote currency USDT
$formatted_amount = $exchange->amount_to_precision($symbol, $amount);
$formatted_price = $exchange->price_to_precision($symbol, $price);
echo $formatted_amount, " ", $formatted_price, "\n";

More practical examples that describe the behavior of exchange.precisionMode:

// case A
exchange.precisionMode = ccxt.DECIMAL_PLACES
market = exchange.market (symbol)
market['precision']['amount'] === 8 // up to 8 decimals after the dot
exchange.amountToPrecision (symbol, 0.123456789) === 0.12345678
exchange.amountToPrecision (symbol, 0.0000000000123456789) === 0.0000000 === 0.0
// case B
exchange.precisionMode = ccxt.TICK_SIZE
market = exchange.market (symbol)
market['precision']['amount'] === 0.00000001 // up to 0.00000001 precision
exchange.amountToPrecision (symbol, 0.123456789) === 0.12345678
exchange.amountToPrecision (symbol, 0.0000000000123456789) === 0.00000000 === 0.0
// case C
exchange.precisionMode = ccxt.SIGNIFICANT_DIGITS
market = exchange.market (symbol)
market['precision']['amount'] === 8 // up to 8 significant non-zero digits
exchange.amountToPrecision (symbol, 0.0000000000123456789) === 0.000000000012345678
exchange.amountToPrecision (symbol, 123.4567890123456789) === 123.45678

Loading Markets

In most cases you are required to load the list of markets and trading symbols for a particular exchange prior to accessing other API methods. If you forget to load markets the ccxt library will do that automatically upon your first call to the unified API. It will send two HTTP requests, first for markets and then the second one for other data, sequentially. For that reason, your first call to a unified CCXT API method like fetchTicker, fetchBalance, etc will take more time, than the consequent calls, since it has to do more work loading the market information from the exchange API. See Notes On Rate Limiter for more details.

In order to load markets manually beforehand call the loadMarkets () / load_markets () method on an exchange instance. It returns an associative array of markets indexed by trading symbol. If you want more control over the execution of your logic, preloading markets by hand is recommended.

Javascript

(async () => {
    let kraken = new ccxt.kraken ()
    let markets = await kraken.loadMarkets ()
    console.log (kraken.id, markets)
}) ()

Python

okcoin = ccxt.okcoin()
markets = okcoin.load_markets()
print(okcoin.id, markets)

PHP

$id = 'huobipro';
$exchange = '\\ccxt\\' . $id;
$huobipro = new $exchange();
$markets = $huobipro->load_markets();
var_dump($huobipro->id, $markets);

Apart from the market info, the loadMarkets() call will also load the currencies from the exchange and will cache the info in the .markets and the .currencies properties respectively.

The user can also bypass the cache and call unified methods for fetching that information from the exchange endpoints directly, fetchMarkets() and fetchCurrencies(), though using these methods is not recommended for end-users. The recommended way to preload markets is by calling the loadMarkets() unified method. However, new exchange integrations are required to implement these methods if the underlying exchange has the corresponding API endpoints.

Symbols And Market Ids

A currency code is a code of three to five letters, like BTC, ETH, USD, GBP, CNY, JPY, DOGE, RUB, ZEC, XRP, XMR, etc. Some exchanges have exotic currencies with longer codes.

A symbol is usually an uppercase string literal name of a pair of traded currencies with a slash in between. The first currency before the slash is usually called base currency, and the one after the slash is called quote currency. Examples of a symbol are: BTC/USD, DOGE/LTC, ETH/EUR, DASH/XRP, BTC/CNY, ZEC/XMR, ETH/JPY.

Market ids are used during the REST request-response process to reference trading pairs within exchanges. The set of market ids is unique per exchange and cannot be used across exchanges. For example, the BTC/USD pair/market may have different ids on various popular exchanges, like btcusd, BTCUSD, XBTUSD, btc/usd, 42 (numeric id), BTC/USD, Btc/Usd, tBTCUSD, XXBTZUSD. You don't need to remember or use market ids, they are there for internal HTTP request-response purposes inside exchange implementations.

The ccxt library abstracts uncommon market ids to symbols, standardized to a common format. Symbols aren't the same as market ids. Every market is referenced by a corresponding symbol. Symbols are common across exchanges which makes them suitable for arbitrage and many other things.

Sometimes the user might notice a symbol like 'XBTM18' or '.XRPUSDM20180101' or some other "exotic/rare symbols". The symbol is not required to have a slash or to be a pair of currencies. The string in the symbol really depends on the type of the market (whether it is a spot market or a futures market, a darkpool market or an expired market, etc). Attempting to parse the symbol string is highly discouraged, one should not rely on the symbol format, it is recommended to use market properties instead.

Market structures are indexed by symbols and ids. The base exchange class also has builtin methods for accessing markets by symbols. Most API methods require a symbol to be passed in their first argument. You are often required to specify a symbol when querying current prices, making orders, etc.

Most of the time users will be working with market symbols. You will get a standard userland exception if you access non-existent keys in these dicts.

Methods For Markets And Currencies

Javascript

(async () => {

    console.log (await exchange.loadMarkets ())

    let btcusd1 = exchange.markets['BTC/USD']     // get market structure by symbol
    let btcusd2 = exchange.market ('BTC/USD')     // same result in a slightly different way

    let btcusdId = exchange.marketId ('BTC/USD')  // get market id by symbol

    let symbols = exchange.symbols                // get an array of symbols
    let symbols2 = Object.keys (exchange.markets) // same as previous line

    console.log (exchange.id, symbols)            // print all symbols

    let currencies = exchange.currencies          // a dictionary of currencies

    let bitfinex = new ccxt.bitfinex ()
    await bitfinex.loadMarkets ()

    bitfinex.markets['BTC/USD']                   // symbol → market (get market by symbol)
    bitfinex.markets_by_id['XRPBTC'][0]           // id → market (get market by id)

    bitfinex.markets['BTC/USD']['id']             // symbol → id (get id by symbol)
    bitfinex.markets_by_id['XRPBTC'][0]['symbol'] // id → symbol (get symbol by id)

}) ()

Python

print(exchange.load_markets())

etheur1 = exchange.markets['ETH/EUR']         # get market structure by symbol
etheur2 = exchange.market('ETH/EUR')          # same result in a slightly different way

etheurId = exchange.market_id('ETH/EUR')      # get market id by symbol

symbols = exchange.symbols                    # get a list of symbols
symbols2 = list(exchange.markets.keys())      # same as previous line

print(exchange.id, symbols)                   # print all symbols

currencies = exchange.currencies              # a dictionary of currencies

kraken = ccxt.kraken()
kraken.load_markets()

kraken.markets['BTC/USD']                     # symbol → market (get market by symbol)
kraken.markets_by_id['XXRPZUSD'][0]           # id → market (get market by id)

kraken.markets['BTC/USD']['id']               # symbol → id (get id by symbol)
kraken.markets_by_id['XXRPZUSD'][0]['symbol'] # id → symbol (get symbol by id)

PHP

$var_dump($exchange->load_markets());

$dashcny1 = $exchange->markets['DASH/CNY'];        // get market structure by symbol
$dashcny2 = $exchange->market('DASH/CNY');         // same result in a slightly different way

$dashcnyId = $exchange->market_id('DASH/CNY');     // get market id by symbol

$symbols = $exchange->symbols;                     // get an array of symbols
$symbols2 = array_keys($exchange->markets);        // same as previous line

var_dump($exchange->id, $symbols);                 // print all symbols

$currencies = $exchange->currencies;               // an associative array of currencies

$okcoin = '\\ccxt\\okcoin';
$okcoin = new $okcoin();

$okcoin->load_markets();

$okcoin->markets['BTC/USD'];                    // symbol → market (get market by symbol)
$okcoin->markets_by_id['btc_usd'][0];              // id → market (get market by id)

$okcoin->markets['BTC/USD']['id'];              // symbol → id (get id by symbol)
$okcoin->markets_by_id['btc_usd'][0]['symbol']; // id → symbol (get symbol by id)

Naming Consistency

There is a bit of term ambiguity across various exchanges that may cause confusion among newcoming traders. Some exchanges call markets as pairs, whereas other exchanges call symbols as products. In terms of the ccxt library, each exchange contains one or more trading markets. Each market has an id and a symbol. Most symbols are pairs of base currency and quote currency.

Exchanges → Markets → Symbols → Currencies

Historically various symbolic names have been used to designate same trading pairs. Some cryptocurrencies (like Dash) even changed their names more than once during their ongoing lifetime. For consistency across exchanges the ccxt library will perform the following known substitutions for symbols and currencies:

  • XBT → BTC: XBT is newer but BTC is more common among exchanges and sounds more like bitcoin (read more).

  • BCC → BCH: The Bitcoin Cash fork is often called with two different symbolic names: BCC and BCH. The name