Qubx 1.1.2.dev13__tar.gz → 1.1.2.dev15__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.
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/PKG-INFO +1 -1
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/_version.py +2 -2
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/runner.py +5 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/simulated_data.py +11 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/exceptions.py +4 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/runner.py +140 -2
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/.gitignore +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/LICENSE +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/README.md +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/pyproject.toml +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/scripts/build.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/_nb_magic.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/account.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/broker.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/data.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/iteratedstream.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/management.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/ome.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/optimization.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/sentinels.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/simulated_exchange.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/simulator.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/transfers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/backtester/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/commands.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/deploy.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/misc.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/release.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/resolver.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/s3.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/theme.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/tui.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/cli/user_config.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/config.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/account.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/broker.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/connection_manager.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/data.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exceptions.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/base.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/account.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/broker.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/okx/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/okx/account.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/okx/broker.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/okx/okx.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/factory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/ohlc.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/warmup_service.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/registry.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/tardis/data.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/tardis/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/account.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/basics.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/context.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/detectors/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/detectors/delisting.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/detectors/stale.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/errors.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/helpers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/initializer.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/interfaces.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/loggers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/lookups.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/metrics.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/market.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/processing.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/subscription.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/trading.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/universe.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/mixins/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/series.pxd +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/series.pyi +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/series.pyx +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/utils.pyi +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/core/utils.pyx +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/cache.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/containers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/guards.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/registry.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storage.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/ccxt.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/csv.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/handy.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/multi.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/questdb.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/stub.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/storages/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/data/transformers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/base.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/composite.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/csv.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/indicator.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/inmemory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/prometheus.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/emitters/questdb.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/composite.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/formatters/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/formatters/base.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/formatters/incremental.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/formatters/slack.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/formatters/target_position.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/redis_streams.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/exporters/slack.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/gathering/simplest.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/health/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/health/base.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/health/dummy.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/health/server.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/loggers/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/loggers/csv.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/loggers/factory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/loggers/inmemory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/loggers/mongo.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/loggers/postgres.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/notifications/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/notifications/composite.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/notifications/slack.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/notifications/throttler.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/pandaz/stats.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/pandaz/ta.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/pandaz/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/plugins/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/plugins/loader.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/_build.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/crypto-fees.ini +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restarts/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restarts/state_resolvers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restarts/time_finders.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/balance.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/factory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/interfaces.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/position.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/signal.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/state.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/restorers/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/state/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/state/dummy.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/state/redis.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/ta/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/base.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/accounts.toml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/config.yml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/jlive.sh.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/project/template.yml +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.claude/skills/qubx-cli/SKILL.md +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.claude/skills/qubx-indicators/SKILL.md +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.claude/skills/simulation-explorer/SKILL.md +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.claude/skills/strategy-release/SKILL.md +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.github/workflows/ci.yml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.gitignore.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.python-version +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.vscode/launch.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.vscode/settings.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/.vscode/tasks.json +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/CLAUDE.md.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/README.md.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/configs/.gitkeep +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/justfile.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/pyproject.toml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/research/.gitkeep +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/src/{{ strategy_name }}/cli.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/template.yml +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/repo/tests/test_strategy.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/__init__.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/config.yml.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/strategy.py.j2 +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/templates/simple/template.yml +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/trackers/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/trackers/advanced.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/trackers/composite.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/trackers/sizers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/charting/lookinglass.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/charting/orderbook.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/collections.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/hft/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/hft/numba_utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/hft/orderbook.pyi +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/hft/orderbook.pyx +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/marketdata/ccxt.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/marketdata/dukas.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/misc.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/nonce.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/ntp.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/numbers_utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/orderbook.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/plotting/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/plotting/dashboard.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/plotting/data.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/plotting/interfaces.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/questdb.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/rate_limiter.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/results.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/ringbuffer.pxd +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/ringbuffer.pyi +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/ringbuffer.pyx +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/accounts.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/configs.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/factory.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/kernel_service.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/app.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/handlers.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/init_code.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/kernel.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/styles.tcss +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/account_summary.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/s3.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/slack.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/throttler.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/time.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/utils/websocket_manager.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
- {qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/tests/strategies/obi_trader/src/obi_trader/models/obi_trader.py +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.1.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 1, 2, '
|
|
21
|
+
__version__ = version = '1.1.2.dev15'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 1, 2, 'dev15')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -131,6 +131,11 @@ class SimulationRunner:
|
|
|
131
131
|
self._create_backtest_context()
|
|
132
132
|
self._handle_ctx_subscriptions()
|
|
133
133
|
|
|
134
|
+
@property
|
|
135
|
+
def data_time_range(self) -> tuple[int, int] | None:
|
|
136
|
+
"""Time range (ns) of historical data actually processed: (first, last), or None if no data arrived."""
|
|
137
|
+
return self._simulated_data_source.data_time_range
|
|
138
|
+
|
|
134
139
|
def run(self, silent: bool = False, catch_keyboard_interrupt: bool = True, close_data_readers: bool = False):
|
|
135
140
|
"""
|
|
136
141
|
Run the backtest from start to stop.
|
|
@@ -846,9 +846,17 @@ class SimulatedDataIterator(Iterator):
|
|
|
846
846
|
self._slicer = None
|
|
847
847
|
self._slicing_iterator = None
|
|
848
848
|
self._current_time = None
|
|
849
|
+
self._first_data_time: int | None = None
|
|
849
850
|
self._start = None
|
|
850
851
|
self._stop = None
|
|
851
852
|
|
|
853
|
+
@property
|
|
854
|
+
def data_time_range(self) -> tuple[int, int] | None:
|
|
855
|
+
"""Time range (ns) of historical data actually processed: (first, last), or None if no data arrived."""
|
|
856
|
+
if self._first_data_time is not None and self._current_time is not None:
|
|
857
|
+
return (self._first_data_time, self._current_time)
|
|
858
|
+
return None
|
|
859
|
+
|
|
852
860
|
@property
|
|
853
861
|
def emulation_time_indent_seconds(self) -> float:
|
|
854
862
|
"""
|
|
@@ -1104,6 +1112,7 @@ class SimulatedDataIterator(Iterator):
|
|
|
1104
1112
|
self._start = to_timestamp(start)
|
|
1105
1113
|
self._stop = to_timestamp(stop)
|
|
1106
1114
|
self._current_time = None
|
|
1115
|
+
self._first_data_time = None
|
|
1107
1116
|
self._slicer = IteratedDataStreamsSlicer()
|
|
1108
1117
|
return self
|
|
1109
1118
|
|
|
@@ -1137,6 +1146,8 @@ class SimulatedDataIterator(Iterator):
|
|
|
1137
1146
|
if t < self._current_time:
|
|
1138
1147
|
is_historical = True
|
|
1139
1148
|
else:
|
|
1149
|
+
if self._first_data_time is None:
|
|
1150
|
+
self._first_data_time = t
|
|
1140
1151
|
self._current_time = t
|
|
1141
1152
|
|
|
1142
1153
|
return instr, data_type, v, is_historical
|
|
@@ -2,6 +2,7 @@ import asyncio
|
|
|
2
2
|
import socket
|
|
3
3
|
import time
|
|
4
4
|
from collections import defaultdict
|
|
5
|
+
from dataclasses import dataclass
|
|
5
6
|
from functools import reduce
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from threading import Thread
|
|
@@ -28,6 +29,7 @@ from qubx.core.basics import (
|
|
|
28
29
|
TransactionCostsCalculator,
|
|
29
30
|
)
|
|
30
31
|
from qubx.core.context import StrategyContext
|
|
32
|
+
from qubx.core.exceptions import WarmupValidationError
|
|
31
33
|
from qubx.core.helpers import BasicScheduler
|
|
32
34
|
from qubx.core.initializer import BasicStrategyInitializer
|
|
33
35
|
from qubx.core.interfaces import (
|
|
@@ -274,7 +276,15 @@ def run_strategy(
|
|
|
274
276
|
_health_server.start()
|
|
275
277
|
|
|
276
278
|
# Restore state if configured
|
|
277
|
-
restored_state =
|
|
279
|
+
restored_state = (
|
|
280
|
+
_restore_state(
|
|
281
|
+
restorer_config=config.live.warmup.restorer if config.live.warmup else None,
|
|
282
|
+
logging_config=config.live.logging if config.live.logging else None,
|
|
283
|
+
strategy_name=_get_strategy_name(config),
|
|
284
|
+
)
|
|
285
|
+
if restore
|
|
286
|
+
else None
|
|
287
|
+
)
|
|
278
288
|
|
|
279
289
|
# Resolve aux config with live section override (needed for both warmup and live context)
|
|
280
290
|
aux_configs = resolve_aux_config(config.aux, getattr(config.live, "aux", None))
|
|
@@ -335,7 +345,50 @@ def run_strategy(
|
|
|
335
345
|
return ctx
|
|
336
346
|
|
|
337
347
|
|
|
338
|
-
def
|
|
348
|
+
def _infer_restorer_from_logger(logging_config: LoggingConfig, strategy_name: str) -> RestorerConfig | None:
|
|
349
|
+
"""Infer a matching state restorer config from the logger config."""
|
|
350
|
+
logger_type = logging_config.logger
|
|
351
|
+
args = logging_config.args
|
|
352
|
+
|
|
353
|
+
if logger_type == "PostgresLogsWriter":
|
|
354
|
+
return RestorerConfig(
|
|
355
|
+
type="PostgresStateRestorer",
|
|
356
|
+
parameters={
|
|
357
|
+
"strategy_name": strategy_name,
|
|
358
|
+
"postgres_uri": args.get("postgres_uri", "postgresql://localhost:5432/qubx_logs"),
|
|
359
|
+
"table_prefix": args.get("table_prefix", "qubx_logs"),
|
|
360
|
+
},
|
|
361
|
+
)
|
|
362
|
+
elif logger_type == "MongoDBLogsWriter":
|
|
363
|
+
return RestorerConfig(
|
|
364
|
+
type="MongoDBStateRestorer",
|
|
365
|
+
parameters={
|
|
366
|
+
"strategy_name": strategy_name,
|
|
367
|
+
"mongo_uri": args.get("mongo_uri", "mongodb://localhost:27017/"),
|
|
368
|
+
"db_name": args.get("db_name", "default_logs_db"),
|
|
369
|
+
"collection_name_prefix": args.get("collection_name_prefix", "qubx_logs"),
|
|
370
|
+
},
|
|
371
|
+
)
|
|
372
|
+
elif logger_type == "CsvFileLogsWriter":
|
|
373
|
+
return RestorerConfig(
|
|
374
|
+
type="CsvStateRestorer",
|
|
375
|
+
parameters={
|
|
376
|
+
"strategy_name": strategy_name,
|
|
377
|
+
"base_dir": args.get("log_folder", "logs"),
|
|
378
|
+
},
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
return None
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def _restore_state(
|
|
385
|
+
restorer_config: RestorerConfig | None,
|
|
386
|
+
logging_config: LoggingConfig | None = None,
|
|
387
|
+
strategy_name: str = "",
|
|
388
|
+
) -> RestoredState | None:
|
|
389
|
+
if restorer_config is None and logging_config is not None:
|
|
390
|
+
restorer_config = _infer_restorer_from_logger(logging_config, strategy_name)
|
|
391
|
+
|
|
339
392
|
if restorer_config is None:
|
|
340
393
|
restorer_config = RestorerConfig(type="CsvStateRestorer", parameters={"base_dir": "logs"})
|
|
341
394
|
|
|
@@ -828,6 +881,79 @@ def _apply_inverse_exchange_mapping(exchanges: list[str]) -> list[str]:
|
|
|
828
881
|
return mapped_exchanges
|
|
829
882
|
|
|
830
883
|
|
|
884
|
+
@dataclass(frozen=True)
|
|
885
|
+
class WarmupResult:
|
|
886
|
+
"""Captures the outcome of a warmup simulation for validation."""
|
|
887
|
+
|
|
888
|
+
requested_start_ns: int
|
|
889
|
+
requested_stop_ns: int
|
|
890
|
+
data_start_ns: int | None
|
|
891
|
+
data_stop_ns: int | None
|
|
892
|
+
initial_capital: float
|
|
893
|
+
final_capital: float
|
|
894
|
+
|
|
895
|
+
@property
|
|
896
|
+
def requested_duration_ns(self) -> int:
|
|
897
|
+
return self.requested_stop_ns - self.requested_start_ns
|
|
898
|
+
|
|
899
|
+
@property
|
|
900
|
+
def data_duration_ns(self) -> int:
|
|
901
|
+
if self.data_start_ns is not None and self.data_stop_ns is not None:
|
|
902
|
+
return self.data_stop_ns - self.data_start_ns
|
|
903
|
+
return 0
|
|
904
|
+
|
|
905
|
+
@property
|
|
906
|
+
def coverage_ratio(self) -> float:
|
|
907
|
+
if self.requested_duration_ns <= 0:
|
|
908
|
+
return 1.0
|
|
909
|
+
if self.data_start_ns is None:
|
|
910
|
+
return 0.0
|
|
911
|
+
return max(0.0, self.data_duration_ns / self.requested_duration_ns)
|
|
912
|
+
|
|
913
|
+
@property
|
|
914
|
+
def has_data(self) -> bool:
|
|
915
|
+
return self.data_start_ns is not None
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
def _validate_warmup_result(result: WarmupResult, min_coverage_ratio: float = 0.5) -> None:
|
|
919
|
+
"""Validate that warmup simulation produced usable state for live trading."""
|
|
920
|
+
if not result.has_data:
|
|
921
|
+
raise WarmupValidationError(
|
|
922
|
+
f"Warmup received no data at all. "
|
|
923
|
+
f"Requested window: {to_timedelta(result.requested_duration_ns, unit='ns')}. "
|
|
924
|
+
f"Check your warmup data source configuration."
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
if result.coverage_ratio < min_coverage_ratio:
|
|
928
|
+
data_start_gap = to_timedelta(result.data_start_ns - result.requested_start_ns, unit="ns")
|
|
929
|
+
data_end_gap = to_timedelta(result.requested_stop_ns - result.data_stop_ns, unit="ns")
|
|
930
|
+
raise WarmupValidationError(
|
|
931
|
+
f"Warmup data coverage insufficient: "
|
|
932
|
+
f"received {to_timedelta(result.data_duration_ns, unit='ns')} "
|
|
933
|
+
f"of requested {to_timedelta(result.requested_duration_ns, unit='ns')} "
|
|
934
|
+
f"({result.coverage_ratio:.1%} coverage, minimum required: {min_coverage_ratio:.0%}). "
|
|
935
|
+
f"Data started {data_start_gap} late, ended {data_end_gap} early. "
|
|
936
|
+
f"Check your warmup data source — it may have a max_history limit "
|
|
937
|
+
f"that is shorter than the warmup period."
|
|
938
|
+
)
|
|
939
|
+
|
|
940
|
+
if result.final_capital <= 0:
|
|
941
|
+
raise WarmupValidationError(
|
|
942
|
+
f"Warmup resulted in non-positive capital: {result.final_capital:.2f} "
|
|
943
|
+
f"(started with {result.initial_capital:.2f}). "
|
|
944
|
+
f"This typically means the warmup simulation traded with insufficient data, "
|
|
945
|
+
f"causing unrealistic losses. Check warmup data coverage and indicator warmup periods."
|
|
946
|
+
)
|
|
947
|
+
|
|
948
|
+
if result.initial_capital > 0 and result.final_capital < result.initial_capital * 0.5:
|
|
949
|
+
logger.warning(
|
|
950
|
+
f"<red>Warmup capital dropped significantly: "
|
|
951
|
+
f"{result.initial_capital:.2f} -> {result.final_capital:.2f} "
|
|
952
|
+
f"({(1 - result.final_capital / result.initial_capital):.1%} loss). "
|
|
953
|
+
f"Review warmup data coverage and strategy behavior during warmup.</red>"
|
|
954
|
+
)
|
|
955
|
+
|
|
956
|
+
|
|
831
957
|
def _run_warmup(
|
|
832
958
|
ctx: IStrategyContext,
|
|
833
959
|
restored_state: RestoredState | None,
|
|
@@ -922,6 +1048,7 @@ def _run_warmup(
|
|
|
922
1048
|
initializer=ctx.initializer,
|
|
923
1049
|
warmup_mode=True,
|
|
924
1050
|
)
|
|
1051
|
+
_initial_capital = ctx.account.get_total_capital()
|
|
925
1052
|
|
|
926
1053
|
# - set the time provider to the simulated runner
|
|
927
1054
|
_live_time_provider = simulated_formatter.time_provider
|
|
@@ -944,6 +1071,17 @@ def _run_warmup(
|
|
|
944
1071
|
|
|
945
1072
|
logger.info("<yellow>Warmup completed</yellow>")
|
|
946
1073
|
|
|
1074
|
+
data_range = warmup_runner.data_time_range
|
|
1075
|
+
warmup_result = WarmupResult(
|
|
1076
|
+
requested_start_ns=to_timestamp(warmup_start_time).value,
|
|
1077
|
+
requested_stop_ns=to_timestamp(current_time).value,
|
|
1078
|
+
data_start_ns=data_range[0] if data_range else None,
|
|
1079
|
+
data_stop_ns=data_range[1] if data_range else None,
|
|
1080
|
+
initial_capital=_initial_capital,
|
|
1081
|
+
final_capital=warmup_runner.ctx.account.get_total_capital(),
|
|
1082
|
+
)
|
|
1083
|
+
_validate_warmup_result(warmup_result)
|
|
1084
|
+
|
|
947
1085
|
# - reset the strategy ctx to point back to live context
|
|
948
1086
|
if hasattr(ctx.strategy, "ctx"):
|
|
949
1087
|
setattr(ctx.strategy, "ctx", ctx)
|
|
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
|
|
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
|
{qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py
RENAMED
|
File without changes
|
{qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py
RENAMED
|
File without changes
|
{qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/account.py
RENAMED
|
File without changes
|
{qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/broker.py
RENAMED
|
File without changes
|
{qubx-1.1.2.dev13 → qubx-1.1.2.dev15}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py
RENAMED
|
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
|
|
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
|
|
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
|