@reefclaw/openclaw-plugin 0.1.0
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/.gitignore +8 -0
- package/audit/mode-transition-audit.d.ts +11 -0
- package/audit/mode-transition-audit.js +29 -0
- package/balance-utils.d.ts +36 -0
- package/balance-utils.js +98 -0
- package/bridge/bridge.d.ts +109 -0
- package/bridge/bridge.js +1036 -0
- package/bridge/config.d.ts +43 -0
- package/bridge/config.js +176 -0
- package/bridge/connector.d.ts +52 -0
- package/bridge/connector.js +293 -0
- package/bridge/event-replay-buffer.d.ts +43 -0
- package/bridge/event-replay-buffer.js +109 -0
- package/bridge/gateway/event-parser.d.ts +209 -0
- package/bridge/gateway/event-parser.js +793 -0
- package/bridge/gateway/gateway-config.d.ts +39 -0
- package/bridge/gateway/gateway-config.js +86 -0
- package/bridge/gateway/gateway-http-client.d.ts +50 -0
- package/bridge/gateway/gateway-http-client.js +165 -0
- package/bridge/gateway/gateway-ws-client.d.ts +116 -0
- package/bridge/gateway/gateway-ws-client.js +417 -0
- package/bridge/gateway/poller.d.ts +146 -0
- package/bridge/gateway/poller.js +505 -0
- package/bridge/gateway/tool-discovery.d.ts +25 -0
- package/bridge/gateway/tool-discovery.js +198 -0
- package/bridge/index.d.ts +2 -0
- package/bridge/index.js +253 -0
- package/bridge/logger.d.ts +2 -0
- package/bridge/logger.js +2 -0
- package/bridge/provider.d.ts +156 -0
- package/bridge/provider.js +2 -0
- package/bridge/providers/emergency-commands.d.ts +54 -0
- package/bridge/providers/emergency-commands.js +235 -0
- package/bridge/providers/gateway.d.ts +322 -0
- package/bridge/providers/gateway.js +2302 -0
- package/bridge/providers/mock.d.ts +37 -0
- package/bridge/providers/mock.js +385 -0
- package/bridge/providers/onboarding-commands.d.ts +83 -0
- package/bridge/providers/onboarding-commands.js +213 -0
- package/bridge/providers/risk-calculator.d.ts +96 -0
- package/bridge/providers/risk-calculator.js +369 -0
- package/bridge/setup.d.ts +32 -0
- package/bridge/setup.js +226 -0
- package/bridge/types.d.ts +584 -0
- package/bridge/types.js +50 -0
- package/bridge/utils/reconnect.d.ts +6 -0
- package/bridge/utils/reconnect.js +6 -0
- package/bridge/utils/skill-signing.d.ts +51 -0
- package/bridge/utils/skill-signing.js +138 -0
- package/bridge/utils/skill-version.d.ts +17 -0
- package/bridge/utils/skill-version.js +74 -0
- package/ccxt/binance-ban-gate.d.ts +47 -0
- package/ccxt/binance-ban-gate.js +409 -0
- package/ccxt/binance-private.d.ts +325 -0
- package/ccxt/binance-private.js +1415 -0
- package/ccxt/binance-public.d.ts +18 -0
- package/ccxt/binance-public.js +147 -0
- package/config/agent-config-client.d.ts +55 -0
- package/config/agent-config-client.js +145 -0
- package/config/agent-config-poller.d.ts +25 -0
- package/config/agent-config-poller.js +100 -0
- package/config/brackets-config.d.ts +22 -0
- package/config/brackets-config.js +58 -0
- package/config/gate-store.d.ts +18 -0
- package/config/gate-store.js +61 -0
- package/config/plugin-config-io.d.ts +181 -0
- package/config/plugin-config-io.js +84 -0
- package/config/position-review-config.d.ts +35 -0
- package/config/position-review-config.js +105 -0
- package/config/tool-gate.d.ts +53 -0
- package/config/tool-gate.js +125 -0
- package/config/user-data-stream-config.d.ts +85 -0
- package/config/user-data-stream-config.js +224 -0
- package/connector-supervisor.d.ts +36 -0
- package/connector-supervisor.js +149 -0
- package/exchange-adapter.d.ts +49 -0
- package/exchange-adapter.js +4 -0
- package/index.d.ts +30 -0
- package/index.js +2030 -0
- package/ingest/pending-entry-metadata.d.ts +52 -0
- package/ingest/pending-entry-metadata.js +182 -0
- package/ingest/position-auto-capture.d.ts +98 -0
- package/ingest/position-auto-capture.js +394 -0
- package/ingest/position-decisions-client.d.ts +318 -0
- package/ingest/position-decisions-client.js +296 -0
- package/ingest/reconcile-db-vs-exchange.d.ts +13 -0
- package/ingest/reconcile-db-vs-exchange.js +114 -0
- package/ingest/reconciler-cleanup.d.ts +37 -0
- package/ingest/reconciler-cleanup.js +147 -0
- package/ingest/rest-gap-filler.d.ts +191 -0
- package/ingest/rest-gap-filler.js +565 -0
- package/ingest/touched-symbols-store.d.ts +25 -0
- package/ingest/touched-symbols-store.js +96 -0
- package/ingest/trade-store-client.d.ts +40 -0
- package/ingest/trade-store-client.js +125 -0
- package/ingest/ws-ingest.d.ts +43 -0
- package/ingest/ws-ingest.js +126 -0
- package/learning/setup-family.d.ts +21 -0
- package/learning/setup-family.js +103 -0
- package/lifecycle/install-signal-handlers.d.ts +33 -0
- package/lifecycle/install-signal-handlers.js +112 -0
- package/lifecycle/shutdown-coordinator.d.ts +43 -0
- package/lifecycle/shutdown-coordinator.js +131 -0
- package/live/bracket-id.d.ts +18 -0
- package/live/bracket-id.js +81 -0
- package/live/bracket-ledger.d.ts +54 -0
- package/live/bracket-ledger.js +267 -0
- package/live/bracket-manager.d.ts +82 -0
- package/live/bracket-manager.js +478 -0
- package/live/bracket-params.d.ts +22 -0
- package/live/bracket-params.js +124 -0
- package/live/bracket-reconciler.d.ts +95 -0
- package/live/bracket-reconciler.js +573 -0
- package/live/bracket-types.d.ts +102 -0
- package/live/bracket-types.js +8 -0
- package/live/deposit-tracker.d.ts +62 -0
- package/live/deposit-tracker.js +97 -0
- package/live/emergency-controls.d.ts +32 -0
- package/live/emergency-controls.js +226 -0
- package/live/exchange-errors.d.ts +12 -0
- package/live/exchange-errors.js +130 -0
- package/live/exchange-info-cache.d.ts +35 -0
- package/live/exchange-info-cache.js +119 -0
- package/live/fact-subscriber.d.ts +78 -0
- package/live/fact-subscriber.js +182 -0
- package/live/intent-journal.d.ts +42 -0
- package/live/intent-journal.js +122 -0
- package/live/listen-key-manager.d.ts +70 -0
- package/live/listen-key-manager.js +169 -0
- package/live/live-adapter.d.ts +264 -0
- package/live/live-adapter.js +1665 -0
- package/live/live-balance-enricher.d.ts +32 -0
- package/live/live-balance-enricher.js +104 -0
- package/live/live-bracket-api.d.ts +13 -0
- package/live/live-bracket-api.js +20 -0
- package/live/live-state-store.d.ts +194 -0
- package/live/live-state-store.js +450 -0
- package/live/local-signal-service.d.ts +57 -0
- package/live/local-signal-service.js +146 -0
- package/live/local-strategy-evaluator.d.ts +62 -0
- package/live/local-strategy-evaluator.js +127 -0
- package/live/microstructure-assembler.d.ts +54 -0
- package/live/microstructure-assembler.js +148 -0
- package/live/order-poller.d.ts +29 -0
- package/live/order-poller.js +125 -0
- package/live/position-state-store.d.ts +83 -0
- package/live/position-state-store.js +237 -0
- package/live/proposal-decision-listener.d.ts +64 -0
- package/live/proposal-decision-listener.js +288 -0
- package/live/proposal-manager.d.ts +76 -0
- package/live/proposal-manager.js +140 -0
- package/live/rate-limiter.d.ts +47 -0
- package/live/rate-limiter.js +159 -0
- package/live/reconciler.d.ts +39 -0
- package/live/reconciler.js +175 -0
- package/live/setup-buckets.d.ts +7 -0
- package/live/setup-buckets.js +33 -0
- package/live/slippage-tracker.d.ts +45 -0
- package/live/slippage-tracker.js +78 -0
- package/live/stop-watcher.d.ts +34 -0
- package/live/stop-watcher.js +158 -0
- package/live/user-data-active-probe.d.ts +54 -0
- package/live/user-data-active-probe.js +180 -0
- package/live/user-data-stream-controller.d.ts +200 -0
- package/live/user-data-stream-controller.js +579 -0
- package/live/user-data-stream-ws.d.ts +22 -0
- package/live/user-data-stream-ws.js +63 -0
- package/live/user-data-stream.d.ts +243 -0
- package/live/user-data-stream.js +704 -0
- package/logger.d.ts +2 -0
- package/logger.js +2 -0
- package/mfe.d.ts +21 -0
- package/mfe.js +68 -0
- package/onboarding/mode-ladder.d.ts +1 -0
- package/onboarding/mode-ladder.js +3 -0
- package/onboarding/runtime.d.ts +71 -0
- package/onboarding/runtime.js +153 -0
- package/openclaw.plugin.json +94 -0
- package/package.json +27 -0
- package/paper-adapter.d.ts +24 -0
- package/paper-adapter.js +91 -0
- package/persistence/state-manager.d.ts +42 -0
- package/persistence/state-manager.js +164 -0
- package/pinned-plan.d.ts +9 -0
- package/pinned-plan.js +23 -0
- package/risk/pre-trade-check.d.ts +38 -0
- package/risk/pre-trade-check.js +345 -0
- package/risk/pre-trade-types.d.ts +60 -0
- package/risk/pre-trade-types.js +3 -0
- package/scripts/assemble.mjs +114 -0
- package/shadow/shadow-tracker.d.ts +36 -0
- package/shadow/shadow-tracker.js +151 -0
- package/shadow/types.d.ts +42 -0
- package/shadow/types.js +20 -0
- package/shared/indicators-extended.d.ts +52 -0
- package/shared/indicators-extended.js +291 -0
- package/shared/indicators.d.ts +15 -0
- package/shared/indicators.js +114 -0
- package/signals/conditions/registry.d.ts +16 -0
- package/signals/conditions/registry.js +1274 -0
- package/signals/conditions/types.d.ts +1 -0
- package/signals/conditions/types.js +4 -0
- package/signals/direction-rules.d.ts +3 -0
- package/signals/direction-rules.js +24 -0
- package/signals/entry-rules.d.ts +6 -0
- package/signals/entry-rules.js +33 -0
- package/signals/serialize-context.d.ts +4 -0
- package/signals/serialize-context.js +39 -0
- package/signals/stop-rules.d.ts +3 -0
- package/signals/stop-rules.js +48 -0
- package/signals/strategy-adapter.d.ts +14 -0
- package/signals/strategy-adapter.js +122 -0
- package/signals/types.d.ts +1 -0
- package/signals/types.js +8 -0
- package/simulator/exchange-simulator.d.ts +93 -0
- package/simulator/exchange-simulator.js +684 -0
- package/simulator/fill-engine.d.ts +53 -0
- package/simulator/fill-engine.js +276 -0
- package/simulator/paper-market-feed.d.ts +26 -0
- package/simulator/paper-market-feed.js +104 -0
- package/simulator/realistic-fills.d.ts +59 -0
- package/simulator/realistic-fills.js +175 -0
- package/simulator/types.d.ts +219 -0
- package/simulator/types.js +43 -0
- package/skills/reefclaw/SKILL.md +97 -0
- package/strategy/builtin-strategies.d.ts +2 -0
- package/strategy/builtin-strategies.js +109 -0
- package/strategy/condition-registry.d.ts +3 -0
- package/strategy/condition-registry.js +153 -0
- package/strategy/evaluator.d.ts +67 -0
- package/strategy/evaluator.js +93 -0
- package/tools/assessment-validation.d.ts +118 -0
- package/tools/assessment-validation.js +415 -0
- package/tools/attach-brackets.d.ts +34 -0
- package/tools/attach-brackets.js +363 -0
- package/tools/audit-bracket-protection.d.ts +49 -0
- package/tools/audit-bracket-protection.js +527 -0
- package/tools/cancel-all-orders.d.ts +7 -0
- package/tools/cancel-all-orders.js +5 -0
- package/tools/cancel-order.d.ts +10 -0
- package/tools/cancel-order.js +14 -0
- package/tools/check-position-health.d.ts +46 -0
- package/tools/check-position-health.js +194 -0
- package/tools/clear-exchange-credentials.d.ts +24 -0
- package/tools/clear-exchange-credentials.js +70 -0
- package/tools/close-position.d.ts +22 -0
- package/tools/close-position.js +449 -0
- package/tools/create-order.d.ts +54 -0
- package/tools/create-order.js +338 -0
- package/tools/exit-gate.d.ts +58 -0
- package/tools/exit-gate.js +162 -0
- package/tools/fetch-balance.d.ts +5 -0
- package/tools/fetch-balance.js +4 -0
- package/tools/fetch-ohlcv.d.ts +11 -0
- package/tools/fetch-ohlcv.js +8 -0
- package/tools/fetch-open-orders.d.ts +7 -0
- package/tools/fetch-open-orders.js +4 -0
- package/tools/fetch-positions.d.ts +7 -0
- package/tools/fetch-positions.js +4 -0
- package/tools/fetch-ticker.d.ts +11 -0
- package/tools/fetch-ticker.js +5 -0
- package/tools/get-agent-profile.d.ts +4 -0
- package/tools/get-agent-profile.js +6 -0
- package/tools/get-analytics.d.ts +6 -0
- package/tools/get-analytics.js +7 -0
- package/tools/get-backtest.d.ts +12 -0
- package/tools/get-backtest.js +91 -0
- package/tools/get-basis.d.ts +7 -0
- package/tools/get-basis.js +7 -0
- package/tools/get-bracket-config.d.ts +11 -0
- package/tools/get-bracket-config.js +24 -0
- package/tools/get-cascade-risk.d.ts +7 -0
- package/tools/get-cascade-risk.js +8 -0
- package/tools/get-crypto-metrics.d.ts +18 -0
- package/tools/get-crypto-metrics.js +45 -0
- package/tools/get-cvd.d.ts +6 -0
- package/tools/get-cvd.js +6 -0
- package/tools/get-divergences.d.ts +6 -0
- package/tools/get-divergences.js +6 -0
- package/tools/get-funding-context.d.ts +6 -0
- package/tools/get-funding-context.js +16 -0
- package/tools/get-liquidation-levels.d.ts +7 -0
- package/tools/get-liquidation-levels.js +7 -0
- package/tools/get-liquidation-pulse.d.ts +9 -0
- package/tools/get-liquidation-pulse.js +22 -0
- package/tools/get-market-breadth.d.ts +6 -0
- package/tools/get-market-breadth.js +8 -0
- package/tools/get-market-intel.d.ts +19 -0
- package/tools/get-market-intel.js +116 -0
- package/tools/get-market-structure.d.ts +47 -0
- package/tools/get-market-structure.js +198 -0
- package/tools/get-my-mined-patterns.d.ts +20 -0
- package/tools/get-my-mined-patterns.js +61 -0
- package/tools/get-my-proposed-learnings.d.ts +20 -0
- package/tools/get-my-proposed-learnings.js +55 -0
- package/tools/get-my-recent-reviews.d.ts +22 -0
- package/tools/get-my-recent-reviews.js +66 -0
- package/tools/get-orderbook.d.ts +21 -0
- package/tools/get-orderbook.js +32 -0
- package/tools/get-pattern-scan.d.ts +7 -0
- package/tools/get-pattern-scan.js +8 -0
- package/tools/get-regime.d.ts +6 -0
- package/tools/get-regime.js +7 -0
- package/tools/get-relevant-learnings.d.ts +21 -0
- package/tools/get-relevant-learnings.js +65 -0
- package/tools/get-resting-liquidity.d.ts +6 -0
- package/tools/get-resting-liquidity.js +11 -0
- package/tools/get-risk-scenario.d.ts +29 -0
- package/tools/get-risk-scenario.js +47 -0
- package/tools/get-risk-summary.d.ts +51 -0
- package/tools/get-risk-summary.js +118 -0
- package/tools/get-sentiment.d.ts +4 -0
- package/tools/get-sentiment.js +6 -0
- package/tools/get-session-review.d.ts +7 -0
- package/tools/get-session-review.js +8 -0
- package/tools/get-setup-detail.d.ts +7 -0
- package/tools/get-setup-detail.js +303 -0
- package/tools/get-signals.d.ts +15 -0
- package/tools/get-signals.js +54 -0
- package/tools/get-sizing.d.ts +6 -0
- package/tools/get-sizing.js +6 -0
- package/tools/get-trade-feedback.d.ts +7 -0
- package/tools/get-trade-feedback.js +8 -0
- package/tools/get-trade-flow.d.ts +7 -0
- package/tools/get-trade-flow.js +7 -0
- package/tools/get-volume-analysis.d.ts +21 -0
- package/tools/get-volume-analysis.js +74 -0
- package/tools/get-volume-profile.d.ts +7 -0
- package/tools/get-volume-profile.js +7 -0
- package/tools/helpers.d.ts +25 -0
- package/tools/helpers.js +38 -0
- package/tools/intel-api.d.ts +14 -0
- package/tools/intel-api.js +52 -0
- package/tools/intel-cache.d.ts +25 -0
- package/tools/intel-cache.js +133 -0
- package/tools/list-strategies.d.ts +7 -0
- package/tools/list-strategies.js +6 -0
- package/tools/modify-stop.d.ts +17 -0
- package/tools/modify-stop.js +81 -0
- package/tools/modify-target.d.ts +17 -0
- package/tools/modify-target.js +71 -0
- package/tools/propose-learning.d.ts +22 -0
- package/tools/propose-learning.js +65 -0
- package/tools/query-review-outcomes.d.ts +30 -0
- package/tools/query-review-outcomes.js +64 -0
- package/tools/query-trades.d.ts +21 -0
- package/tools/query-trades.js +37 -0
- package/tools/record-position-reviews.d.ts +38 -0
- package/tools/record-position-reviews.js +147 -0
- package/tools/save-strategy.d.ts +16 -0
- package/tools/save-strategy.js +46 -0
- package/tools/scan-pairs.d.ts +18 -0
- package/tools/scan-pairs.js +220 -0
- package/tools/score-setup.d.ts +31 -0
- package/tools/score-setup.js +268 -0
- package/tools/set-bracket-requirement.d.ts +18 -0
- package/tools/set-bracket-requirement.js +81 -0
- package/tools/set-exchange-credentials.d.ts +25 -0
- package/tools/set-exchange-credentials.js +80 -0
- package/tools/set-trading-mode.d.ts +26 -0
- package/tools/set-trading-mode.js +135 -0
- package/tools/test-exchange-credentials.d.ts +16 -0
- package/tools/test-exchange-credentials.js +100 -0
- package/tools/toggle-strategy.d.ts +8 -0
- package/tools/toggle-strategy.js +8 -0
- package/trading-params-cache.d.ts +26 -0
- package/trading-params-cache.js +52 -0
- package/types.d.ts +110 -0
- package/types.js +7 -0
- package/util/plugin-paths.d.ts +3 -0
- package/util/plugin-paths.js +15 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PositionDecisionsClient, ProposeLearningResponse } from '../ingest/position-decisions-client.js';
|
|
2
|
+
export interface ProposeLearningArgs {
|
|
3
|
+
applies_at: 'entry' | 'heartbeat' | 'close';
|
|
4
|
+
title: string;
|
|
5
|
+
directive: string;
|
|
6
|
+
source_mined_pattern_id?: string;
|
|
7
|
+
trigger_condition?: Record<string, unknown>;
|
|
8
|
+
evidence?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export interface ProposeLearningDeps {
|
|
11
|
+
decisionsClient?: PositionDecisionsClient;
|
|
12
|
+
userId?: string;
|
|
13
|
+
}
|
|
14
|
+
export type ProposeLearningResult = (ProposeLearningResponse & {
|
|
15
|
+
ok: true;
|
|
16
|
+
}) | {
|
|
17
|
+
error: string;
|
|
18
|
+
throttled?: boolean;
|
|
19
|
+
proposals_used?: number;
|
|
20
|
+
proposals_limit?: number;
|
|
21
|
+
};
|
|
22
|
+
export declare function proposeLearningTool(args: ProposeLearningArgs, deps: ProposeLearningDeps): Promise<ProposeLearningResult>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Tool: propose_learning — Phase 4.5 agent-side write capability.
|
|
2
|
+
//
|
|
3
|
+
// The agent calls this once per UTC day during its self-assessment routine,
|
|
4
|
+
// after reading get_my_mined_patterns + get_my_proposed_learnings, to draft a
|
|
5
|
+
// new candidate learning for its operator to review.
|
|
6
|
+
//
|
|
7
|
+
// Critically:
|
|
8
|
+
// - confidence is determined SERVER-SIDE by the operator's trust mode.
|
|
9
|
+
// The agent never writes 'confirmed' directly. Under trust=auto, the
|
|
10
|
+
// server flips confidence='confirmed' + auto_confirmed=true so the
|
|
11
|
+
// proposal takes effect immediately.
|
|
12
|
+
// - proposed_by is hardcoded 'agent' in the route — never trusted from
|
|
13
|
+
// this caller.
|
|
14
|
+
// - Server-side throttle of 3 proposals per 24h per user means most days
|
|
15
|
+
// the agent will draft 0-3, not 30.
|
|
16
|
+
//
|
|
17
|
+
// Directive style guide (enforced in SKILL.md, not in code, to preserve
|
|
18
|
+
// agency over wording): n / effect size / p / a recent concrete example /
|
|
19
|
+
// default action / override conditions.
|
|
20
|
+
import { logger, formatError } from '../logger.js';
|
|
21
|
+
const TAG = 'propose-learning';
|
|
22
|
+
const APPLIES_AT_VALUES = new Set(['entry', 'heartbeat', 'close']);
|
|
23
|
+
export async function proposeLearningTool(args, deps) {
|
|
24
|
+
if (!deps.decisionsClient || !deps.userId) {
|
|
25
|
+
return { error: 'Position-decisions ingest is not configured; cannot propose learnings.' };
|
|
26
|
+
}
|
|
27
|
+
if (!args.applies_at || !APPLIES_AT_VALUES.has(args.applies_at)) {
|
|
28
|
+
return { error: "applies_at is required and must be one of: 'entry', 'heartbeat', 'close'." };
|
|
29
|
+
}
|
|
30
|
+
if (typeof args.title !== 'string' || args.title.trim().length < 4) {
|
|
31
|
+
return { error: 'title required (min 4 chars).' };
|
|
32
|
+
}
|
|
33
|
+
if (typeof args.directive !== 'string' || args.directive.trim().length < 20) {
|
|
34
|
+
return { error: 'directive required (min 20 chars).' };
|
|
35
|
+
}
|
|
36
|
+
let response;
|
|
37
|
+
try {
|
|
38
|
+
response = await deps.decisionsClient.proposeLearning(deps.userId, {
|
|
39
|
+
appliesAt: args.applies_at,
|
|
40
|
+
title: args.title.trim(),
|
|
41
|
+
directive: args.directive.trim(),
|
|
42
|
+
sourceMinedPatternId: args.source_mined_pattern_id,
|
|
43
|
+
triggerCondition: args.trigger_condition,
|
|
44
|
+
evidence: args.evidence,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
logger.warn(TAG, `proposeLearning threw: ${formatError(err)}`);
|
|
49
|
+
return { error: 'Failed to post proposal to webapp.' };
|
|
50
|
+
}
|
|
51
|
+
if (!response) {
|
|
52
|
+
// The client treats 4xx as terminal-dropped and 5xx+network as retry-
|
|
53
|
+
// exhausted. Either way we get null and surface a generic error. The
|
|
54
|
+
// throttle status (429) would have been a 4xx terminal drop without a
|
|
55
|
+
// structured body returned through this path — agent can call
|
|
56
|
+
// get_my_proposed_learnings to check.
|
|
57
|
+
return {
|
|
58
|
+
error: 'Proposal was not accepted (could be throttled, validation error, or network failure). Inspect logs and recent proposals to diagnose.',
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
...response,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PositionDecisionsClient, ReviewOutcomesResponse } from '../ingest/position-decisions-client.js';
|
|
2
|
+
export interface QueryReviewOutcomesArgs {
|
|
3
|
+
verdict?: 'hold' | 'add_on' | 'close_recommended';
|
|
4
|
+
thesis_status?: 'intact' | 'weakening' | 'invalidated' | 'evolving';
|
|
5
|
+
regime_current?: string;
|
|
6
|
+
symbol?: string;
|
|
7
|
+
side?: 'long' | 'short';
|
|
8
|
+
setup_type?: string;
|
|
9
|
+
days_back?: number;
|
|
10
|
+
min_score_delta?: number;
|
|
11
|
+
max_score_delta?: number;
|
|
12
|
+
closed_only?: boolean;
|
|
13
|
+
sample_limit?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface QueryReviewOutcomesDeps {
|
|
16
|
+
decisionsClient?: PositionDecisionsClient;
|
|
17
|
+
userId?: string;
|
|
18
|
+
}
|
|
19
|
+
export type QueryReviewOutcomesResult = (ReviewOutcomesResponse & {
|
|
20
|
+
ok: true;
|
|
21
|
+
}) | {
|
|
22
|
+
ok: true;
|
|
23
|
+
note: string;
|
|
24
|
+
filters: Record<string, unknown>;
|
|
25
|
+
stats: ReviewOutcomesResponse['stats'];
|
|
26
|
+
sample: [];
|
|
27
|
+
} | {
|
|
28
|
+
error: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function queryReviewOutcomesTool(args: QueryReviewOutcomesArgs, deps: QueryReviewOutcomesDeps): Promise<QueryReviewOutcomesResult>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Tool: query_review_outcomes — Phase 2 of the Agent Learning Loop.
|
|
2
|
+
//
|
|
3
|
+
// Aggregate-stats + sample over the position_review_outcomes view. Lets the
|
|
4
|
+
// agent ask "what happened to positions where I filed verdict=hold +
|
|
5
|
+
// thesis_status=weakening over the last 7 days?" and receive a count, win
|
|
6
|
+
// rate, median R, and a small sample of matching reviews.
|
|
7
|
+
//
|
|
8
|
+
// Use case: at session start (and daily), the agent runs this for its
|
|
9
|
+
// most-used (verdict, thesis_status) combinations. Any combination showing
|
|
10
|
+
// median R < 0 across 5+ closed samples is the agent's evidence that the
|
|
11
|
+
// pattern is bleeding edge.
|
|
12
|
+
//
|
|
13
|
+
// See docs/AGENT_LEARNING_LOOP_PLAN.md §3 Phase 2.
|
|
14
|
+
import { logger, formatError } from '../logger.js';
|
|
15
|
+
const TAG = 'query-review-outcomes';
|
|
16
|
+
export async function queryReviewOutcomesTool(args, deps) {
|
|
17
|
+
if (!deps.decisionsClient || !deps.userId) {
|
|
18
|
+
return {
|
|
19
|
+
ok: true,
|
|
20
|
+
note: 'Position-decisions ingest is not configured; outcomes are unavailable.',
|
|
21
|
+
filters: { ...args },
|
|
22
|
+
stats: emptyStats(),
|
|
23
|
+
sample: [],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const filters = {
|
|
27
|
+
verdict: args.verdict,
|
|
28
|
+
thesisStatus: args.thesis_status,
|
|
29
|
+
regimeCurrent: args.regime_current,
|
|
30
|
+
symbol: args.symbol,
|
|
31
|
+
side: args.side,
|
|
32
|
+
setupType: args.setup_type,
|
|
33
|
+
daysBack: args.days_back,
|
|
34
|
+
minScoreDelta: args.min_score_delta,
|
|
35
|
+
maxScoreDelta: args.max_score_delta,
|
|
36
|
+
closedOnly: args.closed_only,
|
|
37
|
+
sampleLimit: args.sample_limit,
|
|
38
|
+
};
|
|
39
|
+
let response;
|
|
40
|
+
try {
|
|
41
|
+
response = await deps.decisionsClient.queryReviewOutcomes(deps.userId, filters);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
logger.warn(TAG, `queryReviewOutcomes threw: ${formatError(err)}`);
|
|
45
|
+
return { error: 'Failed to fetch review outcomes from webapp.' };
|
|
46
|
+
}
|
|
47
|
+
if (!response) {
|
|
48
|
+
return { error: 'Webapp /api/internal/positions/reviews/with-outcomes returned no result.' };
|
|
49
|
+
}
|
|
50
|
+
return { ok: true, ...response };
|
|
51
|
+
}
|
|
52
|
+
function emptyStats() {
|
|
53
|
+
return {
|
|
54
|
+
nTotal: 0,
|
|
55
|
+
nClosed: 0,
|
|
56
|
+
winRate: null,
|
|
57
|
+
medianR: null,
|
|
58
|
+
meanR: null,
|
|
59
|
+
medianGiveBack: null,
|
|
60
|
+
p25R: null,
|
|
61
|
+
p75R: null,
|
|
62
|
+
outcomeCounts: {},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IntelApiDeps } from './intel-api.js';
|
|
2
|
+
export interface QueryTradesArgs {
|
|
3
|
+
symbol?: string;
|
|
4
|
+
setup_type?: string;
|
|
5
|
+
strategy?: string;
|
|
6
|
+
regime?: string;
|
|
7
|
+
direction?: string;
|
|
8
|
+
outcome?: string;
|
|
9
|
+
min_duration_seconds?: number;
|
|
10
|
+
max_duration_seconds?: number;
|
|
11
|
+
min_pnl_pct?: number;
|
|
12
|
+
max_pnl_pct?: number;
|
|
13
|
+
min_confluence_score?: number;
|
|
14
|
+
hours?: number;
|
|
15
|
+
feature_filters?: string;
|
|
16
|
+
group_by?: string;
|
|
17
|
+
limit?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function queryTradesTool(args: QueryTradesArgs, deps: IntelApiDeps): Promise<Record<string, unknown> | {
|
|
20
|
+
error: string;
|
|
21
|
+
}>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Tool: query_trades — flexible trade history query with filters + aggregation.
|
|
2
|
+
// Lets the agent ask arbitrary questions about its own performance:
|
|
3
|
+
// "what's my win rate when ADX > 40?", "best setup per regime?", etc.
|
|
4
|
+
import { fetchIntelApi } from './intel-api.js';
|
|
5
|
+
export async function queryTradesTool(args, deps) {
|
|
6
|
+
// Parse feature_filters from JSON string if provided
|
|
7
|
+
let featureFilters;
|
|
8
|
+
if (args.feature_filters) {
|
|
9
|
+
try {
|
|
10
|
+
featureFilters = JSON.parse(args.feature_filters);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return { error: 'feature_filters must be valid JSON array, e.g. [{"field":"adx","op":"gt","value":40}]' };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return fetchIntelApi('/api/trades/query', deps, {
|
|
17
|
+
method: 'POST',
|
|
18
|
+
body: {
|
|
19
|
+
symbol: args.symbol,
|
|
20
|
+
setup_type: args.setup_type,
|
|
21
|
+
strategy: args.strategy,
|
|
22
|
+
regime: args.regime,
|
|
23
|
+
direction: args.direction,
|
|
24
|
+
outcome: args.outcome,
|
|
25
|
+
min_duration_seconds: args.min_duration_seconds,
|
|
26
|
+
max_duration_seconds: args.max_duration_seconds,
|
|
27
|
+
min_pnl_pct: args.min_pnl_pct,
|
|
28
|
+
max_pnl_pct: args.max_pnl_pct,
|
|
29
|
+
min_confluence_score: args.min_confluence_score,
|
|
30
|
+
hours: args.hours,
|
|
31
|
+
feature_filters: featureFilters,
|
|
32
|
+
group_by: args.group_by,
|
|
33
|
+
limit: args.limit,
|
|
34
|
+
},
|
|
35
|
+
timeoutMs: 15_000,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { IExchangeAdapter } from '../exchange-adapter.js';
|
|
2
|
+
import { type RecordPositionReviewsArgs } from './assessment-validation.js';
|
|
3
|
+
import type { PositionDecisionsClient } from '../ingest/position-decisions-client.js';
|
|
4
|
+
import type { PositionStateStore } from '../live/position-state-store.js';
|
|
5
|
+
import type { MicrostructureAssembler } from '../live/microstructure-assembler.js';
|
|
6
|
+
export interface RecordPositionReviewsDeps {
|
|
7
|
+
adapter: IExchangeAdapter;
|
|
8
|
+
decisionsClient?: PositionDecisionsClient;
|
|
9
|
+
stateStore?: PositionStateStore;
|
|
10
|
+
/** User id used for the webapp ingest header. */
|
|
11
|
+
userId?: string;
|
|
12
|
+
/** Current gate mode — drives the superset rule. */
|
|
13
|
+
gateMode?: 'off' | 'shadow' | 'observe' | 'enforce';
|
|
14
|
+
/** Optional snapshot of currently-open symbols at heartbeat-tick time.
|
|
15
|
+
* Plugin embeds this into the heartbeat result; agent passes it through.
|
|
16
|
+
* When absent we derive from adapter.getPositions(). */
|
|
17
|
+
openSymbolsSnapshot?: ReadonlySet<string>;
|
|
18
|
+
/** Optional pre-fetched microstructure context — when supplied, the tool
|
|
19
|
+
* fills review rows from this map without going to the assembler. Used by
|
|
20
|
+
* tests that don't want to mock the network. */
|
|
21
|
+
microstructureBySymbol?: Map<string, {
|
|
22
|
+
restingBandImbalance05?: number;
|
|
23
|
+
cascadePulse60s?: 'quiet' | 'elevated' | 'active_cascade';
|
|
24
|
+
coverageBpc?: number;
|
|
25
|
+
}>;
|
|
26
|
+
/** When provided AND `microstructureBySymbol` is NOT supplied, the tool
|
|
27
|
+
* fetches microstructure for every reviewed symbol via the assembler
|
|
28
|
+
* before processing reviews. Resolves PR1 deferral #3. */
|
|
29
|
+
microstructureAssembler?: MicrostructureAssembler;
|
|
30
|
+
}
|
|
31
|
+
export interface RecordPositionReviewsResult {
|
|
32
|
+
ok: boolean;
|
|
33
|
+
filed: number;
|
|
34
|
+
error?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function recordPositionReviewsTool(args: RecordPositionReviewsArgs, deps: RecordPositionReviewsDeps): Promise<RecordPositionReviewsResult | {
|
|
37
|
+
error: string;
|
|
38
|
+
}>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// Tool: record_position_reviews — plural-form per-heartbeat-per-open-position
|
|
2
|
+
// review filing. Schema-validated like v2.10.0 close validator. POSTs each
|
|
3
|
+
// review to the webapp's /api/internal/position-reviews endpoint and updates
|
|
4
|
+
// the local position-state-store's lastReviewAt for stale-gate evaluation.
|
|
5
|
+
//
|
|
6
|
+
// Mode behavior (positionReview.mode in plugin-config):
|
|
7
|
+
// - off : tool callable, validator runs, but no SKILL.md mandate.
|
|
8
|
+
// Used while feature is being soaked.
|
|
9
|
+
// - shadow : SKILL.md mandates the call; validator only runs per-review.
|
|
10
|
+
// - observe : same as shadow + soft-warn create_order on stale review.
|
|
11
|
+
// - enforce : same + superset rule + hard-reject create_order on stale.
|
|
12
|
+
//
|
|
13
|
+
// Auto-capture of orderbook context (microstructure.heartbeatPush='on'):
|
|
14
|
+
// the agent need not pass restingBandImbalance05 / cascadePulseAtReview /
|
|
15
|
+
// coveragePctAtReview — the tool fills them from the latest intel reading.
|
|
16
|
+
// When the flag is off, fields stay null.
|
|
17
|
+
//
|
|
18
|
+
// See docs/POSITION_DECISION_JOURNAL_PLAN.md.
|
|
19
|
+
import { logger, formatError } from '../logger.js';
|
|
20
|
+
import { validatePositionReviews, } from './assessment-validation.js';
|
|
21
|
+
import { normalizeBracketSymbol } from '../live/bracket-ledger.js';
|
|
22
|
+
const TAG = 'record-position-reviews';
|
|
23
|
+
export async function recordPositionReviewsTool(args, deps) {
|
|
24
|
+
// Build the open-symbols snapshot for the superset check.
|
|
25
|
+
// Normalize every symbol — Binance live form returns settle-suffixed
|
|
26
|
+
// 'SOL/USDT:USDT' while the state-store + agent-side reviews use the
|
|
27
|
+
// canonical 'SOL/USDT'. Without this the superset check rejects every
|
|
28
|
+
// heartbeat and the discipline gate becomes a brick wall.
|
|
29
|
+
let openSymbols;
|
|
30
|
+
if (deps.openSymbolsSnapshot) {
|
|
31
|
+
openSymbols = new Set(Array.from(deps.openSymbolsSnapshot, normalizeBracketSymbol));
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
let positions;
|
|
35
|
+
try {
|
|
36
|
+
positions = await deps.adapter.getPositionsOrNull();
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
logger.warn(TAG, `getPositions threw for superset check: ${formatError(err)}`);
|
|
40
|
+
positions = null;
|
|
41
|
+
}
|
|
42
|
+
if (positions === null) {
|
|
43
|
+
// Fetch failed / threw — the open-position set is UNKNOWN, not empty.
|
|
44
|
+
// In enforce mode the superset rule iterates ctx.openSymbols; an empty
|
|
45
|
+
// set makes `missing` empty so the gate trivially PASSES — i.e. the
|
|
46
|
+
// agent could file zero reviews during a rate-limit window and the
|
|
47
|
+
// discipline gate would silently miss it. Reject so the agent retries
|
|
48
|
+
// next heartbeat (same null != empty contract as audit / reconciler).
|
|
49
|
+
// At lower gate modes the superset rule never runs (openSymbols unused),
|
|
50
|
+
// so proceeding with an empty set is harmless.
|
|
51
|
+
const mode = deps.gateMode ?? 'off';
|
|
52
|
+
if (mode === 'enforce') {
|
|
53
|
+
logger.warn(TAG, 'getPositions unavailable (null) in enforce mode — cannot verify review superset; rejecting for retry');
|
|
54
|
+
return {
|
|
55
|
+
error: 'Exchange position state unavailable — cannot verify review coverage. Retry next heartbeat.',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
logger.warn(TAG, 'getPositions unavailable (null); proceeding (superset gate not enforced at this mode)');
|
|
59
|
+
openSymbols = new Set();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
openSymbols = new Set(positions.map((p) => normalizeBracketSymbol(p.symbol)));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Validator gate.
|
|
66
|
+
const v = validatePositionReviews(args, {
|
|
67
|
+
openSymbols,
|
|
68
|
+
gateMode: deps.gateMode ?? 'off',
|
|
69
|
+
});
|
|
70
|
+
if (!v.ok) {
|
|
71
|
+
logger.warn(TAG, `record_position_reviews rejected: ${v.error}`);
|
|
72
|
+
return { error: v.error ?? 'Invalid record_position_reviews arguments.' };
|
|
73
|
+
}
|
|
74
|
+
// Cast — validator confirmed the shape.
|
|
75
|
+
const reviews = args.reviews.slice();
|
|
76
|
+
// Resolve microstructure context. Caller-supplied map wins (tests); else
|
|
77
|
+
// fetch via the assembler (live path). Returns an empty map when the
|
|
78
|
+
// heartbeatPush flag is off — review rows then get null orderbook fields.
|
|
79
|
+
let microstructure = deps.microstructureBySymbol;
|
|
80
|
+
if (!microstructure && deps.microstructureAssembler) {
|
|
81
|
+
try {
|
|
82
|
+
const symbols = reviews
|
|
83
|
+
.map((r) => r.symbol)
|
|
84
|
+
.filter((s) => typeof s === 'string' && s.length > 0);
|
|
85
|
+
microstructure = await deps.microstructureAssembler.forSymbols(symbols);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
logger.warn(TAG, `microstructure fetch threw — proceeding with null fields: ${formatError(err)}`);
|
|
89
|
+
microstructure = new Map();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Forward each review to the webapp + update local state-store.
|
|
93
|
+
// We POST in parallel — they target append-only endpoints and the order is
|
|
94
|
+
// not load-bearing (each row carries its own reviewAt).
|
|
95
|
+
let filed = 0;
|
|
96
|
+
if (deps.decisionsClient && deps.userId) {
|
|
97
|
+
const promises = [];
|
|
98
|
+
for (const r of reviews) {
|
|
99
|
+
const stateEntry = deps.stateStore?.get(r.symbol);
|
|
100
|
+
const positionId = stateEntry?.webappPositionId;
|
|
101
|
+
if (!positionId) {
|
|
102
|
+
logger.warn(TAG, `No webappPositionId for ${r.symbol} — review will not be persisted to webapp until the position upserts.`);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const micro = microstructure?.get(r.symbol);
|
|
106
|
+
const payload = {
|
|
107
|
+
positionId,
|
|
108
|
+
reviewAt: Date.now(),
|
|
109
|
+
verdict: r.verdict,
|
|
110
|
+
thesisStatus: r.thesis_status,
|
|
111
|
+
entryScore: r.entry_score,
|
|
112
|
+
currentScore: r.current_score,
|
|
113
|
+
scoreDelta: r.score_delta,
|
|
114
|
+
confluenceComponents: r.confluence_components ?? {},
|
|
115
|
+
regimeEntry: r.regime_entry,
|
|
116
|
+
regimeCurrent: r.regime_current,
|
|
117
|
+
regimeConfidence: r.regime_confidence,
|
|
118
|
+
rMultiple: r.r_multiple,
|
|
119
|
+
distanceToStopBps: r.distance_to_stop_bps,
|
|
120
|
+
distanceToTargetBps: r.distance_to_target_bps ?? null,
|
|
121
|
+
timeInPositionMinutes: r.time_in_position_minutes,
|
|
122
|
+
mfeR: r.mfe_r,
|
|
123
|
+
giveBackPct: r.give_back_pct,
|
|
124
|
+
whatChanged: r.what_changed,
|
|
125
|
+
invalidationTrigger: r.invalidation_trigger,
|
|
126
|
+
// Auto-filled microstructure when push is on.
|
|
127
|
+
restingBandImbalance05: micro?.restingBandImbalance05 ?? null,
|
|
128
|
+
cascadePulseAtReview: micro?.cascadePulse60s ?? null,
|
|
129
|
+
coveragePctAtReview: micro?.coverageBpc != null ? micro.coverageBpc / 100 : null,
|
|
130
|
+
imbalanceDeltaSinceEntry: null, // filled in once we add per-position imbalance baselines
|
|
131
|
+
};
|
|
132
|
+
// Fire-and-forget — caller doesn't block on the network.
|
|
133
|
+
deps.decisionsClient.postReview(deps.userId, payload);
|
|
134
|
+
filed++;
|
|
135
|
+
// Update state-store for stale-gate + exit-gate.
|
|
136
|
+
if (deps.stateStore) {
|
|
137
|
+
deps.stateStore.recordReview(r.symbol, r.verdict, undefined, r.thesis_status);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
await Promise.allSettled(promises);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
logger.info(TAG, `record_position_reviews validated ${reviews.length} reviews; no decisionsClient configured (off-mode).`);
|
|
144
|
+
filed = 0;
|
|
145
|
+
}
|
|
146
|
+
return { ok: true, filed };
|
|
147
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IntelApiDeps } from './intel-api.js';
|
|
2
|
+
export interface SaveStrategyArgs {
|
|
3
|
+
name: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
regimes: string;
|
|
6
|
+
direction_rule: string;
|
|
7
|
+
conditions: string;
|
|
8
|
+
entry_type: string;
|
|
9
|
+
entry_params?: string;
|
|
10
|
+
stop_type: string;
|
|
11
|
+
stop_params?: string;
|
|
12
|
+
target_r_multiples: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function saveStrategyTool(args: SaveStrategyArgs, deps: IntelApiDeps): Promise<Record<string, unknown> | {
|
|
15
|
+
error: string;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Tool: save_strategy — create or update a strategy in the Strategy Box.
|
|
2
|
+
// Posts a declarative strategy config to the Intelligence API.
|
|
3
|
+
import { fetchIntelApi } from './intel-api.js';
|
|
4
|
+
export async function saveStrategyTool(args, deps) {
|
|
5
|
+
let conditions;
|
|
6
|
+
try {
|
|
7
|
+
conditions = JSON.parse(args.conditions);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return { error: 'conditions must be valid JSON array of {type, params} objects' };
|
|
11
|
+
}
|
|
12
|
+
let entryParams = {};
|
|
13
|
+
if (args.entry_params) {
|
|
14
|
+
try {
|
|
15
|
+
entryParams = JSON.parse(args.entry_params);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return { error: 'entry_params must be valid JSON' };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
let stopParams = {};
|
|
22
|
+
if (args.stop_params) {
|
|
23
|
+
try {
|
|
24
|
+
stopParams = JSON.parse(args.stop_params);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return { error: 'stop_params must be valid JSON' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const config = {
|
|
31
|
+
name: args.name,
|
|
32
|
+
description: args.description ?? '',
|
|
33
|
+
version: 1,
|
|
34
|
+
regimeWhitelist: args.regimes.split(',').map(s => s.trim()),
|
|
35
|
+
minConfidence: 0.7,
|
|
36
|
+
directionRule: args.direction_rule,
|
|
37
|
+
conditions,
|
|
38
|
+
entryRule: { type: args.entry_type, params: entryParams },
|
|
39
|
+
stopRule: { type: args.stop_type, params: stopParams },
|
|
40
|
+
targetRMultiples: args.target_r_multiples.split(',').map(s => parseFloat(s.trim())),
|
|
41
|
+
};
|
|
42
|
+
return fetchIntelApi('/api/strategies', deps, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
body: config,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IntelApiDeps } from './intel-api.js';
|
|
2
|
+
import type { PositionDecisionsClient } from '../ingest/position-decisions-client.js';
|
|
3
|
+
export interface ScanPairsArgs {
|
|
4
|
+
/** Minimum confluence score (number of conditions met) to include in rankings. */
|
|
5
|
+
min_score?: number;
|
|
6
|
+
/** Optional whitelist of symbols to scan. When omitted, scans all configured pairs. */
|
|
7
|
+
symbols?: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ScanPairsDecisionsDeps {
|
|
10
|
+
decisionsClient?: PositionDecisionsClient;
|
|
11
|
+
userId?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function scanPairsTool(args: ScanPairsArgs, deps: IntelApiDeps, decisionsDeps?: ScanPairsDecisionsDeps): Promise<Record<string, unknown> | {
|
|
14
|
+
error: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const __testing__: {
|
|
17
|
+
resetCaches(): void;
|
|
18
|
+
};
|