Qubx 0.6.56__cp312-cp312-manylinux_2_39_x86_64.whl → 0.6.58__cp312-cp312-manylinux_2_39_x86_64.whl

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.

qubx/core/context.py CHANGED
@@ -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
 
qubx/core/helpers.py CHANGED
@@ -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)
qubx/core/interfaces.py CHANGED
@@ -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))
qubx/core/series.pyx CHANGED
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: Qubx
3
- Version: 0.6.56
3
+ Version: 0.6.58
4
4
  Summary: Qubx - Quantitative Trading Framework
5
5
  Author: Dmitry Marienko
6
6
  Author-email: dmitry.marienko@xlydian.com
@@ -37,27 +37,27 @@ qubx/connectors/tardis/utils.py,sha256=epThu9DwqbDb7BgScH6fHa_FVpKUaItOqp3JwtKGc
37
37
  qubx/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  qubx/core/account.py,sha256=4_XskMLR9Uh-rpJBDYMrceYiGMvAZw56k1ve-unIW8w,19417
39
39
  qubx/core/basics.py,sha256=0Kk0LwBU4FqxGhzw9Mb3kgf692xZHjRs5Ogy6JW6C94,32928
40
- qubx/core/context.py,sha256=zkDJIilM7Et-gWjtTtQTOZ5zIwwx-Ueqhsxdy5pQZnk,22950
40
+ qubx/core/context.py,sha256=-1WnpHXmxclCuWvq4_d5bBg02r6dtbpPrn2tEmKIoP4,23228
41
41
  qubx/core/deque.py,sha256=3PsmJ5LF76JpsK4Wp5LLogyE15rKn6EDCkNOOWT6EOk,6203
42
42
  qubx/core/errors.py,sha256=LENtlgmVzxxUFNCsuy4PwyHYhkZkxuZQ2BPif8jaGmw,1411
43
43
  qubx/core/exceptions.py,sha256=11wQC3nnNLsl80zBqbE6xiKCqm31kctqo6W_gdnZkg8,581
44
- qubx/core/helpers.py,sha256=OBMwbzc7xK0-VCngtjuSZIiDkdZkNfmi6FJdXXQ-8ho,19692
44
+ qubx/core/helpers.py,sha256=O6d813A5sdJfH-gfvWTpXuV-iQ4xkxxLu8iPMwAbMbw,19926
45
45
  qubx/core/initializer.py,sha256=YgTBs5LpIk6ZFdmMD8zCnJnVNcMh1oeYvt157jhwyMg,4242
46
- qubx/core/interfaces.py,sha256=gwitvNSni2zUWdpcRyqAdw9n3l1-Z6TBvl9D--hIqgM,59104
46
+ qubx/core/interfaces.py,sha256=7mY-2obGPyoKHq4Kv5b7g_70-OP6o69VWyRg_2gIcfE,59768
47
47
  qubx/core/loggers.py,sha256=85Xgt1-Hh-2gAlJez3TxTHr32KSWYNqNhmbeWZwhw0o,13340
48
48
  qubx/core/lookups.py,sha256=2UmODxDeDQqi-xHOvjm2_GckC4piKI3x4ZEf5vny8YI,18275
49
49
  qubx/core/metrics.py,sha256=74xIecCvlxVXl0gy0JvgjJ2X5gg-RMmVZw9hQikkHE0,60269
50
50
  qubx/core/mixins/__init__.py,sha256=AMCLvfNuIb1kkQl3bhCj9jIOEl2eKcVPJeyLgrkB-rk,329
51
- qubx/core/mixins/market.py,sha256=lBappEimPhIuI0vmUvwVlIztkYjlEjJBpP-AdpfudII,3948
52
- qubx/core/mixins/processing.py,sha256=vHfDypUm18qqzwJxLEbR4VZT9QrPyam5tMbLp9Uv5lU,30616
51
+ qubx/core/mixins/market.py,sha256=f0PJTK5Y9nQkV2XWxytixFG1Oc6ihYVwlxIMraTnmms,4566
52
+ qubx/core/mixins/processing.py,sha256=pgzDCrB9A6SvsWaZ1Op-M22yvcWy6Y8L1IIef6rwpGM,30655
53
53
  qubx/core/mixins/subscription.py,sha256=V_g9wCPQ8S5SHkU-qOZ84cV5nReAUrV7DoSNAGG0LPY,10372
54
54
  qubx/core/mixins/trading.py,sha256=idfRPaqrvkfMxzu9mXr9i_xfqLee-ZAOrERxkxv6Ruo,7256
55
55
  qubx/core/mixins/universe.py,sha256=tsMpBriLHwK9lAVYvIrO94EIx8_ETSXUlzxN_sDOsL8,9838
56
- qubx/core/series.cpython-312-x86_64-linux-gnu.so,sha256=5F0rpgIiKkZ4NVLqqbZpRK4gX0rWroyxTOs-Jd6AQtE,978280
56
+ qubx/core/series.cpython-312-x86_64-linux-gnu.so,sha256=2Rl4BZuMQsCEGBBIAPdMjY4zP1QOCPgSOhiB-kmBOrU,978280
57
57
  qubx/core/series.pxd,sha256=jBdMwgO8J4Zrue0e_xQ5RlqTXqihpzQNu6V3ckZvvpY,3978
58
58
  qubx/core/series.pyi,sha256=RaHm_oHHiWiNUMJqVfx5FXAXniGLsHxUFOUpacn7GC0,4604
59
- qubx/core/series.pyx,sha256=7cM3zZThW59waHiYcZmMxvYj-HYD7Ej_l7nKA4emPjE,46477
60
- qubx/core/utils.cpython-312-x86_64-linux-gnu.so,sha256=QYYvbMCEouG15Nw_IgAOXIPZOnEsm81-f0ptBgWQBLs,86568
59
+ qubx/core/series.pyx,sha256=ZQPp1-Kp2lX22n04gaBWak9mW139e-uc8bhsbZMohgs,46507
60
+ qubx/core/utils.cpython-312-x86_64-linux-gnu.so,sha256=wZg_Vn3YxLQ-_kZjAOMBPwpd3Dv1GWPC9yXlB1xwMmE,86568
61
61
  qubx/core/utils.pyi,sha256=a-wS13V2p_dM1CnGq40JVulmiAhixTwVwt0ah5By0Hc,348
62
62
  qubx/core/utils.pyx,sha256=k5QHfEFvqhqWfCob89ANiJDKNG8gGbOh-O4CVoneZ8M,1696
63
63
  qubx/data/__init__.py,sha256=ELZykvpPGWc5rX7QoNyNQwMLgdKMG8MACOByA4pM5hA,549
@@ -129,7 +129,7 @@ qubx/restorers/signal.py,sha256=0QFoy7OzDkK6AAmJEbbmSsHwmAhjMJYYggVFuLraKjk,1089
129
129
  qubx/restorers/state.py,sha256=dLaVnUwRCNRkUqbYyi0RfZs3Q3AdglkI_qTtQ8GDD5Y,7289
130
130
  qubx/restorers/utils.py,sha256=We2gfqwQKWziUYhuUnjb-xo-5tSlbuHWpPQn0CEMTn0,1155
131
131
  qubx/ta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
132
- qubx/ta/indicators.cpython-312-x86_64-linux-gnu.so,sha256=JJIxv2LGZfU648vqau41V6ThdHQmawTvbJTmQ14V55k,654440
132
+ qubx/ta/indicators.cpython-312-x86_64-linux-gnu.so,sha256=it8ZhCVBqU71Y7tLJp0Bri2j8-3hN6CV-2A8OkjgZZ4,654440
133
133
  qubx/ta/indicators.pxd,sha256=Goo0_N0Xnju8XGo3Xs-3pyg2qr_0Nh5C-_26DK8U_IE,4224
134
134
  qubx/ta/indicators.pyi,sha256=19W0uERft49In5bf9jkJHkzJYEyE9gzudN7_DJ5Vdv8,1963
135
135
  qubx/ta/indicators.pyx,sha256=Xgpew46ZxSXsdfSEWYn3A0Q35MLsopB9n7iyCsXTufs,25969
@@ -166,8 +166,8 @@ qubx/utils/runner/factory.py,sha256=eM4-Etcq-FewD2AjH_srFGzP413pm8er95KIZixXRpM,
166
166
  qubx/utils/runner/runner.py,sha256=PnSQ_soWXzjcIYxG5HHUtbZnWSaoeSXr7VxbQWtOsII,31444
167
167
  qubx/utils/time.py,sha256=J0ZFGjzFL5T6GA8RPAel8hKG0sg2LZXeQ5YfDCfcMHA,10055
168
168
  qubx/utils/version.py,sha256=e52fIHyxzCiIuH7svCF6pkHuDlqL64rklqz-2XjWons,5309
169
- qubx-0.6.56.dist-info/LICENSE,sha256=qwMHOSJ2TD0nx6VUJvFhu1ynJdBfNozRMt6tnSul-Ts,35140
170
- qubx-0.6.56.dist-info/METADATA,sha256=BHx0-WPlkdj6KA4s5Idw8MFDBJGQ7GcziG204AeJxY0,4612
171
- qubx-0.6.56.dist-info/WHEEL,sha256=UckHTmFUCaLKpi4yFY8Dewu0c6XkY-KvEAGzGOnaWo8,110
172
- qubx-0.6.56.dist-info/entry_points.txt,sha256=VqilDTe8mVuV9SbR-yVlZJBTjbkHIL2JBgXfQw076HY,47
173
- qubx-0.6.56.dist-info/RECORD,,
169
+ qubx-0.6.58.dist-info/LICENSE,sha256=qwMHOSJ2TD0nx6VUJvFhu1ynJdBfNozRMt6tnSul-Ts,35140
170
+ qubx-0.6.58.dist-info/METADATA,sha256=uy15BxC8rfdCC6fxoJoMwWtGgpa8Z3LfnuZzJXoRZDE,4612
171
+ qubx-0.6.58.dist-info/WHEEL,sha256=UckHTmFUCaLKpi4yFY8Dewu0c6XkY-KvEAGzGOnaWo8,110
172
+ qubx-0.6.58.dist-info/entry_points.txt,sha256=VqilDTe8mVuV9SbR-yVlZJBTjbkHIL2JBgXfQw076HY,47
173
+ qubx-0.6.58.dist-info/RECORD,,
File without changes
File without changes