Qubx 0.6.38__tar.gz → 0.6.40__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 (163) hide show
  1. {qubx-0.6.38 → qubx-0.6.40}/PKG-INFO +1 -1
  2. {qubx-0.6.38 → qubx-0.6.40}/pyproject.toml +1 -1
  3. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/cli/deploy.py +27 -3
  4. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/metrics.py +1 -1
  5. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/runner/configs.py +2 -1
  6. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/runner/factory.py +6 -6
  7. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/runner/runner.py +10 -19
  8. {qubx-0.6.38 → qubx-0.6.40}/LICENSE +0 -0
  9. {qubx-0.6.38 → qubx-0.6.40}/README.md +0 -0
  10. {qubx-0.6.38 → qubx-0.6.40}/build.py +0 -0
  11. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/__init__.py +0 -0
  12. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/_nb_magic.py +0 -0
  13. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/__init__.py +0 -0
  14. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/account.py +0 -0
  15. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/broker.py +0 -0
  16. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/data.py +0 -0
  17. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/management.py +0 -0
  18. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/ome.py +0 -0
  19. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/optimization.py +0 -0
  20. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/runner.py +0 -0
  21. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/simulated_data.py +0 -0
  22. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/simulated_exchange.py +0 -0
  23. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/simulator.py +0 -0
  24. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/backtester/utils.py +0 -0
  25. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/cli/__init__.py +0 -0
  26. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/cli/commands.py +0 -0
  27. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/cli/misc.py +0 -0
  28. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/cli/release.py +0 -0
  29. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/__init__.py +0 -0
  30. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/account.py +0 -0
  31. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/broker.py +0 -0
  32. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/data.py +0 -0
  33. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exceptions.py +0 -0
  34. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
  35. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
  36. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
  37. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
  38. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
  39. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
  40. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/factory.py +0 -0
  41. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/reader.py +0 -0
  42. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/ccxt/utils.py +0 -0
  43. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/tardis/data.py +0 -0
  44. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/connectors/tardis/utils.py +0 -0
  45. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/__init__.py +0 -0
  46. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/account.py +0 -0
  47. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/basics.py +0 -0
  48. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/context.py +0 -0
  49. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/deque.py +0 -0
  50. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/errors.py +0 -0
  51. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/exceptions.py +0 -0
  52. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/helpers.py +0 -0
  53. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/initializer.py +0 -0
  54. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/interfaces.py +0 -0
  55. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/loggers.py +0 -0
  56. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/lookups.py +0 -0
  57. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/mixins/__init__.py +0 -0
  58. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/mixins/market.py +0 -0
  59. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/mixins/processing.py +0 -0
  60. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/mixins/subscription.py +0 -0
  61. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/mixins/trading.py +0 -0
  62. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/mixins/universe.py +0 -0
  63. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/series.pxd +0 -0
  64. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/series.pyi +0 -0
  65. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/series.pyx +0 -0
  66. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/utils.pyi +0 -0
  67. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/core/utils.pyx +0 -0
  68. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/__init__.py +0 -0
  69. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/composite.py +0 -0
  70. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/helpers.py +0 -0
  71. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/hft.py +0 -0
  72. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/readers.py +0 -0
  73. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/registry.py +0 -0
  74. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/data/tardis.py +0 -0
  75. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/emitters/__init__.py +0 -0
  76. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/emitters/base.py +0 -0
  77. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/emitters/composite.py +0 -0
  78. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/emitters/csv.py +0 -0
  79. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/emitters/prometheus.py +0 -0
  80. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/emitters/questdb.py +0 -0
  81. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/__init__.py +0 -0
  82. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/composite.py +0 -0
  83. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/formatters/__init__.py +0 -0
  84. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/formatters/base.py +0 -0
  85. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/formatters/incremental.py +0 -0
  86. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/formatters/slack.py +0 -0
  87. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/redis_streams.py +0 -0
  88. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/exporters/slack.py +0 -0
  89. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/features/__init__.py +0 -0
  90. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/features/core.py +0 -0
  91. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/features/orderbook.py +0 -0
  92. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/features/price.py +0 -0
  93. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/features/trades.py +0 -0
  94. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/features/utils.py +0 -0
  95. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/gathering/simplest.py +0 -0
  96. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/health/__init__.py +0 -0
  97. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/health/base.py +0 -0
  98. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/loggers/__init__.py +0 -0
  99. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/loggers/csv.py +0 -0
  100. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/loggers/factory.py +0 -0
  101. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/loggers/inmemory.py +0 -0
  102. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/loggers/mongo.py +0 -0
  103. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/math/__init__.py +0 -0
  104. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/math/stats.py +0 -0
  105. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/notifications/__init__.py +0 -0
  106. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/notifications/composite.py +0 -0
  107. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/notifications/slack.py +0 -0
  108. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/pandaz/__init__.py +0 -0
  109. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/pandaz/ta.py +0 -0
  110. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/pandaz/utils.py +0 -0
  111. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/_build.py +0 -0
  112. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-binance.cm.json +0 -0
  113. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-binance.json +0 -0
  114. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-binance.um.json +0 -0
  115. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-bitfinex.f.json +0 -0
  116. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-bitfinex.json +0 -0
  117. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-kraken.f.json +0 -0
  118. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/resources/instruments/symbols-kraken.json +0 -0
  119. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restarts/__init__.py +0 -0
  120. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restarts/state_resolvers.py +0 -0
  121. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restarts/time_finders.py +0 -0
  122. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/__init__.py +0 -0
  123. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/balance.py +0 -0
  124. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/factory.py +0 -0
  125. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/interfaces.py +0 -0
  126. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/position.py +0 -0
  127. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/signal.py +0 -0
  128. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/state.py +0 -0
  129. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/restorers/utils.py +0 -0
  130. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/ta/__init__.py +0 -0
  131. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/ta/indicators.pxd +0 -0
  132. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/ta/indicators.pyi +0 -0
  133. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/ta/indicators.pyx +0 -0
  134. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/trackers/__init__.py +0 -0
  135. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/trackers/advanced.py +0 -0
  136. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/trackers/composite.py +0 -0
  137. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/trackers/rebalancers.py +0 -0
  138. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/trackers/riskctrl.py +0 -0
  139. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/trackers/sizers.py +0 -0
  140. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/__init__.py +0 -0
  141. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/_pyxreloader.py +0 -0
  142. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/charting/lookinglass.py +0 -0
  143. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  144. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/collections.py +0 -0
  145. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/marketdata/binance.py +0 -0
  146. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/marketdata/ccxt.py +0 -0
  147. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/marketdata/dukas.py +0 -0
  148. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/misc.py +0 -0
  149. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/ntp.py +0 -0
  150. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/numbers_utils.py +0 -0
  151. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/orderbook.py +0 -0
  152. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/plotting/__init__.py +0 -0
  153. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/plotting/dashboard.py +0 -0
  154. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/plotting/data.py +0 -0
  155. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/plotting/interfaces.py +0 -0
  156. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
  157. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
  158. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/questdb.py +0 -0
  159. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/runner/__init__.py +0 -0
  160. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
  161. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/runner/accounts.py +0 -0
  162. {qubx-0.6.38 → qubx-0.6.40}/src/qubx/utils/time.py +0 -0
  163. {qubx-0.6.38 → qubx-0.6.40}/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.38
3
+ Version: 0.6.40
4
4
  Summary: Qubx - Quantitative Trading Framework
5
5
  Author: Dmitry Marienko
6
6
  Author-email: dmitry.marienko@xlydian.com
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "Qubx"
7
- version = "0.6.38"
7
+ version = "0.6.40"
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"
@@ -182,6 +182,29 @@ def setup_poetry_environment(output_dir: str) -> bool:
182
182
  return False
183
183
 
184
184
 
185
+ def create_strategy_runners(output_dir: str):
186
+ """
187
+ Creates a strategy runner script in the output_dir
188
+ """
189
+ import sys
190
+
191
+ if sys.platform == "win32":
192
+ _pfx = ""
193
+ _f_name = os.path.join(output_dir, "run_paper.bat")
194
+ else:
195
+ _pfx = "#!/bin/bash\n"
196
+ _f_name = os.path.join(output_dir, "run_paper.sh")
197
+
198
+ logger.info(f"Creating strategy paper runner script: {_f_name}")
199
+
200
+ try:
201
+ with open(_f_name, "w") as f:
202
+ f.write(f"{_pfx}poetry run qubx run config.yml --paper -j")
203
+ os.chmod(_f_name, 0o755)
204
+ except Exception as e:
205
+ logger.error(f"Failed to create strategy paper runner script: {e}")
206
+
207
+
185
208
  def deploy_strategy(zip_file: str, output_dir: str | None, force: bool) -> bool:
186
209
  """
187
210
  Deploys a strategy from a zip file created by the release command.
@@ -222,9 +245,10 @@ def deploy_strategy(zip_file: str, output_dir: str | None, force: bool) -> bool:
222
245
  if not setup_poetry_environment(resolved_output_dir):
223
246
  return False
224
247
 
248
+ # Create the strategy runners
249
+ create_strategy_runners(resolved_output_dir)
250
+
225
251
  # Success messages
226
252
  logger.info(f"Strategy deployed successfully to {resolved_output_dir}")
227
- logger.info(
228
- f"To run the strategy (paper mode): <cyan>cd {resolved_output_dir} && poetry run qubx run config.yml --paper</cyan>"
229
- )
253
+ logger.info(f" -> To run the strategy (in paper mode): <cyan>cd {resolved_output_dir} && ./run_paper.sh</cyan>")
230
254
  return True
@@ -884,7 +884,7 @@ class TradingSessionResult:
884
884
  _perf = info.pop("performance", None)
885
885
  info["instruments"] = info.pop("symbols")
886
886
  # - fix for old versions
887
- _exch = info.pop("exchange")
887
+ _exch = info.pop("exchange") if "exchange" in info else info.pop("exchanges")
888
888
  info["exchanges"] = _exch if isinstance(_exch, list) else [_exch]
889
889
  tsr = TradingSessionResult(**info, portfolio_log=portfolio, executions_log=executions, signals_log=signals)
890
890
  tsr.qubx_version = _qbx_version
@@ -121,7 +121,8 @@ def load_strategy_config_from_yaml(path: Path | str, key: str | None = None) ->
121
121
  class StrategySimulationConfig(BaseModel):
122
122
  strategy: str | list[str]
123
123
  parameters: dict = Field(default_factory=dict)
124
- data: dict = Field(default_factory=dict)
124
+ data: list[TypedReaderConfig] = Field(default_factory=list)
125
+ aux: ReaderConfig | None = None
125
126
  simulation: dict = Field(default_factory=dict)
126
127
  description: str | list[str] | None = None
127
128
  variate: dict = Field(default_factory=dict)
@@ -12,7 +12,7 @@ from qubx.data.composite import CompositeReader
12
12
  from qubx.data.readers import DataReader
13
13
  from qubx.emitters.composite import CompositeMetricEmitter
14
14
  from qubx.utils.misc import class_import
15
- from qubx.utils.runner.configs import EmissionConfig, ExporterConfig, NotifierConfig, ReaderConfig, WarmupConfig
15
+ from qubx.utils.runner.configs import EmissionConfig, ExporterConfig, NotifierConfig, ReaderConfig, TypedReaderConfig
16
16
 
17
17
 
18
18
  def resolve_env_vars(value: str | Any) -> str | Any:
@@ -118,27 +118,27 @@ def create_metric_emitters(emission_config: EmissionConfig, strategy_name: str)
118
118
  return CompositeMetricEmitter(emitters, stats_interval=stats_interval)
119
119
 
120
120
 
121
- def create_data_type_readers(warmup: WarmupConfig | None) -> dict[str, DataReader]:
121
+ def create_data_type_readers(readers_configs: list[TypedReaderConfig] | None) -> dict[str, DataReader]:
122
122
  """
123
- Create a dictionary mapping data types to readers based on the warmup configuration.
123
+ Create a dictionary mapping data types to readers based on the readers list.
124
124
 
125
125
  This function ensures that identical reader configurations are only instantiated once,
126
126
  and multiple data types can share the same reader instance if they have identical configurations.
127
127
 
128
128
  Args:
129
- warmup: The warmup configuration containing reader definitions.
129
+ readers_configs: The readers list containing reader definitions.
130
130
 
131
131
  Returns:
132
132
  A dictionary mapping data types to reader instances.
133
133
  """
134
- if warmup is None:
134
+ if readers_configs is None:
135
135
  return {}
136
136
 
137
137
  # First, create unique readers to avoid duplicate instantiation
138
138
  unique_readers = {} # Maps reader config hash to reader instance
139
139
  data_type_to_reader = {} # Maps data type to reader instance
140
140
 
141
- for typed_reader_config in warmup.readers:
141
+ for typed_reader_config in readers_configs:
142
142
  data_types = typed_reader_config.data_type
143
143
  if isinstance(data_types, str):
144
144
  data_types = [data_types]
@@ -49,7 +49,7 @@ from qubx.loggers import create_logs_writer
49
49
  from qubx.restarts.state_resolvers import StateResolver
50
50
  from qubx.restarts.time_finders import TimeFinder
51
51
  from qubx.restorers import create_state_restorer
52
- from qubx.utils.misc import class_import, makedirs, red
52
+ from qubx.utils.misc import class_import, green, makedirs, red
53
53
  from qubx.utils.runner.configs import (
54
54
  ExchangeConfig,
55
55
  LoggingConfig,
@@ -533,9 +533,7 @@ def _create_broker(
533
533
  secret=creds.secret,
534
534
  enable_mm=_enable_mm,
535
535
  )
536
- return get_ccxt_broker(
537
- exchange_name, exchange, channel, time_provider, account, data_provider, **params
538
- )
536
+ return get_ccxt_broker(exchange_name, exchange, channel, time_provider, account, data_provider, **params)
539
537
  case "paper":
540
538
  assert isinstance(account, SimulatedAccountProcessor)
541
539
  return SimulatedBroker(channel=channel, account=account, simulated_exchange=account._exchange)
@@ -597,7 +595,7 @@ def _run_warmup(
597
595
  logger.info(f"<yellow>Warmup start time: {warmup_start_time}</yellow>")
598
596
 
599
597
  # - construct warmup readers
600
- data_type_to_reader = create_data_type_readers(warmup)
598
+ data_type_to_reader = create_data_type_readers(warmup.readers) if warmup else {}
601
599
 
602
600
  if not data_type_to_reader:
603
601
  logger.warning("<yellow>No readers were created for warmup</yellow>")
@@ -745,10 +743,8 @@ def simulate_strategy(
745
743
  experiments = {simulation_name: strategy}
746
744
  _n_jobs = 1
747
745
 
748
- data_i = {}
749
-
750
- for k, v in cfg.data.items():
751
- data_i[k] = eval(v)
746
+ # - resolve data readers
747
+ data_i = create_data_type_readers(cfg.data) if cfg.data else {}
752
748
 
753
749
  sim_params = cfg.simulation
754
750
  for mp in ["instruments", "capital", "commissions", "start", "stop"]:
@@ -764,18 +760,13 @@ def simulate_strategy(
764
760
  logger.info(f"Stop date set to {stop}")
765
761
 
766
762
  # - check for aux_data parameter
767
- if "aux_data" in sim_params:
768
- aux_data = sim_params.pop("aux_data")
769
- if aux_data is not None:
770
- try:
771
- sim_params["aux_data"] = eval(aux_data)
772
- except Exception as e:
773
- raise ValueError(f"Invalid aux_data parameter: {aux_data}") from e
763
+ if cfg.aux is not None:
764
+ sim_params["aux_data"] = construct_reader(cfg.aux)
774
765
 
775
766
  # - run simulation
776
767
  print(f" > Run simulation for [{red(simulation_name)}] ::: {sim_params['start']} - {sim_params['stop']}")
777
768
  sim_params["n_jobs"] = sim_params.get("n_jobs", _n_jobs)
778
- test_res = simulate(experiments, data=data_i, **sim_params)
769
+ test_res = simulate(experiments, data=data_i, **sim_params) # type: ignore
779
770
 
780
771
  _where_to_save = save_path if save_path is not None else Path("results/")
781
772
  s_path = Path(makedirs(str(_where_to_save))) / simulation_name
@@ -791,13 +782,13 @@ def simulate_strategy(
791
782
  if len(test_res) > 1:
792
783
  # - TODO: think how to deal with variations !
793
784
  s_path = s_path / f"variations.{_v_id}"
794
- print(f" > Saving variations results to <g>{s_path}</g> ...")
785
+ print(f" > Saving variations results to {green(s_path)} ...")
795
786
  for k, t in enumerate(test_res):
796
787
  # - set variation name
797
788
  t.variation_name = f"{simulation_name}.{_v_id}"
798
789
  t.to_file(str(s_path), description=_descr, suffix=f".{k}", attachments=[str(config_file)])
799
790
  else:
800
- print(f" > Saving simulation results to <g>{s_path}</g> ...")
791
+ print(f" > Saving simulation results to {green(s_path)} ...")
801
792
  test_res[0].to_file(str(s_path), description=_descr, attachments=[str(config_file)])
802
793
 
803
794
  return test_res
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes