Qubx 0.6.67__tar.gz → 0.6.71__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.
Potentially problematic release.
This version of Qubx might be problematic. Click here for more details.
- {qubx-0.6.67 → qubx-0.6.71}/PKG-INFO +50 -4
- {qubx-0.6.67 → qubx-0.6.71}/README.md +48 -3
- {qubx-0.6.67 → qubx-0.6.71}/pyproject.toml +3 -2
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/__init__.py +1 -1
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/data.py +19 -2
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/commands.py +129 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/release.py +333 -25
- qubx-0.6.71/src/qubx/connectors/ccxt/adapters/__init__.py +7 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/adapters/polling_adapter.py +439 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/connection_manager.py +310 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/data.py +241 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/__init__.py +7 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/binance/exchange.py +216 -17
- qubx-0.6.71/src/qubx/connectors/ccxt/exchanges/hyperliquid/__init__.py +1 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/exchanges/hyperliquid/hyperliquid.py +161 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/__init__.py +29 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/base.py +93 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/factory.py +124 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/funding_rate.py +219 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/liquidation.py +91 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/ohlc.py +346 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/open_interest.py +206 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/orderbook.py +193 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/quote.py +98 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/handlers/trade.py +94 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/reader.py +560 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/subscription_config.py +82 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/subscription_manager.py +331 -0
- qubx-0.6.71/src/qubx/connectors/ccxt/subscription_orchestrator.py +328 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/utils.py +88 -1
- qubx-0.6.71/src/qubx/connectors/ccxt/warmup_service.py +116 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/tardis/data.py +6 -6
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/basics.py +20 -3
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/helpers.py +48 -29
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/initializer.py +5 -9
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/lookups.py +1 -1
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/metrics.py +252 -22
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/series.pxd +22 -5
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/series.pyi +33 -3
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/series.pyx +116 -59
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/composite.py +252 -9
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/readers.py +70 -35
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/gathering/simplest.py +1 -1
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/pandaz/ta.py +202 -22
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/crypto-fees.ini +8 -1
- qubx-0.6.71/src/qubx/resources/instruments/hyperliquid-spot.json +4204 -0
- qubx-0.6.71/src/qubx/resources/instruments/hyperliquid.f-perpetual.json +4424 -0
- qubx-0.6.71/src/qubx/templates/__init__.py +5 -0
- qubx-0.6.71/src/qubx/templates/base.py +166 -0
- qubx-0.6.71/src/qubx/templates/project/accounts.toml.j2 +22 -0
- qubx-0.6.71/src/qubx/templates/project/config.yml.j2 +33 -0
- qubx-0.6.71/src/qubx/templates/project/jlive.sh.j2 +43 -0
- qubx-0.6.71/src/qubx/templates/project/jpaper.sh.j2 +6 -0
- qubx-0.6.71/src/qubx/templates/project/pyproject.toml.j2 +18 -0
- qubx-0.6.71/src/qubx/templates/project/src/{{ strategy_name }}/__init__.py.j2 +5 -0
- qubx-0.6.71/src/qubx/templates/project/src/{{ strategy_name }}/strategy.py.j2 +170 -0
- qubx-0.6.71/src/qubx/templates/project/template.yml +20 -0
- qubx-0.6.71/src/qubx/templates/simple/__init__.py.j2 +5 -0
- qubx-0.6.71/src/qubx/templates/simple/accounts.toml.j2 +22 -0
- qubx-0.6.71/src/qubx/templates/simple/config.yml.j2 +30 -0
- qubx-0.6.71/src/qubx/templates/simple/jlive.sh.j2 +43 -0
- qubx-0.6.71/src/qubx/templates/simple/jpaper.sh.j2 +6 -0
- qubx-0.6.71/src/qubx/templates/simple/strategy.py.j2 +95 -0
- qubx-0.6.71/src/qubx/templates/simple/template.yml +20 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/sizers.py +9 -2
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/charting/lookinglass.py +93 -15
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/marketdata/ccxt.py +6 -1
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/misc.py +9 -2
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/_jupyter_runner.pyt +5 -1
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/configs.py +42 -1
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/factory.py +35 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/runner.py +23 -7
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/time.py +13 -13
- qubx-0.6.67/src/qubx/connectors/ccxt/data.py +0 -831
- qubx-0.6.67/src/qubx/connectors/ccxt/reader.py +0 -237
- qubx-0.6.67/src/qubx/resources/instruments/symbols-hyperliquid-spot.json +0 -1
- qubx-0.6.67/src/qubx/resources/instruments/symbols-hyperliquid.f-perpetual.json +0 -1
- {qubx-0.6.67 → qubx-0.6.71}/LICENSE +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/build.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/_nb_magic.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/account.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/broker.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/management.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/ome.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/optimization.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/runner.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/sentinels.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/simulated_data.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/simulated_exchange.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/simulator.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/backtester/utils.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/deploy.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/misc.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/cli/tui.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/account.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/broker.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exceptions.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/binance/broker.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/bitfinex/bitfinex_account.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/exchanges/kraken/kraken.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/ccxt/factory.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/connectors/tardis/utils.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/account.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/context.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/deque.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/errors.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/exceptions.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/interfaces.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/loggers.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/market.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/processing.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/subscription.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/trading.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/mixins/universe.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/stale_data_detector.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/utils.pyi +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/core/utils.pyx +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/helpers.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/hft.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/registry.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/data/tardis.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/base.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/composite.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/csv.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/indicator.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/inmemory.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/prometheus.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/emitters/questdb.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/composite.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/base.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/incremental.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/formatters/slack.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/redis_streams.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/exporters/slack.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/core.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/orderbook.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/price.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/trades.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/features/utils.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/health/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/health/base.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/csv.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/factory.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/inmemory.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/loggers/mongo.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/math/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/math/stats.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/composite.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/slack.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/notifications/throttler.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/pandaz/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/pandaz/utils.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/_build.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance-spot.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.cm-future.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.cm-perpetual.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.um-future.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-binance.um-perpetual.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-bitfinex.f-perpetual.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-kraken-spot.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-kraken.f-future.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/resources/instruments/symbols-kraken.f-perpetual.json +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restarts/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restarts/state_resolvers.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restarts/time_finders.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/balance.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/factory.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/interfaces.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/position.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/signal.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/state.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/restorers/utils.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/indicators.pxd +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/indicators.pyi +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/ta/indicators.pyx +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/advanced.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/composite.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/rebalancers.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/trackers/riskctrl.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/_pyxreloader.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/charting/mpl_helpers.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/collections.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/marketdata/binance.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/marketdata/dukas.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/ntp.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/numbers_utils.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/orderbook.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/dashboard.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/data.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/interfaces.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/renderers/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/plotting/renderers/plotly.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/questdb.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/__init__.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/runner/accounts.py +0 -0
- {qubx-0.6.67 → qubx-0.6.71}/src/qubx/utils/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: Qubx
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.71
|
|
4
4
|
Summary: Qubx - Quantitative Trading Framework
|
|
5
5
|
Author: Dmitry Marienko
|
|
6
6
|
Author-email: dmitry.marienko@xlydian.com
|
|
@@ -19,6 +19,7 @@ Requires-Dist: dash-bootstrap-components (>=1.6.0,<2.0.0)
|
|
|
19
19
|
Requires-Dist: gitpython (>=3.1.44,<4.0.0)
|
|
20
20
|
Requires-Dist: importlib-metadata
|
|
21
21
|
Requires-Dist: ipywidgets (>=8.1.5,<9.0.0)
|
|
22
|
+
Requires-Dist: jinja2 (>=3.1.0,<4.0.0)
|
|
22
23
|
Requires-Dist: jupyter (>=1.1.1,<2.0.0)
|
|
23
24
|
Requires-Dist: jupyter-console (>=6.6.3,<7.0.0)
|
|
24
25
|
Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
@@ -69,6 +70,49 @@ Description-Content-Type: text/markdown
|
|
|
69
70
|
|
|
70
71
|
Qubx is a next-generation quantitative trading framework designed for efficient backtesting and live trading. Built with Python, it offers a robust environment for developing, testing, and deploying trading strategies.
|
|
71
72
|
|
|
73
|
+
## Quick Start
|
|
74
|
+
|
|
75
|
+
### 1. Install Dependencies
|
|
76
|
+
```bash
|
|
77
|
+
poetry install
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Create a Strategy
|
|
81
|
+
```bash
|
|
82
|
+
# Create a simple strategy template (default)
|
|
83
|
+
poetry run qubx init
|
|
84
|
+
|
|
85
|
+
# Or specify a name and symbols
|
|
86
|
+
poetry run qubx init --name my_strategy --symbols BTCUSDT,ETHUSDT
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3. Run Your Strategy
|
|
90
|
+
```bash
|
|
91
|
+
cd my_strategy
|
|
92
|
+
|
|
93
|
+
# Run in paper trading mode
|
|
94
|
+
poetry run qubx run config.yml --paper
|
|
95
|
+
|
|
96
|
+
# Or run in Jupyter mode for interactive development
|
|
97
|
+
./jpaper.sh
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Available Templates
|
|
101
|
+
```bash
|
|
102
|
+
# List available strategy templates
|
|
103
|
+
poetry run qubx init --list-templates
|
|
104
|
+
|
|
105
|
+
# Create strategy with full project structure and MACD example
|
|
106
|
+
poetry run qubx init --template project --name my_project
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Strategy Development Workflow
|
|
110
|
+
1. **Initialize**: `poetry run qubx init` - Create strategy from template
|
|
111
|
+
2. **Develop**: Edit `strategy.py` to implement your trading logic
|
|
112
|
+
3. **Test**: `poetry run qubx run config.yml --paper` - Run in paper mode
|
|
113
|
+
4. **Debug**: `./jpaper.sh` - Use Jupyter for interactive development
|
|
114
|
+
5. **Deploy**: Configure for live trading when ready
|
|
115
|
+
|
|
72
116
|
## Features
|
|
73
117
|
|
|
74
118
|
- 🚀 High-performance backtesting engine
|
|
@@ -119,11 +163,13 @@ qubx --help # Show all available commands
|
|
|
119
163
|
|
|
120
164
|
Available commands:
|
|
121
165
|
|
|
122
|
-
- `qubx
|
|
123
|
-
- `qubx ls` - List all strategies in a directory
|
|
124
|
-
- `qubx release` - Package a strategy into a zip file
|
|
166
|
+
- `qubx init` - Create a new strategy from template
|
|
125
167
|
- `qubx run` - Start a strategy with given configuration
|
|
126
168
|
- `qubx simulate` - Run strategy simulation
|
|
169
|
+
- `qubx ls` - List all strategies in a directory
|
|
170
|
+
- `qubx release` - Package a strategy into a zip file
|
|
171
|
+
- `qubx deploy` - Deploy a strategy from a zip file
|
|
172
|
+
- `qubx browse` - Browse backtest results using interactive TUI
|
|
127
173
|
|
|
128
174
|
## Development
|
|
129
175
|
|
|
@@ -11,6 +11,49 @@
|
|
|
11
11
|
|
|
12
12
|
Qubx is a next-generation quantitative trading framework designed for efficient backtesting and live trading. Built with Python, it offers a robust environment for developing, testing, and deploying trading strategies.
|
|
13
13
|
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### 1. Install Dependencies
|
|
17
|
+
```bash
|
|
18
|
+
poetry install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. Create a Strategy
|
|
22
|
+
```bash
|
|
23
|
+
# Create a simple strategy template (default)
|
|
24
|
+
poetry run qubx init
|
|
25
|
+
|
|
26
|
+
# Or specify a name and symbols
|
|
27
|
+
poetry run qubx init --name my_strategy --symbols BTCUSDT,ETHUSDT
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 3. Run Your Strategy
|
|
31
|
+
```bash
|
|
32
|
+
cd my_strategy
|
|
33
|
+
|
|
34
|
+
# Run in paper trading mode
|
|
35
|
+
poetry run qubx run config.yml --paper
|
|
36
|
+
|
|
37
|
+
# Or run in Jupyter mode for interactive development
|
|
38
|
+
./jpaper.sh
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Available Templates
|
|
42
|
+
```bash
|
|
43
|
+
# List available strategy templates
|
|
44
|
+
poetry run qubx init --list-templates
|
|
45
|
+
|
|
46
|
+
# Create strategy with full project structure and MACD example
|
|
47
|
+
poetry run qubx init --template project --name my_project
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Strategy Development Workflow
|
|
51
|
+
1. **Initialize**: `poetry run qubx init` - Create strategy from template
|
|
52
|
+
2. **Develop**: Edit `strategy.py` to implement your trading logic
|
|
53
|
+
3. **Test**: `poetry run qubx run config.yml --paper` - Run in paper mode
|
|
54
|
+
4. **Debug**: `./jpaper.sh` - Use Jupyter for interactive development
|
|
55
|
+
5. **Deploy**: Configure for live trading when ready
|
|
56
|
+
|
|
14
57
|
## Features
|
|
15
58
|
|
|
16
59
|
- 🚀 High-performance backtesting engine
|
|
@@ -61,11 +104,13 @@ qubx --help # Show all available commands
|
|
|
61
104
|
|
|
62
105
|
Available commands:
|
|
63
106
|
|
|
64
|
-
- `qubx
|
|
65
|
-
- `qubx ls` - List all strategies in a directory
|
|
66
|
-
- `qubx release` - Package a strategy into a zip file
|
|
107
|
+
- `qubx init` - Create a new strategy from template
|
|
67
108
|
- `qubx run` - Start a strategy with given configuration
|
|
68
109
|
- `qubx simulate` - Run strategy simulation
|
|
110
|
+
- `qubx ls` - List all strategies in a directory
|
|
111
|
+
- `qubx release` - Package a strategy into a zip file
|
|
112
|
+
- `qubx deploy` - Deploy a strategy from a zip file
|
|
113
|
+
- `qubx browse` - Browse backtest results using interactive TUI
|
|
69
114
|
|
|
70
115
|
## Development
|
|
71
116
|
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "Qubx"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.71"
|
|
8
8
|
description = "Qubx - Quantitative Trading Framework"
|
|
9
9
|
authors = [ "Dmitry Marienko <dmitry.marienko@xlydian.com>", "Yuriy Arabskyy <yuriy.arabskyy@xlydian.com>",]
|
|
10
10
|
readme = "README.md"
|
|
@@ -76,6 +76,7 @@ websockets = "15.0.1"
|
|
|
76
76
|
qubx-bitfinex-api = "^3.0.7"
|
|
77
77
|
textual = "^0.88.0"
|
|
78
78
|
rich = "^13.9.4"
|
|
79
|
+
jinja2 = "^3.1.0"
|
|
79
80
|
|
|
80
81
|
[tool.ruff.lint]
|
|
81
82
|
extend-select = [ "I",]
|
|
@@ -87,7 +88,7 @@ asyncio_default_fixture_loop_scope = "function"
|
|
|
87
88
|
pythonpath = [ "src",]
|
|
88
89
|
markers = [ "integration: mark test as requiring external services like Redis", "e2e: mark test as requiring external exchange connections and API credentials",]
|
|
89
90
|
addopts = "--disable-warnings"
|
|
90
|
-
filterwarnings = [ "ignore:.*Jupyter is migrating.*:DeprecationWarning",]
|
|
91
|
+
filterwarnings = [ "ignore:.*Jupyter is migrating.*:DeprecationWarning", "ignore:coroutine.*AsyncMockMixin._execute_mock_call.*was never awaited:RuntimeWarning",]
|
|
91
92
|
|
|
92
93
|
[tool.ruff.lint.extend-per-file-ignores]
|
|
93
94
|
"*.ipynb" = [ "F405", "F401", "E701", "E402", "F403", "E401", "E702", "I001",]
|
|
@@ -186,7 +186,7 @@ if runtime_env() in ["notebook", "shell"]:
|
|
|
186
186
|
return
|
|
187
187
|
|
|
188
188
|
ipy = get_ipython()
|
|
189
|
-
for a in [x for x in re.split(r"[\
|
|
189
|
+
for a in [x for x in re.split(r"[\s,;]", line.strip()) if x]:
|
|
190
190
|
ipy.push({a: self._get_manager().Value(None, None)})
|
|
191
191
|
|
|
192
192
|
# code to run
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from collections import defaultdict
|
|
2
|
+
from typing import Any, TypeVar
|
|
2
3
|
|
|
3
4
|
import pandas as pd
|
|
4
5
|
|
|
@@ -19,6 +20,17 @@ from qubx.utils.time import infer_series_frequency
|
|
|
19
20
|
from .account import SimulatedAccountProcessor
|
|
20
21
|
from .utils import SimulatedTimeProvider
|
|
21
22
|
|
|
23
|
+
T = TypeVar("T")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _get_first_existing(data: dict, keys: list, default: T = None) -> T:
|
|
27
|
+
data_get = data.get # Cache method lookup
|
|
28
|
+
sentinel = object()
|
|
29
|
+
for key in keys:
|
|
30
|
+
if (value := data_get(key, sentinel)) is not sentinel:
|
|
31
|
+
return value
|
|
32
|
+
return default
|
|
33
|
+
|
|
22
34
|
|
|
23
35
|
class SimulatedDataProvider(IDataProvider):
|
|
24
36
|
time_provider: SimulatedTimeProvider
|
|
@@ -164,8 +176,13 @@ class SimulatedDataProvider(IDataProvider):
|
|
|
164
176
|
r.data["high"],
|
|
165
177
|
r.data["low"],
|
|
166
178
|
r.data["close"],
|
|
167
|
-
r.data.get("volume", 0),
|
|
168
|
-
r.data
|
|
179
|
+
volume=r.data.get("volume", 0),
|
|
180
|
+
bought_volume=_get_first_existing(r.data, ["taker_buy_volume", "bought_volume"], 0),
|
|
181
|
+
volume_quote=_get_first_existing(r.data, ["quote_volume", "volume_quote"], 0),
|
|
182
|
+
bought_volume_quote=_get_first_existing(
|
|
183
|
+
r.data, ["taker_buy_quote_volume", "bought_volume_quote"], 0
|
|
184
|
+
),
|
|
185
|
+
trade_count=_get_first_existing(r.data, ["count", "trade_count"], 0),
|
|
169
186
|
)
|
|
170
187
|
)
|
|
171
188
|
|
|
@@ -32,6 +32,10 @@ def main(debug: bool, debug_port: int, log_level: str):
|
|
|
32
32
|
"""
|
|
33
33
|
Qubx CLI.
|
|
34
34
|
"""
|
|
35
|
+
# Suppress syntax warnings from AST parsing during import resolution
|
|
36
|
+
import warnings
|
|
37
|
+
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
|
38
|
+
|
|
35
39
|
os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1"
|
|
36
40
|
log_level = log_level.upper() if not debug else "DEBUG"
|
|
37
41
|
|
|
@@ -275,5 +279,130 @@ def browse(results_path: str):
|
|
|
275
279
|
run_backtest_browser(results_path)
|
|
276
280
|
|
|
277
281
|
|
|
282
|
+
@main.command()
|
|
283
|
+
@click.option(
|
|
284
|
+
"--template",
|
|
285
|
+
"-t",
|
|
286
|
+
type=str,
|
|
287
|
+
default="simple",
|
|
288
|
+
help="Built-in template to use (default: simple)",
|
|
289
|
+
show_default=True,
|
|
290
|
+
)
|
|
291
|
+
@click.option(
|
|
292
|
+
"--template-path",
|
|
293
|
+
type=click.Path(exists=True, resolve_path=True),
|
|
294
|
+
help="Path to custom template directory",
|
|
295
|
+
)
|
|
296
|
+
@click.option(
|
|
297
|
+
"--name",
|
|
298
|
+
"-n",
|
|
299
|
+
type=str,
|
|
300
|
+
default="my_strategy",
|
|
301
|
+
help="Name of the strategy to create",
|
|
302
|
+
show_default=True,
|
|
303
|
+
)
|
|
304
|
+
@click.option(
|
|
305
|
+
"--exchange",
|
|
306
|
+
"-e",
|
|
307
|
+
type=str,
|
|
308
|
+
default="BINANCE.UM",
|
|
309
|
+
help="Exchange to configure for the strategy",
|
|
310
|
+
show_default=True,
|
|
311
|
+
)
|
|
312
|
+
@click.option(
|
|
313
|
+
"--symbols",
|
|
314
|
+
"-s",
|
|
315
|
+
type=str,
|
|
316
|
+
default="BTCUSDT",
|
|
317
|
+
help="Comma-separated list of symbols to trade",
|
|
318
|
+
show_default=True,
|
|
319
|
+
)
|
|
320
|
+
@click.option(
|
|
321
|
+
"--timeframe",
|
|
322
|
+
type=str,
|
|
323
|
+
default="1h",
|
|
324
|
+
help="Timeframe for market data",
|
|
325
|
+
show_default=True,
|
|
326
|
+
)
|
|
327
|
+
@click.option(
|
|
328
|
+
"--output-dir",
|
|
329
|
+
"-o",
|
|
330
|
+
type=click.Path(resolve_path=True),
|
|
331
|
+
default=".",
|
|
332
|
+
help="Directory to create the strategy in",
|
|
333
|
+
show_default=True,
|
|
334
|
+
)
|
|
335
|
+
@click.option(
|
|
336
|
+
"--list-templates",
|
|
337
|
+
is_flag=True,
|
|
338
|
+
help="List all available built-in templates",
|
|
339
|
+
)
|
|
340
|
+
def init(
|
|
341
|
+
template: str,
|
|
342
|
+
template_path: str | None,
|
|
343
|
+
name: str,
|
|
344
|
+
exchange: str,
|
|
345
|
+
symbols: str,
|
|
346
|
+
timeframe: str,
|
|
347
|
+
output_dir: str,
|
|
348
|
+
list_templates: bool,
|
|
349
|
+
):
|
|
350
|
+
"""
|
|
351
|
+
Create a new strategy from a template.
|
|
352
|
+
|
|
353
|
+
This command generates a complete strategy project structure with:
|
|
354
|
+
- Strategy class implementing IStrategy interface
|
|
355
|
+
- Configuration file for qubx run command
|
|
356
|
+
- Package structure for proper imports
|
|
357
|
+
|
|
358
|
+
The generated strategy can be run immediately with:
|
|
359
|
+
poetry run qubx run --config config.yml --paper
|
|
360
|
+
"""
|
|
361
|
+
from qubx.templates import TemplateManager, TemplateError
|
|
362
|
+
|
|
363
|
+
try:
|
|
364
|
+
manager = TemplateManager()
|
|
365
|
+
|
|
366
|
+
if list_templates:
|
|
367
|
+
templates = manager.list_templates()
|
|
368
|
+
if not templates:
|
|
369
|
+
click.echo("No templates available.")
|
|
370
|
+
return
|
|
371
|
+
|
|
372
|
+
click.echo("Available templates:")
|
|
373
|
+
for template_name, metadata in templates.items():
|
|
374
|
+
description = metadata.get("description", "No description")
|
|
375
|
+
click.echo(f" {template_name:<15} - {description}")
|
|
376
|
+
return
|
|
377
|
+
|
|
378
|
+
# Generate strategy
|
|
379
|
+
strategy_path = manager.generate_strategy(
|
|
380
|
+
template_name=template if not template_path else None,
|
|
381
|
+
template_path=template_path,
|
|
382
|
+
output_dir=output_dir,
|
|
383
|
+
name=name,
|
|
384
|
+
exchange=exchange,
|
|
385
|
+
symbols=symbols,
|
|
386
|
+
timeframe=timeframe,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
click.echo(f"✅ Strategy '{name}' created successfully!")
|
|
390
|
+
click.echo(f"📁 Location: {strategy_path}")
|
|
391
|
+
click.echo()
|
|
392
|
+
click.echo("To run your strategy:")
|
|
393
|
+
click.echo(f" cd {strategy_path}")
|
|
394
|
+
click.echo(" poetry run qubx run config.yml --paper")
|
|
395
|
+
click.echo()
|
|
396
|
+
click.echo("To run in Jupyter mode:")
|
|
397
|
+
click.echo(" ./jpaper.sh")
|
|
398
|
+
|
|
399
|
+
except TemplateError as e:
|
|
400
|
+
click.echo(f"❌ Template error: {e}", err=True)
|
|
401
|
+
raise click.Abort()
|
|
402
|
+
except Exception as e:
|
|
403
|
+
click.echo(f"❌ Unexpected error: {e}", err=True)
|
|
404
|
+
raise click.Abort()
|
|
405
|
+
|
|
406
|
+
|
|
278
407
|
if __name__ == "__main__":
|
|
279
408
|
main()
|