Qubx 0.6.41__tar.gz → 0.6.43__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 (164) hide show
  1. {qubx-0.6.41 → qubx-0.6.43}/PKG-INFO +1 -1
  2. {qubx-0.6.41 → qubx-0.6.43}/pyproject.toml +1 -1
  3. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/mixins/universe.py +2 -0
  4. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/formatters/incremental.py +10 -1
  5. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/redis_streams.py +6 -0
  6. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/pandaz/ta.py +15 -2
  7. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/runner/factory.py +12 -3
  8. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/runner/runner.py +3 -3
  9. {qubx-0.6.41 → qubx-0.6.43}/LICENSE +0 -0
  10. {qubx-0.6.41 → qubx-0.6.43}/README.md +0 -0
  11. {qubx-0.6.41 → qubx-0.6.43}/build.py +0 -0
  12. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/__init__.py +0 -0
  13. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/_nb_magic.py +0 -0
  14. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/__init__.py +0 -0
  15. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/account.py +0 -0
  16. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/broker.py +0 -0
  17. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/data.py +0 -0
  18. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/management.py +0 -0
  19. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/ome.py +0 -0
  20. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/optimization.py +0 -0
  21. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/runner.py +0 -0
  22. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/simulated_data.py +0 -0
  23. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/simulated_exchange.py +0 -0
  24. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/simulator.py +0 -0
  25. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/backtester/utils.py +0 -0
  26. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/cli/__init__.py +0 -0
  27. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/cli/commands.py +0 -0
  28. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/cli/deploy.py +0 -0
  29. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/cli/misc.py +0 -0
  30. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/cli/release.py +0 -0
  31. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/__init__.py +0 -0
  32. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/account.py +0 -0
  33. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/broker.py +0 -0
  34. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/data.py +0 -0
  35. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exceptions.py +0 -0
  36. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
  37. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
  38. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
  39. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
  40. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
  41. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
  42. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/factory.py +0 -0
  43. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/reader.py +0 -0
  44. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/ccxt/utils.py +0 -0
  45. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/tardis/data.py +0 -0
  46. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/connectors/tardis/utils.py +0 -0
  47. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/__init__.py +0 -0
  48. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/account.py +0 -0
  49. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/basics.py +0 -0
  50. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/context.py +0 -0
  51. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/deque.py +0 -0
  52. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/errors.py +0 -0
  53. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/exceptions.py +0 -0
  54. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/helpers.py +0 -0
  55. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/initializer.py +0 -0
  56. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/interfaces.py +0 -0
  57. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/loggers.py +0 -0
  58. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/lookups.py +0 -0
  59. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/metrics.py +0 -0
  60. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/mixins/__init__.py +0 -0
  61. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/mixins/market.py +0 -0
  62. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/mixins/processing.py +0 -0
  63. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/mixins/subscription.py +0 -0
  64. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/mixins/trading.py +0 -0
  65. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/series.pxd +0 -0
  66. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/series.pyi +0 -0
  67. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/series.pyx +0 -0
  68. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/utils.pyi +0 -0
  69. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/core/utils.pyx +0 -0
  70. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/__init__.py +0 -0
  71. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/composite.py +0 -0
  72. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/helpers.py +0 -0
  73. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/hft.py +0 -0
  74. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/readers.py +0 -0
  75. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/registry.py +0 -0
  76. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/data/tardis.py +0 -0
  77. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/emitters/__init__.py +0 -0
  78. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/emitters/base.py +0 -0
  79. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/emitters/composite.py +0 -0
  80. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/emitters/csv.py +0 -0
  81. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/emitters/prometheus.py +0 -0
  82. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/emitters/questdb.py +0 -0
  83. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/__init__.py +0 -0
  84. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/composite.py +0 -0
  85. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/formatters/__init__.py +0 -0
  86. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/formatters/base.py +0 -0
  87. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/formatters/slack.py +0 -0
  88. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/exporters/slack.py +0 -0
  89. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/features/__init__.py +0 -0
  90. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/features/core.py +0 -0
  91. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/features/orderbook.py +0 -0
  92. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/features/price.py +0 -0
  93. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/features/trades.py +0 -0
  94. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/features/utils.py +0 -0
  95. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/gathering/simplest.py +0 -0
  96. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/health/__init__.py +0 -0
  97. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/health/base.py +0 -0
  98. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/loggers/__init__.py +0 -0
  99. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/loggers/csv.py +0 -0
  100. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/loggers/factory.py +0 -0
  101. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/loggers/inmemory.py +0 -0
  102. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/loggers/mongo.py +0 -0
  103. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/math/__init__.py +0 -0
  104. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/math/stats.py +0 -0
  105. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/notifications/__init__.py +0 -0
  106. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/notifications/composite.py +0 -0
  107. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/notifications/slack.py +0 -0
  108. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/notifications/throttler.py +0 -0
  109. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/pandaz/__init__.py +0 -0
  110. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/pandaz/utils.py +0 -0
  111. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/_build.py +0 -0
  112. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-binance.cm.json +0 -0
  113. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-binance.json +0 -0
  114. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-binance.um.json +0 -0
  115. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-bitfinex.f.json +0 -0
  116. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-bitfinex.json +0 -0
  117. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-kraken.f.json +0 -0
  118. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/resources/instruments/symbols-kraken.json +0 -0
  119. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restarts/__init__.py +0 -0
  120. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restarts/state_resolvers.py +0 -0
  121. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restarts/time_finders.py +0 -0
  122. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/__init__.py +0 -0
  123. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/balance.py +0 -0
  124. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/factory.py +0 -0
  125. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/interfaces.py +0 -0
  126. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/position.py +0 -0
  127. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/signal.py +0 -0
  128. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/state.py +0 -0
  129. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/restorers/utils.py +0 -0
  130. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/ta/__init__.py +0 -0
  131. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/ta/indicators.pxd +0 -0
  132. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/ta/indicators.pyi +0 -0
  133. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/ta/indicators.pyx +0 -0
  134. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/trackers/__init__.py +0 -0
  135. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/trackers/advanced.py +0 -0
  136. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/trackers/composite.py +0 -0
  137. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/trackers/rebalancers.py +0 -0
  138. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/trackers/riskctrl.py +0 -0
  139. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/trackers/sizers.py +0 -0
  140. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/__init__.py +0 -0
  141. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/_pyxreloader.py +0 -0
  142. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/charting/lookinglass.py +0 -0
  143. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  144. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/collections.py +0 -0
  145. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/marketdata/binance.py +0 -0
  146. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/marketdata/ccxt.py +0 -0
  147. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/marketdata/dukas.py +0 -0
  148. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/misc.py +0 -0
  149. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/ntp.py +0 -0
  150. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/numbers_utils.py +0 -0
  151. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/orderbook.py +0 -0
  152. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/plotting/__init__.py +0 -0
  153. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/plotting/dashboard.py +0 -0
  154. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/plotting/data.py +0 -0
  155. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/plotting/interfaces.py +0 -0
  156. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
  157. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
  158. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/questdb.py +0 -0
  159. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/runner/__init__.py +0 -0
  160. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
  161. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/runner/accounts.py +0 -0
  162. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/runner/configs.py +0 -0
  163. {qubx-0.6.41 → qubx-0.6.43}/src/qubx/utils/time.py +0 -0
  164. {qubx-0.6.41 → qubx-0.6.43}/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.41
3
+ Version: 0.6.43
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.41"
7
+ version = "0.6.43"
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"
@@ -109,6 +109,8 @@ class UniverseManager(IUniverseManager):
109
109
  if self._has_position(instr):
110
110
  self._removal_queue[instr] = (if_has_position_then, skip_callback)
111
111
  to_keep.append(instr)
112
+ else:
113
+ to_remove.append(instr)
112
114
  return to_remove, to_keep
113
115
 
114
116
  def __cleanup_removal_queue(self, instruments: list[Instrument]):
@@ -13,7 +13,12 @@ class IncrementalFormatter(DefaultFormatter):
13
13
  based on leverage changes.
14
14
  """
15
15
 
16
- def __init__(self, alert_name: str, exchange_mapping: Optional[Dict[str, str]] = None):
16
+ def __init__(
17
+ self,
18
+ alert_name: str,
19
+ exchange_mapping: Optional[Dict[str, str]] = None,
20
+ account: Optional[IAccountViewer] = None
21
+ ):
17
22
  """
18
23
  Initialize the IncrementalFormatter.
19
24
 
@@ -21,12 +26,16 @@ class IncrementalFormatter(DefaultFormatter):
21
26
  alert_name: The name of the alert to include in the messages
22
27
  exchange_mapping: Optional mapping of exchange names to use in messages.
23
28
  If an exchange is not in the mapping, the instrument's exchange is used.
29
+ account: The account viewer to get account information like total capital, leverage, etc.
24
30
  """
25
31
  super().__init__()
26
32
  self.alert_name = alert_name
27
33
  self.exchange_mapping = exchange_mapping or {}
28
34
  self.instrument_leverages: Dict[Instrument, float] = {}
29
35
 
36
+ if account:
37
+ self.instrument_leverages = dict(account.get_leverages())
38
+
30
39
  def format_position_change(
31
40
  self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
32
41
  ) -> dict[str, Any]:
@@ -36,6 +36,7 @@ class RedisStreamsExporter(ITradeDataExport):
36
36
  max_stream_length: int = 1000,
37
37
  formatter: Optional[IExportFormatter] = None,
38
38
  max_workers: int = 2,
39
+ account: Optional[IAccountViewer] = None,
39
40
  ):
40
41
  """
41
42
  Initialize the Redis Streams Exporter.
@@ -52,6 +53,7 @@ class RedisStreamsExporter(ITradeDataExport):
52
53
  max_stream_length: Maximum length of each stream
53
54
  formatter: Formatter to use for formatting data (default: DefaultFormatter)
54
55
  max_workers: Maximum number of worker threads for Redis operations
56
+ account: Optional account viewer to get account information like total capital, leverage, etc.
55
57
  """
56
58
  self._redis = redis.from_url(redis_url)
57
59
  self._strategy_name = strategy_name
@@ -71,6 +73,9 @@ class RedisStreamsExporter(ITradeDataExport):
71
73
 
72
74
  self._executor = ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="redis_exporter")
73
75
 
76
+ if account:
77
+ self._instrument_to_previous_leverage = dict(account.get_leverages())
78
+
74
79
  logger.info(
75
80
  f"[RedisStreamsExporter] Initialized for strategy '{strategy_name}' with "
76
81
  f"signals: {export_signals}, targets: {export_targets}, position_changes: {export_position_changes}"
@@ -201,6 +206,7 @@ class RedisStreamsExporter(ITradeDataExport):
201
206
 
202
207
  previous_leverage = self._instrument_to_previous_leverage.get(instrument, 0.0)
203
208
  new_leverage = account.get_leverage(instrument)
209
+ self._instrument_to_previous_leverage[instrument] = new_leverage
204
210
 
205
211
  try:
206
212
  # Format the leverage change using the formatter
@@ -633,6 +633,17 @@ def rolling_std_with_mean(x: pd.Series, mean: float | pd.Series, window: int):
633
633
  return np.sqrt((((x - mean) ** 2).rolling(window=window).sum() / (window - 1)))
634
634
 
635
635
 
636
+ def rolling_zscore(x: pd.Series, window: int):
637
+ """
638
+ Calculates rolling z-score for data from x
639
+ :param x: series data
640
+ :param window: window
641
+ :return: rolling z-score
642
+ """
643
+ r = x.rolling(window=window)
644
+ return (x - r.mean()) / r.std(ddof=0)
645
+
646
+
636
647
  def bollinger(x: pd.Series, window=14, nstd=2, mean="sma") -> pd.DataFrame:
637
648
  """
638
649
  Bollinger Bands indicator
@@ -1532,6 +1543,7 @@ def choppiness(
1532
1543
  volatility_estimator="t",
1533
1544
  volume_adjusting=False,
1534
1545
  identification="strong",
1546
+ with_raw_indicator=False,
1535
1547
  ) -> pd.Series:
1536
1548
  """
1537
1549
  Calculate market choppiness index using volatility-based formula.
@@ -1566,7 +1578,8 @@ def choppiness(
1566
1578
  0 when exiting trending regime (crossing above lower threshold)
1567
1579
  - 'weak': Binary classification focused on choppiness - returns 1 when entering choppy regime (crossing above upper threshold),
1568
1580
  0 when entering trending regime (crossing below lower threshold)
1569
-
1581
+ with_raw_indicator : bool, default False
1582
+ If True, returns the raw indicator value instead of the classification
1570
1583
  Returns
1571
1584
  -------
1572
1585
  pd.Series
@@ -1619,7 +1632,7 @@ def choppiness(
1619
1632
  # f0[(ci < lower) & (ci.shift(1) >= lower)] = 0
1620
1633
  # return f0.ffill().fillna(0)
1621
1634
 
1622
- return f0.ffill().fillna(0)
1635
+ return f0.ffill().fillna(0) if not with_raw_indicator else ci
1623
1636
 
1624
1637
 
1625
1638
  @njit
@@ -4,10 +4,10 @@ Factory functions for creating various components used in strategy running and s
4
4
 
5
5
  import inspect
6
6
  import os
7
- from typing import Any
7
+ from typing import Any, Optional
8
8
 
9
9
  from qubx import logger
10
- from qubx.core.interfaces import IMetricEmitter, IStrategyLifecycleNotifier, ITradeDataExport
10
+ from qubx.core.interfaces import IAccountViewer, IMetricEmitter, IStrategyLifecycleNotifier, ITradeDataExport
11
11
  from qubx.data.composite import CompositeReader
12
12
  from qubx.data.readers import DataReader
13
13
  from qubx.emitters.composite import CompositeMetricEmitter
@@ -180,7 +180,11 @@ def create_data_type_readers(readers_configs: list[TypedReaderConfig] | None) ->
180
180
  return data_type_to_reader
181
181
 
182
182
 
183
- def create_exporters(exporters: list[ExporterConfig] | None, strategy_name: str) -> ITradeDataExport | None:
183
+ def create_exporters(
184
+ exporters: list[ExporterConfig] | None,
185
+ strategy_name: str,
186
+ account: Optional[IAccountViewer] = None,
187
+ ) -> ITradeDataExport | None:
184
188
  """
185
189
  Create exporters from the configuration.
186
190
 
@@ -218,6 +222,9 @@ def create_exporters(exporters: list[ExporterConfig] | None, strategy_name: str)
218
222
  for fmt_key, fmt_value in formatter_args.items():
219
223
  formatter_args[fmt_key] = resolve_env_vars(fmt_value)
220
224
 
225
+ if account and "account" not in formatter_args:
226
+ formatter_args["account"] = account
227
+
221
228
  if formatter_class_name:
222
229
  if "." not in formatter_class_name:
223
230
  formatter_class_name = f"qubx.exporters.formatters.{formatter_class_name}"
@@ -229,6 +236,8 @@ def create_exporters(exporters: list[ExporterConfig] | None, strategy_name: str)
229
236
  # Add strategy_name if the exporter requires it and it's not already provided
230
237
  if "strategy_name" in inspect.signature(exporter_class).parameters and "strategy_name" not in params:
231
238
  params["strategy_name"] = strategy_name
239
+ if account and "account" not in params:
240
+ params["account"] = account
232
241
 
233
242
  # Create the exporter instance
234
243
  exporter = exporter_class(**params)
@@ -261,9 +261,6 @@ def create_strategy_context(
261
261
 
262
262
  _aux_reader = construct_reader(config.aux) if config.aux else None
263
263
 
264
- # Create exporters if configured
265
- _exporter = create_exporters(config.exporters, stg_name)
266
-
267
264
  # Create metric emitters
268
265
  _metric_emitter = create_metric_emitters(config.emission, stg_name) if config.emission else None
269
266
 
@@ -335,6 +332,9 @@ def create_strategy_context(
335
332
  )
336
333
  _initializer = BasicStrategyInitializer(simulation=_exchange_to_data_provider[exchanges[0]].is_simulation)
337
334
 
335
+ # Create exporters if configured
336
+ _exporter = create_exporters(config.exporters, stg_name, _account)
337
+
338
338
  logger.info(f"- Strategy: <blue>{stg_name}</blue>\n- Mode: {_run_mode}\n- Parameters: {config.parameters}")
339
339
  ctx = StrategyContext(
340
340
  strategy=_strategy_class, # type: ignore
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
File without changes