Qubx 3.2.0__tar.gz → 3.2.2.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.2.0 → qubx-3.2.2.dev1}/PKG-INFO +2 -1
- {qubx-3.2.0 → qubx-3.2.2.dev1}/pyproject.toml +1 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/_version.py +2 -2
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/connector.py +2 -6
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/runner.py +14 -5
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/simulator.py +1 -1
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/transfers.py +5 -16
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/utils.py +8 -73
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/connector.py +22 -245
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/base.py +2 -8
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -15
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +1 -13
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/warmup_service.py +3 -25
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/builtin.py +3 -27
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/manager.py +4 -26
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/reconciler.py +2 -6
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/reducer.py +1 -12
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/state.py +8 -41
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/basics.py +6 -15
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/connector.py +1 -12
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/context.py +6 -90
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/errors.py +0 -20
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/events.py +0 -1
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/exceptions.py +0 -11
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/initializer.py +0 -23
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/interfaces.py +15 -118
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/metrics.py +28 -31
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/instrument_service.py +8 -18
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/market.py +26 -193
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/processing.py +13 -205
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/subscription.py +40 -177
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/trading.py +22 -102
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/series.pyi +0 -4
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/questdb.py +22 -30
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/csv.py +2 -2
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/inmemory.py +2 -2
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/questdb.py +1 -1
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/health/base.py +10 -133
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/health/dummy.py +0 -7
- qubx-3.2.2.dev1/src/qubx/utils/ntp.py +63 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/results.py +1 -23
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/configs.py +1 -43
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/runner.py +0 -3
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/handlers.py +0 -1
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/init_code.py +0 -14
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/styles.tcss +0 -7
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/account_summary.py +0 -26
- qubx-3.2.0/src/qubx/core/fit_context.py +0 -481
- qubx-3.2.0/src/qubx/core/fit_executor.py +0 -157
- qubx-3.2.0/src/qubx/core/status.py +0 -107
- qubx-3.2.0/src/qubx/utils/clock.py +0 -167
- {qubx-3.2.0 → qubx-3.2.2.dev1}/.gitignore +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/LICENSE +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/README.md +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/scripts/build.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/_nb_magic.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/data.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/iteratedstream.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/management.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/ome.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/optimization.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/sentinels.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/simulated_data.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/backtester/simulated_exchange.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/commands.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/deploy.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/misc.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/release.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/resolver.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/s3.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/theme.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/tui.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/cli/user_config.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/config.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/connection_manager.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/data.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exceptions.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/_two_stream.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/binance/connector.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/bitfinex/connector.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/okx/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/okx/connector.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/exchanges/okx/okx.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/factory.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/ohlc.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/plugin.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/rate_limits.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/ccxt/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/plugin.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/registry.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/tardis/data.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/tardis/plugin.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/connectors/tardis/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/decorator.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/executor.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/interfaces.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/server.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/control/types.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/config.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/diffs.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/account_manager/state_machine.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/detectors/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/detectors/delisting.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/detectors/stale.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/helpers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/instrument_service.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/loggers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/lookups.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/universe.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/mixins/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/series.pxd +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/series.pyx +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/utils.pyi +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/core/utils.pyx +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/cache.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/containers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/guards.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/registry.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storage.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/ccxt.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/csv.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/handy.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/multi.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/stub.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/storages/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/data/transformers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/base.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/composite.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/indicator.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/emitters/prometheus.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/composite.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/base.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/incremental.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/slack.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/formatters/target_position.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/redis_streams.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/exporters/slack.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/gathering/simplest.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/health/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/csv.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/factory.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/inmemory.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/mongo.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/loggers/postgres.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/composite.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/slack.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/notifications/throttler.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/stats.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/ta.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/pandaz/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/plugins/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/plugins/loader.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/backend.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/config.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/engine.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/ip_resolver.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/manager.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/pools.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/rate_limiting/redis_backend.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/_build.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/crypto-fees.ini +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restarts/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restarts/state_resolvers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restarts/time_finders.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/balance.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/factory.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/interfaces.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/position.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/signal.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/state.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/restorers/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/state/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/state/dummy.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/state/redis.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/base.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/accounts.toml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/config.yml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/jlive.sh.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/project/template.yml +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/qubx-cli/SKILL.md +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/qubx-indicators/SKILL.md +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/simulation-explorer/SKILL.md +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.claude/skills/strategy-release/SKILL.md +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.github/workflows/ci.yml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.gitignore.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.python-version +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.vscode/launch.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.vscode/settings.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/.vscode/tasks.json +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/CLAUDE.md.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/README.md.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/configs/.gitkeep +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/justfile.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/pyproject.toml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/research/.gitkeep +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/cli.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/template.yml +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/repo/tests/test_strategy.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/__init__.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/config.yml.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/strategy.py.j2 +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/templates/simple/template.yml +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/advanced.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/composite.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/trackers/sizers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/charting/lookinglass.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/charting/orderbook.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/collections.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/numba_utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/orderbook.pyi +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/hft/orderbook.pyx +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/marketdata/ccxt.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/marketdata/dukas.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/misc.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/nonce.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/numbers_utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/orderbook.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/dashboard.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/data.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/interfaces.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/questdb.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/rate_limiter.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/ringbuffer.pxd +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/ringbuffer.pyi +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/ringbuffer.pyx +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/accounts.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/factory.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/kernel_service.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/app.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/kernel.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/s3.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/slack.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/throttler.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/time.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/src/qubx/utils/websocket_manager.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.dev1}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
- {qubx-3.2.0 → qubx-3.2.2.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.2.
|
|
3
|
+
Version: 3.2.2.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
|
|
@@ -23,6 +23,7 @@ Requires-Dist: joblib<2,>=1.3.0
|
|
|
23
23
|
Requires-Dist: jupyter-client<9,>=8.0.0
|
|
24
24
|
Requires-Dist: loguru<1,>=0.7.2
|
|
25
25
|
Requires-Dist: msgspec<1,>=0.18.6
|
|
26
|
+
Requires-Dist: ntplib<1,>=0.4.0
|
|
26
27
|
Requires-Dist: numba<1,>=0.59.1
|
|
27
28
|
Requires-Dist: numpy>=2.0.0
|
|
28
29
|
Requires-Dist: orjson<4,>=3.10.15
|
|
@@ -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 = '3.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (3, 2,
|
|
21
|
+
__version__ = version = '3.2.2.dev1'
|
|
22
|
+
__version_tuple__ = version_tuple = (3, 2, 2, 'dev1')
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -298,17 +298,13 @@ class SimulatedConnector(ChannelEmitter):
|
|
|
298
298
|
def is_simulated_trading(self) -> bool:
|
|
299
299
|
return True
|
|
300
300
|
|
|
301
|
-
def
|
|
302
|
-
|
|
303
|
-
return None
|
|
301
|
+
def set_max_instrument_leverage(self, instrument: Instrument, leverage: float) -> bool:
|
|
302
|
+
return True
|
|
304
303
|
|
|
305
304
|
def set_margin_mode(self, instrument: Instrument, mode: str) -> bool:
|
|
306
305
|
return True
|
|
307
306
|
|
|
308
307
|
# Simulation does not model venue margin: the config getters read neutral.
|
|
309
|
-
def get_instrument_leverage(self, instrument: Instrument) -> float | None:
|
|
310
|
-
return None
|
|
311
|
-
|
|
312
308
|
def get_max_instrument_leverage(self, instrument: Instrument) -> float | None:
|
|
313
309
|
return None
|
|
314
310
|
|
|
@@ -11,7 +11,7 @@ from qubx.backtester.sentinels import NoDataContinue
|
|
|
11
11
|
from qubx.backtester.simulated_data import SimulatedDataIterator
|
|
12
12
|
from qubx.backtester.transfers import SimulationTransferManager
|
|
13
13
|
from qubx.core.account_manager import AccountManagerConfig, SimulatedAccountManager
|
|
14
|
-
from qubx.core.basics import SW, DataType, Instrument, TransactionCostsCalculator
|
|
14
|
+
from qubx.core.basics import SW, Balance, DataType, Instrument, TransactionCostsCalculator
|
|
15
15
|
from qubx.core.context import StrategyContext
|
|
16
16
|
from qubx.core.exceptions import SimulationConfigError, SimulationError
|
|
17
17
|
from qubx.core.helpers import extract_parameters_from_object, full_qualified_class_name
|
|
@@ -49,7 +49,6 @@ from .utils import (
|
|
|
49
49
|
SimulationSetup,
|
|
50
50
|
_get_default_warmup_period,
|
|
51
51
|
find_open_close_time_indent_secs_from_subscription,
|
|
52
|
-
initial_balances,
|
|
53
52
|
)
|
|
54
53
|
|
|
55
54
|
|
|
@@ -609,7 +608,7 @@ class SimulationRunner:
|
|
|
609
608
|
|
|
610
609
|
am = SimulatedAccountManager(
|
|
611
610
|
connectors=self._connectors,
|
|
612
|
-
base_currencies=self.setup.
|
|
611
|
+
base_currencies={exchange: self.setup.base_currency for exchange in self.setup.exchanges},
|
|
613
612
|
time=time_provider,
|
|
614
613
|
cfg=AccountManagerConfig(),
|
|
615
614
|
account_id=self.account_id,
|
|
@@ -617,7 +616,17 @@ class SimulationRunner:
|
|
|
617
616
|
)
|
|
618
617
|
|
|
619
618
|
# - seed initial capital per exchange into the account state
|
|
620
|
-
|
|
621
|
-
|
|
619
|
+
assert isinstance(self.setup.capital, dict)
|
|
620
|
+
for exchange, capital in self.setup.capital.items():
|
|
621
|
+
am.seed_balance(
|
|
622
|
+
exchange,
|
|
623
|
+
Balance(
|
|
624
|
+
exchange=exchange,
|
|
625
|
+
currency=self.setup.base_currency,
|
|
626
|
+
total=capital,
|
|
627
|
+
free=capital,
|
|
628
|
+
locked=0.0,
|
|
629
|
+
),
|
|
630
|
+
)
|
|
622
631
|
|
|
623
632
|
return am
|
|
@@ -38,7 +38,7 @@ def simulate(
|
|
|
38
38
|
instruments: list[str] | list[Instrument] | dict[ExchangeName_t, list[SymbolOrInstrument_t]] | None = None,
|
|
39
39
|
commissions: str | dict[str, str | None] | None = None,
|
|
40
40
|
exchange: ExchangeName_t | list[ExchangeName_t] | None = None,
|
|
41
|
-
base_currency: str
|
|
41
|
+
base_currency: str = "USDT",
|
|
42
42
|
n_jobs: int = 1,
|
|
43
43
|
silent: bool = False,
|
|
44
44
|
aux_data: IStorage | None = None,
|
|
@@ -21,15 +21,6 @@ class SimulationTransferManager(ITransferManager):
|
|
|
21
21
|
def transfer_funds(self, from_exchange: str, to_exchange: str, currency: str, amount: float) -> str:
|
|
22
22
|
if amount <= 0:
|
|
23
23
|
raise ValueError(f"Transfer amount must be positive, got {amount}")
|
|
24
|
-
to_currency = self._account.get_base_currency(to_exchange)
|
|
25
|
-
# Venues settle in their own currency: a withdrawal leaves in `currency` and arrives as
|
|
26
|
-
# `to_currency`. Both legs must be priced — an unpriced asset has no transferable value.
|
|
27
|
-
from_rate = self._account.get_state(from_exchange).conversion_rate_to_base(currency)
|
|
28
|
-
to_rate = self._account.get_state(to_exchange).conversion_rate_to_base(to_currency)
|
|
29
|
-
if from_rate is None or to_rate is None:
|
|
30
|
-
raise ValueError(f"Cannot transfer {currency} to {to_exchange} {to_currency}: no conversion rate")
|
|
31
|
-
to_amount = amount * from_rate / to_rate
|
|
32
|
-
|
|
33
24
|
from_balance = self._account.get_balance(currency, exchange=from_exchange)
|
|
34
25
|
if from_balance.free < amount:
|
|
35
26
|
raise ValueError(
|
|
@@ -37,8 +28,11 @@ class SimulationTransferManager(ITransferManager):
|
|
|
37
28
|
f"{from_balance.free:.8f} {currency} available, {amount:.8f} requested"
|
|
38
29
|
)
|
|
39
30
|
|
|
31
|
+
# Instant transfer: debit the source and credit the destination. adjust_balance
|
|
32
|
+
# mutates the held Balance in place (holders keep a live reference) and creates
|
|
33
|
+
# the destination Balance if missing.
|
|
40
34
|
self._account.adjust_balance(from_exchange, currency, -amount)
|
|
41
|
-
self._account.adjust_balance(to_exchange,
|
|
35
|
+
self._account.adjust_balance(to_exchange, currency, amount)
|
|
42
36
|
|
|
43
37
|
transaction_id = f"sim_{uuid.uuid4().hex[:12]}"
|
|
44
38
|
self._transfers[transaction_id] = Transfer(
|
|
@@ -49,13 +43,8 @@ class SimulationTransferManager(ITransferManager):
|
|
|
49
43
|
amount=amount,
|
|
50
44
|
status=TransferStatus.COMPLETED, # transfers are instant in simulation
|
|
51
45
|
timestamp=self._time.time(),
|
|
52
|
-
to_currency=to_currency,
|
|
53
|
-
to_amount=to_amount,
|
|
54
|
-
)
|
|
55
|
-
logger.debug(
|
|
56
|
-
f"[SimTransfer] {amount:.8f} {currency} {from_exchange} -> "
|
|
57
|
-
f"{to_amount:.8f} {to_currency} {to_exchange} ({transaction_id})"
|
|
58
46
|
)
|
|
47
|
+
logger.debug(f"[SimTransfer] {amount:.8f} {currency} {from_exchange} -> {to_exchange} ({transaction_id})")
|
|
59
48
|
return transaction_id
|
|
60
49
|
|
|
61
50
|
def get_transfer_status(self, transaction_id: str) -> Transfer:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import Mapping, Sequence
|
|
2
|
-
from dataclasses import dataclass
|
|
2
|
+
from dataclasses import dataclass
|
|
3
3
|
from enum import Enum
|
|
4
4
|
from typing import Any, Callable, TypeAlias
|
|
5
5
|
|
|
@@ -8,8 +8,6 @@ import pandas as pd
|
|
|
8
8
|
|
|
9
9
|
from qubx import logger
|
|
10
10
|
from qubx.core.basics import (
|
|
11
|
-
STABLE_CURRENCIES,
|
|
12
|
-
Balance,
|
|
13
11
|
CtrlChannel,
|
|
14
12
|
DataType,
|
|
15
13
|
Instrument,
|
|
@@ -82,20 +80,6 @@ def _type(obj: Any) -> SetupTypes:
|
|
|
82
80
|
return t
|
|
83
81
|
|
|
84
82
|
|
|
85
|
-
def _settle_currencies(instruments: list[Instrument], exchange: str) -> set[str]:
|
|
86
|
-
return {i.settle.upper() for i in instruments if i.exchange == exchange and i.settle}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def _derive_settle_currency(instruments: list[Instrument], exchange: str) -> str | None:
|
|
90
|
-
"""The one settle currency a venue's instruments agree on, or None when absent, mixed, or
|
|
91
|
-
not a recognized stable — BINANCE.UM:ETHBTC settles in BTC, and BTC is not 1.0 of capital."""
|
|
92
|
-
settles = _settle_currencies(instruments, exchange)
|
|
93
|
-
if len(settles) != 1:
|
|
94
|
-
return None
|
|
95
|
-
settle = settles.pop()
|
|
96
|
-
return settle if settle in STABLE_CURRENCIES else None
|
|
97
|
-
|
|
98
|
-
|
|
99
83
|
@dataclass
|
|
100
84
|
class SimulationSetup:
|
|
101
85
|
"""
|
|
@@ -109,37 +93,16 @@ class SimulationSetup:
|
|
|
109
93
|
instruments: list[Instrument]
|
|
110
94
|
exchanges: list[str]
|
|
111
95
|
capital: float | dict[str, float]
|
|
112
|
-
base_currency: str
|
|
96
|
+
base_currency: str
|
|
113
97
|
commissions: str | dict[str, str | None] | None = None
|
|
114
98
|
signal_timeframe: str = "1Min"
|
|
115
99
|
accurate_stop_orders_execution: bool = False
|
|
116
100
|
enable_funding: bool = False
|
|
117
|
-
base_currencies: dict[str, str] = field(init=False, default_factory=dict)
|
|
118
101
|
|
|
119
102
|
def __post_init__(self) -> None:
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
explicit = (
|
|
124
|
-
{ex: ccy.upper() for ex, ccy in self.base_currency.items()}
|
|
125
|
-
if isinstance(self.base_currency, dict)
|
|
126
|
-
else {}
|
|
127
|
-
)
|
|
128
|
-
default_ccy = (
|
|
129
|
-
self.base_currency.upper()
|
|
130
|
-
if isinstance(self.base_currency, str)
|
|
131
|
-
else (explicit.get(self.exchanges[0], "USDT") if self.exchanges else "USDT")
|
|
132
|
-
)
|
|
133
|
-
self.base_currencies = {}
|
|
134
|
-
for ex in self.exchanges:
|
|
135
|
-
resolved = explicit.get(ex) or _derive_settle_currency(self.instruments, ex)
|
|
136
|
-
if resolved is None and (settles := _settle_currencies(self.instruments, ex)):
|
|
137
|
-
logger.debug(
|
|
138
|
-
f"No single stable settle currency for {ex} (saw {sorted(settles)}) "
|
|
139
|
-
f"- using {default_ccy} as its base currency"
|
|
140
|
-
)
|
|
141
|
-
self.base_currencies[ex] = resolved or default_ccy
|
|
142
|
-
self.base_currency = self.base_currencies[self.exchanges[0]] if self.exchanges else default_ccy
|
|
103
|
+
# Normalize once at the config boundary: AccountState stores base_currency upper-cased,
|
|
104
|
+
# so a lowercase value here would seed capital under a key total_capital never reads.
|
|
105
|
+
self.base_currency = self.base_currency.upper()
|
|
143
106
|
# Normalize capital to a per-exchange dict: split evenly when a single float is given
|
|
144
107
|
if isinstance(self.capital, (int, float)):
|
|
145
108
|
n = len(self.exchanges)
|
|
@@ -150,21 +113,6 @@ class SimulationSetup:
|
|
|
150
113
|
return f"{self.name} {self.setup_type} capital {self.capital} {self.base_currency} for [{','.join(map(lambda x: x.symbol, self.instruments))}] @ {self.exchanges}[{self.commissions}]"
|
|
151
114
|
|
|
152
115
|
|
|
153
|
-
def initial_balances(setup: SimulationSetup) -> dict[str, Balance]:
|
|
154
|
-
"""Startup balance per exchange, each in that venue's own base currency."""
|
|
155
|
-
assert isinstance(setup.capital, dict)
|
|
156
|
-
return {
|
|
157
|
-
exchange: Balance(
|
|
158
|
-
exchange=exchange,
|
|
159
|
-
currency=setup.base_currencies[exchange],
|
|
160
|
-
total=capital,
|
|
161
|
-
free=capital,
|
|
162
|
-
locked=0.0,
|
|
163
|
-
)
|
|
164
|
-
for exchange, capital in setup.capital.items()
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
116
|
# fmt: off
|
|
169
117
|
@dataclass
|
|
170
118
|
class SimulationDataConfig:
|
|
@@ -339,9 +287,7 @@ def find_instruments_and_exchanges(
|
|
|
339
287
|
_instrs.append(instrument)
|
|
340
288
|
_exchanges.append(resolved_exchange)
|
|
341
289
|
|
|
342
|
-
|
|
343
|
-
# decides the persisted scalar base_currency of a multi-venue run.
|
|
344
|
-
return _instrs, sorted(set(_exchanges))
|
|
290
|
+
return _instrs, list(set(_exchanges))
|
|
345
291
|
|
|
346
292
|
|
|
347
293
|
class _StructureSniffer:
|
|
@@ -399,7 +345,7 @@ def recognize_simulation_configuration(
|
|
|
399
345
|
instruments: list[Instrument],
|
|
400
346
|
exchanges: list[str],
|
|
401
347
|
capital: float | dict[str, float],
|
|
402
|
-
basic_currency: str
|
|
348
|
+
basic_currency: str,
|
|
403
349
|
commissions: str | dict[str, str | None] | None,
|
|
404
350
|
signal_timeframe: str,
|
|
405
351
|
accurate_stop_orders_execution: bool,
|
|
@@ -694,16 +640,7 @@ def recognize_simulation_data_config(
|
|
|
694
640
|
)
|
|
695
641
|
|
|
696
642
|
|
|
697
|
-
_TRANSFERS_LOG_COLUMNS = [
|
|
698
|
-
"transaction_id",
|
|
699
|
-
"from_exchange",
|
|
700
|
-
"to_exchange",
|
|
701
|
-
"currency",
|
|
702
|
-
"amount",
|
|
703
|
-
"status",
|
|
704
|
-
"to_currency",
|
|
705
|
-
"to_amount",
|
|
706
|
-
]
|
|
643
|
+
_TRANSFERS_LOG_COLUMNS = ["transaction_id", "from_exchange", "to_exchange", "currency", "amount", "status"]
|
|
707
644
|
|
|
708
645
|
|
|
709
646
|
def collect_transfers_log(transfer_manager: ITransferManager | None) -> pd.DataFrame | None:
|
|
@@ -730,8 +667,6 @@ def collect_transfers_log(transfer_manager: ITransferManager | None) -> pd.DataF
|
|
|
730
667
|
"currency": t.currency,
|
|
731
668
|
"amount": t.amount,
|
|
732
669
|
"status": str(t.status),
|
|
733
|
-
"to_currency": t.to_currency or t.currency,
|
|
734
|
-
"to_amount": t.to_amount if t.to_amount is not None else t.amount,
|
|
735
670
|
}
|
|
736
671
|
for t in transfers
|
|
737
672
|
]
|