A unified crypto exchange websocket
Project description
UXS - Unified eXchange Streaming
A unified crypto exchange websocket
This free to use python library is ccxt based. I use it for personal trading and data feeds. Pull requests are welcome, although I'll yet have to make some sort of guide on how to implement new exchanges.
DISCLAIMER: Use it at your own risk! I take no responsibility for any losses occurred!
Installation (python 3.5.3+ required):
pip install --upgrade uxs
Latest development version:
pip install git+https://github.com/binares/uxs.git
Supported exchanges:
ticker | all_tickers | orderbook | l3 | ohlcv | trades | balance | order | fill | position | |
---|---|---|---|---|---|---|---|---|---|---|
binance | + | + | + | + | + | + | + | p | ||
binancefu | + | + | + | + | + | + | + | p | + | |
bitmex | p | + | + | p | p | + | o | o | + | |
bittrex | + | + | + | + | + | + | + | + | ||
bw | + | + | + | + | + | p | p | |||
coinbene | + | + | + | + | + | p | p | |||
coindcx | p | p | + | p | + | + | p | + | ||
gateiofu | + | p | ||||||||
hitbtc | + | p | + | p | p | p | + | + | ||
kraken | + | p | + | + | + | + | + | |||
krakenfu | + | p | + | p | + | + | + | + | + | |
kucoin | + | + | + | p | + | + | o | o | ||
luno | p | p | w | + | p | w | p | o | o | |
poloniex | p | + | + | p | p | + | + | + | ||
southxchange | p | p | + | p | + | p | p |
Note that there aren't separate subscription channels for balance, order, fill (your trade) and position - they all belong under account: xs.subscribe_to_account()
. However some exchanges like bitmex require you to subscribe to each market directly for order and fill updates: xs.subscribe_to_own_market(symbol)
(but you'll still want to also subscribe to account, as it contains balance and position updates).
+ - direct streaming
p - emulated via polling (fetch_balance, fetch_tickers etc)
w - emulated via streaming (l3 -> orderbook, l3 -> trades)
o - must be subscribed to own_market
Test environments are currently offered for: binancefu, bitmex, krakenfu and kucoin (kraken also offers some sort of non-sandboxed test env). For using them add {'test': True}
to the config, and make sure you have created a sandbox account.
Simple usage:
import uxs
import asyncio
xs = uxs.binance({'apiKey': '', 'secret': ''})
xs.subscribe_to_orderbook('BTC/USDT')
# Subscribes to balance, order, fill and position updates
xs.subscribe_to_account()
xs.start()
asyncio.get_event_loop().run_forever()
ExchangeSocket
All exchange streamer classes inherit from uxs.ExchangeSocket
. Note that uxs.ExchangeSocket
itself isn't a subclass of ccxt.Exchange
, i.e. uxs.binance
!=~ ccxt.async_support.binance
. Its corresponding (asynchronous) ccxt Exchange instance is accessible under .api
: uxs.binance.api
=~ ccxt.async_support.binance
. The .api
object's class is a wrapped one through, with some extra attributes added for caching data, rounding up/down, calculating payout and altering the markets data (e.g. for personalized fees).
ExchangeSocket
does borrow some ccxt.async_support.Exchange
methods: create_order
, edit_order
, cancel_order
will normally evoke the same method of ccxt class, unless the exchange supports websocket trading (hitbtc). And fetch_ticker
, fetch_tickers
, fetch_order_book
, fetch_ohlcv
, fetch_trades
, fetch_balance
, fetch_order
, fetch_orders
, fetch_open_orders
, fetch_closed_orders
, which may in some cases be evoked through websocket.
The included examples show how to wait for updates, use callbacks, trade, cache fetch results and store tokens in a file / password encrypted file.
Subscriptions
# Subscribe
xs.subscribe_to_ticker(symbol)
xs.subscribe_to_all_tickers()
xs.subscribe_to_orderbook(symbol)
xs.subscribe_to_l3(symbol)
xs.subscribe_to_ohlcv(symbol, timeframe)
xs.subscribe_to_trades(symbol)
xs.subscribe_to_account()
xs.subscribe_to_own_market(symbol)
# Unsubscribe
xs.unsubscibe_to_{channel}(**params)
# Shortened
xs.sub_to_{channel}(**params)
xs.unsub_to_{channel}(**params)
# Dynamically
xs.subscribe_to({'_': channel, **params})
xs.unsubscribe_to({'_': channel, **params})
# Subscription object
s = xs.get_subscription({'_': channel, **params}) # for example {'_': 'orderbook', 'symbol': 'BTC/USDT'}
# or
s = xs.get_subscription((channel, *params)) # for example ('orderbook', 'BTC/USDT')
s.state # 0=inactive, 1=active
await s.wait_till_active() # wait till the subscription becomes active
# or
await xs.wait_till_subscription_active({'_': channel, **params})
Data structures
These are attributes of ExchangeSocket instance (xs). The objects in these dicts are equivalent to those of ccxt.Exchange (except for position, which isn't yet implemented by ccxt).
xs.tickers[symbol]
xs.orderbooks[symbol]
xs.l3_books[symbol]
xs.ohlcv[symbol][timeframe]
xs.trades[symbol]
xs.balances[currency]
xs.orders[order_id]
xs.open_orders[order_id]
xs.fills[order_id]
xs.positions[symbol]
An order also contains 'payout' keyword, which is the current received amount in target currency.
The structures are updated on spot. Bids/asks are inserted directly into the existing list, dict values are updated but the dict objects' id never changes. That includes all sub-level dicts (orders, fills, ...), and even the 'info' dicts (but not the other dicts like 'fee': {'cost': .. , 'currency': ..}). So for any time spanning operation (await create_order()), or if you're accessing the data from another thread, there is a real possibility that the dict has been updated in the meanwhile. To ensure that you'll still have access to the old values, make a (deep)copy of the structure before. Also avoid looping over a structure while for example creating an order (in the loop), as the dict/list size might change, and python throws an error (in dict case).
# Do NOT do this:
for o in xs.open_orders.values():
await xs.cancel_order(o['id'], o['symbol'])
# Instead:
for o in list(xs.open_orders.values()):
await xs.cancel_order(o['id'], o['symbol'])
Note that once a subscription feed is lost/unsubbed, the associated real-time data is automatically deleted. This it to prevent the user using outdated data, and by default includes these channels: all_tickers, ticker, orderbook. E.g. once ('orderbook', 'ETH/BTC') is lost, xs.orderbooks['ETH/BTC']
is deleted. Account relevant data is not deleted, as you might want to cancel the orders / close the positions.
To change it initiate an exchange like this:
# specific channel
uxs.binance({'channels': {'orderbook': {'delete_data_on_unsub': False}}})
Wait on stream event
# See example c / docstring for description
await xs.wait_on(stream, id=-1)
Add stream event callback
# See example d for description
xs.add_callback(cb, stream, id=None)
xs.create_order
xs.create_order automatically rounds the price down for buy orders, and up for sell orders. The amount is also rounded, always down.
Logging
Initialize with verbose
value
- 0.5 - create/edit/cancel order
- 1 - connection, subscription, send, fetch/polling events + above
- 2 - ping + some inner mechanisms + above
- 3 - recv events + above
depending on how detailed log you want. Unexpected errors (not connectivity related) are logged in any case.
uxs.binance({'verbose': 1})
If you just want to see recv output without including 0.5, 1 and 2, init with
uxs.binance({'connection_defaults': {'handle': print}})
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file uxs-0.6.1.tar.gz
.
File metadata
- Download URL: uxs-0.6.1.tar.gz
- Upload date:
- Size: 191.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.1 importlib_metadata/4.5.0 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.61.0 CPython/3.6.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5dab0507789eb579b4ac319942b6beaae5aae4f81f089035cdbbd9024b5cd8c4 |
|
MD5 | 69e60d1cfefe8a5d338e404c8d3c16cc |
|
BLAKE2b-256 | 70712b5cc0aa93e73af23398f8b7bac3b8d51f2277cc87d65b7152c5e0d1a6b3 |