Qubx 0.6.67__tar.gz → 0.6.71__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.

Potentially problematic release.


This version of Qubx might be problematic. Click here for more details.

Files changed (214) hide show
  1. {qubx-0.6.67 → qubx-0.6.71}/PKG-INFO +50 -4
  2. {qubx-0.6.67 → qubx-0.6.71}/README.md +48 -3
  3. {qubx-0.6.67 → qubx-0.6.71}/pyproject.toml +3 -2
  4. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/__init__.py +1 -1
  5. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/data.py +19 -2
  6. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/commands.py +129 -0
  7. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/release.py +333 -25
  8. qubx-0.6.71/src/qubx/connectors/ccxt/adapters/__init__.py +7 -0
  9. qubx-0.6.71/src/qubx/connectors/ccxt/adapters/polling_adapter.py +439 -0
  10. qubx-0.6.71/src/qubx/connectors/ccxt/connection_manager.py +310 -0
  11. qubx-0.6.71/src/qubx/connectors/ccxt/data.py +241 -0
  12. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/__init__.py +7 -0
  13. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +216 -17
  14. qubx-0.6.71/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +1 -0
  15. qubx-0.6.71/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +161 -0
  16. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/__init__.py +29 -0
  17. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/base.py +93 -0
  18. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/factory.py +124 -0
  19. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/funding_rate.py +219 -0
  20. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/liquidation.py +91 -0
  21. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/ohlc.py +346 -0
  22. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/open_interest.py +206 -0
  23. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/orderbook.py +193 -0
  24. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/quote.py +98 -0
  25. qubx-0.6.71/src/qubx/connectors/ccxt/handlers/trade.py +94 -0
  26. qubx-0.6.71/src/qubx/connectors/ccxt/reader.py +560 -0
  27. qubx-0.6.71/src/qubx/connectors/ccxt/subscription_config.py +82 -0
  28. qubx-0.6.71/src/qubx/connectors/ccxt/subscription_manager.py +331 -0
  29. qubx-0.6.71/src/qubx/connectors/ccxt/subscription_orchestrator.py +328 -0
  30. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/utils.py +88 -1
  31. qubx-0.6.71/src/qubx/connectors/ccxt/warmup_service.py +116 -0
  32. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/tardis/data.py +6 -6
  33. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/basics.py +20 -3
  34. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/helpers.py +48 -29
  35. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/initializer.py +5 -9
  36. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/lookups.py +1 -1
  37. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/metrics.py +252 -22
  38. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/series.pxd +22 -5
  39. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/series.pyi +33 -3
  40. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/series.pyx +116 -59
  41. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/composite.py +252 -9
  42. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/readers.py +70 -35
  43. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/gathering/simplest.py +1 -1
  44. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/pandaz/ta.py +202 -22
  45. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/crypto-fees.ini +8 -1
  46. qubx-0.6.71/src/qubx/resources/instruments/hyperliquid-spot.json +4204 -0
  47. qubx-0.6.71/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +4424 -0
  48. qubx-0.6.71/src/qubx/templates/__init__.py +5 -0
  49. qubx-0.6.71/src/qubx/templates/base.py +166 -0
  50. qubx-0.6.71/src/qubx/templates/project/accounts.toml.j2 +22 -0
  51. qubx-0.6.71/src/qubx/templates/project/config.yml.j2 +33 -0
  52. qubx-0.6.71/src/qubx/templates/project/jlive.sh.j2 +43 -0
  53. qubx-0.6.71/src/qubx/templates/project/jpaper.sh.j2 +6 -0
  54. qubx-0.6.71/src/qubx/templates/project/pyproject.toml.j2 +18 -0
  55. qubx-0.6.71/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +5 -0
  56. qubx-0.6.71/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +170 -0
  57. qubx-0.6.71/src/qubx/templates/project/template.yml +20 -0
  58. qubx-0.6.71/src/qubx/templates/simple/__init__.py.j2 +5 -0
  59. qubx-0.6.71/src/qubx/templates/simple/accounts.toml.j2 +22 -0
  60. qubx-0.6.71/src/qubx/templates/simple/config.yml.j2 +30 -0
  61. qubx-0.6.71/src/qubx/templates/simple/jlive.sh.j2 +43 -0
  62. qubx-0.6.71/src/qubx/templates/simple/jpaper.sh.j2 +6 -0
  63. qubx-0.6.71/src/qubx/templates/simple/strategy.py.j2 +95 -0
  64. qubx-0.6.71/src/qubx/templates/simple/template.yml +20 -0
  65. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/sizers.py +9 -2
  66. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/charting/lookinglass.py +93 -15
  67. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/marketdata/ccxt.py +6 -1
  68. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/misc.py +9 -2
  69. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/_jupyter_runner.pyt +5 -1
  70. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/configs.py +42 -1
  71. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/factory.py +35 -0
  72. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/runner.py +23 -7
  73. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/time.py +13 -13
  74. qubx-0.6.67/src/qubx/connectors/ccxt/data.py +0 -831
  75. qubx-0.6.67/src/qubx/connectors/ccxt/reader.py +0 -237
  76. qubx-0.6.67/src/qubx/resources/instruments/symbols-hyperliquid-spot.json +0 -1
  77. qubx-0.6.67/src/qubx/resources/instruments/symbols-hyperliquid.f-perpetual.json +0 -1
  78. {qubx-0.6.67 → qubx-0.6.71}/LICENSE +0 -0
  79. {qubx-0.6.67 → qubx-0.6.71}/build.py +0 -0
  80. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/_nb_magic.py +0 -0
  81. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/__init__.py +0 -0
  82. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/account.py +0 -0
  83. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/broker.py +0 -0
  84. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/management.py +0 -0
  85. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/ome.py +0 -0
  86. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/optimization.py +0 -0
  87. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/runner.py +0 -0
  88. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/sentinels.py +0 -0
  89. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/simulated_data.py +0 -0
  90. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/simulated_exchange.py +0 -0
  91. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/simulator.py +0 -0
  92. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/utils.py +0 -0
  93. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/__init__.py +0 -0
  94. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/deploy.py +0 -0
  95. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/misc.py +0 -0
  96. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/tui.py +0 -0
  97. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/__init__.py +0 -0
  98. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/account.py +0 -0
  99. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/broker.py +0 -0
  100. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exceptions.py +0 -0
  101. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
  102. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
  103. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
  104. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
  105. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/factory.py +0 -0
  106. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/tardis/utils.py +0 -0
  107. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/__init__.py +0 -0
  108. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/account.py +0 -0
  109. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/context.py +0 -0
  110. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/deque.py +0 -0
  111. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/errors.py +0 -0
  112. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/exceptions.py +0 -0
  113. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/interfaces.py +0 -0
  114. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/loggers.py +0 -0
  115. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/__init__.py +0 -0
  116. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/market.py +0 -0
  117. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/processing.py +0 -0
  118. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/subscription.py +0 -0
  119. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/trading.py +0 -0
  120. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/universe.py +0 -0
  121. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/stale_data_detector.py +0 -0
  122. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/utils.pyi +0 -0
  123. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/utils.pyx +0 -0
  124. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/__init__.py +0 -0
  125. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/helpers.py +0 -0
  126. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/hft.py +0 -0
  127. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/registry.py +0 -0
  128. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/tardis.py +0 -0
  129. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/__init__.py +0 -0
  130. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/base.py +0 -0
  131. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/composite.py +0 -0
  132. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/csv.py +0 -0
  133. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/indicator.py +0 -0
  134. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/inmemory.py +0 -0
  135. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/prometheus.py +0 -0
  136. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/questdb.py +0 -0
  137. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/__init__.py +0 -0
  138. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/composite.py +0 -0
  139. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/__init__.py +0 -0
  140. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/base.py +0 -0
  141. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/incremental.py +0 -0
  142. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/slack.py +0 -0
  143. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/redis_streams.py +0 -0
  144. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/slack.py +0 -0
  145. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/__init__.py +0 -0
  146. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/core.py +0 -0
  147. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/orderbook.py +0 -0
  148. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/price.py +0 -0
  149. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/trades.py +0 -0
  150. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/utils.py +0 -0
  151. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/health/__init__.py +0 -0
  152. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/health/base.py +0 -0
  153. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/__init__.py +0 -0
  154. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/csv.py +0 -0
  155. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/factory.py +0 -0
  156. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/inmemory.py +0 -0
  157. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/mongo.py +0 -0
  158. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/math/__init__.py +0 -0
  159. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/math/stats.py +0 -0
  160. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/__init__.py +0 -0
  161. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/composite.py +0 -0
  162. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/slack.py +0 -0
  163. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/throttler.py +0 -0
  164. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/pandaz/__init__.py +0 -0
  165. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/pandaz/utils.py +0 -0
  166. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/_build.py +0 -0
  167. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
  168. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
  169. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
  170. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
  171. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
  172. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
  173. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
  174. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
  175. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
  176. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restarts/__init__.py +0 -0
  177. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restarts/state_resolvers.py +0 -0
  178. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restarts/time_finders.py +0 -0
  179. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/__init__.py +0 -0
  180. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/balance.py +0 -0
  181. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/factory.py +0 -0
  182. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/interfaces.py +0 -0
  183. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/position.py +0 -0
  184. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/signal.py +0 -0
  185. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/state.py +0 -0
  186. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/utils.py +0 -0
  187. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/__init__.py +0 -0
  188. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/indicators.pxd +0 -0
  189. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/indicators.pyi +0 -0
  190. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/indicators.pyx +0 -0
  191. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/__init__.py +0 -0
  192. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/advanced.py +0 -0
  193. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/composite.py +0 -0
  194. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/rebalancers.py +0 -0
  195. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/riskctrl.py +0 -0
  196. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/__init__.py +0 -0
  197. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/_pyxreloader.py +0 -0
  198. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  199. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/collections.py +0 -0
  200. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/marketdata/binance.py +0 -0
  201. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/marketdata/dukas.py +0 -0
  202. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/ntp.py +0 -0
  203. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/numbers_utils.py +0 -0
  204. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/orderbook.py +0 -0
  205. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/__init__.py +0 -0
  206. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/dashboard.py +0 -0
  207. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/data.py +0 -0
  208. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/interfaces.py +0 -0
  209. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
  210. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
  211. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/questdb.py +0 -0
  212. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/__init__.py +0 -0
  213. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/accounts.py +0 -0
  214. {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Qubx
3
- Version: 0.6.67
3
+ Version: 0.6.71
4
4
  Summary: Qubx - Quantitative Trading Framework
5
5
  Author: Dmitry Marienko
6
6
  Author-email: dmitry.marienko@xlydian.com
@@ -19,6 +19,7 @@ Requires-Dist: dash-bootstrap-components (>=1.6.0,<2.0.0)
19
19
  Requires-Dist: gitpython (>=3.1.44,<4.0.0)
20
20
  Requires-Dist: importlib-metadata
21
21
  Requires-Dist: ipywidgets (>=8.1.5,<9.0.0)
22
+ Requires-Dist: jinja2 (>=3.1.0,<4.0.0)
22
23
  Requires-Dist: jupyter (>=1.1.1,<2.0.0)
23
24
  Requires-Dist: jupyter-console (>=6.6.3,<7.0.0)
24
25
  Requires-Dist: loguru (>=0.7.2,<0.8.0)
@@ -69,6 +70,49 @@ Description-Content-Type: text/markdown
69
70
 
70
71
  Qubx is a next-generation quantitative trading framework designed for efficient backtesting and live trading. Built with Python, it offers a robust environment for developing, testing, and deploying trading strategies.
71
72
 
73
+ ## Quick Start
74
+
75
+ ### 1. Install Dependencies
76
+ ```bash
77
+ poetry install
78
+ ```
79
+
80
+ ### 2. Create a Strategy
81
+ ```bash
82
+ # Create a simple strategy template (default)
83
+ poetry run qubx init
84
+
85
+ # Or specify a name and symbols
86
+ poetry run qubx init --name my_strategy --symbols BTCUSDT,ETHUSDT
87
+ ```
88
+
89
+ ### 3. Run Your Strategy
90
+ ```bash
91
+ cd my_strategy
92
+
93
+ # Run in paper trading mode
94
+ poetry run qubx run config.yml --paper
95
+
96
+ # Or run in Jupyter mode for interactive development
97
+ ./jpaper.sh
98
+ ```
99
+
100
+ ### Available Templates
101
+ ```bash
102
+ # List available strategy templates
103
+ poetry run qubx init --list-templates
104
+
105
+ # Create strategy with full project structure and MACD example
106
+ poetry run qubx init --template project --name my_project
107
+ ```
108
+
109
+ ### Strategy Development Workflow
110
+ 1. **Initialize**: `poetry run qubx init` - Create strategy from template
111
+ 2. **Develop**: Edit `strategy.py` to implement your trading logic
112
+ 3. **Test**: `poetry run qubx run config.yml --paper` - Run in paper mode
113
+ 4. **Debug**: `./jpaper.sh` - Use Jupyter for interactive development
114
+ 5. **Deploy**: Configure for live trading when ready
115
+
72
116
  ## Features
73
117
 
74
118
  - 🚀 High-performance backtesting engine
@@ -119,11 +163,13 @@ qubx --help # Show all available commands
119
163
 
120
164
  Available commands:
121
165
 
122
- - `qubx deploy` - Deploy a strategy from a zip file
123
- - `qubx ls` - List all strategies in a directory
124
- - `qubx release` - Package a strategy into a zip file
166
+ - `qubx init` - Create a new strategy from template
125
167
  - `qubx run` - Start a strategy with given configuration
126
168
  - `qubx simulate` - Run strategy simulation
169
+ - `qubx ls` - List all strategies in a directory
170
+ - `qubx release` - Package a strategy into a zip file
171
+ - `qubx deploy` - Deploy a strategy from a zip file
172
+ - `qubx browse` - Browse backtest results using interactive TUI
127
173
 
128
174
  ## Development
129
175
 
@@ -11,6 +11,49 @@
11
11
 
12
12
  Qubx is a next-generation quantitative trading framework designed for efficient backtesting and live trading. Built with Python, it offers a robust environment for developing, testing, and deploying trading strategies.
13
13
 
14
+ ## Quick Start
15
+
16
+ ### 1. Install Dependencies
17
+ ```bash
18
+ poetry install
19
+ ```
20
+
21
+ ### 2. Create a Strategy
22
+ ```bash
23
+ # Create a simple strategy template (default)
24
+ poetry run qubx init
25
+
26
+ # Or specify a name and symbols
27
+ poetry run qubx init --name my_strategy --symbols BTCUSDT,ETHUSDT
28
+ ```
29
+
30
+ ### 3. Run Your Strategy
31
+ ```bash
32
+ cd my_strategy
33
+
34
+ # Run in paper trading mode
35
+ poetry run qubx run config.yml --paper
36
+
37
+ # Or run in Jupyter mode for interactive development
38
+ ./jpaper.sh
39
+ ```
40
+
41
+ ### Available Templates
42
+ ```bash
43
+ # List available strategy templates
44
+ poetry run qubx init --list-templates
45
+
46
+ # Create strategy with full project structure and MACD example
47
+ poetry run qubx init --template project --name my_project
48
+ ```
49
+
50
+ ### Strategy Development Workflow
51
+ 1. **Initialize**: `poetry run qubx init` - Create strategy from template
52
+ 2. **Develop**: Edit `strategy.py` to implement your trading logic
53
+ 3. **Test**: `poetry run qubx run config.yml --paper` - Run in paper mode
54
+ 4. **Debug**: `./jpaper.sh` - Use Jupyter for interactive development
55
+ 5. **Deploy**: Configure for live trading when ready
56
+
14
57
  ## Features
15
58
 
16
59
  - 🚀 High-performance backtesting engine
@@ -61,11 +104,13 @@ qubx --help # Show all available commands
61
104
 
62
105
  Available commands:
63
106
 
64
- - `qubx deploy` - Deploy a strategy from a zip file
65
- - `qubx ls` - List all strategies in a directory
66
- - `qubx release` - Package a strategy into a zip file
107
+ - `qubx init` - Create a new strategy from template
67
108
  - `qubx run` - Start a strategy with given configuration
68
109
  - `qubx simulate` - Run strategy simulation
110
+ - `qubx ls` - List all strategies in a directory
111
+ - `qubx release` - Package a strategy into a zip file
112
+ - `qubx deploy` - Deploy a strategy from a zip file
113
+ - `qubx browse` - Browse backtest results using interactive TUI
69
114
 
70
115
  ## Development
71
116
 
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "Qubx"
7
- version = "0.6.67"
7
+ version = "0.6.71"
8
8
  description = "Qubx - Quantitative Trading Framework"
9
9
  authors = [ "Dmitry Marienko <dmitry.marienko@xlydian.com>", "Yuriy Arabskyy <yuriy.arabskyy@xlydian.com>",]
10
10
  readme = "README.md"
@@ -76,6 +76,7 @@ websockets = "15.0.1"
76
76
  qubx-bitfinex-api = "^3.0.7"
77
77
  textual = "^0.88.0"
78
78
  rich = "^13.9.4"
79
+ jinja2 = "^3.1.0"
79
80
 
80
81
  [tool.ruff.lint]
81
82
  extend-select = [ "I",]
@@ -87,7 +88,7 @@ asyncio_default_fixture_loop_scope = "function"
87
88
  pythonpath = [ "src",]
88
89
  markers = [ "integration: mark test as requiring external services like Redis", "e2e: mark test as requiring external exchange connections and API credentials",]
89
90
  addopts = "--disable-warnings"
90
- filterwarnings = [ "ignore:.*Jupyter is migrating.*:DeprecationWarning",]
91
+ filterwarnings = [ "ignore:.*Jupyter is migrating.*:DeprecationWarning", "ignore:coroutine.*AsyncMockMixin._execute_mock_call.*was never awaited:RuntimeWarning",]
91
92
 
92
93
  [tool.ruff.lint.extend-per-file-ignores]
93
94
  "*.ipynb" = [ "F405", "F401", "E701", "E402", "F403", "E401", "E702", "I001",]
@@ -186,7 +186,7 @@ if runtime_env() in ["notebook", "shell"]:
186
186
  return
187
187
 
188
188
  ipy = get_ipython()
189
- for a in [x for x in re.split(r"[\ ,;]", line.strip()) if x]:
189
+ for a in [x for x in re.split(r"[\s,;]", line.strip()) if x]:
190
190
  ipy.push({a: self._get_manager().Value(None, None)})
191
191
 
192
192
  # code to run
@@ -1,4 +1,5 @@
1
1
  from collections import defaultdict
2
+ from typing import Any, TypeVar
2
3
 
3
4
  import pandas as pd
4
5
 
@@ -19,6 +20,17 @@ from qubx.utils.time import infer_series_frequency
19
20
  from .account import SimulatedAccountProcessor
20
21
  from .utils import SimulatedTimeProvider
21
22
 
23
+ T = TypeVar("T")
24
+
25
+
26
+ def _get_first_existing(data: dict, keys: list, default: T = None) -> T:
27
+ data_get = data.get # Cache method lookup
28
+ sentinel = object()
29
+ for key in keys:
30
+ if (value := data_get(key, sentinel)) is not sentinel:
31
+ return value
32
+ return default
33
+
22
34
 
23
35
  class SimulatedDataProvider(IDataProvider):
24
36
  time_provider: SimulatedTimeProvider
@@ -164,8 +176,13 @@ class SimulatedDataProvider(IDataProvider):
164
176
  r.data["high"],
165
177
  r.data["low"],
166
178
  r.data["close"],
167
- r.data.get("volume", 0),
168
- r.data.get("bought_volume", 0),
179
+ volume=r.data.get("volume", 0),
180
+ bought_volume=_get_first_existing(r.data, ["taker_buy_volume", "bought_volume"], 0),
181
+ volume_quote=_get_first_existing(r.data, ["quote_volume", "volume_quote"], 0),
182
+ bought_volume_quote=_get_first_existing(
183
+ r.data, ["taker_buy_quote_volume", "bought_volume_quote"], 0
184
+ ),
185
+ trade_count=_get_first_existing(r.data, ["count", "trade_count"], 0),
169
186
  )
170
187
  )
171
188
 
@@ -32,6 +32,10 @@ def main(debug: bool, debug_port: int, log_level: str):
32
32
  """
33
33
  Qubx CLI.
34
34
  """
35
+ # Suppress syntax warnings from AST parsing during import resolution
36
+ import warnings
37
+ warnings.filterwarnings("ignore", category=SyntaxWarning)
38
+
35
39
  os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1"
36
40
  log_level = log_level.upper() if not debug else "DEBUG"
37
41
 
@@ -275,5 +279,130 @@ def browse(results_path: str):
275
279
  run_backtest_browser(results_path)
276
280
 
277
281
 
282
+ @main.command()
283
+ @click.option(
284
+ "--template",
285
+ "-t",
286
+ type=str,
287
+ default="simple",
288
+ help="Built-in template to use (default: simple)",
289
+ show_default=True,
290
+ )
291
+ @click.option(
292
+ "--template-path",
293
+ type=click.Path(exists=True, resolve_path=True),
294
+ help="Path to custom template directory",
295
+ )
296
+ @click.option(
297
+ "--name",
298
+ "-n",
299
+ type=str,
300
+ default="my_strategy",
301
+ help="Name of the strategy to create",
302
+ show_default=True,
303
+ )
304
+ @click.option(
305
+ "--exchange",
306
+ "-e",
307
+ type=str,
308
+ default="BINANCE.UM",
309
+ help="Exchange to configure for the strategy",
310
+ show_default=True,
311
+ )
312
+ @click.option(
313
+ "--symbols",
314
+ "-s",
315
+ type=str,
316
+ default="BTCUSDT",
317
+ help="Comma-separated list of symbols to trade",
318
+ show_default=True,
319
+ )
320
+ @click.option(
321
+ "--timeframe",
322
+ type=str,
323
+ default="1h",
324
+ help="Timeframe for market data",
325
+ show_default=True,
326
+ )
327
+ @click.option(
328
+ "--output-dir",
329
+ "-o",
330
+ type=click.Path(resolve_path=True),
331
+ default=".",
332
+ help="Directory to create the strategy in",
333
+ show_default=True,
334
+ )
335
+ @click.option(
336
+ "--list-templates",
337
+ is_flag=True,
338
+ help="List all available built-in templates",
339
+ )
340
+ def init(
341
+ template: str,
342
+ template_path: str | None,
343
+ name: str,
344
+ exchange: str,
345
+ symbols: str,
346
+ timeframe: str,
347
+ output_dir: str,
348
+ list_templates: bool,
349
+ ):
350
+ """
351
+ Create a new strategy from a template.
352
+
353
+ This command generates a complete strategy project structure with:
354
+ - Strategy class implementing IStrategy interface
355
+ - Configuration file for qubx run command
356
+ - Package structure for proper imports
357
+
358
+ The generated strategy can be run immediately with:
359
+ poetry run qubx run --config config.yml --paper
360
+ """
361
+ from qubx.templates import TemplateManager, TemplateError
362
+
363
+ try:
364
+ manager = TemplateManager()
365
+
366
+ if list_templates:
367
+ templates = manager.list_templates()
368
+ if not templates:
369
+ click.echo("No templates available.")
370
+ return
371
+
372
+ click.echo("Available templates:")
373
+ for template_name, metadata in templates.items():
374
+ description = metadata.get("description", "No description")
375
+ click.echo(f" {template_name:<15} - {description}")
376
+ return
377
+
378
+ # Generate strategy
379
+ strategy_path = manager.generate_strategy(
380
+ template_name=template if not template_path else None,
381
+ template_path=template_path,
382
+ output_dir=output_dir,
383
+ name=name,
384
+ exchange=exchange,
385
+ symbols=symbols,
386
+ timeframe=timeframe,
387
+ )
388
+
389
+ click.echo(f"✅ Strategy '{name}' created successfully!")
390
+ click.echo(f"📁 Location: {strategy_path}")
391
+ click.echo()
392
+ click.echo("To run your strategy:")
393
+ click.echo(f" cd {strategy_path}")
394
+ click.echo(" poetry run qubx run config.yml --paper")
395
+ click.echo()
396
+ click.echo("To run in Jupyter mode:")
397
+ click.echo(" ./jpaper.sh")
398
+
399
+ except TemplateError as e:
400
+ click.echo(f"❌ Template error: {e}", err=True)
401
+ raise click.Abort()
402
+ except Exception as e:
403
+ click.echo(f"❌ Unexpected error: {e}", err=True)
404
+ raise click.Abort()
405
+
406
+
278
407
  if __name__ == "__main__":
279
408
  main()