Qubx 1.0.0.dev4__tar.gz → 1.0.0.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/PKG-INFO +1 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/pyproject.toml +1 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/_version.py +2 -2
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/connection_manager.py +7 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/ohlc.py +3 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/basics.py +5 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/interfaces.py +2 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/lookups.py +38 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/processing.py +2 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/composite.py +11 -9
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/formatters/base.py +4 -2
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/formatters/incremental.py +2 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/formatters/slack.py +5 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/redis_streams.py +3 -2
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/slack.py +4 -3
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/factory.py +4 -7
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/runner.py +3 -1
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/.gitignore +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/LICENSE +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/README.md +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/hatch_build.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/_nb_magic.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/account.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/broker.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/data.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/iteratedstream.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/management.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/ome.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/optimization.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/runner.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/sentinels.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/simulated_data.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/simulated_exchange.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/simulator.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/transfers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/backtester/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/commands.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/deploy.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/misc.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/release.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/theme.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/cli/tui.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/config.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/account.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/adapters/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/adapters/polling_adapter.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/broker.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/data.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exceptions.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchange_manager.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/base.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/gateio/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/gateio/gateio.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/account.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/broker.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/factory.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/base.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/factory.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/funding_rate.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/liquidation.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/open_interest.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/orderbook.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/quote.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/handlers/trade.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/subscription_config.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/subscription_manager.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/subscription_orchestrator.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/warmup_service.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/registry.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/tardis/data.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/tardis/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/account.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/context.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/detectors/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/detectors/delisting.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/detectors/stale.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/errors.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/exceptions.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/helpers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/initializer.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/loggers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/metrics.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/market.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/subscription.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/trading.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/universe.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/mixins/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/series.pxd +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/series.pyi +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/series.pyx +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/utils.pyi +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/core/utils.pyx +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/cache.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/containers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/guards.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/registry.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storage.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/ccxt.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/csv.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/handy.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/multi.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/questdb.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/stub.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/storages/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/data/transformers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/base.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/composite.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/csv.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/indicator.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/inmemory.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/prometheus.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/emitters/questdb.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/formatters/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/exporters/formatters/target_position.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/gathering/simplest.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/health/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/health/base.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/health/dummy.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/loggers/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/loggers/csv.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/loggers/factory.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/loggers/inmemory.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/loggers/mongo.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/notifications/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/notifications/composite.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/notifications/slack.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/notifications/throttler.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/pandaz/stats.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/pandaz/ta.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/pandaz/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/plugins/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/plugins/loader.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/_build.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/crypto-fees.ini +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/hyperliquid-spot.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restarts/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restarts/state_resolvers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restarts/time_finders.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/balance.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/factory.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/interfaces.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/position.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/signal.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/state.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/restorers/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/state/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/state/dummy.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/state/redis.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/ta/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/base.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/accounts.toml.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/config.yml.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/jlive.sh.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/jpaper.sh.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/pyproject.toml.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/project/template.yml +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/__init__.py.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/accounts.toml.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/config.yml.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/jlive.sh.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/jpaper.sh.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/strategy.py.j2 +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/templates/simple/template.yml +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/trackers/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/trackers/advanced.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/trackers/composite.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/trackers/sizers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/charting/lookinglass.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/charting/orderbook.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/collections.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/hft/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/hft/numba_utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/hft/orderbook.pyi +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/hft/orderbook.pyx +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/marketdata/ccxt.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/marketdata/dukas.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/misc.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/nonce.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/ntp.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/numbers_utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/orderbook.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/plotting/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/plotting/dashboard.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/plotting/data.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/plotting/interfaces.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/questdb.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/rate_limiter.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/results.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/ringbuffer.pxd +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/ringbuffer.pyi +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/ringbuffer.pyx +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/_jupyter_runner.pyt +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/accounts.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/configs.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/kernel_service.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/app.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/handlers.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/init_code.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/kernel.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/styles.tcss +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/__init__.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/command_input.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/debug_log.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/orders_table.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/positions_table.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/quotes_table.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/runner/textual/widgets/repl_output.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/slack.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/throttler.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/time.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/utils/websocket_manager.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/tests/strategies/macd_crossover/src/macd_crossover/indicators/macd.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/tests/strategies/macd_crossover/src/macd_crossover/models/macd_crossover.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/tests/strategies/macd_crossover/src/macd_crossover/models/utils.py +0 -0
- {qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/tests/strategies/obi_trader/src/obi_trader/models/obi_trader.py +0 -0
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.0.0.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 0, 0, '
|
|
31
|
+
__version__ = version = '1.0.0.dev5'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 0, 0, 'dev5')
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -12,7 +12,7 @@ from asyncio.exceptions import CancelledError
|
|
|
12
12
|
from collections import defaultdict
|
|
13
13
|
from typing import Awaitable, Callable
|
|
14
14
|
|
|
15
|
-
from ccxt import ExchangeClosedByUser, ExchangeError, ExchangeNotAvailable, NetworkError
|
|
15
|
+
from ccxt import BadSymbol, ExchangeClosedByUser, ExchangeError, ExchangeNotAvailable, NetworkError
|
|
16
16
|
from ccxt.async_support.base.ws.client import Client as _WsClient
|
|
17
17
|
from ccxt.pro import Exchange
|
|
18
18
|
|
|
@@ -133,6 +133,12 @@ class ConnectionManager:
|
|
|
133
133
|
# Connection closed by us, stop gracefully
|
|
134
134
|
logger.info(f"<yellow>{self._exchange_id}</yellow> {stream_name} listening has been stopped")
|
|
135
135
|
break
|
|
136
|
+
except BadSymbol as e:
|
|
137
|
+
# Bad symbol is a permanent error - retrying will never succeed
|
|
138
|
+
logger.error(
|
|
139
|
+
f"<yellow>{self._exchange_id}</yellow> BadSymbol :: {stream_name} : {e} - stopping stream"
|
|
140
|
+
)
|
|
141
|
+
break
|
|
136
142
|
except (NetworkError, ExchangeError, ExchangeNotAvailable) as e:
|
|
137
143
|
# Network/exchange errors - retry after short delay
|
|
138
144
|
logger.error(
|
|
@@ -8,6 +8,7 @@ import asyncio
|
|
|
8
8
|
from typing import Set
|
|
9
9
|
|
|
10
10
|
import pandas as pd
|
|
11
|
+
from ccxt import BadSymbol
|
|
11
12
|
|
|
12
13
|
from qubx import logger
|
|
13
14
|
from qubx.core.basics import CtrlChannel, DataType, Instrument
|
|
@@ -274,6 +275,8 @@ class OhlcDataHandler(BaseDataTypeHandler):
|
|
|
274
275
|
# Use private processing method to avoid duplication
|
|
275
276
|
self._process_ohlcv_bar(oh, inst, sub_type, channel, timeframe, ohlcv_data)
|
|
276
277
|
|
|
278
|
+
except BadSymbol:
|
|
279
|
+
raise # Permanent error, let ConnectionManager handle it
|
|
277
280
|
except Exception as e:
|
|
278
281
|
logger.error(
|
|
279
282
|
f"<yellow>{exchange_id}</yellow> Error in individual OHLCV subscription for {inst.symbol}: {e}"
|
|
@@ -1455,3 +1455,8 @@ class InstrumentsLookup:
|
|
|
1455
1455
|
|
|
1456
1456
|
class FeesLookup:
|
|
1457
1457
|
def find_fees(self, exchange: str, spec: str | None) -> TransactionCostsCalculator: ...
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
class AccountsLookup:
|
|
1461
|
+
def get_credentials(self, exchange: str): ...
|
|
1462
|
+
def get_settings(self, exchange: str): ...
|
|
@@ -148,7 +148,8 @@ class ITradeDataExport:
|
|
|
148
148
|
pass
|
|
149
149
|
|
|
150
150
|
def export_position_changes(
|
|
151
|
-
self, time: dt_64, instrument: Instrument, price: float, account: "IAccountViewer"
|
|
151
|
+
self, time: dt_64, instrument: Instrument, price: float, account: "IAccountViewer",
|
|
152
|
+
metadata: dict[str, Any] | None = None,
|
|
152
153
|
) -> None:
|
|
153
154
|
"""
|
|
154
155
|
Export position changes to an external system.
|
|
@@ -13,6 +13,7 @@ import stackprinter
|
|
|
13
13
|
from qubx import logger
|
|
14
14
|
from qubx.core.basics import (
|
|
15
15
|
ZERO_COSTS,
|
|
16
|
+
AccountsLookup,
|
|
16
17
|
FeesLookup,
|
|
17
18
|
Instrument,
|
|
18
19
|
InstrumentsLookup,
|
|
@@ -440,9 +441,30 @@ class InstrumentsLookupMongo(InstrumentsLookup):
|
|
|
440
441
|
return self._lookup
|
|
441
442
|
|
|
442
443
|
|
|
443
|
-
class
|
|
444
|
+
class AccountsLookupFromManager(AccountsLookup):
|
|
445
|
+
"""Concrete AccountsLookup that delegates to an AccountConfigurationManager."""
|
|
446
|
+
|
|
447
|
+
_manager = None
|
|
448
|
+
|
|
449
|
+
def register(self, manager) -> None:
|
|
450
|
+
"""Register account manager. Called once at startup by the runner."""
|
|
451
|
+
self._manager = manager
|
|
452
|
+
|
|
453
|
+
def get_credentials(self, exchange: str):
|
|
454
|
+
if self._manager is None:
|
|
455
|
+
raise RuntimeError("No account manager registered — call lookup.register_accounts() at startup")
|
|
456
|
+
return self._manager.get_exchange_credentials(exchange)
|
|
457
|
+
|
|
458
|
+
def get_settings(self, exchange: str):
|
|
459
|
+
if self._manager is None:
|
|
460
|
+
raise RuntimeError("No account manager registered — call lookup.register_accounts() at startup")
|
|
461
|
+
return self._manager.get_exchange_settings(exchange)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
class LookupsManager(InstrumentsLookup, FeesLookup, AccountsLookup):
|
|
444
465
|
_i_lookup: InstrumentsLookup
|
|
445
466
|
_t_lookup: FeesLookup
|
|
467
|
+
_a_lookup: AccountsLookupFromManager
|
|
446
468
|
|
|
447
469
|
def __new__(cls):
|
|
448
470
|
if not hasattr(cls, "instance"):
|
|
@@ -466,6 +488,7 @@ class LookupsManager(InstrumentsLookup, FeesLookup):
|
|
|
466
488
|
if f_cfg.path:
|
|
467
489
|
f_kwargs["path"] = f_cfg.path
|
|
468
490
|
cls.instance._t_lookup = LookupsManager._get_fees_lookup(type=f_cfg.type, **f_kwargs)
|
|
491
|
+
cls.instance._a_lookup = AccountsLookupFromManager()
|
|
469
492
|
|
|
470
493
|
return cls.instance
|
|
471
494
|
|
|
@@ -511,6 +534,12 @@ class LookupsManager(InstrumentsLookup, FeesLookup):
|
|
|
511
534
|
def __getitem__(self, spath: str) -> list[Instrument]:
|
|
512
535
|
return self._i_lookup[spath]
|
|
513
536
|
|
|
537
|
+
def get_credentials(self, exchange: str):
|
|
538
|
+
return self._a_lookup.get_credentials(exchange)
|
|
539
|
+
|
|
540
|
+
def get_settings(self, exchange: str):
|
|
541
|
+
return self._a_lookup.get_settings(exchange)
|
|
542
|
+
|
|
514
543
|
|
|
515
544
|
# - global lookup helper (lazy-loaded to avoid slow import)
|
|
516
545
|
_lookup = None
|
|
@@ -523,3 +552,11 @@ def __getattr__(name):
|
|
|
523
552
|
_lookup = LookupsManager()
|
|
524
553
|
return _lookup
|
|
525
554
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
def register_accounts(manager) -> None:
|
|
558
|
+
"""Register account manager in the global lookup. Called once at startup by the runner."""
|
|
559
|
+
global _lookup
|
|
560
|
+
if _lookup is None:
|
|
561
|
+
_lookup = LookupsManager()
|
|
562
|
+
_lookup._a_lookup.register(manager)
|
|
@@ -1015,11 +1015,13 @@ class ProcessingManager(IProcessingManager):
|
|
|
1015
1015
|
|
|
1016
1016
|
if self._exporter is not None and (q := self._market_data.quote(instrument)) is not None:
|
|
1017
1017
|
# - export position changes if exporter is available
|
|
1018
|
+
_active = self._active_targets.get(instrument)
|
|
1018
1019
|
self._exporter.export_position_changes(
|
|
1019
1020
|
time=self._time_provider.time(),
|
|
1020
1021
|
instrument=instrument,
|
|
1021
1022
|
price=q.mid_price(),
|
|
1022
1023
|
account=self._account,
|
|
1024
|
+
metadata=_active.options if _active else None,
|
|
1023
1025
|
)
|
|
1024
1026
|
|
|
1025
1027
|
# - notify universe manager about position change
|
|
@@ -5,7 +5,7 @@ This module provides a composite implementation of ITradeDataExport that delegat
|
|
|
5
5
|
to multiple exporters.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import
|
|
8
|
+
from typing import Any
|
|
9
9
|
|
|
10
10
|
from qubx.core.basics import Instrument, Signal, TargetPosition, dt_64
|
|
11
11
|
from qubx.core.interfaces import IAccountViewer, ITradeDataExport
|
|
@@ -19,22 +19,22 @@ class CompositeExporter(ITradeDataExport):
|
|
|
19
19
|
by combining multiple exporters into one.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def __init__(self, exporters:
|
|
22
|
+
def __init__(self, exporters: list[ITradeDataExport]):
|
|
23
23
|
"""
|
|
24
24
|
Initialize the Composite Exporter.
|
|
25
25
|
|
|
26
26
|
Args:
|
|
27
|
-
exporters:
|
|
27
|
+
exporters: list of exporters to delegate to
|
|
28
28
|
"""
|
|
29
29
|
self._exporters = exporters
|
|
30
30
|
|
|
31
|
-
def export_signals(self, time: dt_64, signals:
|
|
31
|
+
def export_signals(self, time: dt_64, signals: list[Signal], account: IAccountViewer) -> None:
|
|
32
32
|
"""
|
|
33
33
|
Export signals to all configured exporters.
|
|
34
34
|
|
|
35
35
|
Args:
|
|
36
36
|
time: Timestamp when the signals were generated
|
|
37
|
-
signals:
|
|
37
|
+
signals: list of signals to export
|
|
38
38
|
account: Account viewer to get account information
|
|
39
39
|
"""
|
|
40
40
|
for exporter in self._exporters:
|
|
@@ -45,13 +45,13 @@ class CompositeExporter(ITradeDataExport):
|
|
|
45
45
|
|
|
46
46
|
logger.error(f"Error exporting signals to {exporter.__class__.__name__}: {e}")
|
|
47
47
|
|
|
48
|
-
def export_target_positions(self, time: dt_64, targets:
|
|
48
|
+
def export_target_positions(self, time: dt_64, targets: list[TargetPosition], account: IAccountViewer) -> None:
|
|
49
49
|
"""
|
|
50
50
|
Export target positions to all configured exporters.
|
|
51
51
|
|
|
52
52
|
Args:
|
|
53
53
|
time: Timestamp when the target positions were generated
|
|
54
|
-
targets:
|
|
54
|
+
targets: list of target positions to export
|
|
55
55
|
account: Account viewer to get account information
|
|
56
56
|
"""
|
|
57
57
|
for exporter in self._exporters:
|
|
@@ -63,7 +63,8 @@ class CompositeExporter(ITradeDataExport):
|
|
|
63
63
|
logger.error(f"Error exporting target positions to {exporter.__class__.__name__}: {e}")
|
|
64
64
|
|
|
65
65
|
def export_position_changes(
|
|
66
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
66
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
67
|
+
metadata: dict[str, Any] | None = None,
|
|
67
68
|
) -> None:
|
|
68
69
|
"""
|
|
69
70
|
Export position changes to all configured exporters.
|
|
@@ -73,10 +74,11 @@ class CompositeExporter(ITradeDataExport):
|
|
|
73
74
|
instrument: The instrument for which the position changed
|
|
74
75
|
price: Price at which the position changed
|
|
75
76
|
account: Account viewer to get account information
|
|
77
|
+
metadata: Optional metadata to pass to exporters
|
|
76
78
|
"""
|
|
77
79
|
for exporter in self._exporters:
|
|
78
80
|
try:
|
|
79
|
-
exporter.export_position_changes(time, instrument, price, account)
|
|
81
|
+
exporter.export_position_changes(time, instrument, price, account, metadata=metadata)
|
|
80
82
|
except Exception as e:
|
|
81
83
|
from qubx import logger
|
|
82
84
|
|
|
@@ -54,7 +54,8 @@ class IExportFormatter(ABC):
|
|
|
54
54
|
|
|
55
55
|
@abstractmethod
|
|
56
56
|
def format_position_change(
|
|
57
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
57
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
58
|
+
metadata: dict[str, Any] | None = None,
|
|
58
59
|
) -> dict[str, Any]:
|
|
59
60
|
"""
|
|
60
61
|
Format a leverage change for export.
|
|
@@ -137,7 +138,8 @@ class DefaultFormatter(IExportFormatter):
|
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
def format_position_change(
|
|
140
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
141
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
142
|
+
metadata: dict[str, Any] | None = None,
|
|
141
143
|
) -> dict[str, Any]:
|
|
142
144
|
"""
|
|
143
145
|
Format a position change for export.
|
|
@@ -37,7 +37,8 @@ class IncrementalFormatter(DefaultFormatter):
|
|
|
37
37
|
self.instrument_leverages = dict(account.get_leverages())
|
|
38
38
|
|
|
39
39
|
def format_position_change(
|
|
40
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
40
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
41
|
+
metadata: dict[str, Any] | None = None,
|
|
41
42
|
) -> dict[str, Any]:
|
|
42
43
|
"""
|
|
43
44
|
Format a position change for export.
|
|
@@ -148,7 +148,8 @@ class SlackMessageFormatter(IExportFormatter):
|
|
|
148
148
|
return {"blocks": blocks}
|
|
149
149
|
|
|
150
150
|
def format_position_change(
|
|
151
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
151
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
152
|
+
metadata: dict[str, Any] | None = None,
|
|
152
153
|
) -> dict[str, Any]:
|
|
153
154
|
"""
|
|
154
155
|
Format a position change as a Slack message.
|
|
@@ -172,6 +173,9 @@ class SlackMessageFormatter(IExportFormatter):
|
|
|
172
173
|
f"*Current Quantity:* {position.quantity}\n"
|
|
173
174
|
)
|
|
174
175
|
|
|
176
|
+
if metadata and "sources" in metadata:
|
|
177
|
+
position_text += f"*Sources:* {', '.join(metadata['sources'])}\n"
|
|
178
|
+
|
|
175
179
|
# Create blocks
|
|
176
180
|
blocks = [self._create_header_block("Position Change", timestamp), self._create_section_block(position_text)]
|
|
177
181
|
|
|
@@ -210,7 +210,8 @@ class RedisStreamsExporter(ITradeDataExport):
|
|
|
210
210
|
logger.exception("[RedisStreamsExporter] Failed to export target positions")
|
|
211
211
|
|
|
212
212
|
def export_position_changes(
|
|
213
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
213
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
214
|
+
metadata: dict[str, Any] | None = None,
|
|
214
215
|
) -> None:
|
|
215
216
|
"""
|
|
216
217
|
Export position changes to Redis Stream.
|
|
@@ -230,7 +231,7 @@ class RedisStreamsExporter(ITradeDataExport):
|
|
|
230
231
|
|
|
231
232
|
try:
|
|
232
233
|
# Format the leverage change using the formatter
|
|
233
|
-
data = self._formatter.format_position_change(time, instrument, price, account)
|
|
234
|
+
data = self._formatter.format_position_change(time, instrument, price, account, metadata=metadata)
|
|
234
235
|
|
|
235
236
|
# Add to Redis stream in background thread
|
|
236
237
|
self._add_to_redis_stream(self._position_changes_stream, data)
|
|
@@ -4,7 +4,7 @@ Slack Exporter for trading data.
|
|
|
4
4
|
This module provides an implementation of ITradeDataExport that exports trading data to Slack channels.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import List, Optional
|
|
7
|
+
from typing import Any, List, Optional
|
|
8
8
|
|
|
9
9
|
from qubx import logger
|
|
10
10
|
from qubx.core.basics import Instrument, Signal, TargetPosition, dt_64
|
|
@@ -140,7 +140,8 @@ class SlackExporter(ITradeDataExport):
|
|
|
140
140
|
logger.error(f"Failed to export target positions: {e}")
|
|
141
141
|
|
|
142
142
|
def export_position_changes(
|
|
143
|
-
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer
|
|
143
|
+
self, time: dt_64, instrument: Instrument, price: float, account: IAccountViewer,
|
|
144
|
+
metadata: dict[str, Any] | None = None,
|
|
144
145
|
) -> None:
|
|
145
146
|
"""
|
|
146
147
|
Export position changes to Slack.
|
|
@@ -156,7 +157,7 @@ class SlackExporter(ITradeDataExport):
|
|
|
156
157
|
|
|
157
158
|
try:
|
|
158
159
|
# Format the position change using the formatter
|
|
159
|
-
data = self._formatter.format_position_change(time, instrument, price, account)
|
|
160
|
+
data = self._formatter.format_position_change(time, instrument, price, account, metadata=metadata)
|
|
160
161
|
|
|
161
162
|
# Extract blocks and create fallback message
|
|
162
163
|
blocks = data.get("blocks", [])
|
|
@@ -4,10 +4,7 @@ Factory functions for creating various components used in strategy running and s
|
|
|
4
4
|
|
|
5
5
|
import inspect
|
|
6
6
|
import os
|
|
7
|
-
from typing import
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from qubx.utils.runner.accounts import AccountConfigurationManager
|
|
7
|
+
from typing import Any
|
|
11
8
|
|
|
12
9
|
from qubx import logger
|
|
13
10
|
from qubx.core.interfaces import IAccountViewer, IMetricEmitter, IStatePersistence, IStrategyNotifier, ITradeDataExport
|
|
@@ -47,7 +44,7 @@ def construct_storage(storage_config: StorageConfig | None) -> IStorage | None:
|
|
|
47
44
|
(e.g., 'qdb::quantlab', 'csv::/data/path/', 'mqdb::nebula').
|
|
48
45
|
|
|
49
46
|
Args:
|
|
50
|
-
|
|
47
|
+
storage_config: Storage configuration
|
|
51
48
|
|
|
52
49
|
Returns:
|
|
53
50
|
IStorage instance or None if storage_config is None
|
|
@@ -222,7 +219,7 @@ def create_data_type_storages(storages_configs: list[TypedStorageConfig] | None)
|
|
|
222
219
|
def create_exporters(
|
|
223
220
|
exporters: list[ExporterConfig] | None,
|
|
224
221
|
strategy_name: str,
|
|
225
|
-
account:
|
|
222
|
+
account: IAccountViewer | None = None,
|
|
226
223
|
) -> ITradeDataExport | None:
|
|
227
224
|
"""
|
|
228
225
|
Create exporters from the configuration.
|
|
@@ -400,7 +397,7 @@ def construct_multi_storage(storage_configs: list[StorageConfig]) -> IStorage |
|
|
|
400
397
|
Construct auxiliary data storage from config.
|
|
401
398
|
|
|
402
399
|
Args:
|
|
403
|
-
|
|
400
|
+
storage_configs: List of storage configurations
|
|
404
401
|
|
|
405
402
|
Returns:
|
|
406
403
|
Single IStorage if only one config, MultiStorage if multiple configs, None if empty
|
|
@@ -42,7 +42,7 @@ from qubx.core.interfaces import (
|
|
|
42
42
|
ITimeProvider,
|
|
43
43
|
)
|
|
44
44
|
from qubx.core.loggers import StrategyLogging
|
|
45
|
-
from qubx.core.lookups import lookup
|
|
45
|
+
from qubx.core.lookups import lookup, register_accounts
|
|
46
46
|
from qubx.core.mixins.utils import EXCHANGE_MAPPINGS
|
|
47
47
|
from qubx.data.cache import CachedStorage, MemoryCache
|
|
48
48
|
from qubx.data.storages.stub import NoConfiguredStorage
|
|
@@ -254,6 +254,8 @@ def run_strategy(
|
|
|
254
254
|
loop_thread.start()
|
|
255
255
|
logger.debug("Shared event loop started in background thread")
|
|
256
256
|
|
|
257
|
+
register_accounts(account_manager)
|
|
258
|
+
|
|
257
259
|
QubxLogConfig.setup_logger(
|
|
258
260
|
level=QubxLogConfig.get_log_level(),
|
|
259
261
|
custom_formatter=(simulated_formatter := SimulatedLogFormatter(LiveTimeProvider())).formatter,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py
RENAMED
|
File without changes
|
{qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/account.py
RENAMED
|
File without changes
|
{qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/broker.py
RENAMED
|
File without changes
|
{qubx-1.0.0.dev4 → qubx-1.0.0.dev5}/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|