cryptofeed 2.4.0__tar.gz → 2.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/AUTHORS.md +5 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/CHANGES.md +23 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/INSTALL.md +5 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/LICENSE +1 -1
- cryptofeed-2.5.0/PKG-INFO +257 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/README.md +8 -7
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/__init__.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/_util.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/aggregate.py +4 -4
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/arctic.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/backend.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/gcppubsub.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/http.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/influxdb.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/kafka.py +2 -3
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/mongo.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/postgres.py +1 -1
- cryptofeed-2.5.0/cryptofeed/backends/quasardb.py +175 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/quest.py +7 -4
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/rabbitmq.py +3 -4
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/redis.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/socket.py +3 -3
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/zmq.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/callback.py +3 -3
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/config.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/connection.py +13 -8
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/connection_handler.py +1 -21
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/defines.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exceptions.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchange.py +4 -4
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/__init__.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/ascendex.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bequant.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance.py +9 -5
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_delivery.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_futures.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_tr.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_us.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitdotcom.py +3 -3
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitfinex.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitflyer.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitget.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bithumb.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitmex.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitstamp.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/blockchain.py +1 -1
- cryptofeed-2.5.0/cryptofeed/exchanges/bybit.py +618 -0
- cryptofeed-2.5.0/cryptofeed/exchanges/coinbase.py +192 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/cryptodotcom.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/delta.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/dydx.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/fmfw.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/gateio.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/gateio_futures.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/gemini.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/hitbtc.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/huobi.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/huobi_dm.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/huobi_swap.py +4 -4
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/independent_reserve.py +6 -6
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/kraken.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/kraken_futures.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/kucoin.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/binance_rest.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/bitfinex_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/bitmex_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/bitstamp_rest.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/coinbase_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/deribit_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/dydx_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/gemini_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/kraken_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/okx_rest.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/upbit_rest.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/okcoin.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/okx.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/phemex.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/poloniex.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/probit.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/upbit.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/feed.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/feedhandler.py +21 -6
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/log.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/nbbo.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/raw_data_collection.py +2 -2
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/symbols.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/types.c +26272 -19961
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/types.pyx +2 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/book.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/perf.py +1 -1
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/time.py +1 -1
- cryptofeed-2.5.0/cryptofeed.egg-info/PKG-INFO +257 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/SOURCES.txt +1 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/requires.txt +6 -2
- cryptofeed-2.5.0/pyproject.toml +121 -0
- cryptofeed-2.5.0/setup.py +27 -0
- cryptofeed-2.4.0/PKG-INFO +0 -1090
- cryptofeed-2.4.0/cryptofeed/exchanges/bybit.py +0 -520
- cryptofeed-2.4.0/cryptofeed/exchanges/coinbase.py +0 -391
- cryptofeed-2.4.0/cryptofeed.egg-info/PKG-INFO +0 -1090
- cryptofeed-2.4.0/pyproject.toml +0 -30
- cryptofeed-2.4.0/setup.py +0 -110
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/MANIFEST.in +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/__init__.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/ascendex_futures.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/deribit.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/exx.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/__init__.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/__init__.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/split.py +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/dependency_links.txt +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/top_level.txt +0 -0
- {cryptofeed-2.4.0 → cryptofeed-2.5.0}/setup.cfg +0 -0
|
@@ -14,3 +14,8 @@ Cryptofeed was originally created by Bryant Moscon, but many others have contrib
|
|
|
14
14
|
* [O. Janche](https://github.com/toyan) - <toyan@yandex.ru>
|
|
15
15
|
* [Bastien Enjalbert](https://github.com/bastienjalbert) - <bastienjalbert@gmail.com>
|
|
16
16
|
* [Jonggyun Kim](https://github.com/gyunt) - <truth0233@gmail.com>
|
|
17
|
+
* [QuasarDB](https://quasar.ai/)
|
|
18
|
+
* [Thomas Bouamoud](https://github.com/thomasbs17) - <thomasbs17@yahoo.fr>
|
|
19
|
+
* [Carlo Eugster](https://github.com/carloe) - <carlo@relaun.ch>
|
|
20
|
+
* [Marten Schlüter](https://github.com/maschlr)
|
|
21
|
+
* [Handel Scholze](https://github.com/HandelSM) - <handel.scholze@gmail.com>
|
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
## Changelog
|
|
2
2
|
|
|
3
|
+
### 2.5.0 (2026-08-08)
|
|
4
|
+
* Update: Python 3.12+ required, completed move to uv, `setup.py` removed
|
|
5
|
+
* Update: CI/CD overhaul
|
|
6
|
+
* Bugfix: various bugs in FeedHandler that prevented it from running on 3.14+
|
|
7
|
+
* Bugfix: various backend issues that prevented them from working with later versions of Python
|
|
8
|
+
* Bugfix: Gemini authenticated issue with newer version of websocket library
|
|
9
|
+
* Bugfix: Binance listenKey refresh now uses aiohttp
|
|
10
|
+
* Update: Binance per connection stream limit (issue #1087)
|
|
11
|
+
* Bugfix: Bybit L2_BOOK callback timestamp normalization (issue #1083)
|
|
12
|
+
|
|
13
|
+
### 2.4.1 (2025-02-08)
|
|
14
|
+
* Update: Added `is_data_json` to `write()` in `HTTPSync` from `connection.py` to support JSON payloads (#1071)
|
|
15
|
+
* Bugfix: Handle empty nextFundingRate in OKX
|
|
16
|
+
* Bugfix: Handle null next_funding_time and estimated_rate in HuobiSwap funding
|
|
17
|
+
* Update: transitioned from Coinbase Pro (retired) to Coinbase Advanced Trade
|
|
18
|
+
* Feature: Bybit spot support
|
|
19
|
+
* Update: Bybit migrate to API V5 for public streams
|
|
20
|
+
* Bugfix: Handle None ids for Kraken trades in QuestDB
|
|
21
|
+
* Bugfix: Handle OrderChanged event in IndependentReserve
|
|
22
|
+
* Bugfix: Remove deprecated `USD` currency from bit.com
|
|
23
|
+
* Bugfix: Make `entry` key optional when retrieving symbols for BitMex
|
|
24
|
+
* Update: Changes to work with latest version of websockets
|
|
25
|
+
|
|
3
26
|
### 2.4.0 (2024-01-07)
|
|
4
27
|
* Update: Fix tests
|
|
5
28
|
* Update: Okcoin moved to v5 API used by OKX
|
|
@@ -47,6 +47,11 @@ for the exhaustive list of these *extra* dependencies.
|
|
|
47
47
|
|
|
48
48
|
pip install --user --upgrade cryptofeed[postgres]
|
|
49
49
|
|
|
50
|
+
* QuasarDB backend
|
|
51
|
+
To install Cryptofeed along with [QuasarDB](https://quasar.ai/) in one bundle:
|
|
52
|
+
|
|
53
|
+
pip install --user --upgrade cryptofeed[quasardb]
|
|
54
|
+
|
|
50
55
|
* RabbitMQ backend
|
|
51
56
|
|
|
52
57
|
pip install --user --upgrade cryptofeed[rabbit]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (C) 2017-
|
|
1
|
+
Copyright (C) 2017-2025 Bryant Moscon - bmoscon@gmail.com
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
of this software and associated documentation files (the "Software"), to
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cryptofeed
|
|
3
|
+
Version: 2.5.0
|
|
4
|
+
Summary: Cryptocurrency Exchange Websocket Data Feed Handler
|
|
5
|
+
Author-email: Bryant Moscon <bmoscon@gmail.com>
|
|
6
|
+
License-Expression: XFree86-1.1
|
|
7
|
+
Project-URL: Homepage, https://github.com/bmoscon/cryptofeed
|
|
8
|
+
Keywords: cryptocurrency,bitcoin,btc,feed handler,market feed,market data,crypto assets,Trades,Tickers,BBO,Funding,Open Interest,Liquidation,Order book,Bid,Ask,fmfw.io,Bitfinex,bitFlyer,AscendEX,Bitstamp,Blockchain.com,Bybit,Binance,Binance Delivery,Binance Futures,Binance US,BitMEX,Coinbase,Deribit,EXX,Gate.io,Gemini,HitBTC,Huobi,Huobi DM,Huobi Swap,Kraken,Kraken Futures,OKCoin,OKX,Poloniex,ProBit,Upbit
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
License-File: AUTHORS.md
|
|
20
|
+
Requires-Dist: requests>=2.18.4
|
|
21
|
+
Requires-Dist: websockets>=14.1
|
|
22
|
+
Requires-Dist: pyyaml
|
|
23
|
+
Requires-Dist: aiohttp>=3.11.6
|
|
24
|
+
Requires-Dist: aiofile>=2.0.0
|
|
25
|
+
Requires-Dist: yapic.json>=1.6.3
|
|
26
|
+
Requires-Dist: uvloop; platform_system != "Windows"
|
|
27
|
+
Requires-Dist: order_book>=0.6.0
|
|
28
|
+
Requires-Dist: aiodns>=1.1
|
|
29
|
+
Provides-Extra: arctic
|
|
30
|
+
Requires-Dist: arctic; extra == "arctic"
|
|
31
|
+
Requires-Dist: pandas; extra == "arctic"
|
|
32
|
+
Provides-Extra: gcp-pubsub
|
|
33
|
+
Requires-Dist: google_cloud_pubsub>=2.4.1; extra == "gcp-pubsub"
|
|
34
|
+
Requires-Dist: gcloud_aio_pubsub; extra == "gcp-pubsub"
|
|
35
|
+
Provides-Extra: kafka
|
|
36
|
+
Requires-Dist: aiokafka>=0.7.0; extra == "kafka"
|
|
37
|
+
Provides-Extra: mongo
|
|
38
|
+
Requires-Dist: motor; extra == "mongo"
|
|
39
|
+
Provides-Extra: postgres
|
|
40
|
+
Requires-Dist: asyncpg; extra == "postgres"
|
|
41
|
+
Provides-Extra: quasardb
|
|
42
|
+
Requires-Dist: quasardb; extra == "quasardb"
|
|
43
|
+
Requires-Dist: numpy; extra == "quasardb"
|
|
44
|
+
Provides-Extra: rabbit
|
|
45
|
+
Requires-Dist: aio_pika; extra == "rabbit"
|
|
46
|
+
Requires-Dist: pika; extra == "rabbit"
|
|
47
|
+
Provides-Extra: redis
|
|
48
|
+
Requires-Dist: hiredis; extra == "redis"
|
|
49
|
+
Requires-Dist: redis>=4.5.1; extra == "redis"
|
|
50
|
+
Provides-Extra: zmq
|
|
51
|
+
Requires-Dist: pyzmq; extra == "zmq"
|
|
52
|
+
Provides-Extra: all
|
|
53
|
+
Requires-Dist: arctic; extra == "all"
|
|
54
|
+
Requires-Dist: google_cloud_pubsub>=2.4.1; extra == "all"
|
|
55
|
+
Requires-Dist: gcloud_aio_pubsub; extra == "all"
|
|
56
|
+
Requires-Dist: aiokafka>=0.7.0; extra == "all"
|
|
57
|
+
Requires-Dist: motor; extra == "all"
|
|
58
|
+
Requires-Dist: asyncpg; extra == "all"
|
|
59
|
+
Requires-Dist: aio_pika; extra == "all"
|
|
60
|
+
Requires-Dist: pika; extra == "all"
|
|
61
|
+
Requires-Dist: hiredis; extra == "all"
|
|
62
|
+
Requires-Dist: redis>=4.5.1; extra == "all"
|
|
63
|
+
Requires-Dist: pyzmq; extra == "all"
|
|
64
|
+
Dynamic: license-file
|
|
65
|
+
|
|
66
|
+
# Cryptocurrency Exchange Feed Handler
|
|
67
|
+
[](LICENSE)
|
|
68
|
+

|
|
69
|
+
[](https://pypi.python.org/pypi/cryptofeed)
|
|
70
|
+
[](https://www.codacy.com/app/bmoscon/cryptofeed?utm_source=github.com&utm_medium=referral&utm_content=bmoscon/cryptofeed&utm_campaign=Badge_Grade)
|
|
71
|
+
|
|
72
|
+
Handles multiple cryptocurrency exchange data feeds and returns normalized and standardized results to client registered callbacks for events like trades, book updates, ticker updates, etc. Utilizes websockets when possible, but can also poll data via REST endpoints if a websocket is not provided.
|
|
73
|
+
|
|
74
|
+
## Supported exchanges
|
|
75
|
+
|
|
76
|
+
* [AscendEX](https://ascendex.com/)
|
|
77
|
+
* [Bequant](https://bequant.io/)
|
|
78
|
+
* [Bitfinex](https://bitfinex.com)
|
|
79
|
+
* [bitFlyer](https://bitflyer.com/)
|
|
80
|
+
* [Bithumb](https://en.bithumb.com/)
|
|
81
|
+
* [Bitstamp](https://www.bitstamp.net/)
|
|
82
|
+
* [Blockchain.com](https://www.blockchain.com/)
|
|
83
|
+
* [Bybit](https://www.bybit.com/)
|
|
84
|
+
* [Binance](https://www.binance.com/en)
|
|
85
|
+
* [Binance Delivery](https://binance-docs.github.io/apidocs/delivery/en/)
|
|
86
|
+
* [Binance Futures](https://www.binance.com/en/futures)
|
|
87
|
+
* [Binance US](https://www.binance.us/en)
|
|
88
|
+
* [Bit.com](https://www.bit.com)
|
|
89
|
+
* [Bitget](https://www.bitget.com/)
|
|
90
|
+
* [BitMEX](https://www.bitmex.com/)
|
|
91
|
+
* [Coinbase](https://www.coinbase.com/)
|
|
92
|
+
* [Crypto.com](https://www.crypto.com)
|
|
93
|
+
* [Delta](https://www.delta.exchange/)
|
|
94
|
+
* [Deribit](https://www.deribit.com/)
|
|
95
|
+
* [dYdX](https://dydx.exchange/)
|
|
96
|
+
* [FMFW.io](https://www.fmfw.io/)
|
|
97
|
+
* [EXX](https://www.exx.com/)
|
|
98
|
+
* [Gate.io](https://www.gate.io/)
|
|
99
|
+
* [Gate.io Futures](https://www.gate.io/futures_center)
|
|
100
|
+
* [Gemini](https://gemini.com/)
|
|
101
|
+
* [HitBTC](https://hitbtc.com/)
|
|
102
|
+
* [Huobi](https://www.hbg.com/)
|
|
103
|
+
* [Huobi DM](https://www.huobi.com/en-us/markets/hb_dm/)
|
|
104
|
+
* Huobi Swap (Coin-M and USDT-M)
|
|
105
|
+
* [Independent Reserve](https://www.independentreserve.com/)
|
|
106
|
+
* [Kraken](https://www.kraken.com/)
|
|
107
|
+
* [Kraken Futures](https://futures.kraken.com/)
|
|
108
|
+
* [KuCoin](https://www.kucoin.com/)
|
|
109
|
+
* [OKCoin](http://okcoin.com/)
|
|
110
|
+
* [OKX](https://www.okx.com/)
|
|
111
|
+
* [Phemex](https://phemex.com/)
|
|
112
|
+
* [Poloniex](https://www.poloniex.com/)
|
|
113
|
+
* [ProBit](https://www.probit.com/)
|
|
114
|
+
* [Upbit](https://sg.upbit.com/home)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## Basic Usage
|
|
118
|
+
|
|
119
|
+
Create a FeedHandler object and add subscriptions. For the various data channels that an exchange supports, you can supply callbacks for data events, or use provided backends (described below) to handle the data for you. Start the feed handler and you're done!
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from cryptofeed import FeedHandler
|
|
123
|
+
# not all imports shown for clarity
|
|
124
|
+
|
|
125
|
+
fh = FeedHandler()
|
|
126
|
+
|
|
127
|
+
# ticker, trade, and book are user defined functions that
|
|
128
|
+
# will be called when ticker, trade and book updates are received
|
|
129
|
+
ticker_cb = {TICKER: ticker}
|
|
130
|
+
trade_cb = {TRADES: trade}
|
|
131
|
+
gemini_cb = {TRADES: trade, L2_BOOK: book}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
fh.add_feed(Coinbase(symbols=['BTC-USD'], channels=[TICKER], callbacks=ticker_cb))
|
|
135
|
+
fh.add_feed(Bitfinex(symbols=['BTC-USD'], channels=[TICKER], callbacks=ticker_cb))
|
|
136
|
+
fh.add_feed(Poloniex(symbols=['BTC-USDT'], channels=[TRADES], callbacks=trade_cb))
|
|
137
|
+
fh.add_feed(Gemini(symbols=['BTC-USD', 'ETH-USD'], channels=[TRADES, L2_BOOK], callbacks=gemini_cb))
|
|
138
|
+
|
|
139
|
+
fh.run()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Please see the [examples](https://github.com/bmoscon/cryptofeed/tree/master/examples) for more code samples and the [documentation](https://github.com/bmoscon/cryptofeed/blob/master/docs/README.md) for more information about the library usage.
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
For an example of a containerized application using cryptofeed to store data to a backend, please see [Cryptostore](https://github.com/bmoscon/cryptostore).
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
## National Best Bid/Offer (NBBO)
|
|
149
|
+
|
|
150
|
+
Cryptofeed also provides a synthetic [NBBO](examples/demo_nbbo.py) (National Best Bid/Offer) feed that aggregates the best bids and asks from the user specified feeds.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from cryptofeed import FeedHandler
|
|
154
|
+
from cryptofeed.exchanges import Coinbase, Gemini, Kraken
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def nbbo_update(symbol, bid, bid_size, ask, ask_size, bid_feed, ask_feed):
|
|
158
|
+
print(f'Pair: {symbol} Bid Price: {bid:.2f} Bid Size: {bid_size:.6f} Bid Feed: {bid_feed} Ask Price: {ask:.2f} Ask Size: {ask_size:.6f} Ask Feed: {ask_feed}')
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def main():
|
|
162
|
+
f = FeedHandler()
|
|
163
|
+
f.add_nbbo([Coinbase, Kraken, Gemini], ['BTC-USD'], nbbo_update)
|
|
164
|
+
f.run()
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Supported Channels
|
|
168
|
+
|
|
169
|
+
Cryptofeed supports the following channels from exchanges:
|
|
170
|
+
|
|
171
|
+
### Market Data Channels (Public)
|
|
172
|
+
|
|
173
|
+
* L1_BOOK - Top of book
|
|
174
|
+
* L2_BOOK - Price aggregated sizes. Some exchanges provide the entire depth, some provide a subset.
|
|
175
|
+
* L3_BOOK - Price aggregated orders. Like the L2 book, some exchanges may only provide partial depth.
|
|
176
|
+
* TRADES - Note this reports the taker's side, even for exchanges that report the maker side.
|
|
177
|
+
* TICKER
|
|
178
|
+
* FUNDING
|
|
179
|
+
* OPEN_INTEREST - Open interest data.
|
|
180
|
+
* LIQUIDATIONS
|
|
181
|
+
* INDEX
|
|
182
|
+
* CANDLES - Candlestick / K-Line data.
|
|
183
|
+
|
|
184
|
+
### Authenticated Data Channels
|
|
185
|
+
|
|
186
|
+
* ORDER_INFO - Order status updates
|
|
187
|
+
* TRANSACTIONS - Real-time updates on account deposits and withdrawals
|
|
188
|
+
* BALANCES - Updates on wallet funds
|
|
189
|
+
* FILLS - User's executed trades
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
## Backends
|
|
193
|
+
|
|
194
|
+
Cryptofeed supports `backend` callbacks that will write directly to storage or other interfaces.
|
|
195
|
+
|
|
196
|
+
Supported Backends:
|
|
197
|
+
* Redis (Streams and Sorted Sets)
|
|
198
|
+
* [Arctic](https://github.com/manahl/arctic)
|
|
199
|
+
* ZeroMQ
|
|
200
|
+
* UDP Sockets
|
|
201
|
+
* TCP Sockets
|
|
202
|
+
* Unix Domain Sockets
|
|
203
|
+
* [InfluxDB v2](https://github.com/influxdata/influxdb)
|
|
204
|
+
* MongoDB
|
|
205
|
+
* Kafka
|
|
206
|
+
* RabbitMQ
|
|
207
|
+
* PostgreSQL
|
|
208
|
+
* [QuasarDB](https://quasar.ai/)
|
|
209
|
+
* GCP Pub/Sub
|
|
210
|
+
* [QuestDB](https://questdb.io/)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
## Installation
|
|
214
|
+
|
|
215
|
+
**Note:** cryptofeed requires Python 3.12+
|
|
216
|
+
|
|
217
|
+
Cryptofeed can be installed from PyPi. (It's recommended that you install in a virtual environment of your choosing).
|
|
218
|
+
|
|
219
|
+
pip install cryptofeed
|
|
220
|
+
|
|
221
|
+
Cryptofeed has optional dependencies, depending on the backends used. You can install them individually, or all at once. To install Cryptofeed along with all its optional dependencies in one bundle:
|
|
222
|
+
|
|
223
|
+
pip install cryptofeed[all]
|
|
224
|
+
|
|
225
|
+
If you wish to clone the repository and work on it (development uses [uv](https://docs.astral.sh/uv/)), run this from the root of the cloned repository:
|
|
226
|
+
|
|
227
|
+
uv sync
|
|
228
|
+
|
|
229
|
+
Alternatively, you can install from source in editable mode with pip:
|
|
230
|
+
|
|
231
|
+
pip install -e .
|
|
232
|
+
|
|
233
|
+
See more discussion of package installation in [INSTALL.md](https://github.com/bmoscon/cryptofeed/blob/master/INSTALL.md).
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
## Rest API
|
|
238
|
+
|
|
239
|
+
Cryptofeed supports some REST interfaces for retrieving real-time and historical data, as well as order placement and account management. These are integrated into the exchange classes directly. You can view the supported methods by calling the `info()` method on any exchange. The methods for interacting with the exchange RET endpoints exist in two flavors, the synchronous methods (suffixed with `_sync`) as well as the asynchronous which can be utilized with asyncio. For more information see the [documentation](docs/rest.md).
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
## Future Work
|
|
243
|
+
|
|
244
|
+
There are a lot of planned features, new exchanges, etc planned! If you'd like to discuss ongoing development, please join the [discord](https://discord.gg/zaBYaGAYfR) or open a thread in the [discussions](https://github.com/bmoscon/cryptofeed/discussions) in GitHub.
|
|
245
|
+
|
|
246
|
+
## Contributing
|
|
247
|
+
|
|
248
|
+
Issues and PRs are welcomed!
|
|
249
|
+
|
|
250
|
+
Cryptofeed wouldn't be possible without the help of many [contributors](AUTHORS.md)! I owe them and all other contributors my thanks!
|
|
251
|
+
|
|
252
|
+
## Donations / Support
|
|
253
|
+
|
|
254
|
+
Support and donations are appreciated but not required. You can donate via [GitHub Sponsors](https://github.com/sponsors/bmoscon), or via the addresses below:
|
|
255
|
+
|
|
256
|
+
* Bitcoin: bc1qm0kxz8hqacaglku5fjhfe9a5hjnuyfwk02lsyr
|
|
257
|
+
* Ethereum: 0x690709FEe13eEce9E7852089BB2D53Ae5D073154
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cryptocurrency Exchange Feed Handler
|
|
2
2
|
[](LICENSE)
|
|
3
|
-

|
|
4
4
|
[](https://pypi.python.org/pypi/cryptofeed)
|
|
5
5
|
[](https://www.codacy.com/app/bmoscon/cryptofeed?utm_source=github.com&utm_medium=referral&utm_content=bmoscon/cryptofeed&utm_campaign=Badge_Grade)
|
|
6
6
|
|
|
@@ -140,13 +140,14 @@ Supported Backends:
|
|
|
140
140
|
* Kafka
|
|
141
141
|
* RabbitMQ
|
|
142
142
|
* PostgreSQL
|
|
143
|
+
* [QuasarDB](https://quasar.ai/)
|
|
143
144
|
* GCP Pub/Sub
|
|
144
145
|
* [QuestDB](https://questdb.io/)
|
|
145
146
|
|
|
146
147
|
|
|
147
148
|
## Installation
|
|
148
149
|
|
|
149
|
-
**Note:** cryptofeed requires Python 3.
|
|
150
|
+
**Note:** cryptofeed requires Python 3.12+
|
|
150
151
|
|
|
151
152
|
Cryptofeed can be installed from PyPi. (It's recommended that you install in a virtual environment of your choosing).
|
|
152
153
|
|
|
@@ -156,13 +157,13 @@ Cryptofeed has optional dependencies, depending on the backends used. You can in
|
|
|
156
157
|
|
|
157
158
|
pip install cryptofeed[all]
|
|
158
159
|
|
|
159
|
-
If you wish to clone the repository and
|
|
160
|
+
If you wish to clone the repository and work on it (development uses [uv](https://docs.astral.sh/uv/)), run this from the root of the cloned repository:
|
|
160
161
|
|
|
161
|
-
|
|
162
|
+
uv sync
|
|
162
163
|
|
|
163
|
-
Alternatively, you can install in
|
|
164
|
+
Alternatively, you can install from source in editable mode with pip:
|
|
164
165
|
|
|
165
|
-
|
|
166
|
+
pip install -e .
|
|
166
167
|
|
|
167
168
|
See more discussion of package installation in [INSTALL.md](https://github.com/bmoscon/cryptofeed/blob/master/INSTALL.md).
|
|
168
169
|
|
|
@@ -175,7 +176,7 @@ Cryptofeed supports some REST interfaces for retrieving real-time and historical
|
|
|
175
176
|
|
|
176
177
|
## Future Work
|
|
177
178
|
|
|
178
|
-
There are a lot of planned features, new exchanges, etc planned! If you'd like to discuss ongoing development, please join the [
|
|
179
|
+
There are a lot of planned features, new exchanges, etc planned! If you'd like to discuss ongoing development, please join the [discord](https://discord.gg/zaBYaGAYfR) or open a thread in the [discussions](https://github.com/bmoscon/cryptofeed/discussions) in GitHub.
|
|
179
180
|
|
|
180
181
|
## Contributing
|
|
181
182
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'''
|
|
2
|
-
Copyright (C) 2017-
|
|
2
|
+
Copyright (C) 2017-2025 Bryant Moscon - bmoscon@gmail.com
|
|
3
3
|
|
|
4
4
|
Please see the LICENSE file for the terms and conditions
|
|
5
5
|
associated with this software.
|
|
@@ -13,9 +13,9 @@ import numpy as np
|
|
|
13
13
|
class AggregateCallback:
|
|
14
14
|
def __init__(self, handler):
|
|
15
15
|
self.handler = handler
|
|
16
|
-
if
|
|
17
|
-
setattr(self,
|
|
18
|
-
setattr(self,
|
|
16
|
+
if hasattr(self.handler, "__class__") and hasattr(self.handler, "start") and hasattr(self.handler, "stop"):
|
|
17
|
+
setattr(self, "start", self.handler.start)
|
|
18
|
+
setattr(self, "stop", self.handler.stop)
|
|
19
19
|
self.__name__ = self.handler.__class__
|
|
20
20
|
|
|
21
21
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'''
|
|
2
|
-
Copyright (C) 2017-
|
|
2
|
+
Copyright (C) 2017-2025 Bryant Moscon - bmoscon@gmail.com
|
|
3
3
|
|
|
4
4
|
Please see the LICENSE file for the terms and conditions
|
|
5
5
|
associated with this software.
|
|
@@ -56,11 +56,10 @@ class KafkaCallback(BackendQueue):
|
|
|
56
56
|
|
|
57
57
|
async def _connect(self):
|
|
58
58
|
if not self.producer:
|
|
59
|
-
loop = asyncio.get_event_loop()
|
|
60
59
|
try:
|
|
61
60
|
config_keys = ', '.join([k for k in self.producer_config.keys()])
|
|
62
61
|
LOG.info(f'{self.__class__.__name__}: Configuring AIOKafka with the following parameters: {config_keys}')
|
|
63
|
-
self.producer = AIOKafkaProducer(**self.producer_config
|
|
62
|
+
self.producer = AIOKafkaProducer(**self.producer_config)
|
|
64
63
|
# Quit if invalid config option passed to AIOKafka
|
|
65
64
|
except (TypeError, ValueError) as e:
|
|
66
65
|
LOG.error(f'{self.__class__.__name__}: Invalid AIOKafka configuration: {e.args}{chr(10)}See https://aiokafka.readthedocs.io/en/stable/api.html#aiokafka.AIOKafkaProducer for list of configuration options')
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
from datetime import datetime, timedelta
|
|
2
|
+
import quasardb.pool as pool
|
|
3
|
+
import quasardb.numpy as qdbnp
|
|
4
|
+
import numpy as np
|
|
5
|
+
from cryptofeed.backends.backend import BackendCallback
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class QuasarCallback(BackendCallback):
|
|
9
|
+
def __init__(self, uri="qdb://127.0.0.1:2836", username: str = "", private_key: str = "", public_key: str = "", none_to=None, shard_size: timedelta = timedelta(minutes=15)):
|
|
10
|
+
self.numeric_type = float
|
|
11
|
+
self.table = ""
|
|
12
|
+
self.running = True
|
|
13
|
+
self.none_to = none_to
|
|
14
|
+
self.shard_size = self._get_str_timedelta(shard_size)
|
|
15
|
+
|
|
16
|
+
pool.initialize(uri=uri, user_name=username, user_private_key=private_key, cluster_public_key=public_key)
|
|
17
|
+
|
|
18
|
+
def _get_str_timedelta(self, delta: timedelta):
|
|
19
|
+
# calculate the number of hours, minutes, and remaining seconds from timedelta, return it in correct format for query
|
|
20
|
+
hours, remainder = divmod(delta.total_seconds(), 3600)
|
|
21
|
+
minutes, seconds = divmod(remainder, 60)
|
|
22
|
+
return f"{int(hours)}hour {int(minutes)}min {int(seconds)}s"
|
|
23
|
+
|
|
24
|
+
def format(self, data: dict):
|
|
25
|
+
data['timestamp'] = np.datetime64(datetime.utcfromtimestamp(data['timestamp']), 'ns')
|
|
26
|
+
data['receipt_timestamp'] = np.datetime64(datetime.utcfromtimestamp(data['receipt_timestamp']), 'ns')
|
|
27
|
+
data['timestamp'], data['receipt_timestamp'] = data['receipt_timestamp'], data['timestamp']
|
|
28
|
+
index = data['timestamp']
|
|
29
|
+
data.pop('timestamp')
|
|
30
|
+
return index, data
|
|
31
|
+
|
|
32
|
+
def _set_table_name(self, data: dict):
|
|
33
|
+
# setting table name
|
|
34
|
+
# {channel}/{exchange}/{symbol_1-symbol_2}
|
|
35
|
+
# eg. ticker/coinbase/btc-usd
|
|
36
|
+
self.table = f"{self.table_prefix.lower()}/{data['exchange'].lower()}/{data['symbol'].lower()}"
|
|
37
|
+
|
|
38
|
+
def _create_table(self, conn):
|
|
39
|
+
if not conn.table(self.table).exists():
|
|
40
|
+
conn.query(self.query)
|
|
41
|
+
|
|
42
|
+
def _insert_format(self, date: np.datetime64, data: dict):
|
|
43
|
+
# converts values to np.array
|
|
44
|
+
for key, value in data.items():
|
|
45
|
+
data[key] = np.array([value])
|
|
46
|
+
return np.array([date]), data
|
|
47
|
+
|
|
48
|
+
async def write(self, data: dict):
|
|
49
|
+
self._set_table_name(data)
|
|
50
|
+
self._create_query()
|
|
51
|
+
index, data = self.format(data)
|
|
52
|
+
idx, np_array = self._insert_format(index, data)
|
|
53
|
+
# write to table, if table doesnt exist it will be created with specified shard_size value
|
|
54
|
+
with pool.instance().connect() as conn:
|
|
55
|
+
self._create_table(conn)
|
|
56
|
+
qdbnp.write_arrays(np_array, conn, conn.table(self.table), index=idx, fast=True, _async=True)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TickerQuasar(QuasarCallback):
|
|
60
|
+
table_prefix = "ticker"
|
|
61
|
+
|
|
62
|
+
def _create_query(self):
|
|
63
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), bid DOUBLE, ask DOUBLE, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class TradeQuasar(QuasarCallback):
|
|
67
|
+
table_prefix = "trades"
|
|
68
|
+
|
|
69
|
+
def _create_query(self):
|
|
70
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), side SYMBOL(side), amount DOUBLE, price DOUBLE, id STRING, type SYMBOL(type), receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class CandlesQuasar(QuasarCallback):
|
|
74
|
+
table_prefix = "candles"
|
|
75
|
+
|
|
76
|
+
def format(self, data: dict):
|
|
77
|
+
index, data = super().format(data)
|
|
78
|
+
data['start'] = datetime.utcfromtimestamp(data['start'])
|
|
79
|
+
data['stop'] = datetime.utcfromtimestamp(data['stop'])
|
|
80
|
+
data['closed'] = int(data['closed'])
|
|
81
|
+
return index, data
|
|
82
|
+
|
|
83
|
+
def _create_query(self):
|
|
84
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), start TIMESTAMP, stop TIMESTAMP, interval STRING, trades STRING, open DOUBLE, close DOUBLE, high DOUBLE, low DOUBLE, volume DOUBLE, closed INT64, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class FundingQuasar(QuasarCallback):
|
|
88
|
+
table_prefix = "funding"
|
|
89
|
+
|
|
90
|
+
def format(self, data: dict):
|
|
91
|
+
index, data = super().format(data)
|
|
92
|
+
data['next_funding_time'] = datetime.utcfromtimestamp(data['next_funding_time'])
|
|
93
|
+
return index, data
|
|
94
|
+
|
|
95
|
+
def _create_query(self):
|
|
96
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), mark_price DOUBLE, rate DOUBLE, next_funding_time TIMESTAMP, predicted_rate DOUBLE, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class BookQuasar(QuasarCallback):
|
|
100
|
+
table_prefix = "book"
|
|
101
|
+
|
|
102
|
+
def format(self, data: dict):
|
|
103
|
+
index, data = super().format(data)
|
|
104
|
+
# store only best bid and best ask
|
|
105
|
+
if not data['book']:
|
|
106
|
+
best_bid = max(data["delta"]["bid"], key=lambda x: x[0])
|
|
107
|
+
best_ask = min(data["delta"]["ask"], key=lambda x: x[0])
|
|
108
|
+
|
|
109
|
+
data['best_bid_price'] = best_bid[0]
|
|
110
|
+
data['best_bid_amount'] = best_bid[1]
|
|
111
|
+
data['best_ask_price'] = best_ask[0]
|
|
112
|
+
data['best_ask_amount'] = best_ask[1]
|
|
113
|
+
data.pop('delta')
|
|
114
|
+
else:
|
|
115
|
+
best_bid = max(data["book"]["bid"].keys())
|
|
116
|
+
best_ask = min(data["book"]["ask"].keys())
|
|
117
|
+
|
|
118
|
+
data['best_bid_price'] = best_bid
|
|
119
|
+
data['best_bid_amount'] = data["book"]["bid"][best_bid]
|
|
120
|
+
data['best_ask_price'] = best_ask
|
|
121
|
+
data['best_ask_amount'] = data["book"]["ask"][best_ask]
|
|
122
|
+
data.pop('book')
|
|
123
|
+
return index, data
|
|
124
|
+
|
|
125
|
+
def _create_query(self):
|
|
126
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), best_bid_price DOUBLE, best_bid_amount DOUBLE, best_ask_price DOUBLE, best_ask_amount DOUBLE, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class LiquidationsQuasar(QuasarCallback):
|
|
130
|
+
table_prefix = "liquidations"
|
|
131
|
+
|
|
132
|
+
def _create_query(self):
|
|
133
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), side SYMBOL(side), quantity DOUBLE, price DOUBLE, id STRING, status SYMBOL(type), receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class OpenInterestQuasar(QuasarCallback):
|
|
137
|
+
table_prefix = "open_interest"
|
|
138
|
+
|
|
139
|
+
def _create_query(self):
|
|
140
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), open_interest FLOAT, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class OrderInfoQuasar(QuasarCallback):
|
|
144
|
+
table_prefix = "order_info"
|
|
145
|
+
|
|
146
|
+
def _create_query(self):
|
|
147
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), id STRING, client_order_id STRING, side SYMBOL(side), status SYMBOL(type), type SYMBOL(type), price DOUBLE, amount DOUBLE, remaining DOUBLE, account STRING, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class TransactionsQuasar(QuasarCallback):
|
|
151
|
+
table_prefix = "transactions"
|
|
152
|
+
|
|
153
|
+
def _create_query(self):
|
|
154
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), currency SYMBOL(currency), type SYMBOL(type), status SYMBOL(type), amount DOUBLE, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class BalancesQuasar(QuasarCallback):
|
|
158
|
+
table_prefix = "balances"
|
|
159
|
+
|
|
160
|
+
def _create_query(self):
|
|
161
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), currency SYMBOL(currency), balance DOUBLE, reserved DOUBLE, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class FillsQuasar(QuasarCallback):
|
|
165
|
+
table_prefix = "fills"
|
|
166
|
+
|
|
167
|
+
def _create_query(self):
|
|
168
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), price DOUBLE, amount DOUBLE, side SYMBOL(side), fee DOUBLE, id STRING, order_id STRING, liquidity DOUBLE, type SYMBOL(type), account STRING, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class IndexQuasar(QuasarCallback):
|
|
172
|
+
table_prefix = "index"
|
|
173
|
+
|
|
174
|
+
def _create_query(self):
|
|
175
|
+
self.query = f'CREATE TABLE "{self.table}" (exchange SYMBOL(exchange), symbol SYMBOL(symbol), price DOUBLE, receipt_timestamp TIMESTAMP) SHARD_SIZE = {self.shard_size}'
|