Qubx 3.22.1__tar.gz → 4.0.0.dev1__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-3.22.1 → qubx-4.0.0.dev1}/PKG-INFO +1 -2
- {qubx-3.22.1 → qubx-4.0.0.dev1}/pyproject.toml +0 -2
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/_version.py +2 -2
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/simulator.py +5 -5
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/config.py +13 -3
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/utils.py +1 -2
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/config.py +4 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/manager.py +1 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/state.py +22 -2
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/basics.py +86 -40
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/detectors/delisting.py +3 -3
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/interfaces.py +4 -5
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/lookups.py +216 -72
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/universe.py +6 -6
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/loggers/__init__.py +1 -3
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/loggers/factory.py +0 -2
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/balance.py +1 -83
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/factory.py +4 -8
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/position.py +1 -120
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/signal.py +1 -153
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/state.py +5 -124
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/utils.py +4 -30
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/marketdata/binance.py +0 -9
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/marketdata/ccxt.py +16 -33
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/marketdata/dukas.py +0 -21
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/configs.py +2 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/runner.py +0 -10
- qubx-3.22.1/src/qubx/loggers/mongo.py +0 -76
- {qubx-3.22.1 → qubx-4.0.0.dev1}/.gitignore +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/LICENSE +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/README.md +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/scripts/build.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/_nb_magic.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/data.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/iteratedstream.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/management.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/ome.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/optimization.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/runner.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/sentinels.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/simulated_data.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/simulated_exchange.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/transfers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/backtester/utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/commands.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/deploy.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/misc.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/release.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/resolver.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/s3.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/theme.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/tui.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/cli/user_config.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/connection_manager.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/data.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exceptions.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/_two_stream.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/base.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/binance/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/bybit/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/bybit/bybit.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/bybit/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/okx/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/okx/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/exchanges/okx/okx.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/factory.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/ohlc.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/plugin.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/rate_limits.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/ccxt/warmup_service.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/plugin.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/registry.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/tardis/data.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/tardis/plugin.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/connectors/tardis/utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/builtin.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/decorator.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/executor.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/interfaces.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/server.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/control/types.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/diffs.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/reconciler.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/reducer.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/account_manager/state_machine.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/boot.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/connector.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/context.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/detectors/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/detectors/stale.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/errors.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/events.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/exceptions.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/fit_context.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/fit_executor.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/helpers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/initializer.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/instrument_service.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/loggers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/metrics.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/instrument_service.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/market.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/processing.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/subscription.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/trading.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/mixins/utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/series.pxd +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/series.pyi +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/series.pyx +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/state_snapshot.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/status.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/subscription_watchdog.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/utils.pyi +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/core/utils.pyx +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/cache.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/containers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/guards.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/registry.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storage.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/_missing_extra.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/ccxt.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/csv.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/dukascopy.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/handy.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/iceberg.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/multi.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/questdb.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/stub.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/storages/yahoo.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/data/transformers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/base.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/composite.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/csv.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/indicator.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/inmemory.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/prometheus.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/emitters/questdb.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/composite.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/formatters/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/formatters/base.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/formatters/incremental.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/formatters/slack.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/formatters/target_position.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/redis_streams.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/exporters/slack.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/gathering/simplest.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/health/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/health/base.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/health/dummy.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/health/status.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/loggers/csv.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/loggers/inmemory.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/loggers/postgres.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/notifications/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/notifications/composite.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/notifications/slack.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/notifications/throttler.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/pandaz/stats.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/pandaz/ta.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/pandaz/utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/plugins/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/plugins/loader.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/backend.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/config.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/engine.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/ip_resolver.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/manager.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/pools.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/redis_backend.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/rate_limiting/resilient.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/_build.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/crypto-fees.ini +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restarts/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restarts/state_resolvers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restarts/time_finders.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/restorers/interfaces.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/state/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/state/dummy.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/state/redis.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/state/runtime_info.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/state/safe.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/ta/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/base.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/accounts.toml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/config.yml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/jlive.sh.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/project/template.yml +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.claude/skills/qubx-cli/SKILL.md +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.claude/skills/qubx-indicators/SKILL.md +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.claude/skills/simulation-explorer/SKILL.md +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.claude/skills/strategy-release/SKILL.md +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.github/workflows/ci.yml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.gitignore.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.python-version +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.vscode/launch.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.vscode/settings.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/.vscode/tasks.json +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/CLAUDE.md.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/README.md.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/configs/.gitkeep +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/justfile.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/pyproject.toml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/research/.gitkeep +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/cli.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/template.yml +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/repo/tests/test_strategy.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/__init__.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/config.yml.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/strategy.py.j2 +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/templates/simple/template.yml +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/trackers/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/trackers/advanced.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/trackers/composite.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/trackers/sizers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/charting/lookinglass.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/charting/orderbook.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/clock.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/collections.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/hft/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/hft/numba_utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/hft/orderbook.pyi +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/hft/orderbook.pyx +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/misc.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/nonce.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/numbers_utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/orderbook.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/plotting/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/plotting/dashboard.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/plotting/data.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/plotting/interfaces.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/questdb.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/rate_limiter.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/results.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/ringbuffer.pxd +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/ringbuffer.pyi +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/ringbuffer.pyx +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/accounts.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/factory.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/kernel_service.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/app.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/handlers.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/init_code.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/kernel.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/styles.tcss +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/account_summary.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/log_filter.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/s3.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/slack.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/threading.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/throttler.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/time.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/src/qubx/utils/websocket_manager.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
- {qubx-3.22.1 → qubx-4.0.0.dev1}/tests/strategies/obi_trader/src/obi_trader/models/obi_trader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: Qubx
|
|
3
|
-
Version:
|
|
3
|
+
Version: 4.0.0.dev1
|
|
4
4
|
Summary: Qubx - Quantitative Trading Framework
|
|
5
5
|
Project-URL: homepage, https://xlydian.com
|
|
6
6
|
Project-URL: repository, https://github.com/xLydianSoftware/Qubx
|
|
@@ -34,7 +34,6 @@ Requires-Dist: psycopg<4,>=3.1.18
|
|
|
34
34
|
Requires-Dist: pyarrow>=15.0.0
|
|
35
35
|
Requires-Dist: pydantic-settings<3,>=2.4.0
|
|
36
36
|
Requires-Dist: pydantic<3,>=2.9.2
|
|
37
|
-
Requires-Dist: pymongo<5,>=4.6.1
|
|
38
37
|
Requires-Dist: python-dotenv<2,>=1.0.0
|
|
39
38
|
Requires-Dist: pyyaml<7,>=6.0.2
|
|
40
39
|
Requires-Dist: questdb<3,>=2.0.3
|
|
@@ -62,7 +62,6 @@ dependencies = [
|
|
|
62
62
|
"statsmodels>=0.14.6,<0.15",
|
|
63
63
|
|
|
64
64
|
# - - - Database backends - - -
|
|
65
|
-
"pymongo>=4.6.1,<5",
|
|
66
65
|
"redis>=5.2.1,<6",
|
|
67
66
|
"psycopg>=3.1.18,<4",
|
|
68
67
|
"psycopg-binary>=3.1.19,<4",
|
|
@@ -177,7 +176,6 @@ dev = [
|
|
|
177
176
|
"pytest-cov>=4.1.0,<5",
|
|
178
177
|
"pytest-xdist>=3.6.1,<4",
|
|
179
178
|
"pytest-textual-snapshot>=1.1.0,<2",
|
|
180
|
-
"mongomock>=4.3.0,<5",
|
|
181
179
|
"pyiceberg[pyarrow,sql-sqlite,pyiceberg-core]==0.12.0",
|
|
182
180
|
|
|
183
181
|
# - - - Linting & formatting - - -
|
|
@@ -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 = '
|
|
22
|
-
__version_tuple__ = version_tuple = (
|
|
21
|
+
__version__ = version = '4.0.0.dev1'
|
|
22
|
+
__version_tuple__ = version_tuple = (4, 0, 0, 'dev1')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -259,13 +259,13 @@ def _run_setup(
|
|
|
259
259
|
# Adjust the start date for the simulation to the onboard date of the instrument with the minimum onboard date.
|
|
260
260
|
# TODO: this can be removed once we add some artificial data stream to move the simulation
|
|
261
261
|
if setup.setup_type in [SetupTypes.SIGNAL, SetupTypes.SIGNAL_AND_TRACKER]:
|
|
262
|
-
|
|
263
|
-
to_utc_naive(to_timestamp(instrument.
|
|
262
|
+
listed_dates = [
|
|
263
|
+
to_utc_naive(to_timestamp(instrument.listed_at))
|
|
264
264
|
for instrument in setup.instruments
|
|
265
|
-
if instrument.
|
|
265
|
+
if instrument.listed_at is not None
|
|
266
266
|
]
|
|
267
|
-
if
|
|
268
|
-
start = max(start, min(
|
|
267
|
+
if listed_dates:
|
|
268
|
+
start = max(start, min(listed_dates))
|
|
269
269
|
|
|
270
270
|
runner = SimulationRunner(
|
|
271
271
|
setup=setup,
|
|
@@ -22,7 +22,7 @@ from functools import lru_cache
|
|
|
22
22
|
from pathlib import Path
|
|
23
23
|
from typing import Any, ClassVar
|
|
24
24
|
|
|
25
|
-
from pydantic import BaseModel
|
|
25
|
+
from pydantic import BaseModel, field_validator
|
|
26
26
|
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
|
|
27
27
|
|
|
28
28
|
|
|
@@ -47,8 +47,18 @@ class IcebergAccount(BaseModel):
|
|
|
47
47
|
class LookupConfig(BaseModel):
|
|
48
48
|
"""Configuration for instrument/fees lookups."""
|
|
49
49
|
|
|
50
|
-
type: str = "file"
|
|
51
|
-
|
|
50
|
+
type: str = "file" # "file" or "service"
|
|
51
|
+
url: str | None = None # instrument-service base, e.g. http://control-api.platform.svc/internal/instrument-service
|
|
52
|
+
token: str | None = None # bearer token for the gateway route
|
|
53
|
+
exchanges: list[str] | None = None # service: snapshot only these exchanges (env: JSON list or comma-separated)
|
|
54
|
+
|
|
55
|
+
@field_validator("exchanges", mode="before")
|
|
56
|
+
@classmethod
|
|
57
|
+
def _split_exchanges(cls, v: Any) -> Any:
|
|
58
|
+
if isinstance(v, str):
|
|
59
|
+
return [e.strip() for e in v.split(",") if e.strip()]
|
|
60
|
+
return v
|
|
61
|
+
|
|
52
62
|
reload_interval: str | None = None
|
|
53
63
|
path: str | None = None
|
|
54
64
|
|
|
@@ -318,8 +318,7 @@ def ccxt_convert_position(info: dict, ccxt_exchange_name: str, markets: dict[str
|
|
|
318
318
|
pos.update_market_price(_pts, info["markPrice"], 1)
|
|
319
319
|
|
|
320
320
|
# Use exchange-provided margins when reported — only the venue knows the configured leverage
|
|
321
|
-
# tier. The internal fallback
|
|
322
|
-
# BINANCE.UM) it yields 0.0, and with metadata it applies a static ratio that ignores the tier.
|
|
321
|
+
# tier. The internal fallback yields 0.0 initial margin and a flat maintenance rate.
|
|
323
322
|
if info.get("maintenanceMargin") is not None:
|
|
324
323
|
pos.set_external_maint_margin(float(info["maintenanceMargin"]))
|
|
325
324
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
|
|
3
|
+
from qubx.core.basics import DEFAULT_MAINTENANCE_MARGIN
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
@dataclass
|
|
5
7
|
class AccountManagerConfig:
|
|
@@ -21,3 +23,5 @@ class AccountManagerConfig:
|
|
|
21
23
|
|
|
22
24
|
terminal_order_retention_ms: int = 30_000
|
|
23
25
|
terminal_order_history_size: int = 10_000
|
|
26
|
+
|
|
27
|
+
maint_margin_rate: float = DEFAULT_MAINTENANCE_MARGIN # - framework-computed maintenance margin (fraction of notional) when the venue reports none
|
|
@@ -161,6 +161,7 @@ class AccountManager(IAccountViewer, IAccountConfigurator):
|
|
|
161
161
|
exchange=ex,
|
|
162
162
|
base_currency=base_currencies[ex],
|
|
163
163
|
terminal_history_size=self._cfg.terminal_order_history_size,
|
|
164
|
+
maint_margin_rate=self._cfg.maint_margin_rate,
|
|
164
165
|
)
|
|
165
166
|
for ex in connectors
|
|
166
167
|
}
|
|
@@ -19,7 +19,16 @@ from dataclasses import dataclass
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
|
|
21
21
|
from qubx import logger
|
|
22
|
-
from qubx.core.basics import
|
|
22
|
+
from qubx.core.basics import (
|
|
23
|
+
DEFAULT_MAINTENANCE_MARGIN,
|
|
24
|
+
STABLE_CURRENCIES,
|
|
25
|
+
Balance,
|
|
26
|
+
Deal,
|
|
27
|
+
Instrument,
|
|
28
|
+
Order,
|
|
29
|
+
OrderStatus,
|
|
30
|
+
Position,
|
|
31
|
+
)
|
|
23
32
|
|
|
24
33
|
# Bounded per-exchange funding-bucket dedup (insertion order ≈ funding-event time order):
|
|
25
34
|
# old buckets evict once the cap is hit so the set can't grow unbounded over long-running
|
|
@@ -57,6 +66,7 @@ class AccountState:
|
|
|
57
66
|
__slots__ = (
|
|
58
67
|
"exchange",
|
|
59
68
|
"base_currency",
|
|
69
|
+
"maint_margin_rate",
|
|
60
70
|
"_active_orders",
|
|
61
71
|
"_positions",
|
|
62
72
|
"_balances",
|
|
@@ -77,9 +87,17 @@ class AccountState:
|
|
|
77
87
|
"_position_deal_booked_at",
|
|
78
88
|
)
|
|
79
89
|
|
|
80
|
-
def __init__(
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
exchange: str,
|
|
93
|
+
base_currency: str,
|
|
94
|
+
*,
|
|
95
|
+
terminal_history_size: int = 10_000,
|
|
96
|
+
maint_margin_rate: float = DEFAULT_MAINTENANCE_MARGIN,
|
|
97
|
+
):
|
|
81
98
|
self.exchange: str = exchange
|
|
82
99
|
self.base_currency: str = base_currency.upper()
|
|
100
|
+
self.maint_margin_rate: float = maint_margin_rate
|
|
83
101
|
|
|
84
102
|
# ---- primary data ------------------------------------------------
|
|
85
103
|
self._active_orders: dict[str, Order] = {} # client_order_id -> Order
|
|
@@ -471,6 +489,7 @@ class AccountState:
|
|
|
471
489
|
# the framework hold references to it), never swapped for a new object.
|
|
472
490
|
existing = self._positions.get(instrument)
|
|
473
491
|
if existing is None:
|
|
492
|
+
position.maint_margin_rate = self.maint_margin_rate
|
|
474
493
|
self._positions[instrument] = position
|
|
475
494
|
else:
|
|
476
495
|
existing.reset_by_position(position)
|
|
@@ -645,6 +664,7 @@ class AccountState:
|
|
|
645
664
|
pos = self._positions.get(instrument)
|
|
646
665
|
if pos is None:
|
|
647
666
|
pos = Position(instrument=instrument)
|
|
667
|
+
pos.maint_margin_rate = self.maint_margin_rate
|
|
648
668
|
self._positions[instrument] = pos
|
|
649
669
|
return pos
|
|
650
670
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import re
|
|
2
|
-
from dataclasses import dataclass, field
|
|
2
|
+
from dataclasses import KW_ONLY, dataclass, field
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from enum import StrEnum
|
|
5
|
-
from functools import cache
|
|
5
|
+
from functools import cache, total_ordering
|
|
6
6
|
from queue import Empty, Queue
|
|
7
7
|
from threading import Event
|
|
8
8
|
from typing import Any, Literal, TypeAlias
|
|
@@ -347,10 +347,47 @@ def multiplier_coin(base: str) -> str:
|
|
|
347
347
|
return base
|
|
348
348
|
|
|
349
349
|
|
|
350
|
-
|
|
350
|
+
class AssetKind(StrEnum):
|
|
351
|
+
CRYPTO = "CRYPTO"
|
|
352
|
+
EQUITY = "EQUITY"
|
|
353
|
+
ETF = "ETF"
|
|
354
|
+
INDEX = "INDEX"
|
|
355
|
+
COMMODITY = "COMMODITY"
|
|
356
|
+
FX = "FX"
|
|
357
|
+
EVENT = "EVENT"
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
@dataclass(frozen=True)
|
|
361
|
+
class Underlying:
|
|
362
|
+
"""What a listing is a contract on: (kind, code) is its identity, e.g. (EQUITY, NVDA.XNAS), (CRYPTO, PEPE)."""
|
|
363
|
+
|
|
364
|
+
kind: AssetKind
|
|
365
|
+
code: str
|
|
366
|
+
|
|
367
|
+
def __post_init__(self):
|
|
368
|
+
object.__setattr__(self, "kind", AssetKind(self.kind))
|
|
369
|
+
|
|
370
|
+
def __str__(self) -> str:
|
|
371
|
+
return f"{self.kind}:{self.code}"
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class VenueAttributes(dict):
|
|
375
|
+
"""Read-only venue labels (Binance contractType, HL dex, ...): filter on them, never branch."""
|
|
376
|
+
|
|
377
|
+
def _readonly(self, *args, **kwargs):
|
|
378
|
+
raise TypeError("venue_attributes is read-only")
|
|
379
|
+
|
|
380
|
+
__setitem__ = __delitem__ = clear = pop = popitem = setdefault = update = __ior__ = _readonly # type: ignore
|
|
381
|
+
|
|
382
|
+
def __reduce__(self):
|
|
383
|
+
return (VenueAttributes, (dict(self),))
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
@total_ordering
|
|
387
|
+
@dataclass(eq=False)
|
|
351
388
|
class Instrument:
|
|
352
389
|
"""
|
|
353
|
-
|
|
390
|
+
A tradable listing: identity (eq/hash/str) is (exchange, market_type, symbol).
|
|
354
391
|
|
|
355
392
|
- 2025-06-11: Important change for FUTURE type: now instrument's symbol contains delivery date in format YYYYMMDD.
|
|
356
393
|
So now for let's say september's BTCUSDT future, symbol would be BTCUSD.20250914
|
|
@@ -368,24 +405,28 @@ class Instrument:
|
|
|
368
405
|
lot_size: float # minimal position size
|
|
369
406
|
min_size: float # minimal allowed position size
|
|
370
407
|
min_notional: float = 0.0 # minimal notional value
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
408
|
+
_: KW_ONLY
|
|
409
|
+
contract_size: float = 1.0 # quantity per contract: base units (linear) or quote units (inverse)
|
|
410
|
+
inverse: bool = False
|
|
411
|
+
listing_id: str | None = None # instrument-service listing id, stable through renames
|
|
412
|
+
underlying: Underlying | None = None
|
|
413
|
+
calendar: str | None = None # when this listing trades: "24/7", a MIC ("XNAS") or None
|
|
414
|
+
expiry: datetime | None = None
|
|
415
|
+
strike: float | None = None
|
|
416
|
+
option_right: str | None = None # CALL / PUT
|
|
417
|
+
listed_at: datetime | None = None
|
|
418
|
+
delisted_at: datetime | None = None # a future value is a scheduled delisting
|
|
419
|
+
margin_tradable: bool = False
|
|
420
|
+
venue_attributes: VenueAttributes = field(default_factory=VenueAttributes)
|
|
380
421
|
|
|
381
422
|
def __post_init__(self):
|
|
382
|
-
|
|
383
|
-
|
|
423
|
+
if not isinstance(self.venue_attributes, VenueAttributes):
|
|
424
|
+
self.venue_attributes = VenueAttributes(self.venue_attributes or {})
|
|
384
425
|
|
|
385
426
|
@property
|
|
386
427
|
def quantity_multiplier(self) -> float:
|
|
387
|
-
"""
|
|
388
|
-
return self.contract_size
|
|
428
|
+
"""Multiply contracts by this to get token quantity (alias of contract_size)."""
|
|
429
|
+
return self.contract_size
|
|
389
430
|
|
|
390
431
|
@property
|
|
391
432
|
def price_precision(self):
|
|
@@ -401,8 +442,15 @@ class Instrument:
|
|
|
401
442
|
|
|
402
443
|
@property
|
|
403
444
|
def asset(self) -> str:
|
|
445
|
+
"""The venue coin, multiplier stripped (1000PEPE -> PEPE): a function of the listing alone, so
|
|
446
|
+
connector-built and lookup-built instruments agree. Economic exposure is `exposure_code`."""
|
|
404
447
|
return multiplier_coin(self.base)
|
|
405
448
|
|
|
449
|
+
@property
|
|
450
|
+
def exposure_code(self) -> str:
|
|
451
|
+
"""What the listing is a contract on (NVDA.XNAS for a bStock, XAU for PAXG); `asset` when the underlying is unknown."""
|
|
452
|
+
return self.underlying.code if self.underlying is not None else self.asset
|
|
453
|
+
|
|
406
454
|
def is_futures(self) -> bool:
|
|
407
455
|
return self.market_type in [MarketType.FUTURE, MarketType.SWAP]
|
|
408
456
|
|
|
@@ -521,6 +569,11 @@ class Instrument:
|
|
|
521
569
|
return False
|
|
522
570
|
return str(self) == str(other)
|
|
523
571
|
|
|
572
|
+
def __lt__(self, other: "Instrument") -> bool:
|
|
573
|
+
if not isinstance(other, Instrument):
|
|
574
|
+
return NotImplemented
|
|
575
|
+
return (self.symbol, self.market_type, self.exchange) < (other.symbol, other.market_type, other.exchange)
|
|
576
|
+
|
|
524
577
|
def __str__(self) -> str:
|
|
525
578
|
return ":".join([self.exchange, self.market_type, self.symbol])
|
|
526
579
|
|
|
@@ -574,11 +627,10 @@ class Instrument:
|
|
|
574
627
|
Min Size: {self.min_size}
|
|
575
628
|
Min Notional: {self.min_notional}
|
|
576
629
|
Contract Size: {self.contract_size}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
Delist Date: {self.delist_date}
|
|
630
|
+
Underlying: {self.underlying}
|
|
631
|
+
Calendar: {self.calendar}
|
|
632
|
+
Listed At: {self.listed_at}
|
|
633
|
+
Delisted At: {self.delisted_at}
|
|
582
634
|
"""
|
|
583
635
|
print(info_str)
|
|
584
636
|
|
|
@@ -1186,6 +1238,7 @@ class Position:
|
|
|
1186
1238
|
_initial_margin_external: bool = False # If True, initial_margin is managed by exchange (skip recalculation)
|
|
1187
1239
|
maint_margin: float = 0.0
|
|
1188
1240
|
_maint_margin_external: bool = False # If True, maint_margin is managed by exchange (skip recalculation)
|
|
1241
|
+
maint_margin_rate: float = DEFAULT_MAINTENANCE_MARGIN # fraction of notional, set from the account config
|
|
1189
1242
|
|
|
1190
1243
|
# ADL queue position from the exchange (None if not reported).
|
|
1191
1244
|
# Lower values = more likely to be auto-deleveraged.
|
|
@@ -1711,8 +1764,9 @@ class Position:
|
|
|
1711
1764
|
# Only apply maintenance margin for leveraged instruments (futures/swaps)
|
|
1712
1765
|
# Spot positions don't have margin requirements since you own the actual asset
|
|
1713
1766
|
if self.instrument.is_futures():
|
|
1714
|
-
|
|
1715
|
-
|
|
1767
|
+
self.maint_margin = (
|
|
1768
|
+
self.maint_margin_rate * abs(self.quantity) * self._qty_multiplier * self.last_update_price
|
|
1769
|
+
)
|
|
1716
1770
|
else:
|
|
1717
1771
|
self.maint_margin = 0.0
|
|
1718
1772
|
|
|
@@ -1727,17 +1781,9 @@ class Position:
|
|
|
1727
1781
|
if self._initial_margin_external:
|
|
1728
1782
|
return
|
|
1729
1783
|
|
|
1730
|
-
#
|
|
1731
|
-
#
|
|
1732
|
-
|
|
1733
|
-
# default without the per-instrument leverage setting, which lives on
|
|
1734
|
-
# the account processor).
|
|
1735
|
-
if self.instrument.is_futures() and self.instrument.initial_margin > 0:
|
|
1736
|
-
self.initial_margin = (
|
|
1737
|
-
self.instrument.initial_margin * abs(self.quantity) * self._qty_multiplier * self.last_update_price
|
|
1738
|
-
)
|
|
1739
|
-
else:
|
|
1740
|
-
self.initial_margin = 0.0
|
|
1784
|
+
# Without a venue-reported value the framework can't infer one: it depends on the
|
|
1785
|
+
# per-instrument leverage setting, which lives on the account processor.
|
|
1786
|
+
self.initial_margin = 0.0
|
|
1741
1787
|
|
|
1742
1788
|
|
|
1743
1789
|
VENUE_SETTINGS_EVENT = "venue_settings"
|
|
@@ -2094,24 +2140,24 @@ class InstrumentsLookup:
|
|
|
2094
2140
|
i
|
|
2095
2141
|
for i in self.get_lookup().values()
|
|
2096
2142
|
if i.exchange == exchange
|
|
2097
|
-
and (base is None or i.base == base or
|
|
2143
|
+
and (base is None or i.base == base or i.asset == base)
|
|
2098
2144
|
and (quote is None or i.quote == quote)
|
|
2099
2145
|
and (market_type is None or i.market_type == market_type)
|
|
2100
2146
|
and (
|
|
2101
2147
|
_limit_time is None
|
|
2102
|
-
or (i.
|
|
2148
|
+
or (i.listed_at is None or pd.Timestamp(i.listed_at).tz_localize(None) <= _limit_time)
|
|
2103
2149
|
)
|
|
2104
2150
|
and (
|
|
2105
2151
|
_limit_time is None
|
|
2106
|
-
or (i.
|
|
2152
|
+
or (i.delisted_at is None or pd.Timestamp(i.delisted_at).tz_localize(None) >= _limit_time)
|
|
2107
2153
|
)
|
|
2108
2154
|
]
|
|
2109
2155
|
if base is not None:
|
|
2110
2156
|
aliases = sorted({i.base for i in matched} - {base})
|
|
2111
2157
|
if aliases and any(i.base == base for i in matched):
|
|
2112
2158
|
logger.warning(
|
|
2113
|
-
f"[lookup] {exchange}
|
|
2114
|
-
f"
|
|
2159
|
+
f"[lookup] {exchange} <y>{base}</y> is ambiguous: it also names the multiplier contracts "
|
|
2160
|
+
f"{aliases}; exact-base matches come first, pass a venue base (e.g. 1000{base}) to select one"
|
|
2115
2161
|
)
|
|
2116
2162
|
matched.sort(key=lambda i: i.base != base)
|
|
2117
2163
|
return matched
|
|
@@ -38,11 +38,11 @@ class DelistingDetector:
|
|
|
38
38
|
|
|
39
39
|
delisting = []
|
|
40
40
|
for instrument in instruments:
|
|
41
|
-
if instrument.
|
|
41
|
+
if instrument.delisted_at is None:
|
|
42
42
|
continue
|
|
43
43
|
|
|
44
44
|
try:
|
|
45
|
-
delist_timestamp = to_timestamp(instrument.
|
|
45
|
+
delist_timestamp = to_timestamp(instrument.delisted_at).replace(tzinfo=None)
|
|
46
46
|
if bool(pd.isna(delist_timestamp)):
|
|
47
47
|
continue
|
|
48
48
|
|
|
@@ -73,7 +73,7 @@ class DelistingDetector:
|
|
|
73
73
|
|
|
74
74
|
# Log instruments being filtered out
|
|
75
75
|
for instrument in delisting_instruments:
|
|
76
|
-
self._info(f"Filtering out {instrument.symbol} - delisting on {instrument.
|
|
76
|
+
self._info(f"Filtering out {instrument.symbol} - delisting on {instrument.delisted_at}")
|
|
77
77
|
|
|
78
78
|
# Return instruments that are NOT in the delisting set
|
|
79
79
|
return [instrument for instrument in instruments if instrument not in delisting_set]
|
|
@@ -516,11 +516,10 @@ class IAccountViewer:
|
|
|
516
516
|
In live this is the venue-reported figure when the venue provides one
|
|
517
517
|
(e.g. Binance ``availableBalance``); otherwise it derives as
|
|
518
518
|
``total_capital - total_initial_margin``. For an accurate derivation,
|
|
519
|
-
the connector must populate ``Position.initial_margin``
|
|
519
|
+
the connector must populate ``Position.initial_margin`` via
|
|
520
520
|
``set_external_initial_margin(...)`` from venue data (e.g. HPL
|
|
521
|
-
``marginUsed``)
|
|
522
|
-
|
|
523
|
-
capital.
|
|
521
|
+
``marginUsed``). Connectors that don't will see this method return the
|
|
522
|
+
full capital.
|
|
524
523
|
|
|
525
524
|
Returns:
|
|
526
525
|
float: Available balance
|
|
@@ -2665,7 +2664,7 @@ class IStrategyInitializer:
|
|
|
2665
2664
|
"""
|
|
2666
2665
|
Set the number of days ahead to check for delisting.
|
|
2667
2666
|
|
|
2668
|
-
When an instrument has a
|
|
2667
|
+
When an instrument has a delisted_at set, this configuration determines how many
|
|
2669
2668
|
days before the delisting date the framework should:
|
|
2670
2669
|
1. Filter the instrument out from universe updates
|
|
2671
2670
|
2. Close positions and remove the instrument during the daily delisting check
|