Qubx 0.1.87__tar.gz → 0.1.89__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.
- {qubx-0.1.87 → qubx-0.1.89}/PKG-INFO +1 -1
- {qubx-0.1.87 → qubx-0.1.89}/build.py +12 -17
- {qubx-0.1.87 → qubx-0.1.89}/pyproject.toml +1 -1
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/ta/indicators.pyx +26 -3
- {qubx-0.1.87 → qubx-0.1.89}/README.md +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/_nb_magic.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/account.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/basics.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/helpers.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/loggers.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/lookups.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/series.pxd +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/series.pyx +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/strategy.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/core/utils.pyx +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/data/readers.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/impl/ccxt_connector.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/impl/ccxt_customizations.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/impl/ccxt_trading.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/impl/ccxt_utils.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/math/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/math/stats.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/pandaz/ta.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/pandaz/utils.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/ta/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/trackers/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/__init__.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/misc.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/runner.py +0 -0
- {qubx-0.1.87 → qubx-0.1.89}/src/qubx/utils/time.py +0 -0
|
@@ -17,6 +17,8 @@ from Cython.Compiler.Version import version as cython_compiler_version
|
|
|
17
17
|
from setuptools import Distribution
|
|
18
18
|
from setuptools import Extension
|
|
19
19
|
|
|
20
|
+
RED, BLUE, GREEN, YLW, RES = "\033[31m", "\033[36m", "\033[32m", "\033[33m", "\033[0m"
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
BUILD_MODE = os.getenv("BUILD_MODE", "release")
|
|
22
24
|
PROFILE_MODE = bool(os.getenv("PROFILE_MODE", ""))
|
|
@@ -95,13 +97,13 @@ def _build_extensions() -> list[Extension]:
|
|
|
95
97
|
"WS2_32.Lib",
|
|
96
98
|
]
|
|
97
99
|
|
|
98
|
-
print("Creating C extension modules...")
|
|
100
|
+
print(f">> {GREEN} Creating C extension modules...{RES}")
|
|
99
101
|
print(f"define_macros={define_macros}")
|
|
100
102
|
print(f"extra_compile_args={extra_compile_args}")
|
|
101
103
|
|
|
102
104
|
return [
|
|
103
105
|
Extension(
|
|
104
|
-
name=str(pyx.relative_to("
|
|
106
|
+
name=str(pyx.relative_to("src")).replace(os.path.sep, ".")[:-4],
|
|
105
107
|
sources=[str(pyx)],
|
|
106
108
|
include_dirs=[np.get_include()], # , *RUST_INCLUDES],
|
|
107
109
|
define_macros=define_macros,
|
|
@@ -138,7 +140,7 @@ def _build_distribution(extensions: list[Extension]) -> Distribution:
|
|
|
138
140
|
def _copy_build_dir_to_project(cmd: build_ext) -> None:
|
|
139
141
|
# Copy built extensions back to the project tree
|
|
140
142
|
for output in cmd.get_outputs():
|
|
141
|
-
relative_extension = Path(output).relative_to(cmd.build_lib)
|
|
143
|
+
relative_extension = Path("src") / Path(output).relative_to(cmd.build_lib)
|
|
142
144
|
if not Path(output).exists():
|
|
143
145
|
continue
|
|
144
146
|
|
|
@@ -148,21 +150,19 @@ def _copy_build_dir_to_project(cmd: build_ext) -> None:
|
|
|
148
150
|
mode |= (mode & 0o444) >> 2
|
|
149
151
|
relative_extension.chmod(mode)
|
|
150
152
|
|
|
151
|
-
print("Copied all compiled dynamic library files into source")
|
|
153
|
+
print(f" >> {GREEN}Copied all compiled dynamic library files into source{RES}")
|
|
152
154
|
|
|
153
155
|
|
|
154
156
|
def _strip_unneeded_symbols() -> None:
|
|
155
157
|
try:
|
|
156
|
-
print("Stripping unneeded symbols from binaries...")
|
|
158
|
+
print(f" >> {YLW}Stripping unneeded symbols from binaries...{RES}")
|
|
157
159
|
for so in itertools.chain(Path("src/qubx").rglob("*.so")):
|
|
158
160
|
if platform.system() == "Linux":
|
|
159
161
|
strip_cmd = ["strip", "--strip-unneeded", so]
|
|
160
162
|
elif platform.system() == "Darwin":
|
|
161
163
|
strip_cmd = ["strip", "-x", so]
|
|
162
164
|
else:
|
|
163
|
-
raise RuntimeError(
|
|
164
|
-
f"Cannot strip symbols for platform {platform.system()}"
|
|
165
|
-
)
|
|
165
|
+
raise RuntimeError(f"Cannot strip symbols for platform {platform.system()}")
|
|
166
166
|
subprocess.run(
|
|
167
167
|
strip_cmd, # type: ignore [arg-type] # noqa
|
|
168
168
|
check=True,
|
|
@@ -185,7 +185,7 @@ def build() -> None:
|
|
|
185
185
|
distribution = _build_distribution(extensions)
|
|
186
186
|
|
|
187
187
|
# Build and run the command
|
|
188
|
-
print("Compiling C extension modules...")
|
|
188
|
+
print(f">> {GREEN} Compiling C extension modules...{RES}")
|
|
189
189
|
cmd: build_ext = build_ext(distribution)
|
|
190
190
|
# if PARALLEL_BUILD:
|
|
191
191
|
# cmd.parallel = os.cpu_count()
|
|
@@ -201,15 +201,12 @@ def build() -> None:
|
|
|
201
201
|
_strip_unneeded_symbols()
|
|
202
202
|
|
|
203
203
|
|
|
204
|
-
RED, BLUE, GREEN, YLW, RES = "\033[31m", "\033[36m", "\033[32m", "\033[33m", "\033[0m"
|
|
205
204
|
if __name__ == "__main__":
|
|
206
205
|
qubx_platform = toml.load("pyproject.toml")["tool"]["poetry"]["version"]
|
|
207
206
|
print(BLUE)
|
|
208
207
|
print("=====================================================================")
|
|
209
208
|
print(f"Qubx Builder {qubx_platform}")
|
|
210
|
-
print(
|
|
211
|
-
"=====================================================================\033[0m"
|
|
212
|
-
)
|
|
209
|
+
print("=====================================================================\033[0m")
|
|
213
210
|
print(f"System: {GREEN}{platform.system()} {platform.machine()}{RES}")
|
|
214
211
|
# print(f"Clang: {GREEN}{_get_clang_version()}{RES}")
|
|
215
212
|
# print(f"Rust: {GREEN}{_get_rustc_version()}{RES}")
|
|
@@ -225,12 +222,10 @@ if __name__ == "__main__":
|
|
|
225
222
|
print(f"COPY_TO_SOURCE={COPY_TO_SOURCE}")
|
|
226
223
|
# print(f"PYO3_ONLY={PYO3_ONLY}\n")
|
|
227
224
|
|
|
228
|
-
print("Starting build...")
|
|
225
|
+
print(f">> {GREEN}Starting build...{RES}")
|
|
229
226
|
ts_start = datetime.datetime.now(datetime.timezone.utc)
|
|
230
227
|
build()
|
|
231
|
-
print(
|
|
232
|
-
f"Build time: {YLW}{datetime.datetime.now(datetime.timezone.utc) - ts_start}{RES}"
|
|
233
|
-
)
|
|
228
|
+
print(f"Build time: {YLW}{datetime.datetime.now(datetime.timezone.utc) - ts_start}{RES}")
|
|
234
229
|
print(GREEN + "Build completed" + RES)
|
|
235
230
|
|
|
236
231
|
# # See if Cython is installed
|
|
@@ -627,14 +627,21 @@ cdef class Swings(IndicatorOHLC):
|
|
|
627
627
|
cdef long long _max_t
|
|
628
628
|
cdef OHLCV base
|
|
629
629
|
cdef Indicator trend
|
|
630
|
-
|
|
631
|
-
|
|
630
|
+
# tops contain upper pivot point prices
|
|
631
|
+
# tops_detection_lag contain time lag when top was actually spotted
|
|
632
|
+
cdef public TimeSeries tops, tops_detection_lag
|
|
633
|
+
cdef public TimeSeries bottoms, bottoms_detection_lag
|
|
632
634
|
|
|
633
635
|
def __init__(self, str name, OHLCV series, trend_indicator, **indicator_args):
|
|
634
636
|
self.base = OHLCV("base", series.timeframe, series.max_series_length)
|
|
635
637
|
self.trend = trend_indicator(self.base, **indicator_args)
|
|
638
|
+
|
|
636
639
|
self.tops = TimeSeries("tops", series.timeframe, series.max_series_length)
|
|
640
|
+
self.tops_detection_lag = TimeSeries("tops_lag", series.timeframe, series.max_series_length)
|
|
641
|
+
|
|
637
642
|
self.bottoms = TimeSeries("bottoms", series.timeframe, series.max_series_length)
|
|
643
|
+
self.bottoms_detection_lag = TimeSeries("bottoms_lag", series.timeframe, series.max_series_length)
|
|
644
|
+
|
|
638
645
|
self._min_l = +np.inf
|
|
639
646
|
self._max_h = -np.inf
|
|
640
647
|
self._max_t = 0
|
|
@@ -652,6 +659,7 @@ cdef class Swings(IndicatorOHLC):
|
|
|
652
659
|
if not np.isnan(_u):
|
|
653
660
|
if self._max_t > 0:
|
|
654
661
|
self.tops.update(self._max_t, self._max_h)
|
|
662
|
+
self.tops_detection_lag.update(self._max_t, time - self._max_t)
|
|
655
663
|
|
|
656
664
|
if bar.low <= self._min_l:
|
|
657
665
|
self._min_l = bar.low
|
|
@@ -663,6 +671,7 @@ cdef class Swings(IndicatorOHLC):
|
|
|
663
671
|
elif not np.isnan(_d):
|
|
664
672
|
if self._min_t > 0:
|
|
665
673
|
self.bottoms.update(self._min_t, self._min_l)
|
|
674
|
+
self.bottoms_detection_lag.update(self._min_t, time - self._min_t)
|
|
666
675
|
|
|
667
676
|
if bar.high >= self._max_h:
|
|
668
677
|
self._max_h = bar.high
|
|
@@ -684,20 +693,34 @@ cdef class Swings(IndicatorOHLC):
|
|
|
684
693
|
def pd(self) -> pd.DataFrame:
|
|
685
694
|
_t, _d = self.get_current_trend_end()
|
|
686
695
|
tps, bts = self.tops.pd(), self.bottoms.pd()
|
|
696
|
+
tpl, btl = self.tops_detection_lag.pd(), self.bottoms_detection_lag.pd()
|
|
687
697
|
if _t is not None:
|
|
688
698
|
if bts.index[-1] < tps.index[-1]:
|
|
689
699
|
bts = srows(bts, pd.Series({_t: _d}))
|
|
700
|
+
btl = srows(btl, pd.Series({_t: 0})) # last lag is 0
|
|
690
701
|
else:
|
|
691
702
|
tps = srows(tps, pd.Series({_t: _d}))
|
|
703
|
+
tpl = srows(tpl, pd.Series({_t: 0})) # last lag is 0
|
|
704
|
+
|
|
705
|
+
# - convert tpl / btl to timedeltas
|
|
706
|
+
tpl, btl = tpl.apply(lambda x: pd.Timedelta(x, unit='ns')), btl.apply(lambda x: pd.Timedelta(x, unit='ns'))
|
|
692
707
|
|
|
693
708
|
eid = pd.Series(tps.index, tps.index)
|
|
694
709
|
mx = scols(bts, tps, eid, names=["start_price", "end_price", "end"])
|
|
695
710
|
dt = scols(mx["start_price"], mx["end_price"].shift(-1), mx["end"].shift(-1)) # .dropna()
|
|
696
|
-
dt = dt.assign(
|
|
711
|
+
dt = dt.assign(
|
|
712
|
+
delta = dt["end_price"] - dt["start_price"],
|
|
713
|
+
spotted = pd.Series(bts.index + btl, bts.index)
|
|
714
|
+
)
|
|
697
715
|
|
|
698
716
|
eid = pd.Series(bts.index, bts.index)
|
|
699
717
|
mx = scols(tps, bts, eid, names=["start_price", "end_price", "end"])
|
|
700
718
|
ut = scols(mx["start_price"], mx["end_price"].shift(-1), mx["end"].shift(-1)) # .dropna()
|
|
719
|
+
ut = ut.assign(
|
|
720
|
+
delta = ut["end_price"] - ut["start_price"],
|
|
721
|
+
spotted = pd.Series(tps.index + tpl, tps.index)
|
|
722
|
+
)
|
|
723
|
+
|
|
701
724
|
return scols(ut, dt, keys=["DownTrends", "UpTrends"])
|
|
702
725
|
|
|
703
726
|
|
|
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
|