Qubx 0.2.63__cp311-cp311-manylinux_2_35_x86_64.whl → 0.2.65__cp311-cp311-manylinux_2_35_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/metrics.py +32 -1
- qubx/core/series.cpython-311-x86_64-linux-gnu.so +0 -0
- qubx/core/series.pxd +6 -6
- qubx/core/series.pyi +6 -1
- qubx/core/utils.cpython-311-x86_64-linux-gnu.so +0 -0
- qubx/ta/indicators.cpython-311-x86_64-linux-gnu.so +0 -0
- qubx/ta/indicators.pxd +1 -0
- qubx/ta/indicators.pyi +12 -0
- qubx/ta/indicators.pyx +9 -0
- qubx/utils/charting/lookinglass.py +50 -57
- {qubx-0.2.63.dist-info → qubx-0.2.65.dist-info}/METADATA +1 -1
- {qubx-0.2.63.dist-info → qubx-0.2.65.dist-info}/RECORD +13 -13
- {qubx-0.2.63.dist-info → qubx-0.2.65.dist-info}/WHEEL +0 -0
qubx/core/metrics.py
CHANGED
|
@@ -11,6 +11,8 @@ import re
|
|
|
11
11
|
from scipy import stats
|
|
12
12
|
from scipy.stats import norm
|
|
13
13
|
from statsmodels.regression.linear_model import OLS
|
|
14
|
+
from copy import copy
|
|
15
|
+
from itertools import chain
|
|
14
16
|
|
|
15
17
|
import plotly.graph_objects as go
|
|
16
18
|
|
|
@@ -892,6 +894,7 @@ def chart_signals(
|
|
|
892
894
|
overlay=[],
|
|
893
895
|
info=True,
|
|
894
896
|
show_trades: bool = True,
|
|
897
|
+
show_signals: bool = False,
|
|
895
898
|
show_quantity: bool = False,
|
|
896
899
|
show_value: bool = False,
|
|
897
900
|
show_leverage: bool = True,
|
|
@@ -917,10 +920,13 @@ def chart_signals(
|
|
|
917
920
|
end = executions.index[-1]
|
|
918
921
|
|
|
919
922
|
if portfolio is not None:
|
|
920
|
-
|
|
923
|
+
symbol_count = len(portfolio.filter(like="_PnL").columns)
|
|
924
|
+
pnl = portfolio.filter(regex=f"{symbol}_PnL").cumsum() + result.capital / symbol_count
|
|
925
|
+
pnl = pnl.loc[start:]
|
|
921
926
|
if apply_commissions:
|
|
922
927
|
comm = portfolio.filter(regex=f"{symbol}_Commissions").loc[start:].cumsum()
|
|
923
928
|
pnl -= comm.values
|
|
929
|
+
pnl = (pnl / pnl.iloc[0] - 1) * 100
|
|
924
930
|
indicators["PnL"] = ["area", "green", pnl]
|
|
925
931
|
if show_quantity:
|
|
926
932
|
pos = portfolio.filter(regex=f"{symbol}_Pos").loc[start:]
|
|
@@ -965,6 +971,10 @@ def chart_signals(
|
|
|
965
971
|
]
|
|
966
972
|
overlay = list(overlay) + [excs]
|
|
967
973
|
|
|
974
|
+
if show_signals:
|
|
975
|
+
sigs = result.signals_log[result.signals_log["instrument_id"] == symbol]
|
|
976
|
+
overlay = list(overlay) + [sigs]
|
|
977
|
+
|
|
968
978
|
chart = LookingGlass([bars, *overlay], indicators).look(start, end, title=symbol).hover(show_info=info, h=height)
|
|
969
979
|
if not show_table:
|
|
970
980
|
return chart.show()
|
|
@@ -1010,3 +1020,24 @@ def get_symbol_pnls(
|
|
|
1010
1020
|
pnls.append(s.portfolio_log.filter(like="_PnL").cumsum().iloc[-1])
|
|
1011
1021
|
|
|
1012
1022
|
return pd.DataFrame(pnls, index=[s.name for s in session])
|
|
1023
|
+
|
|
1024
|
+
|
|
1025
|
+
def combine_sessions(sessions: list[TradingSessionResult], name: str = "Portfolio") -> TradingSessionResult:
|
|
1026
|
+
session = copy(sessions[0])
|
|
1027
|
+
session.name = name
|
|
1028
|
+
session.instruments = list(set(chain.from_iterable([e.instruments for e in sessions])))
|
|
1029
|
+
session.portfolio_log = pd.concat(
|
|
1030
|
+
[e.portfolio_log.loc[:, (e.portfolio_log != 0).any(axis=0)] for e in sessions], axis=1
|
|
1031
|
+
)
|
|
1032
|
+
# remove duplicated columns, keep first
|
|
1033
|
+
session.portfolio_log = session.portfolio_log.loc[:, ~session.portfolio_log.columns.duplicated()]
|
|
1034
|
+
session.executions_log = pd.concat([s.executions_log for s in sessions], axis=0).sort_index()
|
|
1035
|
+
session.signals_log = pd.concat([s.signals_log for s in sessions], axis=0).sort_index()
|
|
1036
|
+
# remove duplicated rows
|
|
1037
|
+
session.executions_log = (
|
|
1038
|
+
session.executions_log.set_index("instrument_id", append=True).drop_duplicates().reset_index("instrument_id")
|
|
1039
|
+
)
|
|
1040
|
+
session.signals_log = (
|
|
1041
|
+
session.signals_log.set_index("instrument_id", append=True).drop_duplicates().reset_index("instrument_id")
|
|
1042
|
+
)
|
|
1043
|
+
return session
|
|
Binary file
|
qubx/core/series.pxd
CHANGED
|
@@ -36,11 +36,6 @@ cdef class Indicator(TimeSeries):
|
|
|
36
36
|
cdef public TimeSeries series
|
|
37
37
|
cdef public TimeSeries parent
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
cdef class IndicatorOHLC(Indicator):
|
|
41
|
-
pass
|
|
42
|
-
|
|
43
|
-
|
|
44
39
|
cdef class RollingSum:
|
|
45
40
|
"""
|
|
46
41
|
Rolling fast summator
|
|
@@ -49,7 +44,7 @@ cdef class RollingSum:
|
|
|
49
44
|
cdef np.ndarray __s
|
|
50
45
|
cdef unsigned int __i
|
|
51
46
|
cdef double rsum
|
|
52
|
-
cdef unsigned short is_init_stage
|
|
47
|
+
cdef public unsigned short is_init_stage
|
|
53
48
|
|
|
54
49
|
cpdef double update(RollingSum self, double value, short new_item_started)
|
|
55
50
|
|
|
@@ -110,3 +105,8 @@ cdef class Quote:
|
|
|
110
105
|
cdef public double ask_size
|
|
111
106
|
|
|
112
107
|
cpdef double mid_price(Quote self)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
cdef class IndicatorOHLC(Indicator):
|
|
111
|
+
pass
|
|
112
|
+
|
qubx/core/series.pyi
CHANGED
|
@@ -83,6 +83,11 @@ class Indicator(TimeSeries):
|
|
|
83
83
|
|
|
84
84
|
def update(self, time: int, value, new_item_started: bool) -> object: ...
|
|
85
85
|
|
|
86
|
-
class IndicatorOHLC(Indicator):
|
|
86
|
+
class IndicatorOHLC(Indicator):
|
|
87
|
+
series: OHLCV
|
|
87
88
|
|
|
88
89
|
def time_as_nsec(time: Any) -> np.datetime64: ...
|
|
90
|
+
|
|
91
|
+
class RollingSum:
|
|
92
|
+
def __init__(self, period: int) -> None: ...
|
|
93
|
+
def update(self, value: float, new_item_started: bool) -> float: ...
|
|
Binary file
|
|
Binary file
|
qubx/ta/indicators.pxd
CHANGED
|
@@ -134,5 +134,6 @@ cdef class Swings(IndicatorOHLC):
|
|
|
134
134
|
# tops_detection_lag contain time lag when top was actually spotted
|
|
135
135
|
cdef public TimeSeries tops, tops_detection_lag
|
|
136
136
|
cdef public TimeSeries bottoms, bottoms_detection_lag
|
|
137
|
+
cdef public TimeSeries middles, deltas
|
|
137
138
|
|
|
138
139
|
cpdef double calculate(self, long long time, Bar bar, short new_item_started)
|
qubx/ta/indicators.pyi
CHANGED
|
@@ -15,8 +15,20 @@ def smooth(series: TimeSeries, smoother: str, *args, **kwargs) -> Indicator: ...
|
|
|
15
15
|
def atr(series: OHLCV, period: int = 14, smoother="sma", percentage: bool = False): ...
|
|
16
16
|
def swings(series: OHLCV, trend_indicator, **indicator_args): ...
|
|
17
17
|
|
|
18
|
+
class Sma(Indicator):
|
|
19
|
+
def __init__(self, name: str, series: TimeSeries, period: int): ...
|
|
20
|
+
|
|
21
|
+
class Ema(Indicator):
|
|
22
|
+
def __init__(self, name: str, series: TimeSeries, period: int, init_mean: bool = True): ...
|
|
23
|
+
|
|
18
24
|
class Kama(Indicator):
|
|
19
25
|
def __init__(self, name: str, series: TimeSeries, period: int, fast_span: int = 2, slow_span: int = 30): ...
|
|
20
26
|
|
|
21
27
|
class Atr(IndicatorOHLC):
|
|
22
28
|
def __init__(self, name: str, series: OHLCV, period: int, smoother: str, percentage: bool): ...
|
|
29
|
+
|
|
30
|
+
class Swings(IndicatorOHLC):
|
|
31
|
+
tops: TimeSeries
|
|
32
|
+
bottoms: TimeSeries
|
|
33
|
+
middles: TimeSeries
|
|
34
|
+
deltas: TimeSeries
|
qubx/ta/indicators.pyx
CHANGED
|
@@ -612,6 +612,9 @@ cdef class Swings(IndicatorOHLC):
|
|
|
612
612
|
self.bottoms = TimeSeries("bottoms", series.timeframe, series.max_series_length)
|
|
613
613
|
self.bottoms_detection_lag = TimeSeries("bottoms_lag", series.timeframe, series.max_series_length)
|
|
614
614
|
|
|
615
|
+
self.middles = TimeSeries("middles", series.timeframe, series.max_series_length)
|
|
616
|
+
self.deltas = TimeSeries("deltas", series.timeframe, series.max_series_length)
|
|
617
|
+
|
|
615
618
|
self._min_l = +np.inf
|
|
616
619
|
self._max_h = -np.inf
|
|
617
620
|
self._max_t = 0
|
|
@@ -630,6 +633,9 @@ cdef class Swings(IndicatorOHLC):
|
|
|
630
633
|
if self._max_t > 0:
|
|
631
634
|
self.tops.update(self._max_t, self._max_h)
|
|
632
635
|
self.tops_detection_lag.update(self._max_t, time - self._max_t)
|
|
636
|
+
if len(self.bottoms) > 0:
|
|
637
|
+
self.middles.update(time, (self.tops[0] + self.bottoms[0]) / 2)
|
|
638
|
+
self.deltas.update(time, self.tops[0] - self.bottoms[0])
|
|
633
639
|
|
|
634
640
|
if bar.low <= self._min_l:
|
|
635
641
|
self._min_l = bar.low
|
|
@@ -642,6 +648,9 @@ cdef class Swings(IndicatorOHLC):
|
|
|
642
648
|
if self._min_t > 0:
|
|
643
649
|
self.bottoms.update(self._min_t, self._min_l)
|
|
644
650
|
self.bottoms_detection_lag.update(self._min_t, time - self._min_t)
|
|
651
|
+
if len(self.tops) > 0:
|
|
652
|
+
self.middles.update(time, (self.tops[0] + self.bottoms[0]) / 2)
|
|
653
|
+
self.deltas.update(time, self.tops[0] - self.bottoms[0])
|
|
645
654
|
|
|
646
655
|
if bar.high >= self._max_h:
|
|
647
656
|
self._max_h = bar.high
|
|
@@ -4,6 +4,7 @@ import plotly.graph_objects as go
|
|
|
4
4
|
from plotly.graph_objs.graph_objs import FigureWidget
|
|
5
5
|
from plotly.subplots import make_subplots
|
|
6
6
|
|
|
7
|
+
from qubx.core.series import OHLCV, TimeSeries
|
|
7
8
|
from qubx.utils.charting.mpl_helpers import ohlc_plot
|
|
8
9
|
from qubx.utils.charting.mpl_helpers import plot_trends
|
|
9
10
|
from qubx.utils.charting.mpl_helpers import subplot
|
|
@@ -110,7 +111,7 @@ def install_plotly_helpers():
|
|
|
110
111
|
arrowcolor=c,
|
|
111
112
|
)
|
|
112
113
|
|
|
113
|
-
def
|
|
114
|
+
def hover(v, h=600, n=2, legend=False, show_info=True):
|
|
114
115
|
return (
|
|
115
116
|
v.update_traces(xaxis="x1")
|
|
116
117
|
.update_layout(
|
|
@@ -140,7 +141,7 @@ def install_plotly_helpers():
|
|
|
140
141
|
)
|
|
141
142
|
)
|
|
142
143
|
|
|
143
|
-
FigureWidget.hover =
|
|
144
|
+
FigureWidget.hover = hover # type: ignore
|
|
144
145
|
FigureWidget.rline = rline # type: ignore
|
|
145
146
|
FigureWidget.rlinex = rlinex # type: ignore
|
|
146
147
|
FigureWidget.rline_ = rline_ # type: ignore
|
|
@@ -287,7 +288,8 @@ class LookingGlassMatplotLib(AbstractLookingGlass):
|
|
|
287
288
|
else:
|
|
288
289
|
_lbl = y.name if hasattr(y, "name") and y.name else ("%s_%d" % (study_name, k))
|
|
289
290
|
|
|
290
|
-
if isinstance(y, pd.DataFrame):
|
|
291
|
+
if isinstance(y, (pd.DataFrame, OHLCV)):
|
|
292
|
+
y = y.pd() if isinstance(y, OHLCV) else y
|
|
291
293
|
|
|
292
294
|
yy = y[zoom] if zoom else y
|
|
293
295
|
|
|
@@ -429,6 +431,7 @@ class LookingGlassMatplotLib(AbstractLookingGlass):
|
|
|
429
431
|
for _col in yy.columns:
|
|
430
432
|
self.__plot_as_type(yy[_col], plot_style, self._n_style, _col)
|
|
431
433
|
else:
|
|
434
|
+
y = y.pd() if isinstance(y, TimeSeries) else y
|
|
432
435
|
yy = y[zoom] if zoom else y
|
|
433
436
|
self.__plot_as_type(yy, plot_style, self._n_style, _lbl)
|
|
434
437
|
|
|
@@ -544,7 +547,25 @@ class LookingGlassPlotly(AbstractLookingGlass):
|
|
|
544
547
|
def __plt_series(self, y, zoom, study_name, k, row, col, plot_style="line"):
|
|
545
548
|
_lbl = y.name if hasattr(y, "name") and y.name else ("%s_%d" % (study_name, k))
|
|
546
549
|
|
|
547
|
-
|
|
550
|
+
def _scatter(
|
|
551
|
+
xs: pd.Series, comments: pd.Series | None, name: str, marker: str, color: str, size: int = 11
|
|
552
|
+
) -> None:
|
|
553
|
+
_args = dict(
|
|
554
|
+
x=xs.index,
|
|
555
|
+
y=xs,
|
|
556
|
+
mode="markers",
|
|
557
|
+
name=name,
|
|
558
|
+
text=comments,
|
|
559
|
+
marker={
|
|
560
|
+
"symbol": marker,
|
|
561
|
+
"size": size,
|
|
562
|
+
"color": color,
|
|
563
|
+
},
|
|
564
|
+
)
|
|
565
|
+
self.fig.add_trace(go.Scatter(**_args), row=row, col=col)
|
|
566
|
+
|
|
567
|
+
if isinstance(y, (pd.DataFrame, OHLCV)):
|
|
568
|
+
y = y.pd() if isinstance(y, OHLCV) else y
|
|
548
569
|
yy = y[zoom] if zoom else y
|
|
549
570
|
|
|
550
571
|
# candlesticks
|
|
@@ -760,70 +781,42 @@ class LookingGlassPlotly(AbstractLookingGlass):
|
|
|
760
781
|
elif self._frame_has_cols(y, ["Type", "Time", "Price", "PriceOccured"]):
|
|
761
782
|
_bot = yy[yy.Type == "-"]
|
|
762
783
|
_top = yy[yy.Type == "+"]
|
|
763
|
-
self.fig.add_trace(
|
|
764
|
-
go.Scatter(
|
|
765
|
-
x=_bot.index,
|
|
766
|
-
y=_bot.PriceOccured,
|
|
767
|
-
mode="markers",
|
|
768
|
-
name="B",
|
|
769
|
-
marker={"symbol": "triangle-right"},
|
|
770
|
-
),
|
|
771
|
-
row=row,
|
|
772
|
-
col=col,
|
|
773
|
-
)
|
|
774
784
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
x=_top.index,
|
|
778
|
-
y=_top.PriceOccured,
|
|
779
|
-
mode="markers",
|
|
780
|
-
name="T",
|
|
781
|
-
marker={"symbol": "triangle-right"},
|
|
782
|
-
),
|
|
783
|
-
row=row,
|
|
784
|
-
col=col,
|
|
785
|
-
)
|
|
785
|
+
_scatter(_bot.PriceOccured, None, "B", "triangle-right", "#3cfa00", 12)
|
|
786
|
+
_scatter(_top.PriceOccured, None, "T", "triangle-right", "#3cfa00", 12)
|
|
786
787
|
|
|
787
|
-
#
|
|
788
|
+
# executions from executor's log
|
|
788
789
|
elif self._frame_has_cols(y, ["exec_price", "quantity"]):
|
|
789
790
|
_b_ords = yy[yy.quantity > 0]
|
|
790
791
|
_s_ords = yy[yy.quantity < 0]
|
|
791
|
-
self.fig.add_trace(
|
|
792
|
-
go.Scatter(
|
|
793
|
-
x=_b_ords.index,
|
|
794
|
-
y=_b_ords.exec_price,
|
|
795
|
-
mode="markers",
|
|
796
|
-
name="BOT",
|
|
797
|
-
marker={
|
|
798
|
-
"symbol": "triangle-up",
|
|
799
|
-
"size": 13,
|
|
800
|
-
"color": "#3cfa00",
|
|
801
|
-
},
|
|
802
|
-
),
|
|
803
|
-
row=row,
|
|
804
|
-
col=col,
|
|
805
|
-
)
|
|
806
792
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
793
|
+
_scatter(_b_ords.exec_price, None, "BOT", "triangle-up", "#3cfa00", 12)
|
|
794
|
+
_scatter(_s_ords.exec_price, None, "SLD", "triangle-down", "#20ffff", 12)
|
|
795
|
+
|
|
796
|
+
# 27-aug-2024: show generated signals from Qubx backtester
|
|
797
|
+
elif self._frame_has_cols(y, ["signal", "reference_price", "price", "take", "stop", "group", "comment"]):
|
|
798
|
+
_sel_price = lambda x: x["reference_price"].where(x["price"].isna(), x["price"])
|
|
799
|
+
_b_sigs = yy[yy.signal > 0]
|
|
800
|
+
_z_sigs = yy[yy.signal == 0]
|
|
801
|
+
_s_sigs = yy[yy.signal < 0]
|
|
802
|
+
# - Longs
|
|
803
|
+
_scatter(_sel_price(_b_sigs), _b_sigs["comment"], "LONG", "triangle-up-open-dot", "#3cfa00")
|
|
804
|
+
_scatter(_b_sigs[~_b_sigs["take"].isna()]["take"], None, "Take", "line-ew-open", "#3cfa00")
|
|
805
|
+
_scatter(_b_sigs[~_b_sigs["stop"].isna()]["stop"], None, "Stop", "line-ew-open", "#fa3c00")
|
|
806
|
+
|
|
807
|
+
# - Shorts
|
|
808
|
+
_scatter(_sel_price(_s_sigs), _s_sigs["comment"], "SHORTS", "triangle-down-open-dot", "#20ffff")
|
|
809
|
+
_scatter(_s_sigs[~_s_sigs["take"].isna()]["take"], None, "Take", "line-ew-open", "#3cfa00")
|
|
810
|
+
_scatter(_s_sigs[~_s_sigs["stop"].isna()]["stop"], None, "Stop", "line-ew-open", "#fa3c00")
|
|
811
|
+
|
|
812
|
+
# - Exits
|
|
813
|
+
_scatter(_sel_price(_z_sigs), _z_sigs["comment"], "EXITS", "circle-open-dot", "#ffffff")
|
|
822
814
|
|
|
823
815
|
else:
|
|
824
816
|
for _col in yy.columns:
|
|
825
817
|
self.__plot_as_type(yy[_col], row, col, plot_style, _col)
|
|
826
818
|
else:
|
|
819
|
+
y = y.pd() if isinstance(y, TimeSeries) else y
|
|
827
820
|
yy = y[zoom] if zoom else y
|
|
828
821
|
self.__plot_as_type(yy, row, col, plot_style, _lbl)
|
|
829
822
|
|
|
@@ -13,13 +13,13 @@ qubx/core/exceptions.py,sha256=W1gG_0fE3o2EMGUfOeOl3vVJDp8Z1iHLv4iZ0ThNkTs,306
|
|
|
13
13
|
qubx/core/helpers.py,sha256=JAB1kcKO8l--gxg9_W2BzWW1N4x72sicw1oBszKYcbo,12657
|
|
14
14
|
qubx/core/loggers.py,sha256=6P3NwoyHe_pTW8Kdvmi8eHoCxHAWm7LEvwgmX-vZKR4,16530
|
|
15
15
|
qubx/core/lookups.py,sha256=qGOSb2SIxmgVPGJFLJnPDI1P9hCzFMVipRDcVLUm8qk,14599
|
|
16
|
-
qubx/core/metrics.py,sha256=
|
|
17
|
-
qubx/core/series.cpython-311-x86_64-linux-gnu.so,sha256=
|
|
18
|
-
qubx/core/series.pxd,sha256=
|
|
19
|
-
qubx/core/series.pyi,sha256=
|
|
16
|
+
qubx/core/metrics.py,sha256=ekralqco-lEW1wryUChQJXck4NXeBS_6o4raC9HIi-c,38010
|
|
17
|
+
qubx/core/series.cpython-311-x86_64-linux-gnu.so,sha256=cDOxqeo2LYUOJO0zdJstmVcwmtBEvtxdOaBl2HfiG5w,762504
|
|
18
|
+
qubx/core/series.pxd,sha256=34g0Q3VCGfqgseCIwOXj4QdIhwT1PO_Nt0nJjNCHBd8,3001
|
|
19
|
+
qubx/core/series.pyi,sha256=CHPQYl96qzfJkZwh1ZIUpLlnUxxfPsxCV54h_Bkwrok,2409
|
|
20
20
|
qubx/core/series.pyx,sha256=7R0SQ3OKfxqdxlbBXAG1ld3WS-vrMT9us1Tvq21GLFY,31116
|
|
21
21
|
qubx/core/strategy.py,sha256=RY2fdg7lvLquTxfUamewO51yaRVTElJLmariTB4e3CQ,10901
|
|
22
|
-
qubx/core/utils.cpython-311-x86_64-linux-gnu.so,sha256=
|
|
22
|
+
qubx/core/utils.cpython-311-x86_64-linux-gnu.so,sha256=a4hfxig8tIu_qYfNl3GaQYOZHyYNq69Qkm-UuhpZYr0,82504
|
|
23
23
|
qubx/core/utils.pyi,sha256=DAjyRVPJSxK4Em-9wui2F0yYHfP5tI5DjKavXNOnHa8,276
|
|
24
24
|
qubx/core/utils.pyx,sha256=gWLTJzFvvqYlVjSbGccAizdkLinAUEVUcfF-eKWpCHo,1660
|
|
25
25
|
qubx/data/helpers.py,sha256=A0NGzhpXYWD92-GeB8TghwMnR0NW8bjcNJOCXybQw3g,782
|
|
@@ -35,10 +35,10 @@ qubx/pandaz/__init__.py,sha256=Iw5uzicYGSC3FEKZ-W1O5-7cXq_P0kH11-EcXV0zZhs,175
|
|
|
35
35
|
qubx/pandaz/ta.py,sha256=NthiiueUoqWGRcjovcKKThcCcdImZn3JRdWDA2vL28k,85075
|
|
36
36
|
qubx/pandaz/utils.py,sha256=XB28Zwv3cXWbKFXbcV5QGj_d6w-i8Yo4LYkX8aPuCHo,19613
|
|
37
37
|
qubx/ta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
38
|
-
qubx/ta/indicators.cpython-311-x86_64-linux-gnu.so,sha256=
|
|
39
|
-
qubx/ta/indicators.pxd,sha256=
|
|
40
|
-
qubx/ta/indicators.pyi,sha256=
|
|
41
|
-
qubx/ta/indicators.pyx,sha256=
|
|
38
|
+
qubx/ta/indicators.cpython-311-x86_64-linux-gnu.so,sha256=JIJfyHATfo-Cu82ly-AypZhP7UIbewsGbWFEj7MxZqM,563816
|
|
39
|
+
qubx/ta/indicators.pxd,sha256=N_p3HNlBDq5S7fRNgN4ZmmdslMBTS_nvn-vNn7T0vHQ,3941
|
|
40
|
+
qubx/ta/indicators.pyi,sha256=l63i_sk3wpy7HHAjgspOPjuIi6QLVPMfgpAHGHSKOcs,1670
|
|
41
|
+
qubx/ta/indicators.pyx,sha256=Cf2_38EnxqqwRXoGqfEoE3th9b4G0VllZ5jtnNYr2_E,23251
|
|
42
42
|
qubx/trackers/__init__.py,sha256=-Hmlc8Mpdi_t6kyeW4ZtmYkHzrULaIb6gUsAkhUxA-4,169
|
|
43
43
|
qubx/trackers/composite.py,sha256=rYQCaxu4IKLf5sS3DCyUUJaSUQwbCy6UMoVjsS-481A,6222
|
|
44
44
|
qubx/trackers/rebalancers.py,sha256=dp-jemxczT8ndkjjzljsIgGnnA6lZQhsf5c4YdmHKCw,6048
|
|
@@ -46,13 +46,13 @@ qubx/trackers/riskctrl.py,sha256=8P5iyaJ-PKhIX8GkGBpncQdxnefL1QWRWG-Jx1PFTuk,125
|
|
|
46
46
|
qubx/trackers/sizers.py,sha256=Wkpclaw7mfR_eMc9xMjN2AFgvOpY1jzaz3wDQvs9H0U,5988
|
|
47
47
|
qubx/utils/__init__.py,sha256=AL2YibJ3tqBKsZZLUjM9N2J5yy-Kq__k_44oTODQ5sM,321
|
|
48
48
|
qubx/utils/_pyxreloader.py,sha256=FyqGzfSpZGYziB8JYS5AP3cLRAvJSIPAKgwQn0E4YQ0,12017
|
|
49
|
-
qubx/utils/charting/lookinglass.py,sha256=
|
|
49
|
+
qubx/utils/charting/lookinglass.py,sha256=cyNGy-df5f9tg-gskb1IFUv7Nh8etn5a3BubdeQh7Ew,39111
|
|
50
50
|
qubx/utils/charting/mpl_helpers.py,sha256=z6vL0IllTZeD-Oe-alVW-kYOP_deHyyoFcukvOVwSz8,35354
|
|
51
51
|
qubx/utils/marketdata/binance.py,sha256=36dl4rxOAGTeY3uoONmiPanj8BkP0oBdDiH-URJJo9A,10993
|
|
52
52
|
qubx/utils/misc.py,sha256=Av0mhrPCy5NZRrRmjOAhTKusa8wVdL7vCQtEy9bVnz4,10450
|
|
53
53
|
qubx/utils/ntp.py,sha256=LZo4FPVY3rqLUV9VWkLcZaPOpUDFC8Qleynmfggg9No,1758
|
|
54
54
|
qubx/utils/runner.py,sha256=Czo01KUCc9Oj9TIcs03d6Qh7fOpQV5w8oH6UDZ6Yqn0,9539
|
|
55
55
|
qubx/utils/time.py,sha256=ioIos3VLA-iYI8LiQIn2m-t0Y37CEQAHFw_-C9Uwo0o,5188
|
|
56
|
-
qubx-0.2.
|
|
57
|
-
qubx-0.2.
|
|
58
|
-
qubx-0.2.
|
|
56
|
+
qubx-0.2.65.dist-info/METADATA,sha256=Ej6wJoKYygR3GPWrkKuLjgIORFZF2JRphvXyNN_Iyvo,2573
|
|
57
|
+
qubx-0.2.65.dist-info/WHEEL,sha256=MLOa6LysROdjgj4FVxsHitAnIh8Be2D_c9ZSBHKrz2M,110
|
|
58
|
+
qubx-0.2.65.dist-info/RECORD,,
|
|
File without changes
|