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:
| Exchange | Class |
|---|---|
| Binance | ccxt.binance() |
| Coinbase | ccxt.coinbase() |
| Kraken | ccxt.kraken() |
| Bybit | ccxt.bybit() |
| OKX | ccxt.okx() |
import ccxt
# List first 10 exchanges
print(ccxt.exchanges[:10])['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.
import ccxt
import roboquant as rq
from roboquant.feeds.crypto import CryptoFeed
from roboquant.common.monetary import USDT
rq.set_light_style()
exchange = ccxt.binance()
# exchange = ccxt.kraken() # or any other exchange supported by ccxt
feed = CryptoFeed(exchange, "BTC/USDT", "ETH/USDT", start_date="2020-01-01 00:00:00", interval="1d")
strategy = rq.strategies.EMACrossover()
trader = rq.traders.FlexTrader(step_size="0.001", max_order_pct=0.2, max_position_pct=0.5, shorting=True)
broker = rq.brokers.SimBroker(deposit=10_000@USDT)
account = rq.run(feed, strategy, trader=trader, broker=broker)
print(account)
for asset in feed.assets():
feed.plot(asset)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()