Qubx 1.0.1.dev2__tar.gz → 1.0.4.dev1__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 (268) hide show
  1. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/.gitignore +4 -1
  2. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/PKG-INFO +32 -25
  3. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/pyproject.toml +117 -90
  4. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/_version.py +2 -2
  5. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/commands.py +13 -2
  6. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/deploy.py +55 -3
  7. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/release.py +457 -653
  8. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/metrics.py +5 -0
  9. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/ta/indicators.pxd +70 -1
  10. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/ta/indicators.pyi +36 -0
  11. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/ta/indicators.pyx +495 -19
  12. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/configs.py +2 -0
  13. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/runner.py +11 -0
  14. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/time.py +1 -0
  15. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/LICENSE +0 -0
  16. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/README.md +0 -0
  17. /qubx-1.0.1.dev2/hatch_build.py → /qubx-1.0.4.dev1/scripts/build.py +0 -0
  18. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/__init__.py +0 -0
  19. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/_nb_magic.py +0 -0
  20. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/__init__.py +0 -0
  21. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/account.py +0 -0
  22. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/broker.py +0 -0
  23. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/data.py +0 -0
  24. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/iteratedstream.py +0 -0
  25. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/management.py +0 -0
  26. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/ome.py +0 -0
  27. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/optimization.py +0 -0
  28. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/runner.py +0 -0
  29. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/sentinels.py +0 -0
  30. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/simulated_data.py +0 -0
  31. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/simulated_exchange.py +0 -0
  32. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/simulator.py +0 -0
  33. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/transfers.py +0 -0
  34. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/backtester/utils.py +0 -0
  35. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/__init__.py +0 -0
  36. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/misc.py +0 -0
  37. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/theme.py +0 -0
  38. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/cli/tui.py +0 -0
  39. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/config.py +0 -0
  40. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/__init__.py +0 -0
  41. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/__init__.py +0 -0
  42. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/account.py +0 -0
  43. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
  44. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
  45. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/broker.py +0 -0
  46. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/connection_manager.py +0 -0
  47. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/data.py +0 -0
  48. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exceptions.py +0 -0
  49. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
  50. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
  51. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/base.py +0 -0
  52. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
  53. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
  54. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
  55. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
  56. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
  57. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -0
  58. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
  59. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/account.py +0 -0
  60. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/broker.py +0 -0
  61. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +0 -0
  62. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
  63. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/okx/__init__.py +0 -0
  64. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/okx/account.py +0 -0
  65. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/okx/broker.py +0 -0
  66. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/exchanges/okx/okx.py +0 -0
  67. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/factory.py +0 -0
  68. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
  69. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
  70. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
  71. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
  72. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
  73. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/ohlc.py +0 -0
  74. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
  75. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
  76. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
  77. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
  78. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
  79. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
  80. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
  81. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/utils.py +0 -0
  82. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/ccxt/warmup_service.py +0 -0
  83. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/registry.py +0 -0
  84. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/tardis/data.py +0 -0
  85. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/connectors/tardis/utils.py +0 -0
  86. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/__init__.py +0 -0
  87. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/account.py +0 -0
  88. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/basics.py +0 -0
  89. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/context.py +0 -0
  90. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/detectors/__init__.py +0 -0
  91. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/detectors/delisting.py +0 -0
  92. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/detectors/stale.py +0 -0
  93. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/errors.py +0 -0
  94. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/exceptions.py +0 -0
  95. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/helpers.py +0 -0
  96. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/initializer.py +0 -0
  97. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/interfaces.py +0 -0
  98. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/loggers.py +0 -0
  99. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/lookups.py +0 -0
  100. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/__init__.py +0 -0
  101. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/market.py +0 -0
  102. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/processing.py +0 -0
  103. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/subscription.py +0 -0
  104. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/trading.py +0 -0
  105. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/universe.py +0 -0
  106. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/mixins/utils.py +0 -0
  107. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/series.pxd +0 -0
  108. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/series.pyi +0 -0
  109. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/series.pyx +0 -0
  110. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/utils.pyi +0 -0
  111. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/core/utils.pyx +0 -0
  112. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/__init__.py +0 -0
  113. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/cache.py +0 -0
  114. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/containers.py +0 -0
  115. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/guards.py +0 -0
  116. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/registry.py +0 -0
  117. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storage.py +0 -0
  118. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/ccxt.py +0 -0
  119. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/csv.py +0 -0
  120. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/handy.py +0 -0
  121. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/multi.py +0 -0
  122. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/questdb.py +0 -0
  123. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/stub.py +0 -0
  124. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/storages/utils.py +0 -0
  125. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/data/transformers.py +0 -0
  126. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/__init__.py +0 -0
  127. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/base.py +0 -0
  128. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/composite.py +0 -0
  129. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/csv.py +0 -0
  130. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/indicator.py +0 -0
  131. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/inmemory.py +0 -0
  132. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/prometheus.py +0 -0
  133. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/emitters/questdb.py +0 -0
  134. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/__init__.py +0 -0
  135. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/composite.py +0 -0
  136. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/formatters/__init__.py +0 -0
  137. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/formatters/base.py +0 -0
  138. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/formatters/incremental.py +0 -0
  139. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/formatters/slack.py +0 -0
  140. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/formatters/target_position.py +0 -0
  141. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/redis_streams.py +0 -0
  142. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/exporters/slack.py +0 -0
  143. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/gathering/simplest.py +0 -0
  144. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/health/__init__.py +0 -0
  145. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/health/base.py +0 -0
  146. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/health/dummy.py +0 -0
  147. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/health/server.py +0 -0
  148. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/loggers/__init__.py +0 -0
  149. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/loggers/csv.py +0 -0
  150. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/loggers/factory.py +0 -0
  151. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/loggers/inmemory.py +0 -0
  152. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/loggers/mongo.py +0 -0
  153. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/notifications/__init__.py +0 -0
  154. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/notifications/composite.py +0 -0
  155. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/notifications/slack.py +0 -0
  156. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/notifications/throttler.py +0 -0
  157. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/pandaz/__init__.py +0 -0
  158. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/pandaz/stats.py +0 -0
  159. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/pandaz/ta.py +0 -0
  160. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/pandaz/utils.py +0 -0
  161. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/plugins/__init__.py +0 -0
  162. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/plugins/loader.py +0 -0
  163. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/_build.py +0 -0
  164. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/crypto-fees.ini +0 -0
  165. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
  166. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
  167. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
  168. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
  169. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
  170. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
  171. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
  172. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
  173. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
  174. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
  175. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
  176. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restarts/__init__.py +0 -0
  177. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restarts/state_resolvers.py +0 -0
  178. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restarts/time_finders.py +0 -0
  179. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/__init__.py +0 -0
  180. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/balance.py +0 -0
  181. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/factory.py +0 -0
  182. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/interfaces.py +0 -0
  183. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/position.py +0 -0
  184. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/signal.py +0 -0
  185. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/state.py +0 -0
  186. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/restorers/utils.py +0 -0
  187. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/state/__init__.py +0 -0
  188. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/state/dummy.py +0 -0
  189. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/state/redis.py +0 -0
  190. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/ta/__init__.py +0 -0
  191. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/__init__.py +0 -0
  192. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/base.py +0 -0
  193. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/accounts.toml.j2 +0 -0
  194. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/config.yml.j2 +0 -0
  195. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/jlive.sh.j2 +0 -0
  196. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
  197. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
  198. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
  199. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
  200. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/project/template.yml +0 -0
  201. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/__init__.py.j2 +0 -0
  202. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
  203. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/config.yml.j2 +0 -0
  204. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
  205. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
  206. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/strategy.py.j2 +0 -0
  207. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/templates/simple/template.yml +0 -0
  208. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/trackers/__init__.py +0 -0
  209. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/trackers/advanced.py +0 -0
  210. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/trackers/composite.py +0 -0
  211. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/trackers/rebalancers.py +0 -0
  212. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/trackers/riskctrl.py +0 -0
  213. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/trackers/sizers.py +0 -0
  214. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/__init__.py +0 -0
  215. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/_pyxreloader.py +0 -0
  216. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/charting/lookinglass.py +0 -0
  217. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  218. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/charting/orderbook.py +0 -0
  219. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/collections.py +0 -0
  220. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/hft/__init__.py +0 -0
  221. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/hft/numba_utils.py +0 -0
  222. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/hft/orderbook.pyi +0 -0
  223. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/hft/orderbook.pyx +0 -0
  224. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/marketdata/binance.py +0 -0
  225. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/marketdata/ccxt.py +0 -0
  226. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/marketdata/dukas.py +0 -0
  227. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/misc.py +0 -0
  228. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/nonce.py +0 -0
  229. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/ntp.py +0 -0
  230. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/numbers_utils.py +0 -0
  231. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/orderbook.py +0 -0
  232. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/plotting/__init__.py +0 -0
  233. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/plotting/dashboard.py +0 -0
  234. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/plotting/data.py +0 -0
  235. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/plotting/interfaces.py +0 -0
  236. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
  237. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
  238. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/questdb.py +0 -0
  239. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/rate_limiter.py +0 -0
  240. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/results.py +0 -0
  241. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/ringbuffer.pxd +0 -0
  242. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/ringbuffer.pyi +0 -0
  243. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/ringbuffer.pyx +0 -0
  244. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/__init__.py +0 -0
  245. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
  246. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/accounts.py +0 -0
  247. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/factory.py +0 -0
  248. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/kernel_service.py +0 -0
  249. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/__init__.py +0 -0
  250. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/app.py +0 -0
  251. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/handlers.py +0 -0
  252. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/init_code.py +0 -0
  253. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/kernel.py +0 -0
  254. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/styles.tcss +0 -0
  255. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
  256. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
  257. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
  258. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
  259. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
  260. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
  261. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
  262. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/slack.py +0 -0
  263. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/throttler.py +0 -0
  264. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/src/qubx/utils/websocket_manager.py +0 -0
  265. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
  266. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
  267. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
  268. {qubx-1.0.1.dev2 → qubx-1.0.4.dev1}/tests/strategies/obi_trader/src/obi_trader/models/obi_trader.py +0 -0
@@ -180,4 +180,7 @@ cython_debug/
180
180
 
181
181
  accounts/
182
182
 
183
- **/.DS_Store
183
+ **/.DS_Store
184
+ *.code-workspace
185
+
186
+ **/_version.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Qubx
3
- Version: 1.0.1.dev2
3
+ Version: 1.0.4.dev1
4
4
  Summary: Qubx - Quantitative Trading Framework
5
5
  Project-URL: homepage, https://xlydian.com
6
6
  Project-URL: repository, https://github.com/xLydianSoftware/Qubx
@@ -9,57 +9,64 @@ Author-email: Dmitry Marienko <dmitry.marienko@xlydian.com>, Yuriy Arabskyy <yur
9
9
  License-File: LICENSE
10
10
  Requires-Python: <4.0,>=3.12
11
11
  Requires-Dist: aiohttp<3.11,>=3.10.11
12
- Requires-Dist: ccxt<5,>=4.2.68
12
+ Requires-Dist: click<9,>=8.1.7
13
13
  Requires-Dist: croniter<3,>=2.0.5
14
- Requires-Dist: cython==3.0.8
15
- Requires-Dist: dash-bootstrap-components<2,>=1.6.0
16
- Requires-Dist: dash<3,>=2.18.2
17
14
  Requires-Dist: gitpython<4,>=3.1.44
18
15
  Requires-Dist: importlib-metadata
19
- Requires-Dist: ipywidgets<9,>=8.1.5
20
16
  Requires-Dist: jinja2<4,>=3.1.0
21
- Requires-Dist: jupyter-console<7,>=6.6.3
22
- Requires-Dist: jupyter<2,>=1.1.1
17
+ Requires-Dist: joblib<2,>=1.3.0
23
18
  Requires-Dist: loguru<1,>=0.7.2
24
- Requires-Dist: matplotlib<4,>=3.8.4
25
19
  Requires-Dist: msgspec<1,>=0.18.6
26
20
  Requires-Dist: ntplib<1,>=0.4.0
27
21
  Requires-Dist: numba<1,>=0.59.1
28
22
  Requires-Dist: numpy>=1.26.3
29
23
  Requires-Dist: orjson<4,>=3.10.15
30
24
  Requires-Dist: pandas<3,>=2.2.2
31
- Requires-Dist: plotly<6,>=5.22.0
32
- Requires-Dist: psycopg-binary<4,>=3.1.19
33
- Requires-Dist: psycopg-pool<4,>=3.2.2
34
- Requires-Dist: psycopg<4,>=3.1.18
35
25
  Requires-Dist: pyarrow>=15.0.0
36
26
  Requires-Dist: pydantic-settings<3,>=2.4.0
37
27
  Requires-Dist: pydantic<3,>=2.9.2
38
- Requires-Dist: pymongo<5,>=4.6.1
39
- Requires-Dist: python-binance<2,>=1.0.19
40
28
  Requires-Dist: python-dotenv<2,>=1.0.0
41
29
  Requires-Dist: pyyaml<7,>=6.0.2
42
- Requires-Dist: qubx-bitfinex-api<4,>=3.0.7
43
- Requires-Dist: questdb<3,>=2.0.3
44
- Requires-Dist: redis<6,>=5.2.1
45
30
  Requires-Dist: rich<14,>=13.9.4
46
- Requires-Dist: scikit-learn>=1.8.0
47
31
  Requires-Dist: scipy<2,>=1.12.0
48
32
  Requires-Dist: sortedcontainers<3,>=2.4.0
49
33
  Requires-Dist: stackprinter<1,>=0.2.10
50
34
  Requires-Dist: statsmodels<1,>=0.14.6
51
35
  Requires-Dist: tabulate<1,>=0.9.0
52
- Requires-Dist: textual-autocomplete<5,>=4.0.0
53
- Requires-Dist: textual-serve<2,>=1.0.0
54
- Requires-Dist: textual[syntax]<7,>=6.0.0
55
36
  Requires-Dist: toml<1,>=0.10.2
56
- Requires-Dist: tqdm
37
+ Requires-Dist: tqdm<5,>=4.66.0
57
38
  Requires-Dist: uvloop<1,>=0.22.1; sys_platform != 'win32'
58
39
  Requires-Dist: websockets==15.0.1
40
+ Provides-Extra: binance
41
+ Requires-Dist: python-binance<2,>=1.0.19; extra == 'binance'
42
+ Provides-Extra: bitfinex
43
+ Requires-Dist: qubx-bitfinex-api<4,>=3.0.7; extra == 'bitfinex'
44
+ Provides-Extra: connectors
45
+ Requires-Dist: ccxt<5,>=4.2.68; extra == 'connectors'
46
+ Provides-Extra: db
47
+ Requires-Dist: duckdb>=1.0.0; extra == 'db'
48
+ Requires-Dist: psycopg-binary<4,>=3.1.19; extra == 'db'
49
+ Requires-Dist: psycopg-pool<4,>=3.2.2; extra == 'db'
50
+ Requires-Dist: psycopg<4,>=3.1.18; extra == 'db'
51
+ Requires-Dist: pymongo<5,>=4.6.1; extra == 'db'
52
+ Requires-Dist: questdb<3,>=2.0.3; extra == 'db'
53
+ Requires-Dist: redis<6,>=5.2.1; extra == 'db'
54
+ Provides-Extra: jupyter
55
+ Requires-Dist: ipywidgets<9,>=8.1.5; extra == 'jupyter'
56
+ Requires-Dist: jupyter-console<7,>=6.6.3; extra == 'jupyter'
57
+ Requires-Dist: jupyter<2,>=1.1.1; extra == 'jupyter'
59
58
  Provides-Extra: k8
59
+ Requires-Dist: boto3<2,>=1.34.0; extra == 'k8'
60
60
  Requires-Dist: prometheus-client<1,>=0.21.1; extra == 'k8'
61
- Provides-Extra: storage
62
- Requires-Dist: duckdb>=1.0.0; extra == 'storage'
61
+ Provides-Extra: tui
62
+ Requires-Dist: textual-autocomplete<5,>=4.0.0; extra == 'tui'
63
+ Requires-Dist: textual-serve<2,>=1.0.0; extra == 'tui'
64
+ Requires-Dist: textual[syntax]<7,>=6.0.0; extra == 'tui'
65
+ Provides-Extra: viz
66
+ Requires-Dist: dash-bootstrap-components<2,>=1.6.0; extra == 'viz'
67
+ Requires-Dist: dash<3,>=2.18.2; extra == 'viz'
68
+ Requires-Dist: matplotlib<4,>=3.8.4; extra == 'viz'
69
+ Requires-Dist: plotly<6,>=5.22.0; extra == 'viz'
63
70
  Description-Content-Type: text/markdown
64
71
 
65
72
  # Qubx - Quantitative Trading Framework
@@ -1,3 +1,6 @@
1
+ # ============================================================
2
+ # PROJECT METADATA
3
+ # ============================================================
1
4
  [project]
2
5
  name = "Qubx"
3
6
  dynamic = ["version"]
@@ -9,54 +12,40 @@ authors = [
9
12
  readme = "README.md"
10
13
  requires-python = ">=3.12,<4.0"
11
14
  dependencies = [
15
+ # Data & numerics
12
16
  "numpy>=1.26.3",
13
17
  "pandas>=2.2.2,<3",
14
18
  "pyarrow>=15.0.0",
15
19
  "scipy>=1.12.0,<2",
16
- "scikit-learn>=1.8.0",
17
- "statsmodels>=0.14.6,<1",
18
20
  "numba>=0.59.1,<1",
19
21
  "sortedcontainers>=2.4.0,<3",
20
- "ntplib>=0.4.0,<1",
21
- "python-binance>=1.0.19,<2",
22
- "ccxt>=4.2.68,<5",
23
- "pymongo>=4.6.1,<5",
24
- "redis>=5.2.1,<6",
25
- "psycopg>=3.1.18,<4",
26
- "psycopg-binary>=3.1.19,<4",
27
- "psycopg-pool>=3.2.2,<4",
28
- "matplotlib>=3.8.4,<4",
29
- "plotly>=5.22.0,<6",
30
- "dash>=2.18.2,<3",
31
- "dash-bootstrap-components>=1.6.0,<2",
22
+ "joblib>=1.3.0,<2",
23
+ # Logging & diagnostics
32
24
  "loguru>=0.7.2,<1",
33
- "tqdm",
34
- "importlib-metadata",
25
+ "tqdm>=4.66.0,<5",
35
26
  "stackprinter>=0.2.10,<1",
27
+ # Config & serialization
36
28
  "pydantic>=2.9.2,<3",
37
29
  "pydantic-settings>=2.4.0,<3",
38
30
  "python-dotenv>=1.0.0,<2",
39
- "cython==3.0.8",
40
- "croniter>=2.0.5,<3",
41
31
  "msgspec>=0.18.6,<1",
42
32
  "pyyaml>=6.0.2,<7",
43
- "tabulate>=0.9.0,<1",
44
33
  "toml>=0.10.2,<1",
45
- "gitpython>=3.1.44,<4",
46
- "jupyter>=1.1.1,<2",
47
- "jupyter-console>=6.6.3,<7",
48
- "ipywidgets>=8.1.5,<9",
49
- "questdb>=2.0.3,<3",
50
34
  "orjson>=3.10.15,<4",
35
+ # Networking & async
51
36
  "aiohttp>=3.10.11,<3.11",
52
37
  "websockets==15.0.1",
53
- "qubx-bitfinex-api>=3.0.7,<4",
54
- "textual-autocomplete>=4.0.0,<5",
55
- "textual-serve>=1.0.0,<2",
56
- "rich>=13.9.4,<14",
57
- "jinja2>=3.1.0,<4",
58
38
  "uvloop>=0.22.1,<1; sys_platform != 'win32'",
59
- "textual[syntax]>=6.0.0,<7",
39
+ # Utilities
40
+ "importlib-metadata",
41
+ "croniter>=2.0.5,<3",
42
+ "tabulate>=0.9.0,<1",
43
+ "gitpython>=3.1.44,<4",
44
+ "ntplib>=0.4.0,<1",
45
+ "jinja2>=3.1.0,<4",
46
+ "rich>=13.9.4,<14",
47
+ "click>=8.1.7,<9",
48
+ "statsmodels>=0.14.6,<1",
60
49
  ]
61
50
 
62
51
  [project.urls]
@@ -64,15 +53,57 @@ homepage = "https://xlydian.com"
64
53
  repository = "https://github.com/xLydianSoftware/Qubx"
65
54
  docs = "https://xlydiansoftware.github.io/Qubx"
66
55
 
67
- [project.optional-dependencies]
68
- # Runtime optional features only (shipped with package)
69
- k8 = ["prometheus-client>=0.21.1,<1"]
70
- # Parquet-based backtest storage with DuckDB search and cloud (S3/GCS/Azure) support
71
- storage = ["duckdb>=1.0.0"]
72
-
73
56
  [project.scripts]
74
57
  qubx = "qubx.cli.commands:main"
75
58
 
59
+ # ============================================================
60
+ # OPTIONAL DEPENDENCIES (`pip install qubx[connectors,db,...]`)
61
+ # ============================================================
62
+ [project.optional-dependencies]
63
+ # Exchange connectors (ccxt-based)
64
+ connectors = ["ccxt>=4.2.68,<5"]
65
+ # Binance-specific (historical data utilities)
66
+ binance = ["python-binance>=1.0.19,<2"]
67
+ # Bitfinex-specific (custom API client)
68
+ bitfinex = ["qubx-bitfinex-api>=3.0.7,<4"]
69
+ # Database backends (MongoDB, Redis, PostgreSQL/QuestDB, DuckDB)
70
+ db = [
71
+ "pymongo>=4.6.1,<5",
72
+ "redis>=5.2.1,<6",
73
+ "psycopg>=3.1.18,<4",
74
+ "psycopg-binary>=3.1.19,<4",
75
+ "psycopg-pool>=3.2.2,<4",
76
+ "questdb>=2.0.3,<3",
77
+ "duckdb>=1.0.0",
78
+ ]
79
+ # Visualization & charting
80
+ viz = [
81
+ "matplotlib>=3.8.4,<4",
82
+ "plotly>=5.22.0,<6",
83
+ "dash>=2.18.2,<3",
84
+ "dash-bootstrap-components>=1.6.0,<2",
85
+ ]
86
+ # Terminal UI (textual TUI, browse command)
87
+ tui = [
88
+ "textual[syntax]>=6.0.0,<7",
89
+ "textual-autocomplete>=4.0.0,<5",
90
+ "textual-serve>=1.0.0,<2",
91
+ ]
92
+ # Jupyter integration
93
+ jupyter = [
94
+ "jupyter>=1.1.1,<2",
95
+ "jupyter-console>=6.6.3,<7",
96
+ "ipywidgets>=8.1.5,<9",
97
+ ]
98
+ # Kubernetes / production monitoring
99
+ k8 = [
100
+ "prometheus-client>=0.21.1,<1",
101
+ "boto3>=1.34.0,<2",
102
+ ]
103
+
104
+ # ============================================================
105
+ # BUILD SYSTEM
106
+ # ============================================================
76
107
  [build-system]
77
108
  requires = [
78
109
  "hatchling>=1.21.0",
@@ -84,7 +115,6 @@ requires = [
84
115
  ]
85
116
  build-backend = "hatchling.build"
86
117
 
87
- # Hatch version configuration - tag-driven via VCS
88
118
  [tool.hatch.version]
89
119
  source = "vcs"
90
120
 
@@ -95,36 +125,67 @@ local_scheme = "no-local-version"
95
125
  [tool.hatch.build.hooks.vcs]
96
126
  version-file = "src/qubx/_version.py"
97
127
 
98
- # Hatch build configuration
99
128
  [tool.hatch.build]
100
129
  packages = ["src/qubx"]
101
- # Include VCS-ignored files (compiled .so/.pyd from build hooks)
102
- artifacts = [
103
- "src/qubx/**/*.so",
104
- "src/qubx/**/*.pyd",
105
- ]
130
+ artifacts = ["src/qubx/**/*.so", "src/qubx/**/*.pyd"]
106
131
 
107
132
  [tool.hatch.build.targets.sdist]
108
- include = [
109
- "src/",
110
- "hatch_build.py",
111
- ]
133
+ include = ["src/", "scripts/build.py"]
112
134
  exclude = ["**/__pycache__", "**/*.so", "**/*.pyd", "**/*.c"]
113
- # Don't relocate - keep src/ layout in sdist
114
135
  packages = []
115
136
 
116
137
  [tool.hatch.build.targets.wheel]
117
138
  packages = ["src/qubx"]
118
- # Include compiled extensions in wheel (VCS-ignored files)
119
- artifacts = [
120
- "src/qubx/**/*.so",
121
- "src/qubx/**/*.pyd",
122
- ]
139
+ artifacts = ["src/qubx/**/*.so", "src/qubx/**/*.pyd"]
123
140
 
124
- # Custom build hook for Cython compilation and platform-specific wheel tags
125
141
  [tool.hatch.build.targets.wheel.hooks.custom]
126
- path = "hatch_build.py"
142
+ path = "scripts/build.py"
127
143
 
144
+ # ============================================================
145
+ # DEV DEPENDENCIES (installed with `uv sync`, not shipped)
146
+ # Use `uv sync --all-extras` or `just install` for full dev setup
147
+ # ============================================================
148
+ [dependency-groups]
149
+ dev = [
150
+ # Testing
151
+ "pytest>=8.2.0,<9",
152
+ "pytest-asyncio>=0.24.0,<1",
153
+ "pytest-mock>=3.12.0,<4",
154
+ "pytest-lazy-fixture>=0.6.3,<1",
155
+ "pytest-cov>=4.1.0,<5",
156
+ "pytest-xdist>=3.6.1,<4",
157
+ "pytest-textual-snapshot>=1.1.0,<2",
158
+ "mongomock>=4.3.0,<5",
159
+ # Linting & formatting
160
+ "ruff>=0.9.7,<1",
161
+ "pre-commit>=2.20.0,<3",
162
+ # Debugging & profiling
163
+ "debugpy>=1.8.12,<2",
164
+ "py-spy>=0.4.1,<1",
165
+ # Jupyter / notebooks
166
+ "ipykernel>=6.29.4,<7",
167
+ "iprogress>=0.4,<1",
168
+ "nbformat>=5.10.4,<6",
169
+ # Documentation
170
+ "markdown==3.7",
171
+ "mkdocs==1.6.1",
172
+ "mkdocs-material==9.6.5",
173
+ "mdx-truly-sane-lists==1.3",
174
+ "pymdown-extensions==10.14.3",
175
+ "jinja2==3.1.5",
176
+ "mike==2.1.3",
177
+ "mkdocs-jupyter==0.25.1",
178
+ # Build tooling
179
+ "cython==3.0.8",
180
+ # Release tooling
181
+ "rust-just>=1.36.0,<2",
182
+ "twine>=5.1.1,<6",
183
+ "git-cliff>=2.0.0",
184
+ ]
185
+
186
+ # ============================================================
187
+ # TOOL CONFIGURATION
188
+ # ============================================================
128
189
  [tool.ruff]
129
190
  line-length = 120
130
191
 
@@ -133,7 +194,7 @@ extend-select = ["I"]
133
194
  ignore = ["E731", "E722", "E741"]
134
195
 
135
196
  [tool.ruff.lint.extend-per-file-ignores]
136
- "*.ipynb" = [ "F405", "F401", "E701", "E402", "F403", "E401", "E702", "F821", "E731", "I001", ]
197
+ "*.ipynb" = ["F405", "F401", "E701", "E402", "F403", "E401", "E702", "F821", "E731", "I001"]
137
198
 
138
199
  [tool.pytest.ini_options]
139
200
  asyncio_mode = "auto"
@@ -148,37 +209,3 @@ filterwarnings = [
148
209
  "ignore:.*Jupyter is migrating.*:DeprecationWarning",
149
210
  "ignore:coroutine.*AsyncMockMixin._execute_mock_call.*was never awaited:RuntimeWarning",
150
211
  ]
151
-
152
- [dependency-groups]
153
- # Dev/test tools (not shipped with package, only for local development)
154
- dev = [
155
- "pre-commit>=2.20.0,<3",
156
- "rust-just>=1.36.0,<2",
157
- "twine>=5.1.1,<6",
158
- "ipykernel>=6.29.4,<7",
159
- "iprogress>=0.4,<1",
160
- "click>=8.1.7,<9",
161
- "ipywidgets>=8.1.5,<9",
162
- "ruff>=0.9.7,<1",
163
- "pytest-xdist>=3.6.1,<4",
164
- "nbformat>=5.10.4,<6",
165
- "markdown==3.7",
166
- "mkdocs==1.6.1",
167
- "mkdocs-material==9.6.5",
168
- "mdx-truly-sane-lists==1.3",
169
- "pymdown-extensions==10.14.3",
170
- "jinja2==3.1.5",
171
- "mike==2.1.3",
172
- "mkdocs-jupyter==0.25.1",
173
- "debugpy>=1.8.12,<2",
174
- "py-spy>=0.4.1,<1",
175
- "pytest>=8.2.0,<9",
176
- "pytest-asyncio>=0.24.0,<1",
177
- "pytest-mock>=3.12.0,<4",
178
- "pytest-lazy-fixture>=0.6.3,<1",
179
- "pytest-cov>=4.1.0,<5",
180
- "mongomock>=4.3.0,<5",
181
- "pytest-textual-snapshot>=1.1.0,<2",
182
- "git-cliff>=2.0.0",
183
- "duckdb>=1.0.0",
184
- ]
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.0.1.dev2'
32
- __version_tuple__ = version_tuple = (1, 0, 1, 'dev2')
31
+ __version__ = version = '1.0.4.dev1'
32
+ __version_tuple__ = version_tuple = (1, 0, 4, 'dev1')
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -433,7 +433,14 @@ def release(
433
433
  help="Force overwrite if the output directory already exists.",
434
434
  show_default=True,
435
435
  )
436
- def deploy(zip_file: str, output_dir: str | None, force: bool):
436
+ @click.option(
437
+ "--system",
438
+ is_flag=True,
439
+ default=False,
440
+ help="Install wheels into system site-packages (Docker mode, no venv/uv needed).",
441
+ show_default=True,
442
+ )
443
+ def deploy(zip_file: str, output_dir: str | None, force: bool, system: bool):
437
444
  """
438
445
  Deploys a strategy from a zip file created by the release command.
439
446
 
@@ -442,6 +449,10 @@ def deploy(zip_file: str, output_dir: str | None, force: bool):
442
449
  2. Auto-detects the package manager (uv or legacy poetry) from the lock file
443
450
  3. Creates a virtual environment and installs dependencies
444
451
 
452
+ With --system flag (Docker mode):
453
+ - Installs wheels directly into system site-packages via pip
454
+ - No virtual environment or uv needed
455
+
445
456
  Supports both uv-based releases (uv.lock) and legacy Poetry-based releases (poetry.lock).
446
457
 
447
458
  If no output directory is specified, the zip file is unpacked in the same directory
@@ -449,7 +460,7 @@ def deploy(zip_file: str, output_dir: str | None, force: bool):
449
460
  """
450
461
  from .deploy import deploy_strategy
451
462
 
452
- deploy_strategy(zip_file, output_dir, force)
463
+ deploy_strategy(zip_file, output_dir, force, system=system)
453
464
 
454
465
 
455
466
  @main.command()
@@ -275,21 +275,65 @@ def create_strategy_runners(output_dir: str, pkg_manager: str = "uv"):
275
275
  logger.error(f"Failed to create strategy paper runner script: {e}")
276
276
 
277
277
 
278
- def deploy_strategy(zip_file: str, output_dir: str | None, force: bool) -> bool:
278
+ def install_system_wheels(output_dir: str) -> bool:
279
+ """
280
+ Install all wheels from wheels/ directory into system site-packages.
281
+
282
+ This is the Docker deployment path: no venv, no uv, just pip install.
283
+
284
+ Args:
285
+ output_dir: Directory containing the extracted release (with wheels/ subdirectory)
286
+
287
+ Returns:
288
+ bool: True if successful, False otherwise
289
+ """
290
+ wheels_dir = os.path.join(output_dir, "wheels")
291
+ if not os.path.isdir(wheels_dir):
292
+ logger.warning("No wheels/ directory found — skipping system wheel install")
293
+ return True
294
+
295
+ wheel_files = [os.path.join(wheels_dir, f) for f in os.listdir(wheels_dir) if f.endswith(".whl")]
296
+ if not wheel_files:
297
+ logger.warning("No .whl files found in wheels/ — skipping system wheel install")
298
+ return True
299
+
300
+ logger.info(f"Installing {len(wheel_files)} wheel(s) into system site-packages...")
301
+ pip_exe = shutil.which("pip") or shutil.which("pip3")
302
+ if not pip_exe:
303
+ logger.error("pip not found — cannot install wheels into system site-packages")
304
+ return False
305
+
306
+ try:
307
+ subprocess.run(
308
+ [pip_exe, "install", *wheel_files],
309
+ check=True,
310
+ capture_output=False,
311
+ text=True,
312
+ )
313
+ logger.info("System wheel install complete")
314
+ return True
315
+ except subprocess.CalledProcessError as e:
316
+ logger.error(f"Failed to install wheels: {e}")
317
+ return False
318
+
319
+
320
+ def deploy_strategy(zip_file: str, output_dir: str | None, force: bool, system: bool = False) -> bool:
279
321
  """
280
322
  Deploys a strategy from a zip file created by the release command.
281
323
 
282
324
  This function:
283
325
  1. Unpacks the zip file to the specified output directory
284
326
  2. Auto-detects the package manager (uv or poetry) based on the lock file
285
- 3. Creates a virtual environment and installs dependencies
327
+ 3. Creates a virtual environment and installs dependencies (default)
328
+ OR installs wheels into system site-packages (--system mode for Docker)
286
329
 
287
- Supports both new uv-based releases and legacy Poetry-based releases.
330
+ Supports both uv-based releases, legacy Poetry-based releases, and system mode.
288
331
 
289
332
  Args:
290
333
  zip_file: Path to the zip file to deploy
291
334
  output_dir: Output directory to unpack the zip file. If None, uses the directory containing the zip file.
292
335
  force: Whether to force overwrite if the output directory already exists
336
+ system: If True, install wheels directly into system site-packages (Docker mode)
293
337
 
294
338
  Returns:
295
339
  bool: True if deployment was successful, False otherwise
@@ -309,6 +353,14 @@ def deploy_strategy(zip_file: str, output_dir: str | None, force: bool) -> bool:
309
353
  if not extract_zip_file(zip_file, resolved_output_dir):
310
354
  return False
311
355
 
356
+ if system:
357
+ # Docker path: pip install wheels directly into system site-packages
358
+ if not install_system_wheels(resolved_output_dir):
359
+ return False
360
+ logger.info(f"Strategy deployed (system mode) to {resolved_output_dir}")
361
+ return True
362
+
363
+ # Default path: venv-based install
312
364
  # Detect package manager
313
365
  pkg_manager = _detect_package_manager(resolved_output_dir)
314
366
  logger.info(f"Detected package manager: {pkg_manager}")