Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Crypto

Overview

The integration with crypto exchanges is done by using the CCXT package. It provides both market data and broker functionality from these exchanges.


Supported Exchanges

CCXT supports 100+ exchanges. Some popular ones include:

ExchangeClass
Binanceccxt.binance()
Coinbaseccxt.coinbase()
Krakenccxt.kraken()
Bybitccxt.bybit()
OKXccxt.okx()
['alpaca', 'apex', 'aster', 'backpack', 'bequant', 'bigone', 'binance', 'binancecoinm', 'binanceus', 'binanceusdm']

Market Data

CCXT provides access to historical OHLCV data, order books, and live ticker feeds from hundreds of cryptocurrency exchanges.

The following example shows a back test over historical data gotten from Binance exchange. This uses a public API, so no account with Binance is required to run this example.

Error retrieving symbol=BTC/USDT
Traceback (most recent call last):
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 652, in fetch
    response.raise_for_status()
  File "/home/runner/work/_temp/setup-uv-cache/archive-v0/IF_oVRbpX7zwJbQH/lib/python3.12/site-packages/requests/models.py", line 1167, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 451 Client Error:  for url: https://api.binance.com/api/v3/exchangeInfo

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/runner/work/roboquant.py/roboquant.py/roboquant/feeds/crypto.py", line 55, in __init__
    rows: list[tuple[Any]] = exchange.fetch_ohlcv(
                             ^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/binance.py", line 4959, in fetch_ohlcv
    self.load_markets()
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 1899, in load_markets
    markets = self.fetch_markets(params)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/binance.py", line 3407, in fetch_markets
    promisesRaw.append(self.publicGetExchangeInfo(params))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/types.py", line 43, in unbound_method
    return _self.request(self.path, self.api, self.method, params, config=self.config)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/binance.py", line 12473, in request
    response = self.fetch2(path, api, method, params, headers, body, config)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 5718, in fetch2
    raise e
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 5701, in fetch2
    response = self.fetch(request['url'], request['method'], request['headers'], request['body'])
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 670, in fetch
    self.handle_http_status_code(http_status_code, http_status_text, url, method, http_response)
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 2076, in handle_http_status_code
    raise ErrorClass(self.id + ' ' + method + ' ' + url + ' ' + codeAsString + ' ' + reason + ' ' + body)
ccxt.base.errors.ExchangeNotAvailable: binance GET https://api.binance.com/api/v3/exchangeInfo 451  {
  "code": 0,
  "msg": "Service unavailable from a restricted location according to 'b. Eligibility' in https://www.binance.com/en/terms. Please contact customer service if you believe you received this message in error."
}
Error retrieving symbol=ETH/USDT
Traceback (most recent call last):
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 652, in fetch
    response.raise_for_status()
  File "/home/runner/work/_temp/setup-uv-cache/archive-v0/IF_oVRbpX7zwJbQH/lib/python3.12/site-packages/requests/models.py", line 1167, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 451 Client Error:  for url: https://api.binance.com/api/v3/exchangeInfo

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/runner/work/roboquant.py/roboquant.py/roboquant/feeds/crypto.py", line 55, in __init__
    rows: list[tuple[Any]] = exchange.fetch_ohlcv(
                             ^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/binance.py", line 4959, in fetch_ohlcv
    self.load_markets()
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 1899, in load_markets
    markets = self.fetch_markets(params)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/binance.py", line 3407, in fetch_markets
    promisesRaw.append(self.publicGetExchangeInfo(params))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/types.py", line 43, in unbound_method
    return _self.request(self.path, self.api, self.method, params, config=self.config)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/binance.py", line 12473, in request
    response = self.fetch2(path, api, method, params, headers, body, config)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 5718, in fetch2
    raise e
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 5701, in fetch2
    response = self.fetch(request['url'], request['method'], request['headers'], request['body'])
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 670, in fetch
    self.handle_http_status_code(http_status_code, http_status_text, url, method, http_response)
  File "/home/runner/work/roboquant.py/roboquant.py/.venv/lib/python3.12/site-packages/ccxt/base/exchange.py", line 2076, in handle_http_status_code
    raise ErrorClass(self.id + ' ' + method + ' ' + url + ' ' + codeAsString + ' ' + reason + ' ' + body)
ccxt.base.errors.ExchangeNotAvailable: binance GET https://api.binance.com/api/v3/exchangeInfo 451  {
  "code": 0,
  "msg": "Service unavailable from a restricted location according to 'b. Eligibility' in https://www.binance.com/en/terms. Please contact customer service if you believe you received this message in error."
}
buying power : 10,000@USDT
cash         : 10,000@USDT
equity       : 10,000@USDT
positions    : none
trades       : 0
mkt value    : 0@USDT
orders       : none
last update  : 1900-01-01 00:00:00+00:00

Broker Integration

For broker integration you typically need a trading account with the Exchange/Broker you want to use. Often the onboarding is restricted to certain regions.

  from dotenv import load_env
  load_env()

  key = os.getenv("ALPACA_API_KEY")
  secret = os.getenv("ALPACA_SECRET")

  alpaca = ccxt.alpaca({
      "apiKey": key,
      "secret": secret
  })
  alpaca.set_sandbox_mode(True)
  broker = CryptoBroker(alpaca)
  account = broker.sync()