Qubx 4.0.0.dev1__tar.gz → 4.0.1__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-4.0.0.dev1 → qubx-4.0.1}/PKG-INFO +1 -1
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/_version.py +2 -2
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/runner.py +1 -1
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/simulator.py +10 -3
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/utils.py +13 -9
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/state.py +12 -6
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/basics.py +22 -13
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/lookups.py +223 -205
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/multi.py +70 -41
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/questdb.py +47 -10
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/configs.py +1 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/runner.py +10 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/time.py +3 -3
- {qubx-4.0.0.dev1 → qubx-4.0.1}/.gitignore +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/LICENSE +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/README.md +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/pyproject.toml +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/scripts/build.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/_nb_magic.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/data.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/iteratedstream.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/management.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/ome.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/optimization.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/sentinels.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/simulated_data.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/simulated_exchange.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/backtester/transfers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/commands.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/deploy.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/misc.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/release.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/resolver.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/s3.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/theme.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/tui.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/cli/user_config.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/config.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/connection_manager.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/data.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exceptions.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/_two_stream.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/base.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/binance/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/bitfinex/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/bybit/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/bybit/bybit.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/bybit/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/okx/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/okx/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/exchanges/okx/okx.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/factory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/ohlc.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/plugin.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/rate_limits.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/ccxt/warmup_service.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/plugin.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/registry.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/tardis/data.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/tardis/plugin.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/connectors/tardis/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/builtin.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/decorator.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/executor.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/interfaces.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/server.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/control/types.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/config.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/diffs.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/manager.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/reconciler.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/reducer.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/account_manager/state_machine.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/boot.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/connector.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/context.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/detectors/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/detectors/delisting.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/detectors/stale.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/errors.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/events.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/exceptions.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/fit_context.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/fit_executor.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/helpers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/initializer.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/instrument_service.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/interfaces.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/loggers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/metrics.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/instrument_service.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/market.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/processing.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/subscription.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/trading.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/universe.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/mixins/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/series.pxd +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/series.pyi +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/series.pyx +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/state_snapshot.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/status.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/subscription_watchdog.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/utils.pyi +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/core/utils.pyx +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/cache.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/containers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/guards.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/registry.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storage.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/_missing_extra.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/ccxt.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/csv.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/dukascopy.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/handy.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/iceberg.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/stub.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/storages/yahoo.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/data/transformers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/base.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/composite.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/csv.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/indicator.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/inmemory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/prometheus.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/emitters/questdb.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/composite.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/formatters/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/formatters/base.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/formatters/incremental.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/formatters/slack.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/formatters/target_position.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/redis_streams.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/exporters/slack.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/gathering/simplest.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/health/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/health/base.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/health/dummy.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/health/status.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/loggers/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/loggers/csv.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/loggers/factory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/loggers/inmemory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/loggers/postgres.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/notifications/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/notifications/composite.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/notifications/slack.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/notifications/throttler.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/pandaz/stats.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/pandaz/ta.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/pandaz/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/plugins/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/plugins/loader.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/backend.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/config.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/engine.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/ip_resolver.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/manager.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/pools.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/redis_backend.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/rate_limiting/resilient.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/_build.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/crypto-fees.ini +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restarts/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restarts/state_resolvers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restarts/time_finders.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/balance.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/factory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/interfaces.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/position.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/signal.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/state.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/restorers/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/state/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/state/dummy.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/state/redis.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/state/runtime_info.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/state/safe.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/ta/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/base.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/accounts.toml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/config.yml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/jlive.sh.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/project/template.yml +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.claude/skills/qubx-cli/SKILL.md +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.claude/skills/qubx-indicators/SKILL.md +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.claude/skills/simulation-explorer/SKILL.md +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.claude/skills/strategy-release/SKILL.md +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.github/workflows/ci.yml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.gitignore.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.python-version +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.vscode/launch.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.vscode/settings.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/.vscode/tasks.json +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/CLAUDE.md.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/README.md.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/configs/.gitkeep +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/justfile.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/pyproject.toml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/research/.gitkeep +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/src/{{ strategy_name }}/cli.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/template.yml +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/repo/tests/test_strategy.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/__init__.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/config.yml.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/strategy.py.j2 +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/templates/simple/template.yml +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/trackers/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/trackers/advanced.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/trackers/composite.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/trackers/sizers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/charting/lookinglass.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/charting/orderbook.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/clock.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/collections.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/hft/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/hft/numba_utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/hft/orderbook.pyi +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/hft/orderbook.pyx +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/marketdata/ccxt.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/marketdata/dukas.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/misc.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/nonce.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/numbers_utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/orderbook.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/plotting/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/plotting/dashboard.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/plotting/data.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/plotting/interfaces.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/questdb.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/rate_limiter.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/results.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/ringbuffer.pxd +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/ringbuffer.pyi +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/ringbuffer.pyx +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/accounts.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/factory.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/kernel_service.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/app.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/handlers.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/init_code.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/kernel.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/styles.tcss +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/account_summary.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/log_filter.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/s3.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/slack.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/threading.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/throttler.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/src/qubx/utils/websocket_manager.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
- {qubx-4.0.0.dev1 → qubx-4.0.1}/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 = '4.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (4, 0,
|
|
21
|
+
__version__ = version = '4.0.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (4, 0, 1)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -612,7 +612,7 @@ class SimulationRunner:
|
|
|
612
612
|
connectors=self._connectors,
|
|
613
613
|
base_currencies=self.setup.base_currencies,
|
|
614
614
|
time=time_provider,
|
|
615
|
-
cfg=AccountManagerConfig(),
|
|
615
|
+
cfg=AccountManagerConfig(maint_margin_rate=self.setup.maint_margin_rate),
|
|
616
616
|
account_id=self.account_id,
|
|
617
617
|
tcc=_exchange_to_tcc,
|
|
618
618
|
)
|
|
@@ -5,8 +5,9 @@ from joblib import delayed
|
|
|
5
5
|
|
|
6
6
|
from qubx import QubxLogConfig, file_formatter, logger
|
|
7
7
|
from qubx.backtester.utils import SetupTypes
|
|
8
|
-
from qubx.core.basics import Instrument
|
|
8
|
+
from qubx.core.basics import DEFAULT_MAINTENANCE_MARGIN, Instrument
|
|
9
9
|
from qubx.core.exceptions import SimulationError
|
|
10
|
+
from qubx.core.lookups import lookup
|
|
10
11
|
from qubx.core.metrics import TradingSessionResult
|
|
11
12
|
from qubx.data.storage import IStorage
|
|
12
13
|
from qubx.emitters.inmemory import InMemoryMetricEmitter
|
|
@@ -45,6 +46,7 @@ def simulate(
|
|
|
45
46
|
accurate_stop_orders_execution: bool = False,
|
|
46
47
|
signal_timeframe: str = "1Min",
|
|
47
48
|
enable_funding: bool = False,
|
|
49
|
+
maint_margin_rate: float = DEFAULT_MAINTENANCE_MARGIN,
|
|
48
50
|
debug: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = "WARNING",
|
|
49
51
|
show_latency_report: bool = False,
|
|
50
52
|
portfolio_log_freq: str = "5Min",
|
|
@@ -76,6 +78,7 @@ def simulate(
|
|
|
76
78
|
- accurate_stop_orders_execution (bool): If True, enables more accurate stop order execution simulation.
|
|
77
79
|
- signal_timeframe (str): Timeframe for signals, default is "1Min".
|
|
78
80
|
- enable_funding (bool): If True, enables funding rate simulation, default is False.
|
|
81
|
+
- maint_margin_rate (float): Maintenance margin as a fraction of notional for simulated positions (the account's `maint_margin_rate`).
|
|
79
82
|
- debug (Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None): Logging level for debugging.
|
|
80
83
|
- show_latency_report: If True, shows simulator's latency report.
|
|
81
84
|
- portfolio_log_freq (str): Frequency for portfolio logging, default is "5Min".
|
|
@@ -125,6 +128,7 @@ def simulate(
|
|
|
125
128
|
accurate_stop_orders_execution=accurate_stop_orders_execution,
|
|
126
129
|
run_separate_instruments=run_separate_instruments,
|
|
127
130
|
enable_funding=enable_funding,
|
|
131
|
+
maint_margin_rate=maint_margin_rate,
|
|
128
132
|
)
|
|
129
133
|
if not simulation_setups:
|
|
130
134
|
logger.error(
|
|
@@ -259,10 +263,13 @@ def _run_setup(
|
|
|
259
263
|
# Adjust the start date for the simulation to the onboard date of the instrument with the minimum onboard date.
|
|
260
264
|
# TODO: this can be removed once we add some artificial data stream to move the simulation
|
|
261
265
|
if setup.setup_type in [SetupTypes.SIGNAL, SetupTypes.SIGNAL_AND_TRACKER]:
|
|
266
|
+
# - a relisted symbol has data from its first listing on
|
|
262
267
|
listed_dates = [
|
|
263
|
-
to_utc_naive(to_timestamp(
|
|
268
|
+
to_utc_naive(to_timestamp(listing.listed_at))
|
|
264
269
|
for instrument in setup.instruments
|
|
265
|
-
|
|
270
|
+
for listing in lookup.find_listings(instrument.exchange, instrument.symbol, instrument.market_type)
|
|
271
|
+
or [instrument]
|
|
272
|
+
if listing.listed_at is not None
|
|
266
273
|
]
|
|
267
274
|
if listed_dates:
|
|
268
275
|
start = max(start, min(listed_dates))
|
|
@@ -8,6 +8,7 @@ import pandas as pd
|
|
|
8
8
|
|
|
9
9
|
from qubx import logger
|
|
10
10
|
from qubx.core.basics import (
|
|
11
|
+
DEFAULT_MAINTENANCE_MARGIN,
|
|
11
12
|
STABLE_CURRENCIES,
|
|
12
13
|
Balance,
|
|
13
14
|
CtrlChannel,
|
|
@@ -114,6 +115,7 @@ class SimulationSetup:
|
|
|
114
115
|
signal_timeframe: str = "1Min"
|
|
115
116
|
accurate_stop_orders_execution: bool = False
|
|
116
117
|
enable_funding: bool = False
|
|
118
|
+
maint_margin_rate: float = DEFAULT_MAINTENANCE_MARGIN
|
|
117
119
|
base_currencies: dict[str, str] = field(init=False, default_factory=dict)
|
|
118
120
|
|
|
119
121
|
def __post_init__(self) -> None:
|
|
@@ -405,6 +407,7 @@ def recognize_simulation_configuration(
|
|
|
405
407
|
accurate_stop_orders_execution: bool,
|
|
406
408
|
run_separate_instruments: bool = False,
|
|
407
409
|
enable_funding: bool = False,
|
|
410
|
+
maint_margin_rate: float = DEFAULT_MAINTENANCE_MARGIN,
|
|
408
411
|
) -> list[SimulationSetup]:
|
|
409
412
|
"""
|
|
410
413
|
Recognize and create setups based on the provided simulation configuration.
|
|
@@ -426,6 +429,7 @@ def recognize_simulation_configuration(
|
|
|
426
429
|
- accurate_stop_orders_execution (bool): If True, enables more accurate stop order execution simulation.
|
|
427
430
|
- run_separate_instruments (bool): If True, creates separate setups for each instrument.
|
|
428
431
|
- enable_funding (bool): If True, enables funding rate simulation, default is False.
|
|
432
|
+
- maint_margin_rate (float): Maintenance margin as a fraction of notional for simulated positions.
|
|
429
433
|
|
|
430
434
|
Returns:
|
|
431
435
|
- list[SimulationSetup]: A list of SimulationSetup objects, each representing a
|
|
@@ -447,7 +451,7 @@ def recognize_simulation_configuration(
|
|
|
447
451
|
recognize_simulation_configuration(
|
|
448
452
|
_n + n, v, instruments, exchanges, capital, basic_currency, commissions,
|
|
449
453
|
signal_timeframe, accurate_stop_orders_execution, run_separate_instruments,
|
|
450
|
-
enable_funding
|
|
454
|
+
enable_funding, maint_margin_rate
|
|
451
455
|
)
|
|
452
456
|
)
|
|
453
457
|
|
|
@@ -468,14 +472,14 @@ def recognize_simulation_configuration(
|
|
|
468
472
|
if run_separate_instruments:
|
|
469
473
|
# Create separate setups for each instrument
|
|
470
474
|
for instrument in setup_instruments:
|
|
471
|
-
_s1 =
|
|
475
|
+
_s1 = _s[instrument.symbol] if isinstance(_s, pd.DataFrame) else _s
|
|
472
476
|
r.append(
|
|
473
477
|
SimulationSetup(
|
|
474
478
|
_t, f"{name}/{instrument.symbol}", _s1, c1, # type: ignore
|
|
475
479
|
[instrument],
|
|
476
480
|
exchanges, capital, basic_currency, commissions,
|
|
477
481
|
signal_timeframe, accurate_stop_orders_execution,
|
|
478
|
-
enable_funding
|
|
482
|
+
enable_funding, maint_margin_rate
|
|
479
483
|
)
|
|
480
484
|
)
|
|
481
485
|
else:
|
|
@@ -485,7 +489,7 @@ def recognize_simulation_configuration(
|
|
|
485
489
|
setup_instruments,
|
|
486
490
|
exchanges, capital, basic_currency, commissions,
|
|
487
491
|
signal_timeframe, accurate_stop_orders_execution,
|
|
488
|
-
enable_funding
|
|
492
|
+
enable_funding, maint_margin_rate
|
|
489
493
|
)
|
|
490
494
|
)
|
|
491
495
|
else:
|
|
@@ -495,7 +499,7 @@ def recognize_simulation_configuration(
|
|
|
495
499
|
# name + "/" + str(j), s, instruments, exchange, capital, basic_currency, commissions
|
|
496
500
|
name, s, instruments, exchanges, capital, basic_currency, commissions, # type: ignore
|
|
497
501
|
signal_timeframe, accurate_stop_orders_execution, run_separate_instruments,
|
|
498
|
-
enable_funding
|
|
502
|
+
enable_funding, maint_margin_rate
|
|
499
503
|
)
|
|
500
504
|
)
|
|
501
505
|
|
|
@@ -509,7 +513,7 @@ def recognize_simulation_configuration(
|
|
|
509
513
|
f"{name}/{instrument.symbol}", configs, None, [instrument],
|
|
510
514
|
exchanges, capital, basic_currency, commissions,
|
|
511
515
|
signal_timeframe, accurate_stop_orders_execution,
|
|
512
|
-
enable_funding
|
|
516
|
+
enable_funding, maint_margin_rate
|
|
513
517
|
)
|
|
514
518
|
)
|
|
515
519
|
else:
|
|
@@ -519,7 +523,7 @@ def recognize_simulation_configuration(
|
|
|
519
523
|
name, configs, None, instruments,
|
|
520
524
|
exchanges, capital, basic_currency, commissions,
|
|
521
525
|
signal_timeframe, accurate_stop_orders_execution,
|
|
522
|
-
enable_funding
|
|
526
|
+
enable_funding, maint_margin_rate
|
|
523
527
|
)
|
|
524
528
|
)
|
|
525
529
|
|
|
@@ -538,7 +542,7 @@ def recognize_simulation_configuration(
|
|
|
538
542
|
f"{name}/{instrument.symbol}", _c1, None, [instrument],
|
|
539
543
|
exchanges, capital, basic_currency, commissions,
|
|
540
544
|
signal_timeframe, accurate_stop_orders_execution,
|
|
541
|
-
enable_funding
|
|
545
|
+
enable_funding, maint_margin_rate
|
|
542
546
|
)
|
|
543
547
|
)
|
|
544
548
|
else:
|
|
@@ -548,7 +552,7 @@ def recognize_simulation_configuration(
|
|
|
548
552
|
name, c1, None, setup_instruments,
|
|
549
553
|
exchanges, capital, basic_currency, commissions,
|
|
550
554
|
signal_timeframe, accurate_stop_orders_execution,
|
|
551
|
-
enable_funding
|
|
555
|
+
enable_funding, maint_margin_rate
|
|
552
556
|
)
|
|
553
557
|
)
|
|
554
558
|
|
|
@@ -489,11 +489,19 @@ class AccountState:
|
|
|
489
489
|
# the framework hold references to it), never swapped for a new object.
|
|
490
490
|
existing = self._positions.get(instrument)
|
|
491
491
|
if existing is None:
|
|
492
|
-
|
|
493
|
-
self._positions[instrument] = position
|
|
492
|
+
self._adopt_position(instrument, position)
|
|
494
493
|
else:
|
|
495
494
|
existing.reset_by_position(position)
|
|
496
495
|
|
|
496
|
+
def _adopt_position(self, instrument: Instrument, position: Position) -> Position:
|
|
497
|
+
# - every held position margins at the account's rate, however it got here; a venue-reported
|
|
498
|
+
# margin is kept, a framework one is recomputed now rather than on the next mark
|
|
499
|
+
position.maint_margin_rate = self.maint_margin_rate
|
|
500
|
+
if not position._maint_margin_external and position.is_open() and not np.isnan(position.last_update_price):
|
|
501
|
+
position._update_maint_margin()
|
|
502
|
+
self._positions[instrument] = position
|
|
503
|
+
return position
|
|
504
|
+
|
|
497
505
|
def settle_position(self, instrument: Instrument) -> None:
|
|
498
506
|
# Reconcile a delisted/gone position to flat WITHOUT trading: the exchange has
|
|
499
507
|
# already cash-settled it, so we zero quantity/market value while preserving the
|
|
@@ -525,7 +533,7 @@ class AccountState:
|
|
|
525
533
|
"""
|
|
526
534
|
existing = self._positions.get(snapshot.instrument)
|
|
527
535
|
if existing is None:
|
|
528
|
-
self.
|
|
536
|
+
self._adopt_position(snapshot.instrument, snapshot)
|
|
529
537
|
logger.info(
|
|
530
538
|
f"[{self.exchange}] reconcile: materialized position <y>{snapshot.instrument}</y> from snapshot "
|
|
531
539
|
f"-> size=<g>{snapshot.quantity}</g> avg={snapshot.position_avg_price}"
|
|
@@ -663,9 +671,7 @@ class AccountState:
|
|
|
663
671
|
def ensure_position(self, instrument: Instrument) -> Position:
|
|
664
672
|
pos = self._positions.get(instrument)
|
|
665
673
|
if pos is None:
|
|
666
|
-
pos = Position(instrument=instrument)
|
|
667
|
-
pos.maint_margin_rate = self.maint_margin_rate
|
|
668
|
-
self._positions[instrument] = pos
|
|
674
|
+
pos = self._adopt_position(instrument, Position(instrument=instrument))
|
|
669
675
|
return pos
|
|
670
676
|
|
|
671
677
|
def adjust_balance(self, currency: str, delta: float) -> None:
|
|
@@ -23,7 +23,7 @@ from qubx.core.utils import (
|
|
|
23
23
|
)
|
|
24
24
|
from qubx.utils.clock import start_clock_discipline, time_now
|
|
25
25
|
from qubx.utils.misc import Stopwatch
|
|
26
|
-
from qubx.utils.time import to_timedelta
|
|
26
|
+
from qubx.utils.time import to_timedelta, to_utc_naive
|
|
27
27
|
|
|
28
28
|
dt_64 = np.datetime64
|
|
29
29
|
td_64 = np.timedelta64
|
|
@@ -408,7 +408,7 @@ class Instrument:
|
|
|
408
408
|
_: KW_ONLY
|
|
409
409
|
contract_size: float = 1.0 # quantity per contract: base units (linear) or quote units (inverse)
|
|
410
410
|
inverse: bool = False
|
|
411
|
-
listing_id: str | None = None # instrument-service listing id
|
|
411
|
+
listing_id: str | None = None # instrument-service listing id; a new symbol is a new listing
|
|
412
412
|
underlying: Underlying | None = None
|
|
413
413
|
calendar: str | None = None # when this listing trades: "24/7", a MIC ("XNAS") or None
|
|
414
414
|
expiry: datetime | None = None
|
|
@@ -451,6 +451,13 @@ class Instrument:
|
|
|
451
451
|
"""What the listing is a contract on (NVDA.XNAS for a bStock, XAU for PAXG); `asset` when the underlying is unknown."""
|
|
452
452
|
return self.underlying.code if self.underlying is not None else self.asset
|
|
453
453
|
|
|
454
|
+
def is_listed_at(self, time: datetime | str) -> bool:
|
|
455
|
+
"""listed_at <= time < delisted_at, an unknown date leaving that side open."""
|
|
456
|
+
t = to_utc_naive(time)
|
|
457
|
+
return (self.listed_at is None or to_utc_naive(self.listed_at) <= t) and (
|
|
458
|
+
self.delisted_at is None or t < to_utc_naive(self.delisted_at)
|
|
459
|
+
)
|
|
460
|
+
|
|
454
461
|
def is_futures(self) -> bool:
|
|
455
462
|
return self.market_type in [MarketType.FUTURE, MarketType.SWAP]
|
|
456
463
|
|
|
@@ -2080,6 +2087,10 @@ class RestoredState:
|
|
|
2080
2087
|
class InstrumentsLookup:
|
|
2081
2088
|
def get_lookup(self) -> dict[str, Instrument]: ...
|
|
2082
2089
|
|
|
2090
|
+
def get_listings(self) -> list[Instrument]:
|
|
2091
|
+
"""Every listing, including the earlier, delisted incarnations of relisted symbols that get_lookup() drops."""
|
|
2092
|
+
return list(self.get_lookup().values())
|
|
2093
|
+
|
|
2083
2094
|
def find(
|
|
2084
2095
|
self,
|
|
2085
2096
|
exchange: str,
|
|
@@ -2118,6 +2129,10 @@ class InstrumentsLookup:
|
|
|
2118
2129
|
|
|
2119
2130
|
return None
|
|
2120
2131
|
|
|
2132
|
+
def find_listings(self, exchange: str, symbol: str, market_type: MarketType | None = None) -> list[Instrument]:
|
|
2133
|
+
"""Every listing a symbol has had, the current (find_symbol) one first."""
|
|
2134
|
+
return [i for i in [self.find_symbol(exchange, symbol, market_type)] if i is not None]
|
|
2135
|
+
|
|
2121
2136
|
def find_instruments(
|
|
2122
2137
|
self,
|
|
2123
2138
|
exchange: str,
|
|
@@ -2128,29 +2143,23 @@ class InstrumentsLookup:
|
|
|
2128
2143
|
) -> list[Instrument]:
|
|
2129
2144
|
"""
|
|
2130
2145
|
Find instruments by exchange, quote, market type and as of date.
|
|
2131
|
-
If as_of is not None,
|
|
2146
|
+
If as_of is not None, only instruments listed at that time are returned, delisted predecessors
|
|
2147
|
+
of relisted symbols included (see get_listings).
|
|
2132
2148
|
- exchange: str - exchange name
|
|
2133
2149
|
- base: str | None - base currency
|
|
2134
2150
|
- quote: str | None - quote currency
|
|
2135
2151
|
- market_type: MarketType | None - market type
|
|
2136
2152
|
- as_of is a string in format YYYY-MM-DD or pd.Timestamp or None
|
|
2137
2153
|
"""
|
|
2138
|
-
_limit_time =
|
|
2154
|
+
_limit_time = to_utc_naive(as_of) if as_of else None
|
|
2139
2155
|
matched = [
|
|
2140
2156
|
i
|
|
2141
|
-
for i in self.get_lookup().values()
|
|
2157
|
+
for i in (self.get_lookup().values() if _limit_time is None else self.get_listings())
|
|
2142
2158
|
if i.exchange == exchange
|
|
2143
2159
|
and (base is None or i.base == base or i.asset == base)
|
|
2144
2160
|
and (quote is None or i.quote == quote)
|
|
2145
2161
|
and (market_type is None or i.market_type == market_type)
|
|
2146
|
-
and (
|
|
2147
|
-
_limit_time is None
|
|
2148
|
-
or (i.listed_at is None or pd.Timestamp(i.listed_at).tz_localize(None) <= _limit_time)
|
|
2149
|
-
)
|
|
2150
|
-
and (
|
|
2151
|
-
_limit_time is None
|
|
2152
|
-
or (i.delisted_at is None or pd.Timestamp(i.delisted_at).tz_localize(None) >= _limit_time)
|
|
2153
|
-
)
|
|
2162
|
+
and (_limit_time is None or i.is_listed_at(_limit_time))
|
|
2154
2163
|
]
|
|
2155
2164
|
if base is not None:
|
|
2156
2165
|
aliases = sorted({i.base for i in matched} - {base})
|