@reefclaw/connect 0.1.12 → 0.1.14
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.
- package/assets/plugin/audit/mode-transition-audit.d.ts +11 -0
- package/assets/plugin/audit/mode-transition-audit.js +29 -0
- package/assets/plugin/balance-utils.d.ts +36 -0
- package/assets/plugin/balance-utils.js +98 -0
- package/assets/plugin/ccxt/binance-ban-gate.d.ts +47 -0
- package/assets/plugin/ccxt/binance-ban-gate.js +420 -0
- package/assets/plugin/ccxt/binance-private.d.ts +346 -0
- package/assets/plugin/ccxt/binance-private.js +1525 -0
- package/assets/plugin/ccxt/binance-public.d.ts +34 -0
- package/assets/plugin/ccxt/binance-public.js +180 -0
- package/assets/plugin/ccxt/intel-public.d.ts +25 -0
- package/assets/plugin/ccxt/intel-public.js +80 -0
- package/assets/plugin/ccxt/public-market-data-api.d.ts +26 -0
- package/assets/plugin/ccxt/public-market-data-api.js +23 -0
- package/assets/plugin/config/agent-config-client.d.ts +77 -0
- package/assets/plugin/config/agent-config-client.js +188 -0
- package/assets/plugin/config/agent-config-poller.d.ts +32 -0
- package/assets/plugin/config/agent-config-poller.js +101 -0
- package/assets/plugin/config/brackets-config.d.ts +22 -0
- package/assets/plugin/config/brackets-config.js +58 -0
- package/assets/plugin/config/entitlement-gate.d.ts +51 -0
- package/assets/plugin/config/entitlement-gate.js +137 -0
- package/assets/plugin/config/gate-store.d.ts +18 -0
- package/assets/plugin/config/gate-store.js +61 -0
- package/assets/plugin/config/plugin-config-io.d.ts +222 -0
- package/assets/plugin/config/plugin-config-io.js +126 -0
- package/assets/plugin/config/position-review-config.d.ts +35 -0
- package/assets/plugin/config/position-review-config.js +105 -0
- package/assets/plugin/config/tool-gate.d.ts +53 -0
- package/assets/plugin/config/tool-gate.js +128 -0
- package/assets/plugin/config/user-data-stream-config.d.ts +89 -0
- package/assets/plugin/config/user-data-stream-config.js +239 -0
- package/assets/plugin/connector-supervisor.d.ts +36 -0
- package/assets/plugin/connector-supervisor.js +149 -0
- package/assets/plugin/exchange-adapter.d.ts +65 -0
- package/assets/plugin/exchange-adapter.js +4 -0
- package/assets/plugin/index.d.ts +30 -0
- package/assets/plugin/index.js +2763 -0
- package/assets/plugin/ingest/pending-entry-metadata.d.ts +74 -0
- package/assets/plugin/ingest/pending-entry-metadata.js +236 -0
- package/assets/plugin/ingest/position-auto-capture.d.ts +171 -0
- package/assets/plugin/ingest/position-auto-capture.js +709 -0
- package/assets/plugin/ingest/position-decisions-client.d.ts +327 -0
- package/assets/plugin/ingest/position-decisions-client.js +306 -0
- package/assets/plugin/ingest/readiness-reporter.d.ts +42 -0
- package/assets/plugin/ingest/readiness-reporter.js +163 -0
- package/assets/plugin/ingest/reconcile-db-vs-exchange.d.ts +51 -0
- package/assets/plugin/ingest/reconcile-db-vs-exchange.js +170 -0
- package/assets/plugin/ingest/reconciler-cleanup.d.ts +37 -0
- package/assets/plugin/ingest/reconciler-cleanup.js +147 -0
- package/assets/plugin/ingest/rest-gap-filler.d.ts +191 -0
- package/assets/plugin/ingest/rest-gap-filler.js +565 -0
- package/assets/plugin/ingest/touched-symbols-store.d.ts +25 -0
- package/assets/plugin/ingest/touched-symbols-store.js +96 -0
- package/assets/plugin/ingest/trade-store-client.d.ts +40 -0
- package/assets/plugin/ingest/trade-store-client.js +125 -0
- package/assets/plugin/ingest/ws-ingest.d.ts +43 -0
- package/assets/plugin/ingest/ws-ingest.js +126 -0
- package/assets/plugin/learning/setup-family.d.ts +21 -0
- package/assets/plugin/learning/setup-family.js +103 -0
- package/assets/plugin/lifecycle/install-signal-handlers.d.ts +33 -0
- package/assets/plugin/lifecycle/install-signal-handlers.js +112 -0
- package/assets/plugin/lifecycle/shutdown-coordinator.d.ts +43 -0
- package/assets/plugin/lifecycle/shutdown-coordinator.js +131 -0
- package/assets/plugin/lifecycle/trading-operation-lock.d.ts +17 -0
- package/assets/plugin/lifecycle/trading-operation-lock.js +14 -0
- package/assets/plugin/live/bracket-id.d.ts +26 -0
- package/assets/plugin/live/bracket-id.js +112 -0
- package/assets/plugin/live/bracket-ledger.d.ts +54 -0
- package/assets/plugin/live/bracket-ledger.js +267 -0
- package/assets/plugin/live/bracket-manager.d.ts +82 -0
- package/assets/plugin/live/bracket-manager.js +478 -0
- package/assets/plugin/live/bracket-params.d.ts +22 -0
- package/assets/plugin/live/bracket-params.js +124 -0
- package/assets/plugin/live/bracket-reconciler.d.ts +95 -0
- package/assets/plugin/live/bracket-reconciler.js +573 -0
- package/assets/plugin/live/bracket-types.d.ts +102 -0
- package/assets/plugin/live/bracket-types.js +8 -0
- package/assets/plugin/live/deposit-tracker.d.ts +62 -0
- package/assets/plugin/live/deposit-tracker.js +97 -0
- package/assets/plugin/live/emergency-controls.d.ts +32 -0
- package/assets/plugin/live/emergency-controls.js +226 -0
- package/assets/plugin/live/exchange-errors.d.ts +12 -0
- package/assets/plugin/live/exchange-errors.js +130 -0
- package/assets/plugin/live/exchange-info-cache.d.ts +37 -0
- package/assets/plugin/live/exchange-info-cache.js +134 -0
- package/assets/plugin/live/fact-subscriber.d.ts +78 -0
- package/assets/plugin/live/fact-subscriber.js +182 -0
- package/assets/plugin/live/fill-price.d.ts +13 -0
- package/assets/plugin/live/fill-price.js +37 -0
- package/assets/plugin/live/intent-journal.d.ts +42 -0
- package/assets/plugin/live/intent-journal.js +122 -0
- package/assets/plugin/live/listen-key-manager.d.ts +70 -0
- package/assets/plugin/live/listen-key-manager.js +169 -0
- package/assets/plugin/live/live-adapter.d.ts +319 -0
- package/assets/plugin/live/live-adapter.js +1906 -0
- package/assets/plugin/live/live-balance-enricher.d.ts +32 -0
- package/assets/plugin/live/live-balance-enricher.js +104 -0
- package/assets/plugin/live/live-bracket-api.d.ts +13 -0
- package/assets/plugin/live/live-bracket-api.js +20 -0
- package/assets/plugin/live/live-state-store.d.ts +194 -0
- package/assets/plugin/live/live-state-store.js +450 -0
- package/assets/plugin/live/local-signal-service.d.ts +57 -0
- package/assets/plugin/live/local-signal-service.js +151 -0
- package/assets/plugin/live/local-strategy-evaluator.d.ts +62 -0
- package/assets/plugin/live/local-strategy-evaluator.js +131 -0
- package/assets/plugin/live/microstructure-assembler.d.ts +54 -0
- package/assets/plugin/live/microstructure-assembler.js +148 -0
- package/assets/plugin/live/order-poller.d.ts +29 -0
- package/assets/plugin/live/order-poller.js +125 -0
- package/assets/plugin/live/position-state-store.d.ts +87 -0
- package/assets/plugin/live/position-state-store.js +237 -0
- package/assets/plugin/live/proposal-decision-listener.d.ts +70 -0
- package/assets/plugin/live/proposal-decision-listener.js +292 -0
- package/assets/plugin/live/proposal-manager.d.ts +76 -0
- package/assets/plugin/live/proposal-manager.js +140 -0
- package/assets/plugin/live/rate-limiter.d.ts +47 -0
- package/assets/plugin/live/rate-limiter.js +159 -0
- package/assets/plugin/live/reconciler.d.ts +39 -0
- package/assets/plugin/live/reconciler.js +175 -0
- package/assets/plugin/live/setup-buckets.d.ts +7 -0
- package/assets/plugin/live/setup-buckets.js +33 -0
- package/assets/plugin/live/slippage-tracker.d.ts +45 -0
- package/assets/plugin/live/slippage-tracker.js +78 -0
- package/assets/plugin/live/stop-watcher.d.ts +67 -0
- package/assets/plugin/live/stop-watcher.js +218 -0
- package/assets/plugin/live/user-data-active-probe.d.ts +54 -0
- package/assets/plugin/live/user-data-active-probe.js +180 -0
- package/assets/plugin/live/user-data-stream-controller.d.ts +200 -0
- package/assets/plugin/live/user-data-stream-controller.js +579 -0
- package/assets/plugin/live/user-data-stream-ws.d.ts +22 -0
- package/assets/plugin/live/user-data-stream-ws.js +63 -0
- package/assets/plugin/live/user-data-stream.d.ts +243 -0
- package/assets/plugin/live/user-data-stream.js +704 -0
- package/assets/plugin/logger.d.ts +2 -0
- package/assets/plugin/logger.js +2 -0
- package/assets/plugin/mfe.d.ts +21 -0
- package/assets/plugin/mfe.js +68 -0
- package/assets/plugin/onboarding/mode-ladder.d.ts +1 -0
- package/assets/plugin/onboarding/mode-ladder.js +3 -0
- package/assets/plugin/onboarding/runtime.d.ts +102 -0
- package/assets/plugin/onboarding/runtime.js +215 -0
- package/assets/plugin/openclaw.plugin.json +92 -0
- package/assets/plugin/paper-adapter.d.ts +24 -0
- package/assets/plugin/paper-adapter.js +91 -0
- package/assets/plugin/persistence/state-manager.d.ts +66 -0
- package/assets/plugin/persistence/state-manager.js +222 -0
- package/assets/plugin/pinned-plan.d.ts +9 -0
- package/assets/plugin/pinned-plan.js +23 -0
- package/assets/plugin/portfolio/reentry-tracker.d.ts +36 -0
- package/assets/plugin/portfolio/reentry-tracker.js +127 -0
- package/assets/plugin/portfolio/wave9-admission.d.ts +67 -0
- package/assets/plugin/portfolio/wave9-admission.js +262 -0
- package/assets/plugin/portfolio/wave9-policy.d.ts +36 -0
- package/assets/plugin/portfolio/wave9-policy.js +183 -0
- package/assets/plugin/risk/pre-trade-check.d.ts +38 -0
- package/assets/plugin/risk/pre-trade-check.js +345 -0
- package/assets/plugin/risk/pre-trade-types.d.ts +60 -0
- package/assets/plugin/risk/pre-trade-types.js +3 -0
- package/assets/plugin/shadow/shadow-tracker.d.ts +36 -0
- package/assets/plugin/shadow/shadow-tracker.js +151 -0
- package/assets/plugin/shadow/types.d.ts +42 -0
- package/assets/plugin/shadow/types.js +20 -0
- package/assets/plugin/shared/indicators-extended.d.ts +52 -0
- package/assets/plugin/shared/indicators-extended.js +291 -0
- package/assets/plugin/shared/indicators.d.ts +15 -0
- package/assets/plugin/shared/indicators.js +114 -0
- package/assets/plugin/signals/conditions/registry.d.ts +16 -0
- package/assets/plugin/signals/conditions/registry.js +1333 -0
- package/assets/plugin/signals/conditions/types.d.ts +1 -0
- package/assets/plugin/signals/conditions/types.js +4 -0
- package/assets/plugin/signals/direction-rules.d.ts +3 -0
- package/assets/plugin/signals/direction-rules.js +24 -0
- package/assets/plugin/signals/entry-rules.d.ts +6 -0
- package/assets/plugin/signals/entry-rules.js +33 -0
- package/assets/plugin/signals/serialize-context.d.ts +4 -0
- package/assets/plugin/signals/serialize-context.js +39 -0
- package/assets/plugin/signals/stop-rules.d.ts +3 -0
- package/assets/plugin/signals/stop-rules.js +48 -0
- package/assets/plugin/signals/strategy-adapter.d.ts +47 -0
- package/assets/plugin/signals/strategy-adapter.js +209 -0
- package/assets/plugin/signals/types.d.ts +1 -0
- package/assets/plugin/signals/types.js +8 -0
- package/assets/plugin/simulator/exchange-simulator.d.ts +105 -0
- package/assets/plugin/simulator/exchange-simulator.js +759 -0
- package/assets/plugin/simulator/fill-engine.d.ts +53 -0
- package/assets/plugin/simulator/fill-engine.js +280 -0
- package/assets/plugin/simulator/paper-market-feed.d.ts +26 -0
- package/assets/plugin/simulator/paper-market-feed.js +104 -0
- package/assets/plugin/simulator/realistic-fills.d.ts +59 -0
- package/assets/plugin/simulator/realistic-fills.js +175 -0
- package/assets/plugin/simulator/types.d.ts +228 -0
- package/assets/plugin/simulator/types.js +43 -0
- package/assets/plugin/strategy/builtin-strategies.d.ts +2 -0
- package/assets/plugin/strategy/builtin-strategies.js +113 -0
- package/assets/plugin/strategy/condition-registry.d.ts +3 -0
- package/assets/plugin/strategy/condition-registry.js +153 -0
- package/assets/plugin/strategy/evaluator.d.ts +70 -0
- package/assets/plugin/strategy/evaluator.js +98 -0
- package/assets/plugin/tools/assessment-validation.d.ts +141 -0
- package/assets/plugin/tools/assessment-validation.js +473 -0
- package/assets/plugin/tools/attach-brackets.d.ts +39 -0
- package/assets/plugin/tools/attach-brackets.js +564 -0
- package/assets/plugin/tools/audit-bracket-protection.d.ts +49 -0
- package/assets/plugin/tools/audit-bracket-protection.js +683 -0
- package/assets/plugin/tools/bracket-control.d.ts +12 -0
- package/assets/plugin/tools/bracket-control.js +35 -0
- package/assets/plugin/tools/cancel-all-orders.d.ts +9 -0
- package/assets/plugin/tools/cancel-all-orders.js +8 -0
- package/assets/plugin/tools/cancel-order.d.ts +14 -0
- package/assets/plugin/tools/cancel-order.js +60 -0
- package/assets/plugin/tools/check-position-health.d.ts +46 -0
- package/assets/plugin/tools/check-position-health.js +194 -0
- package/assets/plugin/tools/clear-exchange-credentials.d.ts +24 -0
- package/assets/plugin/tools/clear-exchange-credentials.js +70 -0
- package/assets/plugin/tools/close-position.d.ts +45 -0
- package/assets/plugin/tools/close-position.js +722 -0
- package/assets/plugin/tools/create-order.d.ts +89 -0
- package/assets/plugin/tools/create-order.js +1555 -0
- package/assets/plugin/tools/exit-gate.d.ts +58 -0
- package/assets/plugin/tools/exit-gate.js +162 -0
- package/assets/plugin/tools/fetch-balance.d.ts +5 -0
- package/assets/plugin/tools/fetch-balance.js +4 -0
- package/assets/plugin/tools/fetch-ohlcv.d.ts +11 -0
- package/assets/plugin/tools/fetch-ohlcv.js +8 -0
- package/assets/plugin/tools/fetch-open-orders.d.ts +7 -0
- package/assets/plugin/tools/fetch-open-orders.js +4 -0
- package/assets/plugin/tools/fetch-positions.d.ts +7 -0
- package/assets/plugin/tools/fetch-positions.js +4 -0
- package/assets/plugin/tools/fetch-ticker.d.ts +11 -0
- package/assets/plugin/tools/fetch-ticker.js +5 -0
- package/assets/plugin/tools/get-agent-profile.d.ts +4 -0
- package/assets/plugin/tools/get-agent-profile.js +6 -0
- package/assets/plugin/tools/get-analytics.d.ts +6 -0
- package/assets/plugin/tools/get-analytics.js +7 -0
- package/assets/plugin/tools/get-backtest.d.ts +12 -0
- package/assets/plugin/tools/get-backtest.js +91 -0
- package/assets/plugin/tools/get-basis.d.ts +7 -0
- package/assets/plugin/tools/get-basis.js +7 -0
- package/assets/plugin/tools/get-bracket-config.d.ts +11 -0
- package/assets/plugin/tools/get-bracket-config.js +24 -0
- package/assets/plugin/tools/get-cascade-risk.d.ts +7 -0
- package/assets/plugin/tools/get-cascade-risk.js +8 -0
- package/assets/plugin/tools/get-crypto-metrics.d.ts +18 -0
- package/assets/plugin/tools/get-crypto-metrics.js +62 -0
- package/assets/plugin/tools/get-cvd.d.ts +6 -0
- package/assets/plugin/tools/get-cvd.js +6 -0
- package/assets/plugin/tools/get-divergences.d.ts +6 -0
- package/assets/plugin/tools/get-divergences.js +6 -0
- package/assets/plugin/tools/get-funding-context.d.ts +6 -0
- package/assets/plugin/tools/get-funding-context.js +16 -0
- package/assets/plugin/tools/get-liquidation-levels.d.ts +7 -0
- package/assets/plugin/tools/get-liquidation-levels.js +7 -0
- package/assets/plugin/tools/get-liquidation-pulse.d.ts +9 -0
- package/assets/plugin/tools/get-liquidation-pulse.js +22 -0
- package/assets/plugin/tools/get-market-breadth.d.ts +6 -0
- package/assets/plugin/tools/get-market-breadth.js +8 -0
- package/assets/plugin/tools/get-market-intel.d.ts +19 -0
- package/assets/plugin/tools/get-market-intel.js +116 -0
- package/assets/plugin/tools/get-market-structure.d.ts +47 -0
- package/assets/plugin/tools/get-market-structure.js +198 -0
- package/assets/plugin/tools/get-my-mined-patterns.d.ts +20 -0
- package/assets/plugin/tools/get-my-mined-patterns.js +61 -0
- package/assets/plugin/tools/get-my-proposed-learnings.d.ts +20 -0
- package/assets/plugin/tools/get-my-proposed-learnings.js +55 -0
- package/assets/plugin/tools/get-my-recent-reviews.d.ts +22 -0
- package/assets/plugin/tools/get-my-recent-reviews.js +66 -0
- package/assets/plugin/tools/get-orderbook.d.ts +21 -0
- package/assets/plugin/tools/get-orderbook.js +32 -0
- package/assets/plugin/tools/get-pattern-scan.d.ts +7 -0
- package/assets/plugin/tools/get-pattern-scan.js +8 -0
- package/assets/plugin/tools/get-regime.d.ts +6 -0
- package/assets/plugin/tools/get-regime.js +7 -0
- package/assets/plugin/tools/get-relevant-learnings.d.ts +21 -0
- package/assets/plugin/tools/get-relevant-learnings.js +65 -0
- package/assets/plugin/tools/get-resting-liquidity.d.ts +6 -0
- package/assets/plugin/tools/get-resting-liquidity.js +11 -0
- package/assets/plugin/tools/get-risk-scenario.d.ts +29 -0
- package/assets/plugin/tools/get-risk-scenario.js +47 -0
- package/assets/plugin/tools/get-risk-summary.d.ts +51 -0
- package/assets/plugin/tools/get-risk-summary.js +118 -0
- package/assets/plugin/tools/get-sentiment.d.ts +4 -0
- package/assets/plugin/tools/get-sentiment.js +6 -0
- package/assets/plugin/tools/get-session-review.d.ts +7 -0
- package/assets/plugin/tools/get-session-review.js +8 -0
- package/assets/plugin/tools/get-setup-detail.d.ts +7 -0
- package/assets/plugin/tools/get-setup-detail.js +322 -0
- package/assets/plugin/tools/get-signals.d.ts +15 -0
- package/assets/plugin/tools/get-signals.js +54 -0
- package/assets/plugin/tools/get-sizing.d.ts +6 -0
- package/assets/plugin/tools/get-sizing.js +6 -0
- package/assets/plugin/tools/get-trade-feedback.d.ts +7 -0
- package/assets/plugin/tools/get-trade-feedback.js +8 -0
- package/assets/plugin/tools/get-trade-flow.d.ts +7 -0
- package/assets/plugin/tools/get-trade-flow.js +7 -0
- package/assets/plugin/tools/get-volume-analysis.d.ts +21 -0
- package/assets/plugin/tools/get-volume-analysis.js +74 -0
- package/assets/plugin/tools/get-volume-profile.d.ts +7 -0
- package/assets/plugin/tools/get-volume-profile.js +7 -0
- package/assets/plugin/tools/get-wave9-status.d.ts +127 -0
- package/assets/plugin/tools/get-wave9-status.js +796 -0
- package/assets/plugin/tools/helpers.d.ts +26 -0
- package/assets/plugin/tools/helpers.js +39 -0
- package/assets/plugin/tools/intel-api.d.ts +34 -0
- package/assets/plugin/tools/intel-api.js +119 -0
- package/assets/plugin/tools/intel-cache.d.ts +25 -0
- package/assets/plugin/tools/intel-cache.js +148 -0
- package/assets/plugin/tools/list-strategies.d.ts +17 -0
- package/assets/plugin/tools/list-strategies.js +23 -0
- package/assets/plugin/tools/modify-stop.d.ts +21 -0
- package/assets/plugin/tools/modify-stop.js +120 -0
- package/assets/plugin/tools/modify-target.d.ts +21 -0
- package/assets/plugin/tools/modify-target.js +110 -0
- package/assets/plugin/tools/propose-learning.d.ts +22 -0
- package/assets/plugin/tools/propose-learning.js +65 -0
- package/assets/plugin/tools/query-review-outcomes.d.ts +30 -0
- package/assets/plugin/tools/query-review-outcomes.js +64 -0
- package/assets/plugin/tools/query-trades.d.ts +21 -0
- package/assets/plugin/tools/query-trades.js +37 -0
- package/assets/plugin/tools/record-position-reviews.d.ts +38 -0
- package/assets/plugin/tools/record-position-reviews.js +147 -0
- package/assets/plugin/tools/save-strategy.d.ts +16 -0
- package/assets/plugin/tools/save-strategy.js +46 -0
- package/assets/plugin/tools/scan-pairs.d.ts +22 -0
- package/assets/plugin/tools/scan-pairs.js +234 -0
- package/assets/plugin/tools/score-setup.d.ts +31 -0
- package/assets/plugin/tools/score-setup.js +268 -0
- package/assets/plugin/tools/set-bracket-requirement.d.ts +18 -0
- package/assets/plugin/tools/set-bracket-requirement.js +81 -0
- package/assets/plugin/tools/set-exchange-credentials.d.ts +25 -0
- package/assets/plugin/tools/set-exchange-credentials.js +80 -0
- package/assets/plugin/tools/set-trading-mode.d.ts +26 -0
- package/assets/plugin/tools/set-trading-mode.js +152 -0
- package/assets/plugin/tools/test-exchange-credentials.d.ts +16 -0
- package/assets/plugin/tools/test-exchange-credentials.js +100 -0
- package/assets/plugin/tools/toggle-strategy.d.ts +8 -0
- package/assets/plugin/tools/toggle-strategy.js +15 -0
- package/assets/plugin/trading-params-cache.d.ts +26 -0
- package/assets/plugin/trading-params-cache.js +52 -0
- package/assets/plugin/types.d.ts +134 -0
- package/assets/plugin/types.js +7 -0
- package/assets/plugin/util/plugin-paths.d.ts +3 -0
- package/assets/plugin/util/plugin-paths.js +15 -0
- package/assets/plugin/venues/hyperliquid/hl-balance.d.ts +116 -0
- package/assets/plugin/venues/hyperliquid/hl-balance.js +145 -0
- package/assets/plugin/venues/hyperliquid/hl-bracket-coordinator.d.ts +123 -0
- package/assets/plugin/venues/hyperliquid/hl-bracket-coordinator.js +533 -0
- package/assets/plugin/venues/hyperliquid/hl-brackets.d.ts +102 -0
- package/assets/plugin/venues/hyperliquid/hl-brackets.js +172 -0
- package/assets/plugin/venues/hyperliquid/hl-cloid.d.ts +22 -0
- package/assets/plugin/venues/hyperliquid/hl-cloid.js +82 -0
- package/assets/plugin/venues/hyperliquid/hl-info-cache.d.ts +46 -0
- package/assets/plugin/venues/hyperliquid/hl-info-cache.js +125 -0
- package/assets/plugin/venues/hyperliquid/hl-live-adapter.d.ts +146 -0
- package/assets/plugin/venues/hyperliquid/hl-live-adapter.js +728 -0
- package/assets/plugin/venues/hyperliquid/hl-precision.d.ts +61 -0
- package/assets/plugin/venues/hyperliquid/hl-precision.js +176 -0
- package/assets/plugin/venues/hyperliquid/hl-private.d.ts +88 -0
- package/assets/plugin/venues/hyperliquid/hl-private.js +357 -0
- package/assets/plugin/venues/hyperliquid/hl-public.d.ts +79 -0
- package/assets/plugin/venues/hyperliquid/hl-public.js +436 -0
- package/assets/plugin/venues/hyperliquid/hl-rate-gate.d.ts +57 -0
- package/assets/plugin/venues/hyperliquid/hl-rate-gate.js +220 -0
- package/assets/plugin/venues/hyperliquid/hl-user-stream.d.ts +90 -0
- package/assets/plugin/venues/hyperliquid/hl-user-stream.js +220 -0
- package/assets/plugin/venues/registry.d.ts +38 -0
- package/assets/plugin/venues/registry.js +46 -0
- package/assets/plugin/venues/symbols.d.ts +43 -0
- package/assets/plugin/venues/symbols.js +107 -0
- package/assets/plugin/wave9/live-account-capture.d.ts +67 -0
- package/assets/plugin/wave9/live-account-capture.js +435 -0
- package/assets/plugin/wave9/live-autonomous-protection.d.ts +39 -0
- package/assets/plugin/wave9/live-autonomous-protection.js +112 -0
- package/assets/plugin/wave9/live-durable-reconciliation-scheduler.d.ts +33 -0
- package/assets/plugin/wave9/live-durable-reconciliation-scheduler.js +115 -0
- package/assets/plugin/wave9/live-execution-ledger.d.ts +107 -0
- package/assets/plugin/wave9/live-execution-ledger.js +498 -0
- package/assets/plugin/wave9/live-position-confirmation.d.ts +18 -0
- package/assets/plugin/wave9/live-position-confirmation.js +111 -0
- package/assets/plugin/wave9/live-residual-protection.d.ts +18 -0
- package/assets/plugin/wave9/live-residual-protection.js +250 -0
- package/assets/plugin/wave9/live-startup-reconciliation.d.ts +38 -0
- package/assets/plugin/wave9/live-startup-reconciliation.js +454 -0
- package/assets/plugin/wave9/live-symbol-ownership.d.ts +20 -0
- package/assets/plugin/wave9/live-symbol-ownership.js +132 -0
- package/assets/plugin/wave9/paper-admission-guard.d.ts +199 -0
- package/assets/plugin/wave9/paper-admission-guard.js +650 -0
- package/assets/plugin/wave9/usdm-evidence-provider.d.ts +42 -0
- package/assets/plugin/wave9/usdm-evidence-provider.js +133 -0
- package/dist/plugin.js +24 -15
- package/package.json +1 -1
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
// Pre-trade risk gate — pure function.
|
|
2
|
+
// Validates a proposed order against portfolio limits, drawdown zones, and volatility.
|
|
3
|
+
// Lives in the plugin (synchronous access to simulator state).
|
|
4
|
+
import { getCachedTradingParams } from '../trading-params-cache.js';
|
|
5
|
+
// ---- Default pre-trade limits (now read from trading params cache) ----
|
|
6
|
+
export function getDefaultPreTradeLimits() {
|
|
7
|
+
const tp = getCachedTradingParams();
|
|
8
|
+
return {
|
|
9
|
+
maxPositionSize: tp.maxPositionSize,
|
|
10
|
+
maxOpenPositions: tp.maxOpenPositions,
|
|
11
|
+
maxGrossExposure: tp.maxGrossExposure,
|
|
12
|
+
maxPerTradeLoss: tp.maxPerTradeLoss,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/** @deprecated Use getDefaultPreTradeLimits() for dynamic values */
|
|
16
|
+
export const DEFAULT_PRE_TRADE_LIMITS = {
|
|
17
|
+
maxPositionSize: 10_000,
|
|
18
|
+
maxOpenPositions: 5,
|
|
19
|
+
maxGrossExposure: 1.5,
|
|
20
|
+
maxPerTradeLoss: 500,
|
|
21
|
+
};
|
|
22
|
+
// ---- Drawdown zone thresholds (now read from trading params cache) ----
|
|
23
|
+
export function getDrawdownThresholds() {
|
|
24
|
+
const tp = getCachedTradingParams();
|
|
25
|
+
return {
|
|
26
|
+
YELLOW: tp.drawdownYellow,
|
|
27
|
+
ORANGE: tp.drawdownOrange,
|
|
28
|
+
RED: tp.drawdownRed,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export const DRAWDOWN_ZONE_THRESHOLDS = {
|
|
32
|
+
YELLOW: -0.01, // -1%
|
|
33
|
+
ORANGE: -0.02, // -2%
|
|
34
|
+
RED: -0.025, // -2.5%
|
|
35
|
+
};
|
|
36
|
+
// ---- Pure helpers ----
|
|
37
|
+
/** Determine drawdown zone from drawdown ratio (e.g. -0.015 = -1.5%). */
|
|
38
|
+
export function getDrawdownZone(drawdownRatio) {
|
|
39
|
+
const thresholds = getDrawdownThresholds();
|
|
40
|
+
if (drawdownRatio <= thresholds.RED)
|
|
41
|
+
return 'RED';
|
|
42
|
+
if (drawdownRatio <= thresholds.ORANGE)
|
|
43
|
+
return 'ORANGE';
|
|
44
|
+
if (drawdownRatio <= thresholds.YELLOW)
|
|
45
|
+
return 'YELLOW';
|
|
46
|
+
return 'GREEN';
|
|
47
|
+
}
|
|
48
|
+
/** Compute volatility factor from current ATR vs baseline. Clamped [0.5, 3.0]. */
|
|
49
|
+
export function computeVolFactor(currentAtr, baselineAtr) {
|
|
50
|
+
if (baselineAtr <= 0 || currentAtr <= 0)
|
|
51
|
+
return 1.0;
|
|
52
|
+
return Math.max(0.5, Math.min(3.0, currentAtr / baselineAtr));
|
|
53
|
+
}
|
|
54
|
+
/** Adjust a limit value by volatility factor. Higher vol = tighter limit. */
|
|
55
|
+
export function adjustLimitByVol(defaultLimit, volFactor) {
|
|
56
|
+
if (volFactor <= 1.0)
|
|
57
|
+
return defaultLimit;
|
|
58
|
+
return defaultLimit / volFactor;
|
|
59
|
+
}
|
|
60
|
+
/** Check if an order is closing an existing position (partial or full). */
|
|
61
|
+
export function isClosingOrder(order, positions) {
|
|
62
|
+
const pos = positions.find(p => p.symbol === order.symbol);
|
|
63
|
+
if (!pos)
|
|
64
|
+
return false;
|
|
65
|
+
// Sell against a long = closing; buy against a short = closing
|
|
66
|
+
return (pos.side === 'long' && order.side === 'sell') ||
|
|
67
|
+
(pos.side === 'short' && order.side === 'buy');
|
|
68
|
+
}
|
|
69
|
+
// ---- Main pre-trade gate ----
|
|
70
|
+
// ---- Equity-proportional floors (safety net for tiny accounts) ----
|
|
71
|
+
// These are independent of the configurable trading params and exist so that
|
|
72
|
+
// a $10,000 static `maxPositionSize` default can't allow a $289 account to
|
|
73
|
+
// open an $8,000 position. They shrink the effective caps relative to current
|
|
74
|
+
// equity; the tighter of (absolute limit, equity-proportional floor) wins.
|
|
75
|
+
export const EQUITY_FLOOR = {
|
|
76
|
+
/** Max single-position notional as a fraction of equity.
|
|
77
|
+
* Raised 0.25 → 0.40 on 2026-04-20 so small live accounts ($186) can fit
|
|
78
|
+
* BTC's ~$75 min-lot. Still protects against all-in entries. Tracked for
|
|
79
|
+
* promotion to operator-configurable trading param in the next session. */
|
|
80
|
+
MAX_POSITION_PCT: 0.40,
|
|
81
|
+
/** Max per-trade risk (expected loss) as a fraction of equity. */
|
|
82
|
+
MAX_PER_TRADE_LOSS_PCT: 0.02,
|
|
83
|
+
/** Presumed adverse move when an order has no explicit stopPrice. */
|
|
84
|
+
NO_STOP_ASSUMED_ADVERSE: 0.05,
|
|
85
|
+
};
|
|
86
|
+
export function preTradeRiskCheck(order, portfolio, limits = DEFAULT_PRE_TRADE_LIMITS, options = {}) {
|
|
87
|
+
const violations = [];
|
|
88
|
+
const volFactor = options.volFactor ?? 1.0;
|
|
89
|
+
// Caller-provided equity is authoritative; fall back to local compute for
|
|
90
|
+
// legacy test callers that don't supply it.
|
|
91
|
+
const currentEquity = portfolio.equity ?? computePortfolioEquity(portfolio);
|
|
92
|
+
// Drawdown anchor: prefer sessionStartNav, fall back to current equity.
|
|
93
|
+
const nav = portfolio.sessionStartNav > 0 ? portfolio.sessionStartNav : currentEquity;
|
|
94
|
+
const drawdownRatio = nav > 0 ? (currentEquity - nav) / nav : 0;
|
|
95
|
+
const zone = getDrawdownZone(drawdownRatio);
|
|
96
|
+
// Classify the order against any same-symbol position BEFORE the zone gates:
|
|
97
|
+
// - pure reduce / full close → "closing": exempt from entry gates (exits
|
|
98
|
+
// must always work, even in RED/ORANGE).
|
|
99
|
+
// - flip (over-close) → closes the old leg AND opens a NEW opposite
|
|
100
|
+
// leg; the NEW leg must clear every entry gate (drawdown zone, size,
|
|
101
|
+
// gross, per-trade-loss, bracket requirement). Previously a flip took the
|
|
102
|
+
// exit exemption and opened unchecked, possibly oversized, stop-less
|
|
103
|
+
// exposure — even in the RED zone (M6).
|
|
104
|
+
// - same-direction add (scale-in) / fresh entry → full entry checks (M5).
|
|
105
|
+
// Emergency flatten bypasses this function entirely (EmergencyControls → adapter.createOrder).
|
|
106
|
+
const closingPos = portfolio.positions.find(p => p.symbol === order.symbol &&
|
|
107
|
+
((p.side === 'long' && order.side === 'sell') || (p.side === 'short' && order.side === 'buy')));
|
|
108
|
+
const flipAmount = closingPos ? order.amount - closingPos.quantity : 0;
|
|
109
|
+
const isFlip = closingPos != null && flipAmount > 1e-9 * Math.max(closingPos.quantity, 1);
|
|
110
|
+
const closing = closingPos != null && !isFlip; // reduce/close, opens no new exposure
|
|
111
|
+
// The leg that opens new exposure and must clear the entry gates. For a flip
|
|
112
|
+
// it's ONLY the excess beyond the closed position; otherwise the whole order.
|
|
113
|
+
// stopPrice/targetPrice carry over so the per-trade-loss and live
|
|
114
|
+
// bracket-requirement gates evaluate against the new leg's real stop.
|
|
115
|
+
const entryOrder = isFlip ? { ...order, amount: flipAmount } : order;
|
|
116
|
+
// Bracket requirement gates — only apply to entries (not closes) when the
|
|
117
|
+
// caller explicitly passes `bracketEnforcement`. Closes are exempt so
|
|
118
|
+
// operators can always exit, even if the entry broke the policy.
|
|
119
|
+
if (!closing && options.bracketEnforcement) {
|
|
120
|
+
const { requireStopLoss, requireTakeProfit } = options.bracketEnforcement;
|
|
121
|
+
if (requireStopLoss && (order.stopPrice === undefined || !(order.stopPrice > 0))) {
|
|
122
|
+
violations.push({
|
|
123
|
+
rule: 'requireStopLoss',
|
|
124
|
+
message: 'Live trades require a stopPrice. Disable requireStopLoss in Trading Parameters to override (not recommended).',
|
|
125
|
+
current: 0,
|
|
126
|
+
limit: 1,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (requireTakeProfit && (order.targetPrice === undefined || !(order.targetPrice > 0))) {
|
|
130
|
+
violations.push({
|
|
131
|
+
rule: 'requireTakeProfit',
|
|
132
|
+
message: 'Live trades require a target_price. Disable requireTakeProfit in Trading Parameters to override.',
|
|
133
|
+
current: 0,
|
|
134
|
+
limit: 1,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (violations.length > 0) {
|
|
138
|
+
return {
|
|
139
|
+
allowed: false,
|
|
140
|
+
violations,
|
|
141
|
+
drawdownZone: zone,
|
|
142
|
+
effectiveMaxPositionSize: 0,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Exits are always allowed regardless of drawdown zone
|
|
147
|
+
if (closing) {
|
|
148
|
+
const effectiveMax = computeEffectivePositionSize(limits.maxPositionSize, volFactor, zone);
|
|
149
|
+
return {
|
|
150
|
+
allowed: true,
|
|
151
|
+
violations: [],
|
|
152
|
+
drawdownZone: zone,
|
|
153
|
+
effectiveMaxPositionSize: effectiveMax,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// RED zone: reject new entries (exits already handled above)
|
|
157
|
+
if (zone === 'RED') {
|
|
158
|
+
violations.push({
|
|
159
|
+
rule: 'drawdownZone',
|
|
160
|
+
message: `RED zone (${(drawdownRatio * 100).toFixed(2)}% drawdown) — new entries rejected`,
|
|
161
|
+
current: drawdownRatio,
|
|
162
|
+
limit: DRAWDOWN_ZONE_THRESHOLDS.RED,
|
|
163
|
+
});
|
|
164
|
+
return {
|
|
165
|
+
allowed: false,
|
|
166
|
+
violations,
|
|
167
|
+
drawdownZone: zone,
|
|
168
|
+
effectiveMaxPositionSize: 0,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// ORANGE zone: only exits allowed (already handled above)
|
|
172
|
+
if (zone === 'ORANGE') {
|
|
173
|
+
violations.push({
|
|
174
|
+
rule: 'drawdownZone',
|
|
175
|
+
message: `ORANGE zone (${(drawdownRatio * 100).toFixed(2)}% drawdown) — new entries blocked, exits only`,
|
|
176
|
+
current: drawdownRatio,
|
|
177
|
+
limit: DRAWDOWN_ZONE_THRESHOLDS.ORANGE,
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
allowed: false,
|
|
181
|
+
violations,
|
|
182
|
+
drawdownZone: zone,
|
|
183
|
+
effectiveMaxPositionSize: 0,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
// ---- Entry checks (GREEN/YELLOW) ----
|
|
187
|
+
const streak = options.consecutiveLosses ?? 0;
|
|
188
|
+
const tp = getCachedTradingParams();
|
|
189
|
+
// Equity-proportional floor — shrinks the static cap on small accounts.
|
|
190
|
+
// A $10k default `maxPositionSize` is useless on a $289 account; cap to
|
|
191
|
+
// `EQUITY_FLOOR.MAX_POSITION_PCT` of current equity. The tighter of the two wins.
|
|
192
|
+
const equityPositionCap = currentEquity > 0
|
|
193
|
+
? currentEquity * EQUITY_FLOOR.MAX_POSITION_PCT
|
|
194
|
+
: limits.maxPositionSize;
|
|
195
|
+
const scaledMaxPositionSize = Math.min(limits.maxPositionSize, equityPositionCap);
|
|
196
|
+
let effectiveMaxPositionSize = computeEffectivePositionSize(scaledMaxPositionSize, volFactor, zone);
|
|
197
|
+
// Graduated size reduction on loss streaks (never a hard block — that creates deadlocks)
|
|
198
|
+
// Ensure correct ordering: the harsher reduction (0.25x) needs the higher threshold
|
|
199
|
+
const quarterThreshold = Math.max(tp.lossStreakQuarterSize, tp.lossStreakHalfSize);
|
|
200
|
+
const halfThreshold = Math.min(tp.lossStreakQuarterSize, tp.lossStreakHalfSize);
|
|
201
|
+
if (streak >= quarterThreshold) {
|
|
202
|
+
effectiveMaxPositionSize *= 0.25;
|
|
203
|
+
}
|
|
204
|
+
else if (streak >= halfThreshold) {
|
|
205
|
+
effectiveMaxPositionSize *= 0.5;
|
|
206
|
+
}
|
|
207
|
+
// 1. Position size check — against the RESULTING position notional, not just
|
|
208
|
+
// this order's increment. A same-direction scale-in must include the
|
|
209
|
+
// existing leg, or repeated small adds each pass individually yet build a
|
|
210
|
+
// position far beyond the per-symbol cap (M5). A flip's resulting position
|
|
211
|
+
// is only the new opposite leg (the old leg is closed), so the existing
|
|
212
|
+
// notional is NOT added there.
|
|
213
|
+
const entryNotional = entryOrder.amount * order.price;
|
|
214
|
+
const sameSymbolPos = portfolio.positions.find(p => p.symbol === order.symbol);
|
|
215
|
+
const isScaleIn = sameSymbolPos != null &&
|
|
216
|
+
((sameSymbolPos.side === 'long' && order.side === 'buy') ||
|
|
217
|
+
(sameSymbolPos.side === 'short' && order.side === 'sell'));
|
|
218
|
+
const existingNotional = isScaleIn && sameSymbolPos
|
|
219
|
+
? sameSymbolPos.quantity * (sameSymbolPos.markPrice ?? sameSymbolPos.entryPrice)
|
|
220
|
+
: 0;
|
|
221
|
+
const resultingNotional = existingNotional + entryNotional;
|
|
222
|
+
if (resultingNotional > effectiveMaxPositionSize) {
|
|
223
|
+
violations.push({
|
|
224
|
+
rule: 'positionSize',
|
|
225
|
+
message: `Resulting position notional $${resultingNotional.toFixed(2)} (existing $${existingNotional.toFixed(2)} + order $${entryNotional.toFixed(2)}) exceeds effective max $${effectiveMaxPositionSize.toFixed(2)} (equity $${currentEquity.toFixed(2)}, cap ${(EQUITY_FLOOR.MAX_POSITION_PCT * 100).toFixed(0)}% of equity)`,
|
|
226
|
+
current: resultingNotional,
|
|
227
|
+
limit: effectiveMaxPositionSize,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
// 2. Open positions count (would a new symbol exceed limit?)
|
|
231
|
+
const existingSymbols = new Set(portfolio.positions.map(p => p.symbol));
|
|
232
|
+
if (!existingSymbols.has(order.symbol)) {
|
|
233
|
+
const newCount = existingSymbols.size + 1;
|
|
234
|
+
if (newCount > limits.maxOpenPositions) {
|
|
235
|
+
violations.push({
|
|
236
|
+
rule: 'openPositions',
|
|
237
|
+
message: `New position would bring count to ${newCount}, max is ${limits.maxOpenPositions}`,
|
|
238
|
+
current: newCount,
|
|
239
|
+
limit: limits.maxOpenPositions,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// 3. Projected gross exposure. On a flip the closed leg leaves the book, so
|
|
244
|
+
// net it out — otherwise the projection double-counts the position we close.
|
|
245
|
+
if (nav > 0) {
|
|
246
|
+
const currentGross = computeGrossExposure(portfolio);
|
|
247
|
+
const closedLegNotional = isFlip && closingPos
|
|
248
|
+
? closingPos.quantity * (closingPos.markPrice ?? closingPos.entryPrice)
|
|
249
|
+
: 0;
|
|
250
|
+
const projectedGross = currentGross - closedLegNotional + entryNotional;
|
|
251
|
+
const projectedRatio = projectedGross / nav;
|
|
252
|
+
const effectiveMaxGross = adjustLimitByVol(limits.maxGrossExposure, volFactor);
|
|
253
|
+
if (projectedRatio > effectiveMaxGross) {
|
|
254
|
+
violations.push({
|
|
255
|
+
rule: 'grossExposure',
|
|
256
|
+
message: `Projected gross exposure ${projectedRatio.toFixed(2)}x exceeds limit ${effectiveMaxGross.toFixed(2)}x`,
|
|
257
|
+
current: projectedRatio,
|
|
258
|
+
limit: effectiveMaxGross,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// 4. Per-trade loss check — MANDATORY (was previously opt-in on stopPrice).
|
|
263
|
+
// Without a stop, we presume a 5% adverse move as the worst-case loss. This
|
|
264
|
+
// prevents the gate from waving through stopless entries on thin accounts.
|
|
265
|
+
if (!closing) {
|
|
266
|
+
// Use the opening leg's amount/notional (the flip's new leg, or the whole
|
|
267
|
+
// order for a fresh entry/scale-in) so the flip's new exposure is gated.
|
|
268
|
+
const expectedLoss = order.stopPrice != null
|
|
269
|
+
? Math.abs(order.price - order.stopPrice) * entryOrder.amount
|
|
270
|
+
: entryNotional * EQUITY_FLOOR.NO_STOP_ASSUMED_ADVERSE;
|
|
271
|
+
const equityLossCap = currentEquity > 0
|
|
272
|
+
? currentEquity * EQUITY_FLOOR.MAX_PER_TRADE_LOSS_PCT
|
|
273
|
+
: limits.maxPerTradeLoss;
|
|
274
|
+
const scaledPerTradeLoss = Math.min(limits.maxPerTradeLoss, equityLossCap);
|
|
275
|
+
if (expectedLoss > scaledPerTradeLoss) {
|
|
276
|
+
const stopNote = order.stopPrice != null
|
|
277
|
+
? `stop @ ${order.stopPrice}`
|
|
278
|
+
: `no stop — assumed ${(EQUITY_FLOOR.NO_STOP_ASSUMED_ADVERSE * 100).toFixed(0)}% adverse move`;
|
|
279
|
+
violations.push({
|
|
280
|
+
rule: 'perTradeLoss',
|
|
281
|
+
message: `Expected loss $${expectedLoss.toFixed(2)} (${stopNote}) exceeds per-trade limit $${scaledPerTradeLoss.toFixed(2)} (${(EQUITY_FLOOR.MAX_PER_TRADE_LOSS_PCT * 100).toFixed(0)}% of equity $${currentEquity.toFixed(2)})`,
|
|
282
|
+
current: expectedLoss,
|
|
283
|
+
limit: scaledPerTradeLoss,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
allowed: violations.length === 0,
|
|
289
|
+
violations,
|
|
290
|
+
drawdownZone: zone,
|
|
291
|
+
effectiveMaxPositionSize,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
// ---- Exported helpers ----
|
|
295
|
+
/** Count consecutive losses from the end of a trade history array. */
|
|
296
|
+
export function computeConsecutiveLosses(trades) {
|
|
297
|
+
let streak = 0;
|
|
298
|
+
for (let i = trades.length - 1; i >= 0; i--) {
|
|
299
|
+
if (trades[i].realizedPnl < 0) {
|
|
300
|
+
streak++;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return streak;
|
|
307
|
+
}
|
|
308
|
+
// ---- Internal helpers ----
|
|
309
|
+
function computeEffectivePositionSize(baseMax, volFactor, zone) {
|
|
310
|
+
let effective = adjustLimitByVol(baseMax, volFactor);
|
|
311
|
+
if (zone === 'YELLOW') {
|
|
312
|
+
effective *= 0.5; // YELLOW halves position sizes
|
|
313
|
+
}
|
|
314
|
+
return effective;
|
|
315
|
+
}
|
|
316
|
+
function computePortfolioEquity(portfolio) {
|
|
317
|
+
let equity = portfolio.walletTotal;
|
|
318
|
+
for (const pos of portfolio.positions) {
|
|
319
|
+
const mark = pos.markPrice ?? pos.entryPrice;
|
|
320
|
+
const pnl = pos.side === 'long'
|
|
321
|
+
? (mark - pos.entryPrice) * pos.quantity
|
|
322
|
+
: (pos.entryPrice - mark) * pos.quantity;
|
|
323
|
+
if (portfolio.isLive) {
|
|
324
|
+
// Live Binance: wallet already includes margin — add only unrealized P&L.
|
|
325
|
+
equity += pnl;
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
// Paper simulator (SPOT-collateral model): the full entry notional was
|
|
329
|
+
// deducted from wallet at open and is released on close, so we must add
|
|
330
|
+
// it back here. Same formula for longs and shorts — the previous
|
|
331
|
+
// `-qty*mark` short branch was arithmetically wrong and underrepresented
|
|
332
|
+
// equity by 2*entry*qty whenever the account held a short.
|
|
333
|
+
equity += pos.entryPrice * pos.quantity + pnl;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return equity;
|
|
337
|
+
}
|
|
338
|
+
function computeGrossExposure(portfolio) {
|
|
339
|
+
let gross = 0;
|
|
340
|
+
for (const pos of portfolio.positions) {
|
|
341
|
+
const price = pos.markPrice ?? pos.entryPrice;
|
|
342
|
+
gross += Math.abs(pos.quantity * price);
|
|
343
|
+
}
|
|
344
|
+
return gross;
|
|
345
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type DrawdownZone = 'GREEN' | 'YELLOW' | 'ORANGE' | 'RED';
|
|
2
|
+
export interface PreTradeRiskLimits {
|
|
3
|
+
maxPositionSize: number;
|
|
4
|
+
maxOpenPositions: number;
|
|
5
|
+
maxGrossExposure: number;
|
|
6
|
+
maxPerTradeLoss: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ProposedOrder {
|
|
9
|
+
symbol: string;
|
|
10
|
+
side: 'buy' | 'sell';
|
|
11
|
+
type: 'market' | 'limit';
|
|
12
|
+
amount: number;
|
|
13
|
+
price: number;
|
|
14
|
+
stopPrice?: number;
|
|
15
|
+
targetPrice?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface PortfolioSnapshot {
|
|
18
|
+
positions: Array<{
|
|
19
|
+
symbol: string;
|
|
20
|
+
side: 'long' | 'short';
|
|
21
|
+
quantity: number;
|
|
22
|
+
entryPrice: number;
|
|
23
|
+
markPrice?: number;
|
|
24
|
+
}>;
|
|
25
|
+
walletTotal: number;
|
|
26
|
+
walletAvailable: number;
|
|
27
|
+
sessionStartNav: number;
|
|
28
|
+
/** Mark-to-market total account value. If provided, takes precedence over
|
|
29
|
+
* the gate's own equity computation — the caller's value is authoritative
|
|
30
|
+
* because it has access to the real simulator/exchange state. When absent
|
|
31
|
+
* (legacy test callers), the gate falls back to an internal computation. */
|
|
32
|
+
equity?: number;
|
|
33
|
+
/** Paper simulator deducts notional from wallet at entry — equity = wallet + position value.
|
|
34
|
+
* Live Binance wallet already includes margin — equity = wallet + unrealized PnL only. */
|
|
35
|
+
isLive?: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface PreTradeViolation {
|
|
38
|
+
rule: string;
|
|
39
|
+
message: string;
|
|
40
|
+
current: number;
|
|
41
|
+
limit: number;
|
|
42
|
+
}
|
|
43
|
+
export interface PreTradeResult {
|
|
44
|
+
allowed: boolean;
|
|
45
|
+
violations: PreTradeViolation[];
|
|
46
|
+
drawdownZone: DrawdownZone;
|
|
47
|
+
effectiveMaxPositionSize: number;
|
|
48
|
+
}
|
|
49
|
+
export interface PreTradeOptions {
|
|
50
|
+
volFactor?: number;
|
|
51
|
+
consecutiveLosses?: number;
|
|
52
|
+
/** When true, the gate rejects entries without a stopPrice and/or targetPrice
|
|
53
|
+
* based on the flags below. Only meaningful in live mode with bracket orders
|
|
54
|
+
* enabled — in paper/off mode the stop-watcher handles protection and these
|
|
55
|
+
* flags don't apply (gate ignores them). */
|
|
56
|
+
bracketEnforcement?: {
|
|
57
|
+
requireStopLoss: boolean;
|
|
58
|
+
requireTakeProfit: boolean;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { BinancePrivateApi } from '../ccxt/binance-private.js';
|
|
3
|
+
import type { ExchangeSimulator } from '../simulator/exchange-simulator.js';
|
|
4
|
+
import type { ShadowComparison, ShadowMetrics, ShadowConfig } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* ShadowTracker hooks into the ExchangeSimulator to compute
|
|
7
|
+
* shadow estimates for every paper fill.
|
|
8
|
+
*
|
|
9
|
+
* Events emitted:
|
|
10
|
+
* - 'shadowComparison': ShadowComparison — after each fill comparison
|
|
11
|
+
*/
|
|
12
|
+
export declare class ShadowTracker extends EventEmitter {
|
|
13
|
+
private privateApi;
|
|
14
|
+
private simulator;
|
|
15
|
+
private metrics;
|
|
16
|
+
private config;
|
|
17
|
+
private recentComparisons;
|
|
18
|
+
private active;
|
|
19
|
+
constructor(privateApi: BinancePrivateApi, simulator: ExchangeSimulator, config?: ShadowConfig, existingMetrics?: ShadowMetrics);
|
|
20
|
+
/** Start listening for simulator fill events. */
|
|
21
|
+
start(): void;
|
|
22
|
+
/** Stop listening. */
|
|
23
|
+
stop(): void;
|
|
24
|
+
/** Get current shadow metrics. */
|
|
25
|
+
getMetrics(): ShadowMetrics;
|
|
26
|
+
/** Get recent comparisons. */
|
|
27
|
+
getRecentComparisons(): ShadowComparison[];
|
|
28
|
+
/** Check if shadow mode criteria are met for mode upgrade. */
|
|
29
|
+
isReadyForUpgrade(): {
|
|
30
|
+
ready: boolean;
|
|
31
|
+
reasons: string[];
|
|
32
|
+
};
|
|
33
|
+
private onFill;
|
|
34
|
+
private computeShadowComparison;
|
|
35
|
+
private updateMetrics;
|
|
36
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// Shadow Tracker — compares paper fills against live exchange estimates.
|
|
2
|
+
// Listens for fill events from the simulator, fetches real order book,
|
|
3
|
+
// computes what the live fill would have been, logs the comparison.
|
|
4
|
+
import { EventEmitter } from 'node:events';
|
|
5
|
+
import { logger } from '../logger.js';
|
|
6
|
+
import { priceToBps } from '../simulator/types.js';
|
|
7
|
+
import { computeBookAwareFillPrice } from '../simulator/realistic-fills.js';
|
|
8
|
+
import { createEmptyShadowMetrics, DEFAULT_SHADOW_CONFIG } from './types.js';
|
|
9
|
+
const TAG = 'shadow-tracker';
|
|
10
|
+
/** Maximum recent comparisons to keep in memory. */
|
|
11
|
+
const MAX_RECENT_COMPARISONS = 100;
|
|
12
|
+
/**
|
|
13
|
+
* ShadowTracker hooks into the ExchangeSimulator to compute
|
|
14
|
+
* shadow estimates for every paper fill.
|
|
15
|
+
*
|
|
16
|
+
* Events emitted:
|
|
17
|
+
* - 'shadowComparison': ShadowComparison — after each fill comparison
|
|
18
|
+
*/
|
|
19
|
+
export class ShadowTracker extends EventEmitter {
|
|
20
|
+
privateApi;
|
|
21
|
+
simulator;
|
|
22
|
+
metrics;
|
|
23
|
+
config;
|
|
24
|
+
recentComparisons = [];
|
|
25
|
+
active = false;
|
|
26
|
+
constructor(privateApi, simulator, config, existingMetrics) {
|
|
27
|
+
super();
|
|
28
|
+
this.privateApi = privateApi;
|
|
29
|
+
this.simulator = simulator;
|
|
30
|
+
this.config = config ?? DEFAULT_SHADOW_CONFIG;
|
|
31
|
+
this.metrics = existingMetrics ?? createEmptyShadowMetrics();
|
|
32
|
+
}
|
|
33
|
+
/** Start listening for simulator fill events. */
|
|
34
|
+
start() {
|
|
35
|
+
if (this.active)
|
|
36
|
+
return;
|
|
37
|
+
this.active = true;
|
|
38
|
+
this.simulator.on('fill', this.onFill);
|
|
39
|
+
logger.info(TAG, `Shadow tracker started (${this.metrics.totalShadowTrades} prior comparisons)`);
|
|
40
|
+
}
|
|
41
|
+
/** Stop listening. */
|
|
42
|
+
stop() {
|
|
43
|
+
if (!this.active)
|
|
44
|
+
return;
|
|
45
|
+
this.active = false;
|
|
46
|
+
this.simulator.off('fill', this.onFill);
|
|
47
|
+
logger.info(TAG, 'Shadow tracker stopped');
|
|
48
|
+
}
|
|
49
|
+
/** Get current shadow metrics. */
|
|
50
|
+
getMetrics() {
|
|
51
|
+
return { ...this.metrics };
|
|
52
|
+
}
|
|
53
|
+
/** Get recent comparisons. */
|
|
54
|
+
getRecentComparisons() {
|
|
55
|
+
return [...this.recentComparisons];
|
|
56
|
+
}
|
|
57
|
+
/** Check if shadow mode criteria are met for mode upgrade. */
|
|
58
|
+
isReadyForUpgrade() {
|
|
59
|
+
const reasons = [];
|
|
60
|
+
if (this.metrics.totalShadowTrades < this.config.minTrades) {
|
|
61
|
+
reasons.push(`Need ${this.config.minTrades} shadow trades, have ${this.metrics.totalShadowTrades}`);
|
|
62
|
+
}
|
|
63
|
+
if (this.metrics.tradingDays < this.config.minDays) {
|
|
64
|
+
reasons.push(`Need ${this.config.minDays} trading days, have ${this.metrics.tradingDays}`);
|
|
65
|
+
}
|
|
66
|
+
if (this.metrics.avgDeltaBps > this.config.maxAvgDeltaBps) {
|
|
67
|
+
reasons.push(`Avg delta ${this.metrics.avgDeltaBps.toFixed(2)}bps exceeds max ${this.config.maxAvgDeltaBps}bps`);
|
|
68
|
+
}
|
|
69
|
+
return { ready: reasons.length === 0, reasons };
|
|
70
|
+
}
|
|
71
|
+
// Arrow function to preserve `this` binding when used as event listener
|
|
72
|
+
onFill = (fillData) => {
|
|
73
|
+
// Only compare market order fills (limit orders fill at limit price, no comparison needed)
|
|
74
|
+
if (fillData.type !== 'market')
|
|
75
|
+
return;
|
|
76
|
+
// Fire and forget — shadow comparison is async but doesn't block the fill
|
|
77
|
+
this.computeShadowComparison(fillData).catch(err => {
|
|
78
|
+
logger.warn(TAG, `Shadow comparison failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
async computeShadowComparison(fillData) {
|
|
82
|
+
// Fetch fresh order book from the exchange (authenticated path)
|
|
83
|
+
const liveBook = await this.privateApi.fetchOrderBook(fillData.symbol, 20);
|
|
84
|
+
let shadowPrice;
|
|
85
|
+
let bookDepthUsed = 0;
|
|
86
|
+
let bookDepthAvailable = false;
|
|
87
|
+
if (liveBook && liveBook.asks.length > 0 && liveBook.bids.length > 0) {
|
|
88
|
+
// Walk the live book to compute shadow VWAP
|
|
89
|
+
const { vwap, levelsConsumed } = computeBookAwareFillPrice(fillData.side, fillData.amount, liveBook);
|
|
90
|
+
shadowPrice = vwap;
|
|
91
|
+
bookDepthUsed = levelsConsumed;
|
|
92
|
+
bookDepthAvailable = true;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// No live book available — use paper fill as shadow estimate
|
|
96
|
+
shadowPrice = fillData.fillPrice;
|
|
97
|
+
logger.warn(TAG, `No live order book for ${fillData.symbol} — shadow estimate equals paper`);
|
|
98
|
+
}
|
|
99
|
+
// Compute shadow fee (same taker rate as paper for fair comparison)
|
|
100
|
+
const simConfig = this.simulator.getSimulationConfig();
|
|
101
|
+
const shadowFee = fillData.amount * shadowPrice * simConfig.fees.takerRate;
|
|
102
|
+
// Delta: positive = live would be worse (pay more for buy, receive less for sell)
|
|
103
|
+
const deltaBps = priceToBps(shadowPrice, fillData.fillPrice);
|
|
104
|
+
const comparison = {
|
|
105
|
+
orderId: fillData.orderId,
|
|
106
|
+
symbol: fillData.symbol,
|
|
107
|
+
side: fillData.side,
|
|
108
|
+
type: fillData.type,
|
|
109
|
+
amount: fillData.amount,
|
|
110
|
+
paperFillPrice: fillData.fillPrice,
|
|
111
|
+
shadowEstimatePrice: shadowPrice,
|
|
112
|
+
deltaBps,
|
|
113
|
+
paperFee: fillData.fee,
|
|
114
|
+
shadowEstimateFee: shadowFee,
|
|
115
|
+
bookDepthUsed,
|
|
116
|
+
bookDepthAvailable,
|
|
117
|
+
timestamp: new Date().toISOString(),
|
|
118
|
+
};
|
|
119
|
+
// Update metrics
|
|
120
|
+
this.updateMetrics(comparison);
|
|
121
|
+
// Store recent comparison (match webapp slice pattern — slice instead of shift)
|
|
122
|
+
this.recentComparisons = [
|
|
123
|
+
...this.recentComparisons.slice(-(MAX_RECENT_COMPARISONS - 1)),
|
|
124
|
+
comparison,
|
|
125
|
+
];
|
|
126
|
+
// Emit event for skill/bridge pipeline
|
|
127
|
+
this.emit('shadowComparison', comparison);
|
|
128
|
+
logger.info(TAG, `Shadow comparison: ${fillData.side} ${fillData.amount} ${fillData.symbol}` +
|
|
129
|
+
` | Paper: ${fillData.fillPrice.toFixed(2)} | Shadow: ${shadowPrice.toFixed(2)}` +
|
|
130
|
+
` | Delta: ${deltaBps.toFixed(2)}bps` +
|
|
131
|
+
` | Book: ${bookDepthAvailable ? `${bookDepthUsed} levels` : 'unavailable'}`);
|
|
132
|
+
}
|
|
133
|
+
updateMetrics(comparison) {
|
|
134
|
+
const m = this.metrics;
|
|
135
|
+
m.totalShadowTrades++;
|
|
136
|
+
const absDelta = Math.abs(comparison.deltaBps);
|
|
137
|
+
m.totalDeltaBpsSum += absDelta;
|
|
138
|
+
m.avgDeltaBps = m.totalDeltaBpsSum / m.totalShadowTrades;
|
|
139
|
+
if (absDelta > m.worstDeltaBps) {
|
|
140
|
+
m.worstDeltaBps = absDelta;
|
|
141
|
+
}
|
|
142
|
+
m.paperTotalFees += comparison.paperFee;
|
|
143
|
+
m.shadowTotalFees += comparison.shadowEstimateFee;
|
|
144
|
+
// Track trading days
|
|
145
|
+
const today = comparison.timestamp.slice(0, 10);
|
|
146
|
+
if (today !== m.lastTradeDate) {
|
|
147
|
+
m.tradingDays++;
|
|
148
|
+
m.lastTradeDate = today;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { TradingMode } from '../types.js';
|
|
2
|
+
export type { TradingMode };
|
|
3
|
+
/** A single shadow comparison record: paper fill vs live estimate. */
|
|
4
|
+
export interface ShadowComparison {
|
|
5
|
+
orderId: string;
|
|
6
|
+
symbol: string;
|
|
7
|
+
side: 'buy' | 'sell';
|
|
8
|
+
type: 'market' | 'limit';
|
|
9
|
+
amount: number;
|
|
10
|
+
paperFillPrice: number;
|
|
11
|
+
shadowEstimatePrice: number;
|
|
12
|
+
deltaBps: number;
|
|
13
|
+
paperFee: number;
|
|
14
|
+
shadowEstimateFee: number;
|
|
15
|
+
bookDepthUsed: number;
|
|
16
|
+
bookDepthAvailable: boolean;
|
|
17
|
+
timestamp: string;
|
|
18
|
+
}
|
|
19
|
+
/** Aggregate shadow metrics across all shadow comparisons. */
|
|
20
|
+
export interface ShadowMetrics {
|
|
21
|
+
totalShadowTrades: number;
|
|
22
|
+
avgDeltaBps: number;
|
|
23
|
+
worstDeltaBps: number;
|
|
24
|
+
totalDeltaBpsSum: number;
|
|
25
|
+
paperTotalFees: number;
|
|
26
|
+
shadowTotalFees: number;
|
|
27
|
+
startedAt: string;
|
|
28
|
+
tradingDays: number;
|
|
29
|
+
lastTradeDate: string;
|
|
30
|
+
}
|
|
31
|
+
/** Shadow mode configuration thresholds. */
|
|
32
|
+
export interface ShadowConfig {
|
|
33
|
+
/** Minimum shadow trades before allowing mode upgrade (default: 50) */
|
|
34
|
+
minTrades: number;
|
|
35
|
+
/** Minimum days in shadow mode (default: 7) */
|
|
36
|
+
minDays: number;
|
|
37
|
+
/** Max acceptable average delta in bps (default: 5) */
|
|
38
|
+
maxAvgDeltaBps: number;
|
|
39
|
+
}
|
|
40
|
+
export declare const DEFAULT_SHADOW_CONFIG: ShadowConfig;
|
|
41
|
+
/** Create empty shadow metrics. */
|
|
42
|
+
export declare function createEmptyShadowMetrics(): ShadowMetrics;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Shadow mode types — tracking paper vs live fill comparison.
|
|
2
|
+
export const DEFAULT_SHADOW_CONFIG = {
|
|
3
|
+
minTrades: 50,
|
|
4
|
+
minDays: 7,
|
|
5
|
+
maxAvgDeltaBps: 5,
|
|
6
|
+
};
|
|
7
|
+
/** Create empty shadow metrics. */
|
|
8
|
+
export function createEmptyShadowMetrics() {
|
|
9
|
+
return {
|
|
10
|
+
totalShadowTrades: 0,
|
|
11
|
+
avgDeltaBps: 0,
|
|
12
|
+
worstDeltaBps: 0,
|
|
13
|
+
totalDeltaBpsSum: 0,
|
|
14
|
+
paperTotalFees: 0,
|
|
15
|
+
shadowTotalFees: 0,
|
|
16
|
+
startedAt: new Date().toISOString(),
|
|
17
|
+
tradingDays: 0,
|
|
18
|
+
lastTradeDate: '',
|
|
19
|
+
};
|
|
20
|
+
}
|