Qubx 3.2.0__tar.gz → 3.2.2.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 (324) hide show
  1. {qubx-3.2.0 → qubx-3.2.2.dev1}/PKG-INFO +2 -1
  2. {qubx-3.2.0 → qubx-3.2.2.dev1}/pyproject.toml +1 -0
  3. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/_version.py +2 -2
  4. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/connector.py +2 -6
  5. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/runner.py +14 -5
  6. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/simulator.py +1 -1
  7. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/transfers.py +5 -16
  8. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/utils.py +8 -73
  9. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/connector.py +22 -245
  10. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/base.py +2 -8
  11. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -15
  12. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +1 -13
  13. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/warmup_service.py +3 -25
  14. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/builtin.py +3 -27
  15. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/manager.py +4 -26
  16. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/reconciler.py +2 -6
  17. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/reducer.py +1 -12
  18. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/state.py +8 -41
  19. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/basics.py +6 -15
  20. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/connector.py +1 -12
  21. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/context.py +6 -90
  22. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/errors.py +0 -20
  23. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/events.py +0 -1
  24. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/exceptions.py +0 -11
  25. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/initializer.py +0 -23
  26. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/interfaces.py +15 -118
  27. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/metrics.py +28 -31
  28. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/instrument_service.py +8 -18
  29. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/market.py +26 -193
  30. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/processing.py +13 -205
  31. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/subscription.py +40 -177
  32. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/trading.py +22 -102
  33. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/series.pyi +0 -4
  34. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/questdb.py +22 -30
  35. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/csv.py +2 -2
  36. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/inmemory.py +2 -2
  37. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/questdb.py +1 -1
  38. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/health/base.py +10 -133
  39. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/health/dummy.py +0 -7
  40. qubx-3.2.2.dev1/src/qubx/utils/ntp.py +63 -0
  41. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/results.py +1 -23
  42. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/configs.py +1 -43
  43. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/runner.py +0 -3
  44. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/handlers.py +0 -1
  45. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/init_code.py +0 -14
  46. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/styles.tcss +0 -7
  47. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/account_summary.py +0 -26
  48. qubx-3.2.0/src/qubx/core/fit_context.py +0 -481
  49. qubx-3.2.0/src/qubx/core/fit_executor.py +0 -157
  50. qubx-3.2.0/src/qubx/core/status.py +0 -107
  51. qubx-3.2.0/src/qubx/utils/clock.py +0 -167
  52. {qubx-3.2.0 → qubx-3.2.2.dev1}/.gitignore +0 -0
  53. {qubx-3.2.0 → qubx-3.2.2.dev1}/LICENSE +0 -0
  54. {qubx-3.2.0 → qubx-3.2.2.dev1}/README.md +0 -0
  55. {qubx-3.2.0 → qubx-3.2.2.dev1}/scripts/build.py +0 -0
  56. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/__init__.py +0 -0
  57. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/_nb_magic.py +0 -0
  58. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/__init__.py +0 -0
  59. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/data.py +0 -0
  60. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/iteratedstream.py +0 -0
  61. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/management.py +0 -0
  62. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/ome.py +0 -0
  63. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/optimization.py +0 -0
  64. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/sentinels.py +0 -0
  65. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/simulated_data.py +0 -0
  66. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/simulated_exchange.py +0 -0
  67. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/__init__.py +0 -0
  68. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/commands.py +0 -0
  69. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/deploy.py +0 -0
  70. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/misc.py +0 -0
  71. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/release.py +0 -0
  72. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/resolver.py +0 -0
  73. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/s3.py +0 -0
  74. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/theme.py +0 -0
  75. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/tui.py +0 -0
  76. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/user_config.py +0 -0
  77. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/config.py +0 -0
  78. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/__init__.py +0 -0
  79. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/__init__.py +0 -0
  80. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
  81. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
  82. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/connection_manager.py +0 -0
  83. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/data.py +0 -0
  84. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exceptions.py +0 -0
  85. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
  86. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
  87. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/_two_stream.py +0 -0
  88. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/binance/connector.py +0 -0
  89. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
  90. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
  91. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/connector.py +0 -0
  92. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
  93. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
  94. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
  95. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/okx/__init__.py +0 -0
  96. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/okx/connector.py +0 -0
  97. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/okx/okx.py +0 -0
  98. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/factory.py +0 -0
  99. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
  100. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
  101. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
  102. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
  103. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
  104. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/ohlc.py +0 -0
  105. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
  106. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
  107. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
  108. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
  109. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/plugin.py +0 -0
  110. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/rate_limits.py +0 -0
  111. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
  112. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
  113. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
  114. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/utils.py +0 -0
  115. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/plugin.py +0 -0
  116. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/registry.py +0 -0
  117. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/tardis/data.py +0 -0
  118. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/tardis/plugin.py +0 -0
  119. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/tardis/utils.py +0 -0
  120. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/__init__.py +0 -0
  121. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/decorator.py +0 -0
  122. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/executor.py +0 -0
  123. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/interfaces.py +0 -0
  124. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/server.py +0 -0
  125. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/types.py +0 -0
  126. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/__init__.py +0 -0
  127. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/__init__.py +0 -0
  128. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/config.py +0 -0
  129. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/diffs.py +0 -0
  130. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/state_machine.py +0 -0
  131. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/detectors/__init__.py +0 -0
  132. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/detectors/delisting.py +0 -0
  133. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/detectors/stale.py +0 -0
  134. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/helpers.py +0 -0
  135. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/instrument_service.py +0 -0
  136. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/loggers.py +0 -0
  137. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/lookups.py +0 -0
  138. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/__init__.py +0 -0
  139. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/universe.py +0 -0
  140. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/utils.py +0 -0
  141. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/series.pxd +0 -0
  142. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/series.pyx +0 -0
  143. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/utils.pyi +0 -0
  144. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/utils.pyx +0 -0
  145. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/__init__.py +0 -0
  146. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/cache.py +0 -0
  147. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/containers.py +0 -0
  148. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/guards.py +0 -0
  149. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/registry.py +0 -0
  150. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storage.py +0 -0
  151. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/ccxt.py +0 -0
  152. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/csv.py +0 -0
  153. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/handy.py +0 -0
  154. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/multi.py +0 -0
  155. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/stub.py +0 -0
  156. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/utils.py +0 -0
  157. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/transformers.py +0 -0
  158. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/__init__.py +0 -0
  159. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/base.py +0 -0
  160. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/composite.py +0 -0
  161. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/indicator.py +0 -0
  162. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/prometheus.py +0 -0
  163. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/__init__.py +0 -0
  164. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/composite.py +0 -0
  165. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/__init__.py +0 -0
  166. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/base.py +0 -0
  167. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/incremental.py +0 -0
  168. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/slack.py +0 -0
  169. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/target_position.py +0 -0
  170. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/redis_streams.py +0 -0
  171. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/slack.py +0 -0
  172. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/gathering/simplest.py +0 -0
  173. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/health/__init__.py +0 -0
  174. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/__init__.py +0 -0
  175. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/csv.py +0 -0
  176. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/factory.py +0 -0
  177. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/inmemory.py +0 -0
  178. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/mongo.py +0 -0
  179. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/postgres.py +0 -0
  180. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/__init__.py +0 -0
  181. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/composite.py +0 -0
  182. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/slack.py +0 -0
  183. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/throttler.py +0 -0
  184. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/__init__.py +0 -0
  185. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/stats.py +0 -0
  186. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/ta.py +0 -0
  187. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/utils.py +0 -0
  188. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/plugins/__init__.py +0 -0
  189. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/plugins/loader.py +0 -0
  190. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/__init__.py +0 -0
  191. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/backend.py +0 -0
  192. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/config.py +0 -0
  193. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/engine.py +0 -0
  194. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/ip_resolver.py +0 -0
  195. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/manager.py +0 -0
  196. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/pools.py +0 -0
  197. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/redis_backend.py +0 -0
  198. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/_build.py +0 -0
  199. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/crypto-fees.ini +0 -0
  200. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
  201. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
  202. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
  203. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
  204. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
  205. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
  206. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
  207. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
  208. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
  209. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
  210. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
  211. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restarts/__init__.py +0 -0
  212. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restarts/state_resolvers.py +0 -0
  213. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restarts/time_finders.py +0 -0
  214. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/__init__.py +0 -0
  215. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/balance.py +0 -0
  216. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/factory.py +0 -0
  217. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/interfaces.py +0 -0
  218. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/position.py +0 -0
  219. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/signal.py +0 -0
  220. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/state.py +0 -0
  221. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/utils.py +0 -0
  222. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/state/__init__.py +0 -0
  223. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/state/dummy.py +0 -0
  224. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/state/redis.py +0 -0
  225. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/__init__.py +0 -0
  226. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/indicators.pxd +0 -0
  227. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/indicators.pyi +0 -0
  228. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/indicators.pyx +0 -0
  229. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/__init__.py +0 -0
  230. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/base.py +0 -0
  231. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/accounts.toml.j2 +0 -0
  232. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/config.yml.j2 +0 -0
  233. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/jlive.sh.j2 +0 -0
  234. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
  235. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
  236. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
  237. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
  238. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/template.yml +0 -0
  239. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/qubx-cli/SKILL.md +0 -0
  240. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/qubx-indicators/SKILL.md +0 -0
  241. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/simulation-explorer/SKILL.md +0 -0
  242. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/strategy-release/SKILL.md +0 -0
  243. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.github/workflows/ci.yml.j2 +0 -0
  244. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.gitignore.j2 +0 -0
  245. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.python-version +0 -0
  246. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.vscode/launch.json +0 -0
  247. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.vscode/settings.json +0 -0
  248. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.vscode/tasks.json +0 -0
  249. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/CLAUDE.md.j2 +0 -0
  250. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/README.md.j2 +0 -0
  251. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/configs/.gitkeep +0 -0
  252. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/justfile.j2 +0 -0
  253. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/pyproject.toml.j2 +0 -0
  254. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/research/.gitkeep +0 -0
  255. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/__init__.py.j2 +0 -0
  256. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/cli.py.j2 +0 -0
  257. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/strategy.py.j2 +0 -0
  258. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/template.yml +0 -0
  259. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/tests/test_strategy.py.j2 +0 -0
  260. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/__init__.py.j2 +0 -0
  261. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
  262. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/config.yml.j2 +0 -0
  263. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
  264. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
  265. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/strategy.py.j2 +0 -0
  266. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/template.yml +0 -0
  267. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/__init__.py +0 -0
  268. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/advanced.py +0 -0
  269. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/composite.py +0 -0
  270. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/rebalancers.py +0 -0
  271. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/riskctrl.py +0 -0
  272. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/sizers.py +0 -0
  273. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/__init__.py +0 -0
  274. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/_pyxreloader.py +0 -0
  275. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/charting/lookinglass.py +0 -0
  276. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  277. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/charting/orderbook.py +0 -0
  278. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/collections.py +0 -0
  279. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/__init__.py +0 -0
  280. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/numba_utils.py +0 -0
  281. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/orderbook.pyi +0 -0
  282. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/orderbook.pyx +0 -0
  283. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/marketdata/binance.py +0 -0
  284. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/marketdata/ccxt.py +0 -0
  285. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/marketdata/dukas.py +0 -0
  286. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/misc.py +0 -0
  287. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/nonce.py +0 -0
  288. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/numbers_utils.py +0 -0
  289. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/orderbook.py +0 -0
  290. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/__init__.py +0 -0
  291. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/dashboard.py +0 -0
  292. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/data.py +0 -0
  293. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/interfaces.py +0 -0
  294. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
  295. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
  296. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/questdb.py +0 -0
  297. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/rate_limiter.py +0 -0
  298. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/ringbuffer.pxd +0 -0
  299. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/ringbuffer.pyi +0 -0
  300. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/ringbuffer.pyx +0 -0
  301. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/__init__.py +0 -0
  302. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
  303. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/accounts.py +0 -0
  304. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/factory.py +0 -0
  305. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/kernel_service.py +0 -0
  306. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/__init__.py +0 -0
  307. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/app.py +0 -0
  308. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/kernel.py +0 -0
  309. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
  310. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
  311. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
  312. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
  313. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
  314. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
  315. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
  316. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/s3.py +0 -0
  317. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/slack.py +0 -0
  318. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/throttler.py +0 -0
  319. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/time.py +0 -0
  320. {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/websocket_manager.py +0 -0
  321. {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
  322. {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
  323. {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
  324. {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/obi_trader/src/obi_trader/models/obi_trader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: Qubx
3
- Version: 3.2.0
3
+ Version: 3.2.2.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
@@ -23,6 +23,7 @@ Requires-Dist: joblib<2,>=1.3.0
23
23
  Requires-Dist: jupyter-client<9,>=8.0.0
24
24
  Requires-Dist: loguru<1,>=0.7.2
25
25
  Requires-Dist: msgspec<1,>=0.18.6
26
+ Requires-Dist: ntplib<1,>=0.4.0
26
27
  Requires-Dist: numba<1,>=0.59.1
27
28
  Requires-Dist: numpy>=2.0.0
28
29
  Requires-Dist: orjson<4,>=3.10.15
@@ -53,6 +53,7 @@ dependencies = [
53
53
  "croniter>=2.0.5,<3",
54
54
  "tabulate>=0.9.0,<1",
55
55
  "gitpython>=3.1.44,<4",
56
+ "ntplib>=0.4.0,<1",
56
57
  "jinja2>=3.1.0,<4",
57
58
  "rich>=13.9.4,<14",
58
59
  "click>=8.1.7,<9",
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '3.2.0'
22
- __version_tuple__ = version_tuple = (3, 2, 0)
21
+ __version__ = version = '3.2.2.dev1'
22
+ __version_tuple__ = version_tuple = (3, 2, 2, 'dev1')
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -298,17 +298,13 @@ class SimulatedConnector(ChannelEmitter):
298
298
  def is_simulated_trading(self) -> bool:
299
299
  return True
300
300
 
301
- def set_instrument_leverage(self, instrument: Instrument, leverage: float) -> None:
302
- # - simulation does not model venue leverage settings; accept and forget
303
- return None
301
+ def set_max_instrument_leverage(self, instrument: Instrument, leverage: float) -> bool:
302
+ return True
304
303
 
305
304
  def set_margin_mode(self, instrument: Instrument, mode: str) -> bool:
306
305
  return True
307
306
 
308
307
  # Simulation does not model venue margin: the config getters read neutral.
309
- def get_instrument_leverage(self, instrument: Instrument) -> float | None:
310
- return None
311
-
312
308
  def get_max_instrument_leverage(self, instrument: Instrument) -> float | None:
313
309
  return None
314
310
 
@@ -11,7 +11,7 @@ from qubx.backtester.sentinels import NoDataContinue
11
11
  from qubx.backtester.simulated_data import SimulatedDataIterator
12
12
  from qubx.backtester.transfers import SimulationTransferManager
13
13
  from qubx.core.account_manager import AccountManagerConfig, SimulatedAccountManager
14
- from qubx.core.basics import SW, DataType, Instrument, TransactionCostsCalculator
14
+ from qubx.core.basics import SW, Balance, DataType, Instrument, TransactionCostsCalculator
15
15
  from qubx.core.context import StrategyContext
16
16
  from qubx.core.exceptions import SimulationConfigError, SimulationError
17
17
  from qubx.core.helpers import extract_parameters_from_object, full_qualified_class_name
@@ -49,7 +49,6 @@ from .utils import (
49
49
  SimulationSetup,
50
50
  _get_default_warmup_period,
51
51
  find_open_close_time_indent_secs_from_subscription,
52
- initial_balances,
53
52
  )
54
53
 
55
54
 
@@ -609,7 +608,7 @@ class SimulationRunner:
609
608
 
610
609
  am = SimulatedAccountManager(
611
610
  connectors=self._connectors,
612
- base_currencies=self.setup.base_currencies,
611
+ base_currencies={exchange: self.setup.base_currency for exchange in self.setup.exchanges},
613
612
  time=time_provider,
614
613
  cfg=AccountManagerConfig(),
615
614
  account_id=self.account_id,
@@ -617,7 +616,17 @@ class SimulationRunner:
617
616
  )
618
617
 
619
618
  # - seed initial capital per exchange into the account state
620
- for exchange, balance in initial_balances(self.setup).items():
621
- am.seed_balance(exchange, balance)
619
+ assert isinstance(self.setup.capital, dict)
620
+ for exchange, capital in self.setup.capital.items():
621
+ am.seed_balance(
622
+ exchange,
623
+ Balance(
624
+ exchange=exchange,
625
+ currency=self.setup.base_currency,
626
+ total=capital,
627
+ free=capital,
628
+ locked=0.0,
629
+ ),
630
+ )
622
631
 
623
632
  return am
@@ -38,7 +38,7 @@ def simulate(
38
38
  instruments: list[str] | list[Instrument] | dict[ExchangeName_t, list[SymbolOrInstrument_t]] | None = None,
39
39
  commissions: str | dict[str, str | None] | None = None,
40
40
  exchange: ExchangeName_t | list[ExchangeName_t] | None = None,
41
- base_currency: str | dict[str, str] = "USDT",
41
+ base_currency: str = "USDT",
42
42
  n_jobs: int = 1,
43
43
  silent: bool = False,
44
44
  aux_data: IStorage | None = None,
@@ -21,15 +21,6 @@ class SimulationTransferManager(ITransferManager):
21
21
  def transfer_funds(self, from_exchange: str, to_exchange: str, currency: str, amount: float) -> str:
22
22
  if amount <= 0:
23
23
  raise ValueError(f"Transfer amount must be positive, got {amount}")
24
- to_currency = self._account.get_base_currency(to_exchange)
25
- # Venues settle in their own currency: a withdrawal leaves in `currency` and arrives as
26
- # `to_currency`. Both legs must be priced — an unpriced asset has no transferable value.
27
- from_rate = self._account.get_state(from_exchange).conversion_rate_to_base(currency)
28
- to_rate = self._account.get_state(to_exchange).conversion_rate_to_base(to_currency)
29
- if from_rate is None or to_rate is None:
30
- raise ValueError(f"Cannot transfer {currency} to {to_exchange} {to_currency}: no conversion rate")
31
- to_amount = amount * from_rate / to_rate
32
-
33
24
  from_balance = self._account.get_balance(currency, exchange=from_exchange)
34
25
  if from_balance.free < amount:
35
26
  raise ValueError(
@@ -37,8 +28,11 @@ class SimulationTransferManager(ITransferManager):
37
28
  f"{from_balance.free:.8f} {currency} available, {amount:.8f} requested"
38
29
  )
39
30
 
31
+ # Instant transfer: debit the source and credit the destination. adjust_balance
32
+ # mutates the held Balance in place (holders keep a live reference) and creates
33
+ # the destination Balance if missing.
40
34
  self._account.adjust_balance(from_exchange, currency, -amount)
41
- self._account.adjust_balance(to_exchange, to_currency, to_amount)
35
+ self._account.adjust_balance(to_exchange, currency, amount)
42
36
 
43
37
  transaction_id = f"sim_{uuid.uuid4().hex[:12]}"
44
38
  self._transfers[transaction_id] = Transfer(
@@ -49,13 +43,8 @@ class SimulationTransferManager(ITransferManager):
49
43
  amount=amount,
50
44
  status=TransferStatus.COMPLETED, # transfers are instant in simulation
51
45
  timestamp=self._time.time(),
52
- to_currency=to_currency,
53
- to_amount=to_amount,
54
- )
55
- logger.debug(
56
- f"[SimTransfer] {amount:.8f} {currency} {from_exchange} -> "
57
- f"{to_amount:.8f} {to_currency} {to_exchange} ({transaction_id})"
58
46
  )
47
+ logger.debug(f"[SimTransfer] {amount:.8f} {currency} {from_exchange} -> {to_exchange} ({transaction_id})")
59
48
  return transaction_id
60
49
 
61
50
  def get_transfer_status(self, transaction_id: str) -> Transfer:
@@ -1,5 +1,5 @@
1
1
  from collections.abc import Mapping, Sequence
2
- from dataclasses import dataclass, field
2
+ from dataclasses import dataclass
3
3
  from enum import Enum
4
4
  from typing import Any, Callable, TypeAlias
5
5
 
@@ -8,8 +8,6 @@ import pandas as pd
8
8
 
9
9
  from qubx import logger
10
10
  from qubx.core.basics import (
11
- STABLE_CURRENCIES,
12
- Balance,
13
11
  CtrlChannel,
14
12
  DataType,
15
13
  Instrument,
@@ -82,20 +80,6 @@ def _type(obj: Any) -> SetupTypes:
82
80
  return t
83
81
 
84
82
 
85
- def _settle_currencies(instruments: list[Instrument], exchange: str) -> set[str]:
86
- return {i.settle.upper() for i in instruments if i.exchange == exchange and i.settle}
87
-
88
-
89
- def _derive_settle_currency(instruments: list[Instrument], exchange: str) -> str | None:
90
- """The one settle currency a venue's instruments agree on, or None when absent, mixed, or
91
- not a recognized stable — BINANCE.UM:ETHBTC settles in BTC, and BTC is not 1.0 of capital."""
92
- settles = _settle_currencies(instruments, exchange)
93
- if len(settles) != 1:
94
- return None
95
- settle = settles.pop()
96
- return settle if settle in STABLE_CURRENCIES else None
97
-
98
-
99
83
  @dataclass
100
84
  class SimulationSetup:
101
85
  """
@@ -109,37 +93,16 @@ class SimulationSetup:
109
93
  instruments: list[Instrument]
110
94
  exchanges: list[str]
111
95
  capital: float | dict[str, float]
112
- base_currency: str | dict[str, str]
96
+ base_currency: str
113
97
  commissions: str | dict[str, str | None] | None = None
114
98
  signal_timeframe: str = "1Min"
115
99
  accurate_stop_orders_execution: bool = False
116
100
  enable_funding: bool = False
117
- base_currencies: dict[str, str] = field(init=False, default_factory=dict)
118
101
 
119
102
  def __post_init__(self) -> None:
120
- # Per-exchange base currency: explicit mapping wins, else the venue's shared settle
121
- # currency, else the scalar. AccountState upper-cases, so normalize here or the seeded
122
- # Balance lands under a key total_capital never reads.
123
- explicit = (
124
- {ex: ccy.upper() for ex, ccy in self.base_currency.items()}
125
- if isinstance(self.base_currency, dict)
126
- else {}
127
- )
128
- default_ccy = (
129
- self.base_currency.upper()
130
- if isinstance(self.base_currency, str)
131
- else (explicit.get(self.exchanges[0], "USDT") if self.exchanges else "USDT")
132
- )
133
- self.base_currencies = {}
134
- for ex in self.exchanges:
135
- resolved = explicit.get(ex) or _derive_settle_currency(self.instruments, ex)
136
- if resolved is None and (settles := _settle_currencies(self.instruments, ex)):
137
- logger.debug(
138
- f"No single stable settle currency for {ex} (saw {sorted(settles)}) "
139
- f"- using {default_ccy} as its base currency"
140
- )
141
- self.base_currencies[ex] = resolved or default_ccy
142
- self.base_currency = self.base_currencies[self.exchanges[0]] if self.exchanges else default_ccy
103
+ # Normalize once at the config boundary: AccountState stores base_currency upper-cased,
104
+ # so a lowercase value here would seed capital under a key total_capital never reads.
105
+ self.base_currency = self.base_currency.upper()
143
106
  # Normalize capital to a per-exchange dict: split evenly when a single float is given
144
107
  if isinstance(self.capital, (int, float)):
145
108
  n = len(self.exchanges)
@@ -150,21 +113,6 @@ class SimulationSetup:
150
113
  return f"{self.name} {self.setup_type} capital {self.capital} {self.base_currency} for [{','.join(map(lambda x: x.symbol, self.instruments))}] @ {self.exchanges}[{self.commissions}]"
151
114
 
152
115
 
153
- def initial_balances(setup: SimulationSetup) -> dict[str, Balance]:
154
- """Startup balance per exchange, each in that venue's own base currency."""
155
- assert isinstance(setup.capital, dict)
156
- return {
157
- exchange: Balance(
158
- exchange=exchange,
159
- currency=setup.base_currencies[exchange],
160
- total=capital,
161
- free=capital,
162
- locked=0.0,
163
- )
164
- for exchange, capital in setup.capital.items()
165
- }
166
-
167
-
168
116
  # fmt: off
169
117
  @dataclass
170
118
  class SimulationDataConfig:
@@ -339,9 +287,7 @@ def find_instruments_and_exchanges(
339
287
  _instrs.append(instrument)
340
288
  _exchanges.append(resolved_exchange)
341
289
 
342
- # sorted, not list(set(...)): string hashing is per-process randomized, and exchanges[0]
343
- # decides the persisted scalar base_currency of a multi-venue run.
344
- return _instrs, sorted(set(_exchanges))
290
+ return _instrs, list(set(_exchanges))
345
291
 
346
292
 
347
293
  class _StructureSniffer:
@@ -399,7 +345,7 @@ def recognize_simulation_configuration(
399
345
  instruments: list[Instrument],
400
346
  exchanges: list[str],
401
347
  capital: float | dict[str, float],
402
- basic_currency: str | dict[str, str],
348
+ basic_currency: str,
403
349
  commissions: str | dict[str, str | None] | None,
404
350
  signal_timeframe: str,
405
351
  accurate_stop_orders_execution: bool,
@@ -694,16 +640,7 @@ def recognize_simulation_data_config(
694
640
  )
695
641
 
696
642
 
697
- _TRANSFERS_LOG_COLUMNS = [
698
- "transaction_id",
699
- "from_exchange",
700
- "to_exchange",
701
- "currency",
702
- "amount",
703
- "status",
704
- "to_currency",
705
- "to_amount",
706
- ]
643
+ _TRANSFERS_LOG_COLUMNS = ["transaction_id", "from_exchange", "to_exchange", "currency", "amount", "status"]
707
644
 
708
645
 
709
646
  def collect_transfers_log(transfer_manager: ITransferManager | None) -> pd.DataFrame | None:
@@ -730,8 +667,6 @@ def collect_transfers_log(transfer_manager: ITransferManager | None) -> pd.DataF
730
667
  "currency": t.currency,
731
668
  "amount": t.amount,
732
669
  "status": str(t.status),
733
- "to_currency": t.to_currency or t.currency,
734
- "to_amount": t.to_amount if t.to_amount is not None else t.amount,
735
670
  }
736
671
  for t in transfers
737
672
  ]