Qubx 0.6.56__tar.gz → 0.6.57__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 (170) hide show
  1. {qubx-0.6.56 → qubx-0.6.57}/PKG-INFO +1 -1
  2. {qubx-0.6.56 → qubx-0.6.57}/pyproject.toml +1 -1
  3. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/context.py +7 -0
  4. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/helpers.py +8 -5
  5. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/interfaces.py +14 -0
  6. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/mixins/market.py +21 -0
  7. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/mixins/processing.py +1 -1
  8. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/series.pyx +1 -1
  9. {qubx-0.6.56 → qubx-0.6.57}/LICENSE +0 -0
  10. {qubx-0.6.56 → qubx-0.6.57}/README.md +0 -0
  11. {qubx-0.6.56 → qubx-0.6.57}/build.py +0 -0
  12. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/__init__.py +0 -0
  13. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/_nb_magic.py +0 -0
  14. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/__init__.py +0 -0
  15. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/account.py +0 -0
  16. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/broker.py +0 -0
  17. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/data.py +0 -0
  18. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/management.py +0 -0
  19. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/ome.py +0 -0
  20. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/optimization.py +0 -0
  21. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/runner.py +0 -0
  22. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/simulated_data.py +0 -0
  23. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/simulated_exchange.py +0 -0
  24. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/simulator.py +0 -0
  25. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/backtester/utils.py +0 -0
  26. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/cli/__init__.py +0 -0
  27. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/cli/commands.py +0 -0
  28. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/cli/deploy.py +0 -0
  29. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/cli/misc.py +0 -0
  30. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/cli/release.py +0 -0
  31. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/cli/tui.py +0 -0
  32. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/__init__.py +0 -0
  33. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/account.py +0 -0
  34. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/broker.py +0 -0
  35. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/data.py +0 -0
  36. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exceptions.py +0 -0
  37. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
  38. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
  39. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
  40. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
  41. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
  42. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
  43. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/factory.py +0 -0
  44. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/reader.py +0 -0
  45. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/ccxt/utils.py +0 -0
  46. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/tardis/data.py +0 -0
  47. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/connectors/tardis/utils.py +0 -0
  48. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/__init__.py +0 -0
  49. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/account.py +0 -0
  50. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/basics.py +0 -0
  51. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/deque.py +0 -0
  52. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/errors.py +0 -0
  53. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/exceptions.py +0 -0
  54. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/initializer.py +0 -0
  55. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/loggers.py +0 -0
  56. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/lookups.py +0 -0
  57. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/metrics.py +0 -0
  58. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/mixins/__init__.py +0 -0
  59. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/mixins/subscription.py +0 -0
  60. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/mixins/trading.py +0 -0
  61. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/mixins/universe.py +0 -0
  62. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/series.pxd +0 -0
  63. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/series.pyi +0 -0
  64. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/utils.pyi +0 -0
  65. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/core/utils.pyx +0 -0
  66. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/__init__.py +0 -0
  67. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/composite.py +0 -0
  68. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/helpers.py +0 -0
  69. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/hft.py +0 -0
  70. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/readers.py +0 -0
  71. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/registry.py +0 -0
  72. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/data/tardis.py +0 -0
  73. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/emitters/__init__.py +0 -0
  74. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/emitters/base.py +0 -0
  75. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/emitters/composite.py +0 -0
  76. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/emitters/csv.py +0 -0
  77. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/emitters/prometheus.py +0 -0
  78. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/emitters/questdb.py +0 -0
  79. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/__init__.py +0 -0
  80. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/composite.py +0 -0
  81. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/formatters/__init__.py +0 -0
  82. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/formatters/base.py +0 -0
  83. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/formatters/incremental.py +0 -0
  84. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/formatters/slack.py +0 -0
  85. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/redis_streams.py +0 -0
  86. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/exporters/slack.py +0 -0
  87. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/features/__init__.py +0 -0
  88. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/features/core.py +0 -0
  89. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/features/orderbook.py +0 -0
  90. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/features/price.py +0 -0
  91. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/features/trades.py +0 -0
  92. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/features/utils.py +0 -0
  93. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/gathering/simplest.py +0 -0
  94. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/health/__init__.py +0 -0
  95. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/health/base.py +0 -0
  96. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/loggers/__init__.py +0 -0
  97. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/loggers/csv.py +0 -0
  98. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/loggers/factory.py +0 -0
  99. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/loggers/inmemory.py +0 -0
  100. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/loggers/mongo.py +0 -0
  101. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/math/__init__.py +0 -0
  102. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/math/stats.py +0 -0
  103. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/notifications/__init__.py +0 -0
  104. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/notifications/composite.py +0 -0
  105. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/notifications/slack.py +0 -0
  106. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/notifications/throttler.py +0 -0
  107. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/pandaz/__init__.py +0 -0
  108. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/pandaz/ta.py +0 -0
  109. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/pandaz/utils.py +0 -0
  110. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/_build.py +0 -0
  111. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/crypto-fees.ini +0 -0
  112. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
  113. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
  114. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
  115. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
  116. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
  117. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
  118. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-hyperliquid-spot.json +0 -0
  119. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-hyperliquid.f-perpetual.json +0 -0
  120. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
  121. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
  122. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
  123. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restarts/__init__.py +0 -0
  124. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restarts/state_resolvers.py +0 -0
  125. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restarts/time_finders.py +0 -0
  126. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/__init__.py +0 -0
  127. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/balance.py +0 -0
  128. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/factory.py +0 -0
  129. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/interfaces.py +0 -0
  130. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/position.py +0 -0
  131. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/signal.py +0 -0
  132. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/state.py +0 -0
  133. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/restorers/utils.py +0 -0
  134. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/ta/__init__.py +0 -0
  135. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/ta/indicators.pxd +0 -0
  136. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/ta/indicators.pyi +0 -0
  137. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/ta/indicators.pyx +0 -0
  138. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/trackers/__init__.py +0 -0
  139. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/trackers/advanced.py +0 -0
  140. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/trackers/composite.py +0 -0
  141. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/trackers/rebalancers.py +0 -0
  142. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/trackers/riskctrl.py +0 -0
  143. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/trackers/sizers.py +0 -0
  144. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/__init__.py +0 -0
  145. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/_pyxreloader.py +0 -0
  146. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/charting/lookinglass.py +0 -0
  147. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/charting/mpl_helpers.py +0 -0
  148. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/collections.py +0 -0
  149. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/marketdata/binance.py +0 -0
  150. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/marketdata/ccxt.py +0 -0
  151. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/marketdata/dukas.py +0 -0
  152. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/misc.py +0 -0
  153. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/ntp.py +0 -0
  154. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/numbers_utils.py +0 -0
  155. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/orderbook.py +0 -0
  156. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/plotting/__init__.py +0 -0
  157. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/plotting/dashboard.py +0 -0
  158. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/plotting/data.py +0 -0
  159. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/plotting/interfaces.py +0 -0
  160. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
  161. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
  162. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/questdb.py +0 -0
  163. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/runner/__init__.py +0 -0
  164. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
  165. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/runner/accounts.py +0 -0
  166. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/runner/configs.py +0 -0
  167. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/runner/factory.py +0 -0
  168. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/runner/runner.py +0 -0
  169. {qubx-0.6.56 → qubx-0.6.57}/src/qubx/utils/time.py +0 -0
  170. {qubx-0.6.56 → qubx-0.6.57}/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.56
3
+ Version: 0.6.57
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.56"
7
+ version = "0.6.57"
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"
@@ -2,6 +2,8 @@ import traceback
2
2
  from threading import Thread
3
3
  from typing import Any, Callable
4
4
 
5
+ import pandas as pd
6
+
5
7
  from qubx import logger
6
8
  from qubx.core.basics import (
7
9
  AssetBalance,
@@ -396,6 +398,11 @@ class StrategyContext(IStrategyContext):
396
398
  def ohlc(self, instrument: Instrument, timeframe: str | None = None, length: int | None = None):
397
399
  return self._market_data_provider.ohlc(instrument, timeframe, length)
398
400
 
401
+ def ohlc_pd(
402
+ self, instrument: Instrument, timeframe: str | None = None, length: int | None = None, consolidated: bool = True
403
+ ) -> pd.DataFrame:
404
+ return self._market_data_provider.ohlc_pd(instrument, timeframe, length, consolidated)
405
+
399
406
  def quote(self, instrument: Instrument):
400
407
  return self._market_data_provider.quote(instrument)
401
408
 
@@ -156,7 +156,7 @@ class CachedMarketDataHolder:
156
156
 
157
157
  # Update the last update for this instrument
158
158
  if bars:
159
- self._updates[instrument] = bars[0] # Use the first bar as the update
159
+ self._updates[instrument] = bars[-1] # Use the last bar as the last update
160
160
 
161
161
  return ohlc
162
162
 
@@ -179,7 +179,10 @@ class CachedMarketDataHolder:
179
179
  if instrument in self._ohlcvs:
180
180
  self._last_bar[instrument] = bar
181
181
  for ser in self._ohlcvs[instrument].values():
182
- ser.update_by_bar(bar.time, bar.open, bar.high, bar.low, bar.close, v_tot_inc, v_buy_inc)
182
+ try:
183
+ ser.update_by_bar(bar.time, bar.open, bar.high, bar.low, bar.close, v_tot_inc, v_buy_inc)
184
+ except ValueError as e:
185
+ logger.warning(f"Can't update ohlc series for [{instrument.symbol}] ::: {str(e)}")
183
186
 
184
187
  @SW.watch("CachedMarketDataHolder")
185
188
  def update_by_quote(self, instrument: Instrument, quote: Quote):
@@ -203,12 +206,12 @@ class CachedMarketDataHolder:
203
206
  continue
204
207
  ser.update(trade.time, trade.price, total_vol, bought_vol)
205
208
 
206
- def finalize_all_ohlc(self, time: dt_64):
209
+ def finalize_ohlc_for_instruments(self, time: dt_64, instruments: list[Instrument]):
207
210
  """
208
- Finalize all OHLCV series at the given time.
211
+ Finalize all OHLCV series at the given time for the given instruments.
209
212
  FIXME: (2025-06-17) This is part of urgent live fix and must be removed in future !!!.
210
213
  """
211
- for instrument in self._ohlcvs.keys():
214
+ for instrument in instruments:
212
215
  # - use most recent update
213
216
  if (_u := self._updates.get(instrument)) is not None:
214
217
  _px = extract_price(_u)
@@ -508,6 +508,20 @@ class IMarketManager(ITimeProvider):
508
508
  """
509
509
  ...
510
510
 
511
+ def ohlc_pd(self, instrument: Instrument, timeframe: str | None = None, length: int | None = None, consolidated: bool = True) -> pd.DataFrame:
512
+ """Get OHLCV data for an instrument as pandas DataFrame.
513
+
514
+ Args:
515
+ instrument: The instrument to get data for
516
+ timeframe (optional): The timeframe of the data. If None, the default timeframe is used.
517
+ length (optional): Number of bars to retrieve. If None, full cached data is returned.
518
+ consolidated (optional): If True, only finished bars are returned.
519
+
520
+ Returns:
521
+ pd.DataFrame: The OHLCV data as pandas DataFrame
522
+ """
523
+ ...
524
+
511
525
  def quote(self, instrument: Instrument) -> Quote | None:
512
526
  """Get latest quote for an instrument.
513
527
 
@@ -73,6 +73,27 @@ class MarketManager(IMarketManager):
73
73
  rc = self._cache.update_by_bars(instrument, timeframe, bars)
74
74
  return rc
75
75
 
76
+ def ohlc_pd(
77
+ self,
78
+ instrument: Instrument,
79
+ timeframe: str | None = None,
80
+ length: int | None = None,
81
+ consolidated: bool = True,
82
+ ) -> pd.DataFrame:
83
+ ohlc = self.ohlc(instrument, timeframe, length).pd()
84
+
85
+ if consolidated and timeframe:
86
+ _time = pd.Timestamp(self._time_provider.time())
87
+ _timedelta = pd.Timedelta(timeframe)
88
+ _last_bar_time = ohlc.index[-1]
89
+ if _last_bar_time + _timedelta >= _time:
90
+ ohlc = ohlc.iloc[:-1]
91
+
92
+ if length:
93
+ ohlc = ohlc.tail(length)
94
+
95
+ return ohlc
96
+
76
97
  def quote(self, instrument: Instrument) -> Quote | None:
77
98
  _data_provider = self._exchange_to_data_provider[instrument.exchange]
78
99
  return _data_provider.get_quote(instrument)
@@ -222,7 +222,7 @@ class ProcessingManager(IProcessingManager):
222
222
  # - - - - - - - - - - - - - - - - - - - -
223
223
 
224
224
  # - finalize OHLC data for all instruments
225
- self._cache.finalize_all_ohlc(event.time)
225
+ self._cache.finalize_ohlc_for_instruments(event.time, self._context.instruments)
226
226
 
227
227
  with self._health_monitor("stg.trigger_event"):
228
228
  _signals = self._wrap_signal_list(self._strategy.on_event(self._context, _trigger_event))
@@ -273,7 +273,7 @@ cdef class TimeSeries:
273
273
  return self._is_new_item
274
274
  else:
275
275
  if _dt < 0:
276
- raise ValueError(f"Attempt to update past data at {time_to_str(time)} !")
276
+ raise ValueError(f"{self.name}.{self.timeframe}: Attempt to update past data at {time_to_str(time)} !")
277
277
  self._update_last_item(item_start_time, value)
278
278
 
279
279
  # - update indicators by new data
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