@senpi/trading-recipe 1.0.21
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/README.md +117 -0
- package/dist/actions/close-position/close-position.action.d.ts +16 -0
- package/dist/actions/close-position/close-position.action.d.ts.map +1 -0
- package/dist/actions/close-position/close-position.action.js +215 -0
- package/dist/actions/close-position/close-position.action.js.map +1 -0
- package/dist/actions/decision-engine.d.ts +32 -0
- package/dist/actions/decision-engine.d.ts.map +1 -0
- package/dist/actions/decision-engine.js +103 -0
- package/dist/actions/decision-engine.js.map +1 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.d.ts +12 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.d.ts.map +1 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.js +74 -0
- package/dist/actions/llm-decision/anthropic-llm-decision.js.map +1 -0
- package/dist/actions/llm-decision/factory.d.ts +17 -0
- package/dist/actions/llm-decision/factory.d.ts.map +1 -0
- package/dist/actions/llm-decision/factory.js +29 -0
- package/dist/actions/llm-decision/factory.js.map +1 -0
- package/dist/actions/llm-decision/index.d.ts +8 -0
- package/dist/actions/llm-decision/index.d.ts.map +1 -0
- package/dist/actions/llm-decision/index.js +5 -0
- package/dist/actions/llm-decision/index.js.map +1 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts +14 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.d.ts.map +1 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.js +58 -0
- package/dist/actions/llm-decision/openclaw-llm-decision.js.map +1 -0
- package/dist/actions/llm-decision/shared.d.ts +41 -0
- package/dist/actions/llm-decision/shared.d.ts.map +1 -0
- package/dist/actions/llm-decision/shared.js +117 -0
- package/dist/actions/llm-decision/shared.js.map +1 -0
- package/dist/actions/open-position/open-position.action.d.ts +16 -0
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -0
- package/dist/actions/open-position/open-position.action.js +275 -0
- package/dist/actions/open-position/open-position.action.js.map +1 -0
- package/dist/actions/types.d.ts +123 -0
- package/dist/actions/types.d.ts.map +1 -0
- package/dist/actions/types.js +3 -0
- package/dist/actions/types.js.map +1 -0
- package/dist/cli/guide-commands.d.ts +26 -0
- package/dist/cli/guide-commands.d.ts.map +1 -0
- package/dist/cli/guide-commands.js +345 -0
- package/dist/cli/guide-commands.js.map +1 -0
- package/dist/cli/senpi-commands.d.ts +20 -0
- package/dist/cli/senpi-commands.d.ts.map +1 -0
- package/dist/cli/senpi-commands.js +115 -0
- package/dist/cli/senpi-commands.js.map +1 -0
- package/dist/constants/dsl/index.d.ts +45 -0
- package/dist/constants/dsl/index.d.ts.map +1 -0
- package/dist/constants/dsl/index.js +45 -0
- package/dist/constants/dsl/index.js.map +1 -0
- package/dist/context/context-builder.d.ts +14 -0
- package/dist/context/context-builder.d.ts.map +1 -0
- package/dist/context/context-builder.js +36 -0
- package/dist/context/context-builder.js.map +1 -0
- package/dist/context/index.d.ts +5 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +5 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/interpolate.d.ts +6 -0
- package/dist/context/interpolate.d.ts.map +1 -0
- package/dist/context/interpolate.js +15 -0
- package/dist/context/interpolate.js.map +1 -0
- package/dist/context/providers/asset-trend.provider.d.ts +42 -0
- package/dist/context/providers/asset-trend.provider.d.ts.map +1 -0
- package/dist/context/providers/asset-trend.provider.js +94 -0
- package/dist/context/providers/asset-trend.provider.js.map +1 -0
- package/dist/context/providers/index.d.ts +5 -0
- package/dist/context/providers/index.d.ts.map +1 -0
- package/dist/context/providers/index.js +5 -0
- package/dist/context/providers/index.js.map +1 -0
- package/dist/context/providers/regime.provider.d.ts +14 -0
- package/dist/context/providers/regime.provider.d.ts.map +1 -0
- package/dist/context/providers/regime.provider.js +29 -0
- package/dist/context/providers/regime.provider.js.map +1 -0
- package/dist/context/providers/signal.provider.d.ts +11 -0
- package/dist/context/providers/signal.provider.d.ts.map +1 -0
- package/dist/context/providers/signal.provider.js +27 -0
- package/dist/context/providers/signal.provider.js.map +1 -0
- package/dist/context/providers/strategy.provider.d.ts +14 -0
- package/dist/context/providers/strategy.provider.d.ts.map +1 -0
- package/dist/context/providers/strategy.provider.js +68 -0
- package/dist/context/providers/strategy.provider.js.map +1 -0
- package/dist/context/types.d.ts +30 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +2 -0
- package/dist/context/types.js.map +1 -0
- package/dist/dsl/config/index.d.ts +59 -0
- package/dist/dsl/config/index.d.ts.map +1 -0
- package/dist/dsl/config/index.js +171 -0
- package/dist/dsl/config/index.js.map +1 -0
- package/dist/dsl/constants/index.d.ts +3 -0
- package/dist/dsl/constants/index.d.ts.map +1 -0
- package/dist/dsl/constants/index.js +3 -0
- package/dist/dsl/constants/index.js.map +1 -0
- package/dist/dsl/engine/index.d.ts +7 -0
- package/dist/dsl/engine/index.d.ts.map +1 -0
- package/dist/dsl/engine/index.js +310 -0
- package/dist/dsl/engine/index.js.map +1 -0
- package/dist/dsl/events/bus-types.d.ts +7 -0
- package/dist/dsl/events/bus-types.d.ts.map +1 -0
- package/dist/dsl/events/bus-types.js +6 -0
- package/dist/dsl/events/bus-types.js.map +1 -0
- package/dist/dsl/events/guards.d.ts +17 -0
- package/dist/dsl/events/guards.d.ts.map +1 -0
- package/dist/dsl/events/guards.js +94 -0
- package/dist/dsl/events/guards.js.map +1 -0
- package/dist/dsl/events/handlers.d.ts +15 -0
- package/dist/dsl/events/handlers.d.ts.map +1 -0
- package/dist/dsl/events/handlers.js +252 -0
- package/dist/dsl/events/handlers.js.map +1 -0
- package/dist/dsl/events/index.d.ts +4 -0
- package/dist/dsl/events/index.d.ts.map +1 -0
- package/dist/dsl/events/index.js +4 -0
- package/dist/dsl/events/index.js.map +1 -0
- package/dist/dsl/index.d.ts +13 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +35 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl/monitor/index.d.ts +18 -0
- package/dist/dsl/monitor/index.d.ts.map +1 -0
- package/dist/dsl/monitor/index.js +310 -0
- package/dist/dsl/monitor/index.js.map +1 -0
- package/dist/dsl/plugin/index.d.ts +29 -0
- package/dist/dsl/plugin/index.d.ts.map +1 -0
- package/dist/dsl/plugin/index.js +85 -0
- package/dist/dsl/plugin/index.js.map +1 -0
- package/dist/dsl/types/index.d.ts +3 -0
- package/dist/dsl/types/index.d.ts.map +1 -0
- package/dist/dsl/types/index.js +3 -0
- package/dist/dsl/types/index.js.map +1 -0
- package/dist/health/index.d.ts +9 -0
- package/dist/health/index.d.ts.map +1 -0
- package/dist/health/index.js +9 -0
- package/dist/health/index.js.map +1 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +235 -0
- package/dist/index.js.map +1 -0
- package/dist/leverage/max-leverage-cache.d.ts +10 -0
- package/dist/leverage/max-leverage-cache.d.ts.map +1 -0
- package/dist/leverage/max-leverage-cache.js +51 -0
- package/dist/leverage/max-leverage-cache.js.map +1 -0
- package/dist/leverage/resolve-leverage.d.ts +9 -0
- package/dist/leverage/resolve-leverage.d.ts.map +1 -0
- package/dist/leverage/resolve-leverage.js +15 -0
- package/dist/leverage/resolve-leverage.js.map +1 -0
- package/dist/risk/index.d.ts +9 -0
- package/dist/risk/index.d.ts.map +1 -0
- package/dist/risk/index.js +9 -0
- package/dist/risk/index.js.map +1 -0
- package/dist/runtime/action-registry.d.ts +12 -0
- package/dist/runtime/action-registry.d.ts.map +1 -0
- package/dist/runtime/action-registry.js +20 -0
- package/dist/runtime/action-registry.js.map +1 -0
- package/dist/runtime/build-action-scan-payload.d.ts +20 -0
- package/dist/runtime/build-action-scan-payload.d.ts.map +1 -0
- package/dist/runtime/build-action-scan-payload.js +40 -0
- package/dist/runtime/build-action-scan-payload.js.map +1 -0
- package/dist/runtime/bus.d.ts +6 -0
- package/dist/runtime/bus.d.ts.map +1 -0
- package/dist/runtime/bus.js +19 -0
- package/dist/runtime/bus.js.map +1 -0
- package/dist/runtime/create-action-context.d.ts +34 -0
- package/dist/runtime/create-action-context.d.ts.map +1 -0
- package/dist/runtime/create-action-context.js +22 -0
- package/dist/runtime/create-action-context.js.map +1 -0
- package/dist/runtime/create-actions.d.ts +30 -0
- package/dist/runtime/create-actions.d.ts.map +1 -0
- package/dist/runtime/create-actions.js +71 -0
- package/dist/runtime/create-actions.js.map +1 -0
- package/dist/runtime/create-runtime-context.d.ts +35 -0
- package/dist/runtime/create-runtime-context.d.ts.map +1 -0
- package/dist/runtime/create-runtime-context.js +33 -0
- package/dist/runtime/create-runtime-context.js.map +1 -0
- package/dist/runtime/create-scanner-module.d.ts +14 -0
- package/dist/runtime/create-scanner-module.d.ts.map +1 -0
- package/dist/runtime/create-scanner-module.js +26 -0
- package/dist/runtime/create-scanner-module.js.map +1 -0
- package/dist/runtime/create-scanner-providers-for-run.d.ts +20 -0
- package/dist/runtime/create-scanner-providers-for-run.d.ts.map +1 -0
- package/dist/runtime/create-scanner-providers-for-run.js +34 -0
- package/dist/runtime/create-scanner-providers-for-run.js.map +1 -0
- package/dist/runtime/default-state-dir.d.ts +10 -0
- package/dist/runtime/default-state-dir.d.ts.map +1 -0
- package/dist/runtime/default-state-dir.js +22 -0
- package/dist/runtime/default-state-dir.js.map +1 -0
- package/dist/runtime/env-resolve.d.ts +17 -0
- package/dist/runtime/env-resolve.d.ts.map +1 -0
- package/dist/runtime/env-resolve.js +45 -0
- package/dist/runtime/env-resolve.js.map +1 -0
- package/dist/runtime/hook-system.d.ts +7 -0
- package/dist/runtime/hook-system.d.ts.map +1 -0
- package/dist/runtime/hook-system.js +16 -0
- package/dist/runtime/hook-system.js.map +1 -0
- package/dist/runtime/index.d.ts +37 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +26 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/load-trading-strategy.d.ts +23 -0
- package/dist/runtime/load-trading-strategy.d.ts.map +1 -0
- package/dist/runtime/load-trading-strategy.js +130 -0
- package/dist/runtime/load-trading-strategy.js.map +1 -0
- package/dist/runtime/map-exit-config.d.ts +12 -0
- package/dist/runtime/map-exit-config.d.ts.map +1 -0
- package/dist/runtime/map-exit-config.js +91 -0
- package/dist/runtime/map-exit-config.js.map +1 -0
- package/dist/runtime/map-strategies-registration.d.ts +12 -0
- package/dist/runtime/map-strategies-registration.d.ts.map +1 -0
- package/dist/runtime/map-strategies-registration.js +52 -0
- package/dist/runtime/map-strategies-registration.js.map +1 -0
- package/dist/runtime/map-strategies.d.ts +12 -0
- package/dist/runtime/map-strategies.d.ts.map +1 -0
- package/dist/runtime/map-strategies.js +66 -0
- package/dist/runtime/map-strategies.js.map +1 -0
- package/dist/runtime/notifications.d.ts +12 -0
- package/dist/runtime/notifications.d.ts.map +1 -0
- package/dist/runtime/notifications.js +83 -0
- package/dist/runtime/notifications.js.map +1 -0
- package/dist/runtime/parse-interval.d.ts +11 -0
- package/dist/runtime/parse-interval.d.ts.map +1 -0
- package/dist/runtime/parse-interval.js +35 -0
- package/dist/runtime/parse-interval.js.map +1 -0
- package/dist/runtime/reconcile-state.d.ts +25 -0
- package/dist/runtime/reconcile-state.d.ts.map +1 -0
- package/dist/runtime/reconcile-state.js +112 -0
- package/dist/runtime/reconcile-state.js.map +1 -0
- package/dist/runtime/risk-guard.d.ts +6 -0
- package/dist/runtime/risk-guard.d.ts.map +1 -0
- package/dist/runtime/risk-guard.js +14 -0
- package/dist/runtime/risk-guard.js.map +1 -0
- package/dist/runtime/run.d.ts +21 -0
- package/dist/runtime/run.d.ts.map +1 -0
- package/dist/runtime/run.js +35 -0
- package/dist/runtime/run.js.map +1 -0
- package/dist/runtime/runtime.d.ts +40 -0
- package/dist/runtime/runtime.d.ts.map +1 -0
- package/dist/runtime/runtime.js +251 -0
- package/dist/runtime/runtime.js.map +1 -0
- package/dist/runtime/scanner-registry.d.ts +22 -0
- package/dist/runtime/scanner-registry.d.ts.map +1 -0
- package/dist/runtime/scanner-registry.js +83 -0
- package/dist/runtime/scanner-registry.js.map +1 -0
- package/dist/runtime/strategy-registry.d.ts +49 -0
- package/dist/runtime/strategy-registry.d.ts.map +1 -0
- package/dist/runtime/strategy-registry.js +156 -0
- package/dist/runtime/strategy-registry.js.map +1 -0
- package/dist/runtime/trading-strategy-config.d.ts +6 -0
- package/dist/runtime/trading-strategy-config.d.ts.map +1 -0
- package/dist/runtime/trading-strategy-config.js +5 -0
- package/dist/runtime/trading-strategy-config.js.map +1 -0
- package/dist/runtime/trading-strategy-schema.d.ts +20093 -0
- package/dist/runtime/trading-strategy-schema.d.ts.map +1 -0
- package/dist/runtime/trading-strategy-schema.js +115 -0
- package/dist/runtime/trading-strategy-schema.js.map +1 -0
- package/dist/scanners/__tests__/fixtures/index.d.ts +3 -0
- package/dist/scanners/__tests__/fixtures/index.d.ts.map +1 -0
- package/dist/scanners/__tests__/fixtures/index.js +3 -0
- package/dist/scanners/__tests__/fixtures/index.js.map +1 -0
- package/dist/scanners/__tests__/fixtures/scan-results.d.ts +23 -0
- package/dist/scanners/__tests__/fixtures/scan-results.d.ts.map +1 -0
- package/dist/scanners/__tests__/fixtures/scan-results.js +128 -0
- package/dist/scanners/__tests__/fixtures/scan-results.js.map +1 -0
- package/dist/scanners/__tests__/fixtures/signals.d.ts +18 -0
- package/dist/scanners/__tests__/fixtures/signals.d.ts.map +1 -0
- package/dist/scanners/__tests__/fixtures/signals.js +84 -0
- package/dist/scanners/__tests__/fixtures/signals.js.map +1 -0
- package/dist/scanners/__tests__/test-helpers.d.ts +4 -0
- package/dist/scanners/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/scanners/__tests__/test-helpers.js +23 -0
- package/dist/scanners/__tests__/test-helpers.js.map +1 -0
- package/dist/scanners/artifacts.d.ts +119 -0
- package/dist/scanners/artifacts.d.ts.map +1 -0
- package/dist/scanners/artifacts.js +72 -0
- package/dist/scanners/artifacts.js.map +1 -0
- package/dist/scanners/create-scanner.d.ts +13 -0
- package/dist/scanners/create-scanner.d.ts.map +1 -0
- package/dist/scanners/create-scanner.js +11 -0
- package/dist/scanners/create-scanner.js.map +1 -0
- package/dist/scanners/engine/config-validator.d.ts +7 -0
- package/dist/scanners/engine/config-validator.d.ts.map +1 -0
- package/dist/scanners/engine/config-validator.js +16 -0
- package/dist/scanners/engine/config-validator.js.map +1 -0
- package/dist/scanners/engine/data-providers.d.ts +47 -0
- package/dist/scanners/engine/data-providers.d.ts.map +1 -0
- package/dist/scanners/engine/data-providers.js +8 -0
- package/dist/scanners/engine/data-providers.js.map +1 -0
- package/dist/scanners/engine/engine.d.ts +76 -0
- package/dist/scanners/engine/engine.d.ts.map +1 -0
- package/dist/scanners/engine/engine.js +399 -0
- package/dist/scanners/engine/engine.js.map +1 -0
- package/dist/scanners/engine/index.d.ts +9 -0
- package/dist/scanners/engine/index.d.ts.map +1 -0
- package/dist/scanners/engine/index.js +7 -0
- package/dist/scanners/engine/index.js.map +1 -0
- package/dist/scanners/engine/input-resolver.d.ts +21 -0
- package/dist/scanners/engine/input-resolver.d.ts.map +1 -0
- package/dist/scanners/engine/input-resolver.js +149 -0
- package/dist/scanners/engine/input-resolver.js.map +1 -0
- package/dist/scanners/engine/lifecycle.d.ts +21 -0
- package/dist/scanners/engine/lifecycle.d.ts.map +1 -0
- package/dist/scanners/engine/lifecycle.js +2 -0
- package/dist/scanners/engine/lifecycle.js.map +1 -0
- package/dist/scanners/engine/result-builder.d.ts +30 -0
- package/dist/scanners/engine/result-builder.d.ts.map +1 -0
- package/dist/scanners/engine/result-builder.js +129 -0
- package/dist/scanners/engine/result-builder.js.map +1 -0
- package/dist/scanners/engine/strategy-registry.d.ts +45 -0
- package/dist/scanners/engine/strategy-registry.d.ts.map +1 -0
- package/dist/scanners/engine/strategy-registry.js +93 -0
- package/dist/scanners/engine/strategy-registry.js.map +1 -0
- package/dist/scanners/events.d.ts +41 -0
- package/dist/scanners/events.d.ts.map +1 -0
- package/dist/scanners/events.js +33 -0
- package/dist/scanners/events.js.map +1 -0
- package/dist/scanners/implementations/emerging-movers.d.ts +215 -0
- package/dist/scanners/implementations/emerging-movers.d.ts.map +1 -0
- package/dist/scanners/implementations/emerging-movers.js +709 -0
- package/dist/scanners/implementations/emerging-movers.js.map +1 -0
- package/dist/scanners/implementations/index.d.ts +8 -0
- package/dist/scanners/implementations/index.d.ts.map +1 -0
- package/dist/scanners/implementations/index.js +8 -0
- package/dist/scanners/implementations/index.js.map +1 -0
- package/dist/scanners/implementations/indicators.d.ts +40 -0
- package/dist/scanners/implementations/indicators.d.ts.map +1 -0
- package/dist/scanners/implementations/indicators.js +114 -0
- package/dist/scanners/implementations/indicators.js.map +1 -0
- package/dist/scanners/implementations/liquidation-watchdog.d.ts +74 -0
- package/dist/scanners/implementations/liquidation-watchdog.d.ts.map +1 -0
- package/dist/scanners/implementations/liquidation-watchdog.js +268 -0
- package/dist/scanners/implementations/liquidation-watchdog.js.map +1 -0
- package/dist/scanners/implementations/market-regime.d.ts +52 -0
- package/dist/scanners/implementations/market-regime.d.ts.map +1 -0
- package/dist/scanners/implementations/market-regime.js +201 -0
- package/dist/scanners/implementations/market-regime.js.map +1 -0
- package/dist/scanners/implementations/momentum.d.ts +21 -0
- package/dist/scanners/implementations/momentum.d.ts.map +1 -0
- package/dist/scanners/implementations/momentum.js +128 -0
- package/dist/scanners/implementations/momentum.js.map +1 -0
- package/dist/scanners/implementations/oi-tracker.d.ts +13 -0
- package/dist/scanners/implementations/oi-tracker.d.ts.map +1 -0
- package/dist/scanners/implementations/oi-tracker.js +67 -0
- package/dist/scanners/implementations/oi-tracker.js.map +1 -0
- package/dist/scanners/implementations/opportunity.d.ts +104 -0
- package/dist/scanners/implementations/opportunity.d.ts.map +1 -0
- package/dist/scanners/implementations/opportunity.js +441 -0
- package/dist/scanners/implementations/opportunity.js.map +1 -0
- package/dist/scanners/implementations/prescreener.d.ts +20 -0
- package/dist/scanners/implementations/prescreener.d.ts.map +1 -0
- package/dist/scanners/implementations/prescreener.js +97 -0
- package/dist/scanners/implementations/prescreener.js.map +1 -0
- package/dist/scanners/implementations/sm-flip.d.ts +43 -0
- package/dist/scanners/implementations/sm-flip.d.ts.map +1 -0
- package/dist/scanners/implementations/sm-flip.js +200 -0
- package/dist/scanners/implementations/sm-flip.js.map +1 -0
- package/dist/scanners/index.d.ts +25 -0
- package/dist/scanners/index.d.ts.map +1 -0
- package/dist/scanners/index.js +18 -0
- package/dist/scanners/index.js.map +1 -0
- package/dist/scanners/input-descriptors.d.ts +61 -0
- package/dist/scanners/input-descriptors.d.ts.map +1 -0
- package/dist/scanners/input-descriptors.js +43 -0
- package/dist/scanners/input-descriptors.js.map +1 -0
- package/dist/scanners/protocol/context.d.ts +75 -0
- package/dist/scanners/protocol/context.d.ts.map +1 -0
- package/dist/scanners/protocol/context.js +2 -0
- package/dist/scanners/protocol/context.js.map +1 -0
- package/dist/scanners/protocol/hooks.d.ts +18 -0
- package/dist/scanners/protocol/hooks.d.ts.map +1 -0
- package/dist/scanners/protocol/hooks.js +12 -0
- package/dist/scanners/protocol/hooks.js.map +1 -0
- package/dist/scanners/protocol/index.d.ts +5 -0
- package/dist/scanners/protocol/index.d.ts.map +1 -0
- package/dist/scanners/protocol/index.js +2 -0
- package/dist/scanners/protocol/index.js.map +1 -0
- package/dist/scanners/protocol/scanner.d.ts +47 -0
- package/dist/scanners/protocol/scanner.d.ts.map +1 -0
- package/dist/scanners/protocol/scanner.js +2 -0
- package/dist/scanners/protocol/scanner.js.map +1 -0
- package/dist/scanners/providers/adapter.d.ts +23 -0
- package/dist/scanners/providers/adapter.d.ts.map +1 -0
- package/dist/scanners/providers/adapter.js +227 -0
- package/dist/scanners/providers/adapter.js.map +1 -0
- package/dist/scanners/providers/cache.d.ts +20 -0
- package/dist/scanners/providers/cache.d.ts.map +1 -0
- package/dist/scanners/providers/cache.js +61 -0
- package/dist/scanners/providers/cache.js.map +1 -0
- package/dist/scanners/providers/client.d.ts +53 -0
- package/dist/scanners/providers/client.d.ts.map +1 -0
- package/dist/scanners/providers/client.js +174 -0
- package/dist/scanners/providers/client.js.map +1 -0
- package/dist/scanners/providers/factory.d.ts +43 -0
- package/dist/scanners/providers/factory.d.ts.map +1 -0
- package/dist/scanners/providers/factory.js +192 -0
- package/dist/scanners/providers/factory.js.map +1 -0
- package/dist/scanners/providers/types.d.ts +61 -0
- package/dist/scanners/providers/types.d.ts.map +1 -0
- package/dist/scanners/providers/types.js +6 -0
- package/dist/scanners/providers/types.js.map +1 -0
- package/dist/scanners/runtime-module.d.ts +54 -0
- package/dist/scanners/runtime-module.d.ts.map +1 -0
- package/dist/scanners/runtime-module.js +90 -0
- package/dist/scanners/runtime-module.js.map +1 -0
- package/dist/scanners/scanner-definition.d.ts +58 -0
- package/dist/scanners/scanner-definition.d.ts.map +1 -0
- package/dist/scanners/scanner-definition.js +19 -0
- package/dist/scanners/scanner-definition.js.map +1 -0
- package/dist/scanners/schema-utils.d.ts +6 -0
- package/dist/scanners/schema-utils.d.ts.map +1 -0
- package/dist/scanners/schema-utils.js +14 -0
- package/dist/scanners/schema-utils.js.map +1 -0
- package/dist/scanners/score-utils.d.ts +19 -0
- package/dist/scanners/score-utils.d.ts.map +1 -0
- package/dist/scanners/score-utils.js +47 -0
- package/dist/scanners/score-utils.js.map +1 -0
- package/dist/scanners/store/fs-utils.d.ts +12 -0
- package/dist/scanners/store/fs-utils.d.ts.map +1 -0
- package/dist/scanners/store/fs-utils.js +47 -0
- package/dist/scanners/store/fs-utils.js.map +1 -0
- package/dist/scanners/store/index.d.ts +5 -0
- package/dist/scanners/store/index.d.ts.map +1 -0
- package/dist/scanners/store/index.js +5 -0
- package/dist/scanners/store/index.js.map +1 -0
- package/dist/scanners/store/runtime-store.d.ts +50 -0
- package/dist/scanners/store/runtime-store.d.ts.map +1 -0
- package/dist/scanners/store/runtime-store.js +91 -0
- package/dist/scanners/store/runtime-store.js.map +1 -0
- package/dist/scanners/store/shared-artifact-store.d.ts +31 -0
- package/dist/scanners/store/shared-artifact-store.d.ts.map +1 -0
- package/dist/scanners/store/shared-artifact-store.js +89 -0
- package/dist/scanners/store/shared-artifact-store.js.map +1 -0
- package/dist/scanners/store/signal-store.d.ts +36 -0
- package/dist/scanners/store/signal-store.d.ts.map +1 -0
- package/dist/scanners/store/signal-store.js +135 -0
- package/dist/scanners/store/signal-store.js.map +1 -0
- package/dist/scanners/types.d.ts +115 -0
- package/dist/scanners/types.d.ts.map +1 -0
- package/dist/scanners/types.js +3 -0
- package/dist/scanners/types.js.map +1 -0
- package/dist/scripts/run-dsl-standalone-live.d.ts +27 -0
- package/dist/scripts/run-dsl-standalone-live.d.ts.map +1 -0
- package/dist/scripts/run-dsl-standalone-live.js +207 -0
- package/dist/scripts/run-dsl-standalone-live.js.map +1 -0
- package/dist/scripts/run-dsl-standalone-mock.d.ts +13 -0
- package/dist/scripts/run-dsl-standalone-mock.d.ts.map +1 -0
- package/dist/scripts/run-dsl-standalone-mock.js +255 -0
- package/dist/scripts/run-dsl-standalone-mock.js.map +1 -0
- package/dist/senpi/client.d.ts +77 -0
- package/dist/senpi/client.d.ts.map +1 -0
- package/dist/senpi/client.js +523 -0
- package/dist/senpi/client.js.map +1 -0
- package/dist/senpi/constants.d.ts +7 -0
- package/dist/senpi/constants.d.ts.map +1 -0
- package/dist/senpi/constants.js +7 -0
- package/dist/senpi/constants.js.map +1 -0
- package/dist/senpi/index.d.ts +3 -0
- package/dist/senpi/index.d.ts.map +1 -0
- package/dist/senpi/index.js +2 -0
- package/dist/senpi/index.js.map +1 -0
- package/dist/senpi/types.d.ts +132 -0
- package/dist/senpi/types.d.ts.map +1 -0
- package/dist/senpi/types.js +3 -0
- package/dist/senpi/types.js.map +1 -0
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +3 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/paths.d.ts +8 -0
- package/dist/state/paths.d.ts.map +1 -0
- package/dist/state/paths.js +19 -0
- package/dist/state/paths.js.map +1 -0
- package/dist/state/state-manager.d.ts +58 -0
- package/dist/state/state-manager.d.ts.map +1 -0
- package/dist/state/state-manager.js +221 -0
- package/dist/state/state-manager.js.map +1 -0
- package/dist/strategy/index.d.ts +2 -0
- package/dist/strategy/index.d.ts.map +1 -0
- package/dist/strategy/index.js +2 -0
- package/dist/strategy/index.js.map +1 -0
- package/dist/strategy/strategy-state.d.ts +48 -0
- package/dist/strategy/strategy-state.d.ts.map +1 -0
- package/dist/strategy/strategy-state.js +185 -0
- package/dist/strategy/strategy-state.js.map +1 -0
- package/dist/types/action.d.ts +15 -0
- package/dist/types/action.d.ts.map +1 -0
- package/dist/types/action.js +2 -0
- package/dist/types/action.js.map +1 -0
- package/dist/types/dsl/index.d.ts +215 -0
- package/dist/types/dsl/index.d.ts.map +1 -0
- package/dist/types/dsl/index.js +5 -0
- package/dist/types/dsl/index.js.map +1 -0
- package/dist/types/event-bus.d.ts +11 -0
- package/dist/types/event-bus.d.ts.map +1 -0
- package/dist/types/event-bus.js +6 -0
- package/dist/types/event-bus.js.map +1 -0
- package/dist/types/hooks.d.ts +27 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +15 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/notification.d.ts +4 -0
- package/dist/types/notification.d.ts.map +1 -0
- package/dist/types/notification.js +3 -0
- package/dist/types/notification.js.map +1 -0
- package/dist/types/runtime.d.ts +18 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/runtime.js +2 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/scanner.d.ts +59 -0
- package/dist/types/scanner.d.ts.map +1 -0
- package/dist/types/scanner.js +13 -0
- package/dist/types/scanner.js.map +1 -0
- package/dist/types/strategy.d.ts +100 -0
- package/dist/types/strategy.d.ts.map +1 -0
- package/dist/types/strategy.js +2 -0
- package/dist/types/strategy.js.map +1 -0
- package/dist/utils/logger/dsl.d.ts +8 -0
- package/dist/utils/logger/dsl.d.ts.map +1 -0
- package/dist/utils/logger/dsl.js +7 -0
- package/dist/utils/logger/dsl.js.map +1 -0
- package/dist/utils/logger.d.ts +13 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +65 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/response.d.ts +14 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +44 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/examples/.env.example +15 -0
- package/examples/README.md +75 -0
- package/examples/scanners-consumer-quickstart.mjs +134 -0
- package/examples/scanners-emerging-movers-v4.mjs +285 -0
- package/examples/scanners-liquidation-watchdog.mjs +331 -0
- package/examples/scanners-live-mcp.mjs +208 -0
- package/examples/scanners-multi-strategy.mjs +165 -0
- package/examples/scanners-scheduled-events.mjs +95 -0
- package/examples/scanners-senpi-provider-client.mjs +182 -0
- package/examples/scanners-single-strategy.mjs +198 -0
- package/examples/strategies/README.md +45 -0
- package/examples/strategies/dsl-showcase.yaml +60 -0
- package/examples/strategies/fox-minimal-loosened.yaml +201 -0
- package/examples/strategies/fox-minimal.yaml +209 -0
- package/examples/strategies/minimal.yaml +49 -0
- package/examples/strategies/viper.yaml +64 -0
- package/examples/strategies/wolf.yaml +62 -0
- package/examples/yamls/sample-with-dsl-and-emerging-movers.yaml +116 -0
- package/openclaw.plugin.json +15 -0
- package/package.json +52 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emerging-movers v4 — signal detection showcase
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the five signal types detected by the emerging-movers scanner
|
|
5
|
+
* using a simulated 50-token SM leaderboard that evolves over 4 scans:
|
|
6
|
+
*
|
|
7
|
+
* Scan 1: baseline (warm-up, no signals emitted)
|
|
8
|
+
* Scan 2: FIRST_JUMP (WIF rockets from #45 to #3),
|
|
9
|
+
* CONTRIB_EXPLOSION (ONDO goes 4x contribution),
|
|
10
|
+
* NEW_ENTRY_DEEP (PENDLE appears at #8)
|
|
11
|
+
* Scan 3: IMMEDIATE_MOVER (JUP jumps 15 ranks from #28),
|
|
12
|
+
* DEEP_CLIMBER (RENDER climbs 6 ranks from #32)
|
|
13
|
+
* Scan 4: climb streak + multi-scan climbing for tokens that kept improving
|
|
14
|
+
*
|
|
15
|
+
* Run:
|
|
16
|
+
* npm run build && node examples/scanners-emerging-movers-v4.mjs
|
|
17
|
+
*/
|
|
18
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
19
|
+
import { tmpdir } from "node:os";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import {
|
|
22
|
+
createScannerRuntimeModule,
|
|
23
|
+
emergingMoversScanner,
|
|
24
|
+
} from "../dist/scanners/index.js";
|
|
25
|
+
|
|
26
|
+
// ─── Simulated SM leaderboard ───────────────────────────────────────────────
|
|
27
|
+
// 50 tokens with realistic contribution and trader distributions. Specific
|
|
28
|
+
// tokens are manipulated across scans to trigger each v4 signal type.
|
|
29
|
+
|
|
30
|
+
function makeBaseLeaderboard() {
|
|
31
|
+
const tokens = [
|
|
32
|
+
"BTC", "ETH", "SOL", "DOGE", "PEPE", "AVAX", "LINK", "MATIC",
|
|
33
|
+
"ARB", "OP", "SUI", "APT", "INJ", "TIA", "SEI", "NEAR",
|
|
34
|
+
"FTM", "ATOM", "DOT", "ADA", "XRP", "BNB", "UNI", "AAVE",
|
|
35
|
+
"MKR", "LDO", "CRV", "SNX", "COMP", "ONDO", "WIF", "JUP",
|
|
36
|
+
"RENDER", "FET", "RNDR", "PYTH", "JTO", "STRK", "MANTA", "DYM",
|
|
37
|
+
"PIXEL", "PORTAL", "ETHFI", "W", "ENA", "BOME", "SLERF", "MEW",
|
|
38
|
+
"MYRO", "BONK",
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
return tokens.map((token, i) => ({
|
|
42
|
+
token,
|
|
43
|
+
direction: "up",
|
|
44
|
+
// Contribution decreases roughly linearly; top tokens dominate
|
|
45
|
+
pctOfTopTradersGain: Math.max(0.001, 0.50 - i * 0.009),
|
|
46
|
+
traderCount: Math.max(10, 500 - i * 8),
|
|
47
|
+
tokenPriceChangePct4h: Math.max(-2, 8 - i * 0.3),
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Scan 1: Baseline snapshot. Scanner warms up (no signals emitted). */
|
|
52
|
+
function scan1() {
|
|
53
|
+
return makeBaseLeaderboard();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Scan 2: Three dramatic events.
|
|
58
|
+
* - WIF (was #31, contrib 0.230) rockets to massive contribution → lands ~#3
|
|
59
|
+
* - ONDO (was #30, contrib 0.239) goes 4x contribution → CONTRIB_EXPLOSION
|
|
60
|
+
* - PENDLE (new token, wasn't in scan 1) appears with high contribution → NEW_ENTRY_DEEP
|
|
61
|
+
*/
|
|
62
|
+
function scan2() {
|
|
63
|
+
const board = makeBaseLeaderboard();
|
|
64
|
+
|
|
65
|
+
// WIF: was at index 30 (rank ~31). Boost contribution so it sorts to ~rank 3.
|
|
66
|
+
// Also: WIF was ranked 31 (>= firstJumpMinPrevRank=30), triggering FIRST_JUMP.
|
|
67
|
+
const wif = board.find((m) => m.token === "WIF");
|
|
68
|
+
wif.pctOfTopTradersGain = 0.48;
|
|
69
|
+
wif.traderCount = 420;
|
|
70
|
+
wif.tokenPriceChangePct4h = 15.2;
|
|
71
|
+
|
|
72
|
+
// ONDO: was at index 29 (rank ~30). 4x its contribution for CONTRIB_EXPLOSION.
|
|
73
|
+
const ondo = board.find((m) => m.token === "ONDO");
|
|
74
|
+
ondo.pctOfTopTradersGain = ondo.pctOfTopTradersGain * 4.5;
|
|
75
|
+
ondo.traderCount = 310;
|
|
76
|
+
ondo.tokenPriceChangePct4h = 9.1;
|
|
77
|
+
|
|
78
|
+
// JUP: boost in scan 2 so it lands ~rank 26–29 (between deepClimbRankThreshold
|
|
79
|
+
// and firstJumpMinPrevRank). This sets up scan 3's IMMEDIATE_MOVER — prevRank
|
|
80
|
+
// will be >= 25 (qualifies as deep) but < 30 (not deep enough for FIRST_JUMP).
|
|
81
|
+
const jup = board.find((m) => m.token === "JUP");
|
|
82
|
+
jup.pctOfTopTradersGain = 0.28;
|
|
83
|
+
jup.traderCount = 260;
|
|
84
|
+
|
|
85
|
+
// PENDLE: replace a low-ranked filler token so PENDLE appears fresh.
|
|
86
|
+
const pendle = board.findIndex((m) => m.token === "BONK");
|
|
87
|
+
board[pendle] = {
|
|
88
|
+
token: "PENDLE",
|
|
89
|
+
direction: "up",
|
|
90
|
+
pctOfTopTradersGain: 0.42,
|
|
91
|
+
traderCount: 280,
|
|
92
|
+
tokenPriceChangePct4h: 7.8,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return board;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Scan 3: Rank-based signals.
|
|
100
|
+
* - JUP jumps 15+ ranks from ~#27 → IMMEDIATE_MOVER (not FIRST_JUMP because prevRank < 30)
|
|
101
|
+
* - RENDER climbs 6 ranks from deep → DEEP_CLIMBER
|
|
102
|
+
* - PENDLE continues climbing slightly (building streak history)
|
|
103
|
+
*/
|
|
104
|
+
function scan3() {
|
|
105
|
+
const board = makeBaseLeaderboard();
|
|
106
|
+
|
|
107
|
+
// Keep WIF high (now a returning token, not a first jump)
|
|
108
|
+
const wif = board.find((m) => m.token === "WIF");
|
|
109
|
+
wif.pctOfTopTradersGain = 0.46;
|
|
110
|
+
wif.traderCount = 400;
|
|
111
|
+
|
|
112
|
+
// ONDO settles back a bit (no longer 4x, so no explosion this scan)
|
|
113
|
+
const ondo = board.find((m) => m.token === "ONDO");
|
|
114
|
+
ondo.pctOfTopTradersGain = 0.35;
|
|
115
|
+
|
|
116
|
+
// PENDLE still present, climbing a bit
|
|
117
|
+
const pendle = board.findIndex((m) => m.token === "BONK");
|
|
118
|
+
board[pendle] = {
|
|
119
|
+
token: "PENDLE",
|
|
120
|
+
direction: "up",
|
|
121
|
+
pctOfTopTradersGain: 0.43,
|
|
122
|
+
traderCount: 290,
|
|
123
|
+
tokenPriceChangePct4h: 6.5,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// In scan 2, JUP was at its default position (index 31, contrib ~0.221).
|
|
127
|
+
// After sorting in scan 2 (with WIF and ONDO boosted), JUP lands around rank ~27.
|
|
128
|
+
// Here we give JUP a contribution that sorts it to ~rank 10, a jump of 15+.
|
|
129
|
+
// prevRank ~27 is >= deepClimbRankThreshold (25) but < firstJumpMinPrevRank (30),
|
|
130
|
+
// so it qualifies as IMMEDIATE_MOVER, not FIRST_JUMP.
|
|
131
|
+
const jup = board.find((m) => m.token === "JUP");
|
|
132
|
+
jup.pctOfTopTradersGain = 0.44;
|
|
133
|
+
jup.traderCount = 350;
|
|
134
|
+
jup.tokenPriceChangePct4h = 11.0;
|
|
135
|
+
|
|
136
|
+
// RENDER: was at index 32 (rank ~33). Moderate boost for DEEP_CLIMBER.
|
|
137
|
+
const render = board.find((m) => m.token === "RENDER");
|
|
138
|
+
render.pctOfTopTradersGain = 0.30;
|
|
139
|
+
render.traderCount = 240;
|
|
140
|
+
render.tokenPriceChangePct4h = 5.3;
|
|
141
|
+
|
|
142
|
+
return board;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Scan 4: Sustained climbing.
|
|
147
|
+
* - RENDER continues climbing → STREAK signal
|
|
148
|
+
* - PENDLE continues climbing → multi-scan CLIMBING detection
|
|
149
|
+
*/
|
|
150
|
+
function scan4() {
|
|
151
|
+
const board = makeBaseLeaderboard();
|
|
152
|
+
|
|
153
|
+
// WIF, ONDO, JUP remain high but stable
|
|
154
|
+
const wif = board.find((m) => m.token === "WIF");
|
|
155
|
+
wif.pctOfTopTradersGain = 0.45;
|
|
156
|
+
const ondo = board.find((m) => m.token === "ONDO");
|
|
157
|
+
ondo.pctOfTopTradersGain = 0.34;
|
|
158
|
+
const jup = board.find((m) => m.token === "JUP");
|
|
159
|
+
jup.pctOfTopTradersGain = 0.43;
|
|
160
|
+
|
|
161
|
+
// PENDLE keeps climbing
|
|
162
|
+
const pendle = board.findIndex((m) => m.token === "BONK");
|
|
163
|
+
board[pendle] = {
|
|
164
|
+
token: "PENDLE",
|
|
165
|
+
direction: "up",
|
|
166
|
+
pctOfTopTradersGain: 0.45,
|
|
167
|
+
traderCount: 310,
|
|
168
|
+
tokenPriceChangePct4h: 8.2,
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// RENDER continues improving
|
|
172
|
+
const render = board.find((m) => m.token === "RENDER");
|
|
173
|
+
render.pctOfTopTradersGain = 0.36;
|
|
174
|
+
render.traderCount = 270;
|
|
175
|
+
render.tokenPriceChangePct4h = 6.8;
|
|
176
|
+
|
|
177
|
+
return board;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// ─── Main ───────────────────────────────────────────────────────────────────
|
|
181
|
+
|
|
182
|
+
const SCAN_DATA = [scan1, scan2, scan3, scan4];
|
|
183
|
+
|
|
184
|
+
async function main() {
|
|
185
|
+
const stateDir = await mkdtemp(join(tmpdir(), "emerging-movers-v4-"));
|
|
186
|
+
let scanIndex = 0;
|
|
187
|
+
|
|
188
|
+
const module = createScannerRuntimeModule({
|
|
189
|
+
stateDir,
|
|
190
|
+
scanners: [emergingMoversScanner],
|
|
191
|
+
strategies: [
|
|
192
|
+
{
|
|
193
|
+
id: "wolf",
|
|
194
|
+
name: "Wolf Strategy",
|
|
195
|
+
scannerOverrides: {
|
|
196
|
+
"emerging-movers": {
|
|
197
|
+
config: {
|
|
198
|
+
// Production-like v4 configuration
|
|
199
|
+
topN: 50,
|
|
200
|
+
minRankJump: 5,
|
|
201
|
+
minTopTradersGain: 0.01,
|
|
202
|
+
minScansBeforeSignals: 2,
|
|
203
|
+
historyLimit: 60,
|
|
204
|
+
immediateJumpThreshold: 10,
|
|
205
|
+
deepClimbRankThreshold: 25,
|
|
206
|
+
contribExplosionMultiplier: 3.0,
|
|
207
|
+
contribAccelThreshold: 0.003,
|
|
208
|
+
minVelocityForDeepClimber: 0.0003,
|
|
209
|
+
erraticReversalThreshold: 5,
|
|
210
|
+
climbStreakScans: 3,
|
|
211
|
+
rankClimbThreshold: 3,
|
|
212
|
+
newEntryDeepMaxRank: 20,
|
|
213
|
+
newEntryMaxRank: 35,
|
|
214
|
+
firstJumpMinPrevRank: 30,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
providers: {
|
|
221
|
+
getSmData: async () => {
|
|
222
|
+
const data = SCAN_DATA[scanIndex]();
|
|
223
|
+
scanIndex++;
|
|
224
|
+
return data;
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
for (let i = 0; i < SCAN_DATA.length; i++) {
|
|
231
|
+
const result = await module.runOnce("wolf", "emerging-movers");
|
|
232
|
+
console.log(`\n── Scan ${i + 1} ──────────────────────────────────────`);
|
|
233
|
+
console.log(`Status: ${result.status} | Scanned: ${result.scannedCount} | Signals: ${result.signals.length}`);
|
|
234
|
+
|
|
235
|
+
if (result.signals.length === 0) {
|
|
236
|
+
console.log("(warm-up scan — no signals yet)");
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
for (const signal of result.signals) {
|
|
241
|
+
const m = signal.meta;
|
|
242
|
+
console.log(
|
|
243
|
+
` [${signal.signalType}] ${signal.asset}`,
|
|
244
|
+
`| score=${signal.score}`,
|
|
245
|
+
`| rank=#${m.rank}`,
|
|
246
|
+
`| prev=#${m.prevRank ?? "new"}`,
|
|
247
|
+
`| jump=${m.jump}`,
|
|
248
|
+
`| vel=${m.contribVelocity}`,
|
|
249
|
+
);
|
|
250
|
+
console.log(` reasons: ${(m.reasons).join(", ")}`);
|
|
251
|
+
|
|
252
|
+
const activeFactors = Object.entries(signal.factors)
|
|
253
|
+
.filter(([, v]) => v)
|
|
254
|
+
.map(([k]) => k);
|
|
255
|
+
if (activeFactors.length > 0) {
|
|
256
|
+
console.log(` factors: ${activeFactors.join(", ")}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Print summary breakdown
|
|
261
|
+
const bd = result.summary.signalBreakdown;
|
|
262
|
+
const counts = Object.entries(bd).filter(([, v]) => v > 0);
|
|
263
|
+
if (counts.length > 0) {
|
|
264
|
+
console.log(` summary: ${counts.map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Query all persisted signals
|
|
269
|
+
const allSignals = await module.querySignals({ strategyId: "wolf", limit: 50 });
|
|
270
|
+
console.log(`\n── Total persisted signals: ${allSignals.length} ──`);
|
|
271
|
+
const byType = {};
|
|
272
|
+
for (const s of allSignals) {
|
|
273
|
+
byType[s.signalType] = (byType[s.signalType] || 0) + 1;
|
|
274
|
+
}
|
|
275
|
+
console.log("By type:", byType);
|
|
276
|
+
} finally {
|
|
277
|
+
await module.stop();
|
|
278
|
+
await rm(stateDir, { recursive: true, force: true });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
main().catch((error) => {
|
|
283
|
+
console.error(error);
|
|
284
|
+
process.exit(1);
|
|
285
|
+
});
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Liquidation-watchdog scanner e2e examples.
|
|
3
|
+
*
|
|
4
|
+
* Run: node examples/scanners-liquidation-watchdog.mjs
|
|
5
|
+
*
|
|
6
|
+
* Two scenarios:
|
|
7
|
+
* 1. Without DSL states — scanner operates with margin/liq checks only.
|
|
8
|
+
* 2. With DSL states — scanner enriches liq-distance alerts with DSL floor info.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import {
|
|
15
|
+
createScannerRuntimeModule,
|
|
16
|
+
liquidationWatchdogScanner,
|
|
17
|
+
} from "../dist/scanners/index.js";
|
|
18
|
+
import { StateManager } from "../dist/state/index.js";
|
|
19
|
+
|
|
20
|
+
// ─── Shared fixtures ────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
function makeClearingHouseState({ bufferPct, positions }) {
|
|
23
|
+
// bufferPct controls how much margin room is left:
|
|
24
|
+
// buffer = (accountValue - crossMaintenanceMargin) / accountValue * 100
|
|
25
|
+
// → crossMaintenanceMargin = accountValue * (1 - bufferPct / 100)
|
|
26
|
+
const accountValue = 10_000;
|
|
27
|
+
const crossMaintenanceMargin = accountValue * (1 - bufferPct / 100);
|
|
28
|
+
return {
|
|
29
|
+
accountValue,
|
|
30
|
+
totalMarginUsed: crossMaintenanceMargin,
|
|
31
|
+
crossMaintenanceMargin,
|
|
32
|
+
availableBalance: accountValue - crossMaintenanceMargin,
|
|
33
|
+
positions: positions ?? [],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makePosition({ asset, direction, markPrice, liqPrice, roe, marginType }) {
|
|
38
|
+
return {
|
|
39
|
+
asset,
|
|
40
|
+
direction: direction ?? "LONG",
|
|
41
|
+
size: 1,
|
|
42
|
+
entryPrice: markPrice * 0.95,
|
|
43
|
+
markPrice,
|
|
44
|
+
liquidationPrice: liqPrice ?? null,
|
|
45
|
+
unrealizedPnl: markPrice * 0.05,
|
|
46
|
+
roe: roe ?? 5,
|
|
47
|
+
leverage: 5,
|
|
48
|
+
marginType: marginType ?? "cross",
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─── Scenario 1: Without DSL states ─────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
async function scenarioWithoutDslStates() {
|
|
55
|
+
console.log("\n=== Scenario 1: Without DSL states ===\n");
|
|
56
|
+
|
|
57
|
+
const stateDir = await mkdtemp(join(tmpdir(), "watchdog-no-dsl-"));
|
|
58
|
+
|
|
59
|
+
// Two runs: first healthy, second critical
|
|
60
|
+
let run = 0;
|
|
61
|
+
const clearingHouseRuns = [
|
|
62
|
+
// Run 1: healthy — 80% buffer, positions far from liq
|
|
63
|
+
makeClearingHouseState({
|
|
64
|
+
bufferPct: 80,
|
|
65
|
+
positions: [
|
|
66
|
+
makePosition({ asset: "BTC", markPrice: 60000, liqPrice: 20000, roe: 12 }),
|
|
67
|
+
makePosition({ asset: "ETH", markPrice: 3000, liqPrice: 1000, roe: 8 }),
|
|
68
|
+
],
|
|
69
|
+
}),
|
|
70
|
+
// Run 2: critical — 20% buffer, one position with bad ROE and tight liq
|
|
71
|
+
makeClearingHouseState({
|
|
72
|
+
bufferPct: 20,
|
|
73
|
+
positions: [
|
|
74
|
+
makePosition({ asset: "BTC", markPrice: 60000, liqPrice: 20000, roe: 5 }),
|
|
75
|
+
makePosition({ asset: "ETH", markPrice: 3000, liqPrice: 2700, roe: -25, marginType: "cross" }),
|
|
76
|
+
],
|
|
77
|
+
}),
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const module = createScannerRuntimeModule({
|
|
81
|
+
stateDir,
|
|
82
|
+
scanners: [liquidationWatchdogScanner],
|
|
83
|
+
strategies: [
|
|
84
|
+
{
|
|
85
|
+
id: "wallet-001",
|
|
86
|
+
name: "Trader-A",
|
|
87
|
+
scannerOverrides: {
|
|
88
|
+
"liquidation-watchdog": {
|
|
89
|
+
config: {
|
|
90
|
+
bufferWarningPct: 50,
|
|
91
|
+
bufferCriticalPct: 30,
|
|
92
|
+
liqDistanceWarningPct: 30,
|
|
93
|
+
liqDistanceIsolatedWarningPct: 15,
|
|
94
|
+
roeDangerPct: -15,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
providers: {
|
|
101
|
+
getClearingHouseState: async () => clearingHouseRuns[Math.min(run, clearingHouseRuns.length - 1)],
|
|
102
|
+
getActivePositions: async () => [],
|
|
103
|
+
getInstruments: async () => [],
|
|
104
|
+
// No getDslStatesForStrategy — scanner should handle gracefully
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
// Run 1: healthy
|
|
110
|
+
run = 0;
|
|
111
|
+
const result1 = await module.runOnce("wallet-001", "liquidation-watchdog");
|
|
112
|
+
console.log("Run 1 (healthy):");
|
|
113
|
+
console.log(" scannedCount:", result1.scannedCount);
|
|
114
|
+
console.log(" signals:", result1.signals.length);
|
|
115
|
+
console.log(" summary.marginBuffer:", result1.summary.marginBuffer);
|
|
116
|
+
console.log(" summary.alertCount:", result1.summary.alertCount);
|
|
117
|
+
console.log(" summary.consecutiveCleanChecks:", result1.summary.consecutiveCleanChecks);
|
|
118
|
+
console.assert(result1.signals.length === 0, "Expected 0 signals for healthy state");
|
|
119
|
+
console.assert(result1.summary.consecutiveCleanChecks === 1, "Expected 1 clean check");
|
|
120
|
+
|
|
121
|
+
// Run 2: critical buffer + tight liq + bad ROE
|
|
122
|
+
run = 1;
|
|
123
|
+
const result2 = await module.runOnce("wallet-001", "liquidation-watchdog");
|
|
124
|
+
console.log("\nRun 2 (critical):");
|
|
125
|
+
console.log(" scannedCount:", result2.scannedCount);
|
|
126
|
+
console.log(" signals:", result2.signals.length);
|
|
127
|
+
console.log(" summary.marginBuffer:", result2.summary.marginBuffer);
|
|
128
|
+
console.log(" summary.alertCount:", result2.summary.alertCount);
|
|
129
|
+
console.log(" summary.consecutiveCleanChecks:", result2.summary.consecutiveCleanChecks);
|
|
130
|
+
|
|
131
|
+
const closeSignals = result2.signals.filter((s) => s.signalType === "WATCHDOG_CLOSE");
|
|
132
|
+
const alertSignals = result2.signals.filter((s) => s.signalType === "WATCHDOG_ALERT");
|
|
133
|
+
console.log(" WATCHDOG_CLOSE signals:", closeSignals.length);
|
|
134
|
+
console.log(" WATCHDOG_ALERT signals:", alertSignals.length);
|
|
135
|
+
|
|
136
|
+
if (closeSignals.length > 0) {
|
|
137
|
+
console.log(" Close target asset:", closeSignals[0].asset, "(lowest ROE)");
|
|
138
|
+
console.log(" Close meta:", JSON.stringify(closeSignals[0].meta, null, 2));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Verify no alert message contains "DSL floor" since no DSL states were provided
|
|
142
|
+
const allMessages = alertSignals.map((s) => s.meta.message);
|
|
143
|
+
const hasDslFloorNote = allMessages.some((m) => typeof m === "string" && m.includes("DSL floor"));
|
|
144
|
+
console.assert(!hasDslFloorNote, "Expected no DSL floor notes without dslStates provider");
|
|
145
|
+
console.assert(closeSignals.length >= 1, "Expected at least 1 WATCHDOG_CLOSE signal");
|
|
146
|
+
console.assert(closeSignals[0]?.asset === "ETH", "Expected ETH (lowest ROE) as close target");
|
|
147
|
+
console.assert(result2.summary.consecutiveCleanChecks === 0, "Expected 0 clean checks after alert");
|
|
148
|
+
|
|
149
|
+
console.log("\n [PASS] Scenario 1 completed successfully");
|
|
150
|
+
} finally {
|
|
151
|
+
await module.stop();
|
|
152
|
+
await rm(stateDir, { recursive: true, force: true });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// ─── Scenario 2: With DSL states from StateManager ──────────────────────────
|
|
157
|
+
|
|
158
|
+
async function scenarioWithDslStates() {
|
|
159
|
+
console.log("\n=== Scenario 2: With DSL states from StateManager ===\n");
|
|
160
|
+
|
|
161
|
+
const stateDir = await mkdtemp(join(tmpdir(), "watchdog-with-dsl-"));
|
|
162
|
+
|
|
163
|
+
// Seed the StateManager with DSL state files (as the DSL plugin would)
|
|
164
|
+
const stateManager = new StateManager(stateDir);
|
|
165
|
+
|
|
166
|
+
const baseDslState = {
|
|
167
|
+
version: 1,
|
|
168
|
+
address: "wallet-002",
|
|
169
|
+
wallet: "wallet-002",
|
|
170
|
+
dex: "",
|
|
171
|
+
highWaterPrice: 0,
|
|
172
|
+
hwTimestamp: new Date().toISOString(),
|
|
173
|
+
currentBreachCount: 0,
|
|
174
|
+
currentTierIndex: null,
|
|
175
|
+
tierFloorPrice: 0,
|
|
176
|
+
tiers: [],
|
|
177
|
+
phase1: { retraceThreshold: 5, absoluteFloor: 0, consecutiveBreachesRequired: 3 },
|
|
178
|
+
phase2: { retraceFromHW: 4, consecutiveBreachesRequired: 2 },
|
|
179
|
+
phase2TriggerTier: 0,
|
|
180
|
+
slOrderId: null,
|
|
181
|
+
lastSyncedFloorPrice: null,
|
|
182
|
+
slOrderIdUpdatedAt: null,
|
|
183
|
+
lastSlSyncError: null,
|
|
184
|
+
pendingClose: false,
|
|
185
|
+
active: true,
|
|
186
|
+
createdAt: new Date().toISOString(),
|
|
187
|
+
lastCheck: new Date().toISOString(),
|
|
188
|
+
consecutiveFetchFailures: 0,
|
|
189
|
+
tickCount: 0,
|
|
190
|
+
peakROE: 0,
|
|
191
|
+
lastError: null,
|
|
192
|
+
lastErrorAt: null,
|
|
193
|
+
closedAt: null,
|
|
194
|
+
closeReason: null,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
await stateManager.setDslState("wallet-002", "BTC", "", {
|
|
198
|
+
...baseDslState,
|
|
199
|
+
asset: "BTC",
|
|
200
|
+
direction: "LONG",
|
|
201
|
+
entryPrice: 58000,
|
|
202
|
+
size: 1,
|
|
203
|
+
leverage: 5,
|
|
204
|
+
highWaterPrice: 62000,
|
|
205
|
+
phase: 2,
|
|
206
|
+
currentTierIndex: 1,
|
|
207
|
+
tierFloorPrice: 57000,
|
|
208
|
+
floorPrice: 56500, // DSL floor for BTC
|
|
209
|
+
lastPrice: 60000,
|
|
210
|
+
peakROE: 15,
|
|
211
|
+
tickCount: 100,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
await stateManager.setDslState("wallet-002", "SOL", "", {
|
|
215
|
+
...baseDslState,
|
|
216
|
+
asset: "SOL",
|
|
217
|
+
direction: "LONG",
|
|
218
|
+
entryPrice: 140,
|
|
219
|
+
size: 10,
|
|
220
|
+
leverage: 5,
|
|
221
|
+
highWaterPrice: 155,
|
|
222
|
+
phase: 1,
|
|
223
|
+
tierFloorPrice: 135,
|
|
224
|
+
floorPrice: 133, // DSL floor for SOL
|
|
225
|
+
lastPrice: 150,
|
|
226
|
+
peakROE: 10,
|
|
227
|
+
tickCount: 50,
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
// Verify StateManager has the states
|
|
231
|
+
const loaded = stateManager.listDslStates("wallet-002");
|
|
232
|
+
console.log(" StateManager DSL states loaded:", loaded.length);
|
|
233
|
+
console.assert(loaded.length === 2, "Expected 2 DSL states in StateManager");
|
|
234
|
+
|
|
235
|
+
// Critical clearinghouse scenario
|
|
236
|
+
const clearingHouse = makeClearingHouseState({
|
|
237
|
+
bufferPct: 25, // CRITICAL
|
|
238
|
+
positions: [
|
|
239
|
+
makePosition({ asset: "BTC", markPrice: 60000, liqPrice: 54000, roe: 3 }), // 10% liq dist
|
|
240
|
+
makePosition({ asset: "SOL", markPrice: 150, liqPrice: 130, roe: -18 }), // ~13.3% liq dist
|
|
241
|
+
],
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Wire getDslStatesForStrategy to read from the StateManager — same as Runtime does
|
|
245
|
+
const module = createScannerRuntimeModule({
|
|
246
|
+
stateDir,
|
|
247
|
+
scanners: [liquidationWatchdogScanner],
|
|
248
|
+
strategies: [
|
|
249
|
+
{
|
|
250
|
+
id: "wallet-002",
|
|
251
|
+
name: "Trader-B",
|
|
252
|
+
scannerOverrides: {
|
|
253
|
+
"liquidation-watchdog": {
|
|
254
|
+
config: {
|
|
255
|
+
bufferWarningPct: 50,
|
|
256
|
+
bufferCriticalPct: 30,
|
|
257
|
+
liqDistanceWarningPct: 30,
|
|
258
|
+
roeDangerPct: -15,
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
providers: {
|
|
265
|
+
getClearingHouseState: async () => clearingHouse,
|
|
266
|
+
getActivePositions: async () => [],
|
|
267
|
+
getInstruments: async () => [],
|
|
268
|
+
getDslStatesForStrategy: async (address) => stateManager.listDslStates(address),
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const result = await module.runOnce("wallet-002", "liquidation-watchdog");
|
|
274
|
+
|
|
275
|
+
console.log("Run (critical + DSL from StateManager):");
|
|
276
|
+
console.log(" scannedCount:", result.scannedCount);
|
|
277
|
+
console.log(" signals:", result.signals.length);
|
|
278
|
+
console.log(" summary.marginBuffer:", result.summary.marginBuffer);
|
|
279
|
+
console.log(" summary.alertCount:", result.summary.alertCount);
|
|
280
|
+
|
|
281
|
+
const closeSignals = result.signals.filter((s) => s.signalType === "WATCHDOG_CLOSE");
|
|
282
|
+
const alertSignals = result.signals.filter((s) => s.signalType === "WATCHDOG_ALERT");
|
|
283
|
+
console.log(" WATCHDOG_CLOSE signals:", closeSignals.length);
|
|
284
|
+
console.log(" WATCHDOG_ALERT signals:", alertSignals.length);
|
|
285
|
+
|
|
286
|
+
if (closeSignals.length > 0) {
|
|
287
|
+
console.log(" Close target:", closeSignals[0].asset, "ROE:", closeSignals[0].meta.roe);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Check that liq-distance alerts include DSL floor notes from StateManager
|
|
291
|
+
const liqAlertMessages = alertSignals
|
|
292
|
+
.filter((s) => typeof s.meta.message === "string" && s.meta.message.includes("Liquidation distance"))
|
|
293
|
+
.map((s) => s.meta.message);
|
|
294
|
+
|
|
295
|
+
console.log("\n Liquidation distance alert messages:");
|
|
296
|
+
for (const msg of liqAlertMessages) {
|
|
297
|
+
console.log(" -", msg);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const hasDslFloorNote = liqAlertMessages.some((m) => m.includes("DSL floor"));
|
|
301
|
+
console.assert(hasDslFloorNote, "Expected at least one liq alert with DSL floor note");
|
|
302
|
+
console.assert(closeSignals.length >= 1, "Expected WATCHDOG_CLOSE on critical buffer");
|
|
303
|
+
console.assert(closeSignals[0]?.asset === "SOL", "Expected SOL (lowest ROE -18) as close target");
|
|
304
|
+
|
|
305
|
+
// Verify BTC alert includes DSL floor $56500.00 (from StateManager)
|
|
306
|
+
const btcAlert = liqAlertMessages.find((m) => m.includes("BTC"));
|
|
307
|
+
console.assert(btcAlert?.includes("DSL floor: $56500.00"), "Expected BTC alert to contain DSL floor $56500.00 from StateManager");
|
|
308
|
+
|
|
309
|
+
// Verify SOL alert includes DSL floor $133.00 (from StateManager)
|
|
310
|
+
const solAlert = liqAlertMessages.find((m) => m.includes("SOL"));
|
|
311
|
+
console.assert(solAlert?.includes("DSL floor: $133.00"), "Expected SOL alert to contain DSL floor $133.00 from StateManager");
|
|
312
|
+
|
|
313
|
+
console.log("\n [PASS] Scenario 2 completed successfully");
|
|
314
|
+
} finally {
|
|
315
|
+
await module.stop();
|
|
316
|
+
await rm(stateDir, { recursive: true, force: true });
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ─── Main ───────────────────────────────────────────────────────────────────
|
|
321
|
+
|
|
322
|
+
async function main() {
|
|
323
|
+
await scenarioWithoutDslStates();
|
|
324
|
+
await scenarioWithDslStates();
|
|
325
|
+
console.log("\nAll scenarios passed.\n");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
main().catch((error) => {
|
|
329
|
+
console.error(error);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
});
|