Qubx 0.6.71__cp312-cp312-manylinux_2_39_x86_64.whl → 0.6.73__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/backtester/data.py +16 -6
- qubx/backtester/runner.py +7 -4
- qubx/connectors/ccxt/adapters/polling_adapter.py +151 -343
- qubx/connectors/ccxt/connection_manager.py +122 -133
- qubx/connectors/ccxt/data.py +108 -43
- qubx/connectors/ccxt/exchanges/__init__.py +26 -0
- qubx/connectors/ccxt/exchanges/base.py +63 -0
- qubx/connectors/ccxt/exchanges/binance/exchange.py +186 -166
- qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +3 -1
- qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +6 -1
- qubx/connectors/ccxt/exchanges/hyperliquid/broker.py +69 -0
- qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +385 -27
- qubx/connectors/ccxt/exchanges/kraken/kraken.py +3 -1
- qubx/connectors/ccxt/factory.py +4 -0
- qubx/connectors/ccxt/handlers/base.py +2 -1
- qubx/connectors/ccxt/handlers/funding_rate.py +88 -88
- qubx/connectors/ccxt/handlers/liquidation.py +1 -0
- qubx/connectors/ccxt/handlers/ohlc.py +63 -45
- qubx/connectors/ccxt/handlers/open_interest.py +12 -13
- qubx/connectors/ccxt/handlers/orderbook.py +65 -39
- qubx/connectors/ccxt/handlers/quote.py +3 -1
- qubx/connectors/ccxt/handlers/trade.py +15 -1
- qubx/connectors/ccxt/reader.py +179 -72
- qubx/connectors/ccxt/subscription_config.py +39 -34
- qubx/connectors/ccxt/subscription_manager.py +103 -118
- qubx/connectors/ccxt/subscription_orchestrator.py +265 -228
- qubx/connectors/ccxt/utils.py +50 -26
- qubx/core/account.py +5 -5
- qubx/core/basics.py +24 -0
- qubx/core/initializer.py +7 -0
- qubx/core/interfaces.py +21 -5
- qubx/core/mixins/subscription.py +6 -1
- qubx/core/series.cpython-312-x86_64-linux-gnu.so +0 -0
- qubx/core/utils.cpython-312-x86_64-linux-gnu.so +0 -0
- qubx/data/readers.py +11 -0
- qubx/ta/indicators.cpython-312-x86_64-linux-gnu.so +0 -0
- qubx/trackers/advanced.py +41 -4
- qubx/utils/charting/mpl_helpers.py +134 -0
- qubx/utils/charting/orderbook.py +314 -0
- qubx/utils/runner/runner.py +9 -0
- {qubx-0.6.71.dist-info → qubx-0.6.73.dist-info}/METADATA +1 -1
- {qubx-0.6.71.dist-info → qubx-0.6.73.dist-info}/RECORD +45 -42
- {qubx-0.6.71.dist-info → qubx-0.6.73.dist-info}/LICENSE +0 -0
- {qubx-0.6.71.dist-info → qubx-0.6.73.dist-info}/WHEEL +0 -0
- {qubx-0.6.71.dist-info → qubx-0.6.73.dist-info}/entry_points.txt +0 -0
qubx/backtester/data.py
CHANGED
|
@@ -27,7 +27,7 @@ def _get_first_existing(data: dict, keys: list, default: T = None) -> T:
|
|
|
27
27
|
data_get = data.get # Cache method lookup
|
|
28
28
|
sentinel = object()
|
|
29
29
|
for key in keys:
|
|
30
|
-
if (value := data_get(key, sentinel)) is not sentinel:
|
|
30
|
+
if (value := data_get(key, sentinel)) is not sentinel and value is not None:
|
|
31
31
|
return value
|
|
32
32
|
return default
|
|
33
33
|
|
|
@@ -169,14 +169,24 @@ class SimulatedDataProvider(IDataProvider):
|
|
|
169
169
|
if _b_ts_0 <= cut_time_ns and cut_time_ns < _b_ts_1:
|
|
170
170
|
break
|
|
171
171
|
|
|
172
|
+
# Handle None values in OHLC data
|
|
173
|
+
open_price = r.data["open"]
|
|
174
|
+
high_price = r.data["high"]
|
|
175
|
+
low_price = r.data["low"]
|
|
176
|
+
close_price = r.data["close"]
|
|
177
|
+
|
|
178
|
+
# Skip this record if any OHLC value is None
|
|
179
|
+
if open_price is None or high_price is None or low_price is None or close_price is None:
|
|
180
|
+
continue
|
|
181
|
+
|
|
172
182
|
bars.append(
|
|
173
183
|
Bar(
|
|
174
184
|
_b_ts_0,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
volume=r.data.get("volume", 0),
|
|
185
|
+
open_price,
|
|
186
|
+
high_price,
|
|
187
|
+
low_price,
|
|
188
|
+
close_price,
|
|
189
|
+
volume=r.data.get("volume", 0) or 0, # Handle None volume
|
|
180
190
|
bought_volume=_get_first_existing(r.data, ["taker_buy_volume", "bought_volume"], 0),
|
|
181
191
|
volume_quote=_get_first_existing(r.data, ["quote_volume", "volume_quote"], 0),
|
|
182
192
|
bought_volume_quote=_get_first_existing(
|
qubx/backtester/runner.py
CHANGED
|
@@ -4,10 +4,9 @@ import numpy as np
|
|
|
4
4
|
import pandas as pd
|
|
5
5
|
from tqdm.auto import tqdm
|
|
6
6
|
|
|
7
|
-
from qubx import logger
|
|
7
|
+
from qubx import QubxLogConfig, logger
|
|
8
8
|
from qubx.backtester.sentinels import NoDataContinue
|
|
9
9
|
from qubx.backtester.simulated_data import IterableSimulationData
|
|
10
|
-
from qubx.backtester.utils import SimulationDataConfig, TimeGuardedWrapper
|
|
11
10
|
from qubx.core.account import CompositeAccountProcessor
|
|
12
11
|
from qubx.core.basics import SW, DataType, Instrument, TransactionCostsCalculator
|
|
13
12
|
from qubx.core.context import StrategyContext
|
|
@@ -41,6 +40,7 @@ from .utils import (
|
|
|
41
40
|
SimulatedTimeProvider,
|
|
42
41
|
SimulationDataConfig,
|
|
43
42
|
SimulationSetup,
|
|
43
|
+
TimeGuardedWrapper,
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
|
|
@@ -328,6 +328,7 @@ class SimulationRunner:
|
|
|
328
328
|
|
|
329
329
|
if not _run(instrument, data_type, event, is_hist):
|
|
330
330
|
return False
|
|
331
|
+
|
|
331
332
|
return True
|
|
332
333
|
|
|
333
334
|
def _handle_no_data_scenario(self, stop_time):
|
|
@@ -356,8 +357,9 @@ class SimulationRunner:
|
|
|
356
357
|
return False # No scheduled events, stop simulation
|
|
357
358
|
|
|
358
359
|
def print_latency_report(self) -> None:
|
|
359
|
-
_l_r
|
|
360
|
-
|
|
360
|
+
if (_l_r := SW.latency_report()) is not None:
|
|
361
|
+
_llvl = QubxLogConfig.get_log_level()
|
|
362
|
+
QubxLogConfig.set_log_level("INFO")
|
|
361
363
|
logger.info(
|
|
362
364
|
"<BLUE> Time spent in simulation report </BLUE>\n<r>"
|
|
363
365
|
+ _frame_to_str(
|
|
@@ -365,6 +367,7 @@ class SimulationRunner:
|
|
|
365
367
|
)
|
|
366
368
|
+ "</r>"
|
|
367
369
|
)
|
|
370
|
+
QubxLogConfig.set_log_level(_llvl)
|
|
368
371
|
|
|
369
372
|
def _create_backtest_context(self) -> IStrategyContext:
|
|
370
373
|
logger.debug(
|