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.
Files changed (113) hide show
  1. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/AUTHORS.md +5 -0
  2. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/CHANGES.md +23 -0
  3. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/INSTALL.md +5 -0
  4. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/LICENSE +1 -1
  5. cryptofeed-2.5.0/PKG-INFO +257 -0
  6. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/README.md +8 -7
  7. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/__init__.py +1 -1
  8. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/_util.py +1 -1
  9. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/aggregate.py +4 -4
  10. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/arctic.py +1 -1
  11. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/backend.py +1 -1
  12. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/gcppubsub.py +1 -1
  13. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/http.py +1 -1
  14. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/influxdb.py +1 -1
  15. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/kafka.py +2 -3
  16. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/mongo.py +1 -1
  17. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/postgres.py +1 -1
  18. cryptofeed-2.5.0/cryptofeed/backends/quasardb.py +175 -0
  19. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/quest.py +7 -4
  20. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/rabbitmq.py +3 -4
  21. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/redis.py +2 -2
  22. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/socket.py +3 -3
  23. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/zmq.py +1 -1
  24. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/callback.py +3 -3
  25. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/config.py +1 -1
  26. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/connection.py +13 -8
  27. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/connection_handler.py +1 -21
  28. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/defines.py +1 -1
  29. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exceptions.py +1 -1
  30. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchange.py +4 -4
  31. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/__init__.py +1 -1
  32. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/ascendex.py +1 -1
  33. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bequant.py +1 -1
  34. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance.py +9 -5
  35. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_delivery.py +1 -1
  36. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_futures.py +1 -1
  37. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_tr.py +1 -1
  38. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/binance_us.py +1 -1
  39. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitdotcom.py +3 -3
  40. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitfinex.py +2 -2
  41. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitflyer.py +1 -1
  42. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitget.py +1 -1
  43. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bithumb.py +1 -1
  44. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitmex.py +2 -2
  45. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/bitstamp.py +1 -1
  46. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/blockchain.py +1 -1
  47. cryptofeed-2.5.0/cryptofeed/exchanges/bybit.py +618 -0
  48. cryptofeed-2.5.0/cryptofeed/exchanges/coinbase.py +192 -0
  49. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/cryptodotcom.py +1 -1
  50. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/delta.py +1 -1
  51. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/dydx.py +1 -1
  52. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/fmfw.py +1 -1
  53. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/gateio.py +1 -1
  54. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/gateio_futures.py +1 -1
  55. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/gemini.py +2 -2
  56. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/hitbtc.py +1 -1
  57. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/huobi.py +1 -1
  58. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/huobi_dm.py +1 -1
  59. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/huobi_swap.py +4 -4
  60. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/independent_reserve.py +6 -6
  61. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/kraken.py +1 -1
  62. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/kraken_futures.py +1 -1
  63. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/kucoin.py +2 -2
  64. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/binance_rest.py +2 -2
  65. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/bitfinex_rest.py +1 -1
  66. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/bitmex_rest.py +1 -1
  67. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/bitstamp_rest.py +2 -2
  68. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/coinbase_rest.py +1 -1
  69. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/deribit_rest.py +1 -1
  70. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/dydx_rest.py +1 -1
  71. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/gemini_rest.py +1 -1
  72. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/kraken_rest.py +1 -1
  73. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/okx_rest.py +1 -1
  74. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/upbit_rest.py +2 -2
  75. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/okcoin.py +1 -1
  76. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/okx.py +2 -2
  77. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/phemex.py +1 -1
  78. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/poloniex.py +1 -1
  79. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/probit.py +1 -1
  80. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/upbit.py +1 -1
  81. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/feed.py +1 -1
  82. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/feedhandler.py +21 -6
  83. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/log.py +1 -1
  84. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/nbbo.py +1 -1
  85. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/raw_data_collection.py +2 -2
  86. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/symbols.py +1 -1
  87. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/types.c +26272 -19961
  88. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/types.pyx +2 -1
  89. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/book.py +1 -1
  90. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/perf.py +1 -1
  91. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/time.py +1 -1
  92. cryptofeed-2.5.0/cryptofeed.egg-info/PKG-INFO +257 -0
  93. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/SOURCES.txt +1 -0
  94. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/requires.txt +6 -2
  95. cryptofeed-2.5.0/pyproject.toml +121 -0
  96. cryptofeed-2.5.0/setup.py +27 -0
  97. cryptofeed-2.4.0/PKG-INFO +0 -1090
  98. cryptofeed-2.4.0/cryptofeed/exchanges/bybit.py +0 -520
  99. cryptofeed-2.4.0/cryptofeed/exchanges/coinbase.py +0 -391
  100. cryptofeed-2.4.0/cryptofeed.egg-info/PKG-INFO +0 -1090
  101. cryptofeed-2.4.0/pyproject.toml +0 -30
  102. cryptofeed-2.4.0/setup.py +0 -110
  103. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/MANIFEST.in +0 -0
  104. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/backends/__init__.py +0 -0
  105. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/ascendex_futures.py +0 -0
  106. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/deribit.py +0 -0
  107. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/exx.py +0 -0
  108. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/exchanges/mixins/__init__.py +0 -0
  109. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/__init__.py +0 -0
  110. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed/util/split.py +0 -0
  111. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/dependency_links.txt +0 -0
  112. {cryptofeed-2.4.0 → cryptofeed-2.5.0}/cryptofeed.egg-info/top_level.txt +0 -0
  113. {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-2024 Bryant Moscon - bmoscon@gmail.com
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](https://img.shields.io/badge/license-XFree86-blue.svg)](LICENSE)
68
+ ![Python](https://img.shields.io/badge/Python-3.12+-green.svg)
69
+ [![PyPi](https://img.shields.io/badge/PyPi-cryptofeed-brightgreen.svg)](https://pypi.python.org/pypi/cryptofeed)
70
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/efa4e0d6e10b41d0b51454d08f7b33b1)](https://www.codacy.com/app/bmoscon/cryptofeed?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=bmoscon/cryptofeed&amp;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](https://img.shields.io/badge/license-XFree86-blue.svg)](LICENSE)
3
- ![Python](https://img.shields.io/badge/Python-3.8+-green.svg)
3
+ ![Python](https://img.shields.io/badge/Python-3.12+-green.svg)
4
4
  [![PyPi](https://img.shields.io/badge/PyPi-cryptofeed-brightgreen.svg)](https://pypi.python.org/pypi/cryptofeed)
5
5
  [![Codacy Badge](https://api.codacy.com/project/badge/Grade/efa4e0d6e10b41d0b51454d08f7b33b1)](https://www.codacy.com/app/bmoscon/cryptofeed?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=bmoscon/cryptofeed&amp;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.8+
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 install from source, run this command from the root of the cloned repository.
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
- python setup.py install
162
+ uv sync
162
163
 
163
- Alternatively, you can install in 'edit' mode (also called development mode):
164
+ Alternatively, you can install from source in editable mode with pip:
164
165
 
165
- python setup.py develop
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 [slack](https://join.slack.com/t/cryptofeed-dev/shared_invite/enQtNjY4ODIwODA1MzQ3LTIzMzY3Y2YxMGVhNmQ4YzFhYTc3ODU1MjQ5MDdmY2QyZjdhMGU5ZDFhZDlmMmYzOTUzOTdkYTZiOGUwNGIzYTk) or open a thread in the [discussions](https://github.com/bmoscon/cryptofeed/discussions) in GitHub.
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-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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 not callable(self.handler):
17
- setattr(self, 'start', self.handler.start)
18
- setattr(self, 'stop', self.handler.stop)
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-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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, loop=loop)
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')
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -1,5 +1,5 @@
1
1
  '''
2
- Copyright (C) 2017-2024 Bryant Moscon - bmoscon@gmail.com
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.
@@ -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}'