Qubx 0.6.60__cp312-cp312-manylinux_2_39_x86_64.whl → 0.6.62__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/helpers.py +6 -2
- qubx/core/interfaces.py +5 -0
- qubx/core/mixins/processing.py +13 -12
- qubx/core/series.cpython-312-x86_64-linux-gnu.so +0 -0
- qubx/core/series.pxd +1 -0
- qubx/core/series.pyi +2 -0
- qubx/core/series.pyx +13 -0
- qubx/core/utils.cpython-312-x86_64-linux-gnu.so +0 -0
- qubx/emitters/base.py +1 -1
- qubx/emitters/indicator.py +1 -1
- qubx/ta/indicators.cpython-312-x86_64-linux-gnu.so +0 -0
- qubx/trackers/riskctrl.py +29 -16
- {qubx-0.6.60.dist-info → qubx-0.6.62.dist-info}/METADATA +1 -1
- {qubx-0.6.60.dist-info → qubx-0.6.62.dist-info}/RECORD +17 -17
- {qubx-0.6.60.dist-info → qubx-0.6.62.dist-info}/LICENSE +0 -0
- {qubx-0.6.60.dist-info → qubx-0.6.62.dist-info}/WHEEL +0 -0
- {qubx-0.6.60.dist-info → qubx-0.6.62.dist-info}/entry_points.txt +0 -0
qubx/core/helpers.py
CHANGED
|
@@ -276,6 +276,10 @@ def _parse_schedule_spec(schedule: str) -> dict[str, str]:
|
|
|
276
276
|
return {k: v for k, v in m.groupdict().items() if v} if m else {}
|
|
277
277
|
|
|
278
278
|
|
|
279
|
+
def _to_dt_64(time: float) -> np.datetime64:
|
|
280
|
+
return np.datetime64(int(time * 1000000000), "ns")
|
|
281
|
+
|
|
282
|
+
|
|
279
283
|
def process_schedule_spec(spec_str: str | None) -> dict[str, Any]:
|
|
280
284
|
AS_INT = lambda d, k: int(d.get(k, 0)) # noqa: E731
|
|
281
285
|
S = lambda s: [x for x in re.split(r"[, ]", s) if x] # noqa: E731
|
|
@@ -409,11 +413,11 @@ class BasicScheduler:
|
|
|
409
413
|
prev_time = iter.get_prev()
|
|
410
414
|
next_time = iter.get_next(start_time=start_time)
|
|
411
415
|
if next_time:
|
|
412
|
-
self._scdlr.enterabs(next_time, 1, self._trigger, (event, prev_time, next_time))
|
|
416
|
+
self._scdlr.enterabs(next_time, 1, self._trigger, (event, _to_dt_64(prev_time), _to_dt_64(next_time)))
|
|
413
417
|
|
|
414
418
|
# - update next nearest time
|
|
415
419
|
self._next_times[event] = next_time
|
|
416
|
-
self._next_nearest_time =
|
|
420
|
+
self._next_nearest_time = _to_dt_64(min(self._next_times.values()))
|
|
417
421
|
# logger.debug(f" >>> ({event}) task is scheduled at {self._next_nearest_time}")
|
|
418
422
|
|
|
419
423
|
return True
|
qubx/core/interfaces.py
CHANGED
|
@@ -1148,6 +1148,11 @@ class IStrategyContext(
|
|
|
1148
1148
|
"""Check if the strategy context is running in simulation mode."""
|
|
1149
1149
|
return False
|
|
1150
1150
|
|
|
1151
|
+
@property
|
|
1152
|
+
def is_live_or_warmup(self) -> bool:
|
|
1153
|
+
"""Check if the strategy context is running in live or warmup mode."""
|
|
1154
|
+
return not self.is_simulation or self.is_warmup_in_progress
|
|
1155
|
+
|
|
1151
1156
|
@property
|
|
1152
1157
|
def is_paper_trading(self) -> bool:
|
|
1153
1158
|
"""Check if the strategy context is running in simulated trading mode."""
|
qubx/core/mixins/processing.py
CHANGED
|
@@ -231,18 +231,17 @@ class ProcessingManager(IProcessingManager):
|
|
|
231
231
|
|
|
232
232
|
# FIXME: (2025-06-17) we need to refactor this to avoid doing it here !!!
|
|
233
233
|
# - on trigger event we need to be sure that all instruments have finalized OHLC data
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
self._cache.finalize_ohlc_for_instruments(event.time, self._context.instruments)
|
|
234
|
+
# - - - - - - IMPORTANT NOTES - - - - - -
|
|
235
|
+
# This is a temporary fix to ensure that all instruments have finalized OHLC data.
|
|
236
|
+
# In live mode with multiple instruments, we can have a situation where one instrument
|
|
237
|
+
# is updated with new bar data while other instruments are not updated yet.
|
|
238
|
+
# This leads to a situation where indicators are not calculated correctly for all instruments in the universe.
|
|
239
|
+
# A simple dirty solution is to update OHLC data for all instruments in the universe with the last update value but with the actual time.
|
|
240
|
+
# This leads to finalization of OHLC data, but the open price may differ slightly from the real one.
|
|
241
|
+
# - - - - - - - - - - - - - - - - - - - -
|
|
242
|
+
|
|
243
|
+
# - finalize OHLC data for all instruments
|
|
244
|
+
self._cache.finalize_ohlc_for_instruments(event.time, self._context.instruments)
|
|
246
245
|
|
|
247
246
|
with self._health_monitor("stg.trigger_event"):
|
|
248
247
|
signals.extend(self._as_list(self._strategy.on_event(self._context, _trigger_event)))
|
|
@@ -666,6 +665,8 @@ class ProcessingManager(IProcessingManager):
|
|
|
666
665
|
if not self._is_data_ready():
|
|
667
666
|
return
|
|
668
667
|
self._fit_is_running = True
|
|
668
|
+
current_time = data[1]
|
|
669
|
+
self._cache.finalize_ohlc_for_instruments(current_time, self._context.instruments)
|
|
669
670
|
self._run_in_thread_pool(self.__invoke_on_fit)
|
|
670
671
|
|
|
671
672
|
def _handle_ohlc(self, instrument: Instrument, event_type: str, bar: Bar) -> MarketEvent:
|
|
Binary file
|
qubx/core/series.pxd
CHANGED
qubx/core/series.pyi
CHANGED
|
@@ -125,6 +125,8 @@ class Indicator(TimeSeries):
|
|
|
125
125
|
def update(self, time: int, value, new_item_started: bool) -> object: ...
|
|
126
126
|
@classmethod
|
|
127
127
|
def wrap(cls, series: TimeSeries, *args, **kwargs) -> "Indicator": ...
|
|
128
|
+
@property
|
|
129
|
+
def is_initial_recalculate(self) -> bool: ...
|
|
128
130
|
|
|
129
131
|
class IndicatorOHLC(Indicator):
|
|
130
132
|
series: OHLCV
|
qubx/core/series.pyx
CHANGED
|
@@ -399,6 +399,9 @@ cdef class Indicator(TimeSeries):
|
|
|
399
399
|
series.indicators[name] = self
|
|
400
400
|
self.name = name
|
|
401
401
|
|
|
402
|
+
# - initialize the initial recalculation flag
|
|
403
|
+
self._is_initial_recalculate = 0
|
|
404
|
+
|
|
402
405
|
# - we need to make a empty copy and fill it
|
|
403
406
|
self.series = self._clone_empty(series.name, series.timeframe, series.max_series_length)
|
|
404
407
|
self.parent = series
|
|
@@ -407,7 +410,9 @@ cdef class Indicator(TimeSeries):
|
|
|
407
410
|
self._on_attach_indicator(self, series)
|
|
408
411
|
|
|
409
412
|
# - recalculate indicator on data as if it would being streamed
|
|
413
|
+
self._is_initial_recalculate = 1
|
|
410
414
|
self._initial_data_recalculate(series)
|
|
415
|
+
self._is_initial_recalculate = 0
|
|
411
416
|
|
|
412
417
|
def _on_attach_indicator(self, indicator: Indicator, indicator_input: TimeSeries):
|
|
413
418
|
self.parent._on_attach_indicator(indicator, indicator_input)
|
|
@@ -435,6 +440,14 @@ cdef class Indicator(TimeSeries):
|
|
|
435
440
|
def wrap(clz, series:TimeSeries, *args, **kwargs):
|
|
436
441
|
return _wrap_indicator(series, clz, *args, **kwargs)
|
|
437
442
|
|
|
443
|
+
@property
|
|
444
|
+
def is_initial_recalculate(self) -> bool:
|
|
445
|
+
"""
|
|
446
|
+
Returns True if the indicator is currently in the initial data recalculation phase,
|
|
447
|
+
False otherwise.
|
|
448
|
+
"""
|
|
449
|
+
return self._is_initial_recalculate == 1
|
|
450
|
+
|
|
438
451
|
|
|
439
452
|
cdef class IndicatorOHLC(Indicator):
|
|
440
453
|
"""
|
|
Binary file
|
qubx/emitters/base.py
CHANGED
|
@@ -192,7 +192,7 @@ class BaseMetricEmitter(IMetricEmitter):
|
|
|
192
192
|
Args:
|
|
193
193
|
context: The strategy context to get statistics from
|
|
194
194
|
"""
|
|
195
|
-
if context.
|
|
195
|
+
if not context.is_live_or_warmup:
|
|
196
196
|
return
|
|
197
197
|
|
|
198
198
|
# Convert to pandas timestamp for easier time calculations
|
qubx/emitters/indicator.py
CHANGED
|
@@ -104,7 +104,7 @@ class IndicatorEmitter(Indicator):
|
|
|
104
104
|
if new_item_started and len(self._wrapped_indicator) >= 2:
|
|
105
105
|
should_emit = True
|
|
106
106
|
# Use the previous (completed) value, not the current one
|
|
107
|
-
current_value = self._wrapped_indicator[1]
|
|
107
|
+
current_value = self._wrapped_indicator[1] if not self.is_initial_recalculate else value
|
|
108
108
|
|
|
109
109
|
# Emit if we should and the value is valid
|
|
110
110
|
if should_emit and not np.isnan(current_value):
|
|
Binary file
|
qubx/trackers/riskctrl.py
CHANGED
|
@@ -588,6 +588,7 @@ class AtrRiskTracker(GenericRiskControllerDecorator):
|
|
|
588
588
|
self.atr_period = atr_period
|
|
589
589
|
self.atr_smoother = atr_smoother
|
|
590
590
|
self._full_name = f"{self.__class__.__name__}{purpose}"
|
|
591
|
+
self._instrument_initialized: dict[Instrument, bool] = {}
|
|
591
592
|
|
|
592
593
|
super().__init__(
|
|
593
594
|
sizer,
|
|
@@ -596,33 +597,37 @@ class AtrRiskTracker(GenericRiskControllerDecorator):
|
|
|
596
597
|
),
|
|
597
598
|
)
|
|
598
599
|
|
|
599
|
-
def
|
|
600
|
-
|
|
601
|
-
ctx.ohlc(
|
|
600
|
+
def _get_volatility(self, ctx: IStrategyContext, instrument: Instrument) -> list[float]:
|
|
601
|
+
return atr(
|
|
602
|
+
ctx.ohlc(instrument, self.atr_timeframe, 2 * self.atr_period),
|
|
602
603
|
self.atr_period,
|
|
603
604
|
smoother=self.atr_smoother,
|
|
604
605
|
percentage=False,
|
|
605
606
|
)
|
|
606
607
|
|
|
608
|
+
def update(
|
|
609
|
+
self, ctx: IStrategyContext, instrument: Instrument, update: Quote | Trade | Bar | OrderBook
|
|
610
|
+
) -> list[TargetPosition] | TargetPosition:
|
|
611
|
+
if ctx.is_live_or_warmup and not self._instrument_initialized.get(instrument, False):
|
|
612
|
+
# - emit volatility indicator in live mode
|
|
613
|
+
indicator_emitter(
|
|
614
|
+
wrapped_indicator=self._get_volatility(ctx, instrument),
|
|
615
|
+
metric_emitter=ctx.emitter,
|
|
616
|
+
instrument=instrument,
|
|
617
|
+
)
|
|
618
|
+
self._instrument_initialized[instrument] = True
|
|
619
|
+
|
|
620
|
+
return super().update(ctx, instrument, update)
|
|
621
|
+
|
|
622
|
+
def calculate_risks(self, ctx: IStrategyContext, quote: Quote | None, signal: Signal) -> Signal | None:
|
|
623
|
+
volatility = self._get_volatility(ctx, signal.instrument)
|
|
624
|
+
|
|
607
625
|
if len(volatility) < 2 or ((last_volatility := volatility[1]) is None or not np.isfinite(last_volatility)):
|
|
608
626
|
logger.debug(
|
|
609
627
|
f"[<y>{self._full_name}</y>(<g>{signal.instrument}</g>)] :: not enough ATR data, skipping risk calculation"
|
|
610
628
|
)
|
|
611
629
|
return None
|
|
612
630
|
|
|
613
|
-
if not ctx.is_simulation:
|
|
614
|
-
indicator_emitter(
|
|
615
|
-
wrapped_indicator=volatility,
|
|
616
|
-
metric_emitter=ctx.emitter,
|
|
617
|
-
instrument=signal.instrument,
|
|
618
|
-
)
|
|
619
|
-
if quote is not None:
|
|
620
|
-
mid_price = quote.mid_pice()
|
|
621
|
-
volatility_pct = last_volatility / mid_price
|
|
622
|
-
signal.comment += f", ATR: {volatility_pct:.2%} ({last_volatility:.4f})"
|
|
623
|
-
signal.comment += f", stop_risk: {self.stop_risk}"
|
|
624
|
-
signal.comment += f", take_target: {self.take_target}"
|
|
625
|
-
|
|
626
631
|
if quote is None:
|
|
627
632
|
logger.debug(
|
|
628
633
|
f"[<y>{self._full_name}</y>(<g>{signal.instrument}</g>)] :: there is no actual market data, skipping risk calculation"
|
|
@@ -643,6 +648,14 @@ class AtrRiskTracker(GenericRiskControllerDecorator):
|
|
|
643
648
|
if self.take_target:
|
|
644
649
|
signal.take = entry - self.take_target * last_volatility
|
|
645
650
|
|
|
651
|
+
if ctx.is_live_or_warmup:
|
|
652
|
+
# - additional comments for live debugging
|
|
653
|
+
mid_price = quote.mid_price()
|
|
654
|
+
volatility_pct = last_volatility / mid_price
|
|
655
|
+
signal.comment += f", ATR: {volatility_pct:.2%} ({last_volatility:.4f})"
|
|
656
|
+
signal.comment += f", stop_risk: {self.stop_risk}"
|
|
657
|
+
signal.comment += f", take_target: {self.take_target}"
|
|
658
|
+
|
|
646
659
|
return signal
|
|
647
660
|
|
|
648
661
|
|
|
@@ -41,23 +41,23 @@ qubx/core/context.py,sha256=h2KeQnVe514VDSehjEIdl2Pv8FKjYaCOhpvJZPFFON8,24107
|
|
|
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=
|
|
44
|
+
qubx/core/helpers.py,sha256=nZMe3HVheSkqczZq7-foPHfJ-49HJL69mBirBxynOBQ,20022
|
|
45
45
|
qubx/core/initializer.py,sha256=YgTBs5LpIk6ZFdmMD8zCnJnVNcMh1oeYvt157jhwyMg,4242
|
|
46
|
-
qubx/core/interfaces.py,sha256=
|
|
46
|
+
qubx/core/interfaces.py,sha256=OUv56aUNpaBn6zUgHr1k642ZwGgr_o0xb0_Uu3qmrxk,61380
|
|
47
47
|
qubx/core/loggers.py,sha256=wO6UdFasWu5bNeDkN7eRVDhHUQ2Rj3Apkzk9h2q71Rk,14128
|
|
48
48
|
qubx/core/lookups.py,sha256=2UmODxDeDQqi-xHOvjm2_GckC4piKI3x4ZEf5vny8YI,18275
|
|
49
49
|
qubx/core/metrics.py,sha256=SLbuG66Y3sH86tDHcdoIHovkhM-oSF5o840BRChrvCE,60849
|
|
50
50
|
qubx/core/mixins/__init__.py,sha256=AMCLvfNuIb1kkQl3bhCj9jIOEl2eKcVPJeyLgrkB-rk,329
|
|
51
51
|
qubx/core/mixins/market.py,sha256=f0PJTK5Y9nQkV2XWxytixFG1Oc6ihYVwlxIMraTnmms,4566
|
|
52
|
-
qubx/core/mixins/processing.py,sha256=
|
|
52
|
+
qubx/core/mixins/processing.py,sha256=xFM6HkcucbtwQWKTmTVhxjdwVgKYcInI6fr3hnoDSRo,35252
|
|
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=mzZJA7Me6HNFbAMGg1XOpnYCMtcFKHESTiozjaXyKXY,10100
|
|
56
|
-
qubx/core/series.cpython-312-x86_64-linux-gnu.so,sha256=
|
|
57
|
-
qubx/core/series.pxd,sha256=
|
|
58
|
-
qubx/core/series.pyi,sha256=
|
|
59
|
-
qubx/core/series.pyx,sha256=
|
|
60
|
-
qubx/core/utils.cpython-312-x86_64-linux-gnu.so,sha256=
|
|
56
|
+
qubx/core/series.cpython-312-x86_64-linux-gnu.so,sha256=DRIaH5DjiJNU7ZiH68fQE-QqM0e6ujx17bf_Uyl4WZU,982408
|
|
57
|
+
qubx/core/series.pxd,sha256=aI5PG1hbr827xwcnSYgGMF2IBD4GvCRby_i9lrGrJdQ,4026
|
|
58
|
+
qubx/core/series.pyi,sha256=wRb1_HpZC7KSTyWMi7K0BisaKSEro3LVebr8z5XzoDs,4668
|
|
59
|
+
qubx/core/series.pyx,sha256=TpKMCqRrzrT0cj1pASlB7mLLgMLQZwDNC5o-QOxqhRQ,46936
|
|
60
|
+
qubx/core/utils.cpython-312-x86_64-linux-gnu.so,sha256=dP51I7PhfJPwlZzOQ7zjEG1Ppm3iJGGPftylTrBfDAM,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
|
|
@@ -68,10 +68,10 @@ qubx/data/readers.py,sha256=g3hSkyKdMAVziMCgcaZadsukidECaLwHyIEtArSVDSc,66203
|
|
|
68
68
|
qubx/data/registry.py,sha256=45mjy5maBSO6cf-0zfIRRDs8b0VDW7wHSPn43aRjv-o,3883
|
|
69
69
|
qubx/data/tardis.py,sha256=O-zglpusmO6vCY3arSOgH6KUbkfPajSAIQfMKlVmh_E,33878
|
|
70
70
|
qubx/emitters/__init__.py,sha256=11sYi8CHdPlQ5NLR84C2vUnMDkAqNIAmKo_SfqCMj2c,705
|
|
71
|
-
qubx/emitters/base.py,sha256=
|
|
71
|
+
qubx/emitters/base.py,sha256=RPjOib02h4l8ndZ4_Q7_BGTPA2YvITLUWpWlSrg2b6A,7984
|
|
72
72
|
qubx/emitters/composite.py,sha256=8DsPIUtaJ95Oww9QTVVB6LR7Wcb6TJ-c1jIHMGuttz4,2784
|
|
73
73
|
qubx/emitters/csv.py,sha256=lWl6sP0ke0j6kVlEbQsy11vSOHFudYHjWS9iPbq6kmo,3067
|
|
74
|
-
qubx/emitters/indicator.py,sha256=
|
|
74
|
+
qubx/emitters/indicator.py,sha256=8opNUrkoLLcoTLISCMb7e5mlVZgdH5HduyrBxkA6sg4,7983
|
|
75
75
|
qubx/emitters/prometheus.py,sha256=g2hgcV_G77fWVEXtoGJTUs4JLkB2FQXFzVY_x_sEBfc,8100
|
|
76
76
|
qubx/emitters/questdb.py,sha256=vGi5r6JbKwwi8SpdXj_oG1FYrI-aEYLHYb633UAwNBk,5962
|
|
77
77
|
qubx/exporters/__init__.py,sha256=7HeYHCZfKAaBVAByx9wE8DyGv6C55oeED9uUphcyjuc,360
|
|
@@ -130,7 +130,7 @@ qubx/restorers/signal.py,sha256=7n7eeRhWGUBPbg179GxFH_ifywcl3pQJbwrcDklw0N0,1460
|
|
|
130
130
|
qubx/restorers/state.py,sha256=I1VIN0ZcOjigc3WMHIYTNJeAAbN9YB21MDcMl04ZWmY,8018
|
|
131
131
|
qubx/restorers/utils.py,sha256=We2gfqwQKWziUYhuUnjb-xo-5tSlbuHWpPQn0CEMTn0,1155
|
|
132
132
|
qubx/ta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
133
|
-
qubx/ta/indicators.cpython-312-x86_64-linux-gnu.so,sha256=
|
|
133
|
+
qubx/ta/indicators.cpython-312-x86_64-linux-gnu.so,sha256=Qmvnny0Tq_XxjtK7eqJgizdxbZGFaefIqrkLvJpT3UA,662632
|
|
134
134
|
qubx/ta/indicators.pxd,sha256=Goo0_N0Xnju8XGo3Xs-3pyg2qr_0Nh5C-_26DK8U_IE,4224
|
|
135
135
|
qubx/ta/indicators.pyi,sha256=19W0uERft49In5bf9jkJHkzJYEyE9gzudN7_DJ5Vdv8,1963
|
|
136
136
|
qubx/ta/indicators.pyx,sha256=Xgpew46ZxSXsdfSEWYn3A0Q35MLsopB9n7iyCsXTufs,25969
|
|
@@ -138,7 +138,7 @@ qubx/trackers/__init__.py,sha256=ThIP1jXaACse5hG3lZqQSlWSKYl6APxFmBHaRcVpPdU,100
|
|
|
138
138
|
qubx/trackers/advanced.py,sha256=CONogr5hHHEwfolkegjpEz7NNk4Ruf9pOq5nKifNXVM,12761
|
|
139
139
|
qubx/trackers/composite.py,sha256=Tjupx78SraXmRKkWhu8n81RkPjOgsDbXLd8yz6PhbaA,6318
|
|
140
140
|
qubx/trackers/rebalancers.py,sha256=KFY7xuD4fGALiSLMas8MZ3ueRzlWt5wDT9329dlmNng,5150
|
|
141
|
-
qubx/trackers/riskctrl.py,sha256=
|
|
141
|
+
qubx/trackers/riskctrl.py,sha256=IuxccTgdEnN9lLMoYU8HURqPBqA3Wrk6NiOgL_O6rTM,35094
|
|
142
142
|
qubx/trackers/sizers.py,sha256=OEK-IOuXiXXx8MkZiEsni5zPWFc3kun9AqApY0mIPTY,9527
|
|
143
143
|
qubx/utils/__init__.py,sha256=FEPBtU3dhfLawBkAfm9FEUW4RuOY7pGCBfzDCtKjn9A,481
|
|
144
144
|
qubx/utils/_pyxreloader.py,sha256=34kNd8kQi2ey_ZrGdVVUHbPrO1PEiHZDLEDBscIkT_s,12292
|
|
@@ -167,8 +167,8 @@ qubx/utils/runner/factory.py,sha256=eM4-Etcq-FewD2AjH_srFGzP413pm8er95KIZixXRpM,
|
|
|
167
167
|
qubx/utils/runner/runner.py,sha256=m58a3kEwSs1xfgg_s9FwrQJ3AZV4Lf_VOmKDPQdaWH8,31518
|
|
168
168
|
qubx/utils/time.py,sha256=J0ZFGjzFL5T6GA8RPAel8hKG0sg2LZXeQ5YfDCfcMHA,10055
|
|
169
169
|
qubx/utils/version.py,sha256=e52fIHyxzCiIuH7svCF6pkHuDlqL64rklqz-2XjWons,5309
|
|
170
|
-
qubx-0.6.
|
|
171
|
-
qubx-0.6.
|
|
172
|
-
qubx-0.6.
|
|
173
|
-
qubx-0.6.
|
|
174
|
-
qubx-0.6.
|
|
170
|
+
qubx-0.6.62.dist-info/LICENSE,sha256=qwMHOSJ2TD0nx6VUJvFhu1ynJdBfNozRMt6tnSul-Ts,35140
|
|
171
|
+
qubx-0.6.62.dist-info/METADATA,sha256=bLqkQBXqzXkkcYiAJAc2B4BYKmyBJrbBB6bXxMgoRG8,4612
|
|
172
|
+
qubx-0.6.62.dist-info/WHEEL,sha256=UckHTmFUCaLKpi4yFY8Dewu0c6XkY-KvEAGzGOnaWo8,110
|
|
173
|
+
qubx-0.6.62.dist-info/entry_points.txt,sha256=VqilDTe8mVuV9SbR-yVlZJBTjbkHIL2JBgXfQw076HY,47
|
|
174
|
+
qubx-0.6.62.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|