@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,194 @@
|
|
|
1
|
+
// Tool: check_position_health — Real-time position health monitor.
|
|
2
|
+
// Computes heat, stop proximity, time-in-trade, and risk flags for open positions.
|
|
3
|
+
// Pure local computation — no API calls needed.
|
|
4
|
+
export function checkPositionHealthTool(args) {
|
|
5
|
+
const { positions, account_balance } = args;
|
|
6
|
+
if (!positions || positions.length === 0) {
|
|
7
|
+
return {
|
|
8
|
+
positions: [],
|
|
9
|
+
portfolio: {
|
|
10
|
+
totalHeat: 0,
|
|
11
|
+
totalNotional: 0,
|
|
12
|
+
totalPnl: 0,
|
|
13
|
+
positionCount: 0,
|
|
14
|
+
heatStatus: 'LOW',
|
|
15
|
+
alerts: [],
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (account_balance <= 0) {
|
|
20
|
+
return {
|
|
21
|
+
positions: [],
|
|
22
|
+
portfolio: {
|
|
23
|
+
totalHeat: 0,
|
|
24
|
+
totalNotional: 0,
|
|
25
|
+
totalPnl: 0,
|
|
26
|
+
positionCount: 0,
|
|
27
|
+
heatStatus: 'CRITICAL',
|
|
28
|
+
alerts: ['Account balance is zero or negative'],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
const portfolioAlerts = [];
|
|
34
|
+
let totalHeat = 0;
|
|
35
|
+
let totalNotional = 0;
|
|
36
|
+
let totalPnl = 0;
|
|
37
|
+
const healthResults = positions.map((pos) => {
|
|
38
|
+
const alerts = [];
|
|
39
|
+
const dirMul = pos.side === 'LONG' ? 1 : -1;
|
|
40
|
+
// ── P&L ──
|
|
41
|
+
const pnl = (pos.current_price - pos.entry_price) * pos.quantity * dirMul;
|
|
42
|
+
const notional = pos.entry_price * pos.quantity;
|
|
43
|
+
const pnlPercent = notional > 0 ? (pnl / notional) * 100 : 0;
|
|
44
|
+
// Risk per unit = distance from entry to stop
|
|
45
|
+
const riskPerUnit = Math.abs(pos.entry_price - pos.stop_price);
|
|
46
|
+
const riskAmount = riskPerUnit * pos.quantity;
|
|
47
|
+
const pnlR = riskAmount > 0 ? pnl / riskAmount : 0;
|
|
48
|
+
// ── Stop tracking ──
|
|
49
|
+
const distToStop = pos.side === 'LONG'
|
|
50
|
+
? pos.current_price - pos.stop_price
|
|
51
|
+
: pos.stop_price - pos.current_price;
|
|
52
|
+
const distanceToStopPercent = pos.current_price > 0 ? (distToStop / pos.current_price) * 100 : 0;
|
|
53
|
+
const distanceToStopR = riskPerUnit > 0 ? distToStop / riskPerUnit : 0;
|
|
54
|
+
let stopStatus;
|
|
55
|
+
if (distToStop <= 0) {
|
|
56
|
+
stopStatus = 'BREACHED';
|
|
57
|
+
alerts.push(`STOP BREACHED — price has passed stop level ($${pos.stop_price})`);
|
|
58
|
+
}
|
|
59
|
+
else if (distanceToStopR < 0.3) {
|
|
60
|
+
stopStatus = 'CRITICAL';
|
|
61
|
+
alerts.push(`Stop critically close (${distanceToStopR.toFixed(2)}R away)`);
|
|
62
|
+
}
|
|
63
|
+
else if (distanceToStopR < 0.7) {
|
|
64
|
+
stopStatus = 'CLOSE';
|
|
65
|
+
alerts.push(`Stop approaching (${distanceToStopR.toFixed(2)}R away)`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
stopStatus = 'SAFE';
|
|
69
|
+
}
|
|
70
|
+
// ── Target tracking ──
|
|
71
|
+
let distanceToTargetPercent = null;
|
|
72
|
+
let distanceToTargetR = null;
|
|
73
|
+
let targetReached = false;
|
|
74
|
+
if (pos.target_price != null) {
|
|
75
|
+
const distToTarget = pos.side === 'LONG'
|
|
76
|
+
? pos.target_price - pos.current_price
|
|
77
|
+
: pos.current_price - pos.target_price;
|
|
78
|
+
distanceToTargetPercent = pos.current_price > 0 ? (distToTarget / pos.current_price) * 100 : 0;
|
|
79
|
+
distanceToTargetR = riskPerUnit > 0 ? distToTarget / riskPerUnit : 0;
|
|
80
|
+
targetReached = distToTarget <= 0;
|
|
81
|
+
if (targetReached) {
|
|
82
|
+
alerts.push('TARGET REACHED — consider taking profit');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// If past target but still holding
|
|
86
|
+
if (pnlR >= 2 && !targetReached) {
|
|
87
|
+
alerts.push(`At ${pnlR.toFixed(1)}R profit — consider trailing stop or partial take-profit`);
|
|
88
|
+
}
|
|
89
|
+
// ── Heat (position risk as % of account) ──
|
|
90
|
+
const heatPercent = (riskAmount / account_balance) * 100;
|
|
91
|
+
const notionalPercent = (notional / account_balance) * 100;
|
|
92
|
+
if (heatPercent > 5) {
|
|
93
|
+
alerts.push(`High heat: ${heatPercent.toFixed(1)}% of account at risk in this position`);
|
|
94
|
+
}
|
|
95
|
+
else if (heatPercent > 3) {
|
|
96
|
+
alerts.push(`Elevated heat: ${heatPercent.toFixed(1)}% of account at risk`);
|
|
97
|
+
}
|
|
98
|
+
totalHeat += heatPercent;
|
|
99
|
+
totalNotional += notional;
|
|
100
|
+
totalPnl += pnl;
|
|
101
|
+
// ── Time in trade ──
|
|
102
|
+
const entryMs = new Date(pos.entry_time).getTime();
|
|
103
|
+
const elapsed = Math.max(0, now - entryMs);
|
|
104
|
+
const minutes = Math.floor(elapsed / 60_000);
|
|
105
|
+
const hours = Math.floor(minutes / 60);
|
|
106
|
+
let timeFormatted;
|
|
107
|
+
if (hours >= 24) {
|
|
108
|
+
const days = Math.floor(hours / 24);
|
|
109
|
+
timeFormatted = `${days}d ${hours % 24}h`;
|
|
110
|
+
}
|
|
111
|
+
else if (hours > 0) {
|
|
112
|
+
timeFormatted = `${hours}h ${minutes % 60}m`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
timeFormatted = `${minutes}m`;
|
|
116
|
+
}
|
|
117
|
+
let timeStatus;
|
|
118
|
+
if (minutes < 15)
|
|
119
|
+
timeStatus = 'FRESH';
|
|
120
|
+
else if (minutes < 240)
|
|
121
|
+
timeStatus = 'NORMAL';
|
|
122
|
+
else if (minutes < 720) {
|
|
123
|
+
timeStatus = 'EXTENDED';
|
|
124
|
+
if (pnlR < 0)
|
|
125
|
+
alerts.push(`Held ${timeFormatted} underwater — review thesis`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
timeStatus = 'STALE';
|
|
129
|
+
alerts.push(`Position held ${timeFormatted} — is original thesis still valid?`);
|
|
130
|
+
}
|
|
131
|
+
// Underwater for too long
|
|
132
|
+
if (pnlR < -0.5 && minutes > 60) {
|
|
133
|
+
alerts.push(`Underwater (${pnlR.toFixed(1)}R) for ${timeFormatted} — thesis may be invalid`);
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
symbol: pos.symbol,
|
|
137
|
+
side: pos.side,
|
|
138
|
+
pnl: +pnl.toFixed(2),
|
|
139
|
+
pnlPercent: +pnlPercent.toFixed(2),
|
|
140
|
+
pnlR: +pnlR.toFixed(2),
|
|
141
|
+
distanceToStopPercent: +distanceToStopPercent.toFixed(2),
|
|
142
|
+
distanceToStopR: +distanceToStopR.toFixed(2),
|
|
143
|
+
stopStatus,
|
|
144
|
+
distanceToTargetPercent: distanceToTargetPercent != null ? +distanceToTargetPercent.toFixed(2) : null,
|
|
145
|
+
distanceToTargetR: distanceToTargetR != null ? +distanceToTargetR.toFixed(2) : null,
|
|
146
|
+
targetReached,
|
|
147
|
+
heatPercent: +heatPercent.toFixed(2),
|
|
148
|
+
notionalPercent: +notionalPercent.toFixed(2),
|
|
149
|
+
timeInTradeMinutes: minutes,
|
|
150
|
+
timeInTradeFormatted: timeFormatted,
|
|
151
|
+
timeStatus,
|
|
152
|
+
alerts,
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
// ── Portfolio-level assessment ──
|
|
156
|
+
let heatStatus;
|
|
157
|
+
if (totalHeat >= 15) {
|
|
158
|
+
heatStatus = 'CRITICAL';
|
|
159
|
+
portfolioAlerts.push(`CRITICAL portfolio heat: ${totalHeat.toFixed(1)}% — reduce exposure immediately`);
|
|
160
|
+
}
|
|
161
|
+
else if (totalHeat >= 10) {
|
|
162
|
+
heatStatus = 'HIGH';
|
|
163
|
+
portfolioAlerts.push(`High portfolio heat: ${totalHeat.toFixed(1)}% — no new positions`);
|
|
164
|
+
}
|
|
165
|
+
else if (totalHeat >= 6) {
|
|
166
|
+
heatStatus = 'ELEVATED';
|
|
167
|
+
portfolioAlerts.push(`Elevated portfolio heat: ${totalHeat.toFixed(1)}% — be cautious with new entries`);
|
|
168
|
+
}
|
|
169
|
+
else if (totalHeat >= 3) {
|
|
170
|
+
heatStatus = 'MODERATE';
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
heatStatus = 'LOW';
|
|
174
|
+
}
|
|
175
|
+
const breachedCount = healthResults.filter(p => p.stopStatus === 'BREACHED').length;
|
|
176
|
+
if (breachedCount > 0) {
|
|
177
|
+
portfolioAlerts.push(`${breachedCount} position(s) past stop level — exit immediately`);
|
|
178
|
+
}
|
|
179
|
+
const criticalCount = healthResults.filter(p => p.stopStatus === 'CRITICAL').length;
|
|
180
|
+
if (criticalCount > 0) {
|
|
181
|
+
portfolioAlerts.push(`${criticalCount} position(s) critically close to stop`);
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
positions: healthResults,
|
|
185
|
+
portfolio: {
|
|
186
|
+
totalHeat: +totalHeat.toFixed(2),
|
|
187
|
+
totalNotional: +totalNotional.toFixed(2),
|
|
188
|
+
totalPnl: +totalPnl.toFixed(2),
|
|
189
|
+
positionCount: positions.length,
|
|
190
|
+
heatStatus,
|
|
191
|
+
alerts: portfolioAlerts,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PluginRuntime } from '../onboarding/runtime.js';
|
|
2
|
+
import type { IExchangeAdapter } from '../exchange-adapter.js';
|
|
3
|
+
import type { TradingMode } from '../types.js';
|
|
4
|
+
export interface ClearExchangeCredentialsArgs {
|
|
5
|
+
/** Must be `true`. Required so the skill's tool-discovery probe (which
|
|
6
|
+
* passes empty args) never accidentally wipes credentials on startup. */
|
|
7
|
+
confirm?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ClearExchangeCredentialsResult {
|
|
10
|
+
ok: boolean;
|
|
11
|
+
message: string;
|
|
12
|
+
modeBefore: TradingMode;
|
|
13
|
+
mode: TradingMode;
|
|
14
|
+
rolledBackToPaper: boolean;
|
|
15
|
+
readiness: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ClearExchangeCredentialsDeps {
|
|
18
|
+
runtime: PluginRuntime;
|
|
19
|
+
adapterDeps: {
|
|
20
|
+
adapter: IExchangeAdapter;
|
|
21
|
+
};
|
|
22
|
+
configPath?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function clearExchangeCredentialsTool(args: ClearExchangeCredentialsArgs, deps: ClearExchangeCredentialsDeps): Promise<ClearExchangeCredentialsResult>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// clear_exchange_credentials — operator-only plugin tool.
|
|
2
|
+
//
|
|
3
|
+
// Removes the `exchange` section from ~/.reefclaw/plugin-config.json and,
|
|
4
|
+
// if the plugin is currently running in a mode that requires credentials
|
|
5
|
+
// (SHADOW, MICRO_LIVE, LIVE), de-escalates to PAPER via runtime.reconnect().
|
|
6
|
+
// This is the "pull the plug" button for when the operator wants to
|
|
7
|
+
// remove Binance keys from the machine entirely.
|
|
8
|
+
//
|
|
9
|
+
// Security:
|
|
10
|
+
// - Does NOT accept a new secret — pure delete.
|
|
11
|
+
// - Always de-escalates to PAPER on mode rollback; never stays in a
|
|
12
|
+
// live mode without credentials (would crash the adapter on first
|
|
13
|
+
// order anyway).
|
|
14
|
+
import { updatePluginConfig } from '../config/plugin-config-io.js';
|
|
15
|
+
import { logger } from '../logger.js';
|
|
16
|
+
const TAG = 'clear-exchange-credentials';
|
|
17
|
+
export async function clearExchangeCredentialsTool(args, deps) {
|
|
18
|
+
const modeBefore = deps.runtime.mode;
|
|
19
|
+
if (args?.confirm !== true) {
|
|
20
|
+
return {
|
|
21
|
+
ok: false,
|
|
22
|
+
message: 'clear_exchange_credentials requires confirm: true (prevents accidental probe wipes)',
|
|
23
|
+
modeBefore,
|
|
24
|
+
mode: modeBefore,
|
|
25
|
+
rolledBackToPaper: false,
|
|
26
|
+
readiness: deps.runtime.adapter.readiness,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
updatePluginConfig({ exchange: undefined }, deps.configPath);
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
34
|
+
logger.error(TAG, `Failed to clear credentials: ${msg}`);
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
message: `Failed to remove credentials from config: ${msg}`,
|
|
38
|
+
modeBefore,
|
|
39
|
+
mode: modeBefore,
|
|
40
|
+
rolledBackToPaper: false,
|
|
41
|
+
readiness: deps.runtime.adapter.readiness,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
logger.info(TAG, 'Exchange credentials cleared from plugin-config.json');
|
|
45
|
+
// If we were in a live mode, fall back to PAPER — running SHADOW or
|
|
46
|
+
// MICRO_LIVE without credentials is a guaranteed broken state.
|
|
47
|
+
let rolledBackToPaper = false;
|
|
48
|
+
if (modeBefore !== 'PAPER') {
|
|
49
|
+
try {
|
|
50
|
+
// Also persist the mode downgrade so a subsequent restart doesn't
|
|
51
|
+
// try to bring up a live adapter with no credentials.
|
|
52
|
+
updatePluginConfig({ tradingMode: 'PAPER' }, deps.configPath);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
logger.warn(TAG, `Failed to persist PAPER fallback: ${err instanceof Error ? err.message : String(err)}`);
|
|
56
|
+
}
|
|
57
|
+
await deps.runtime.reconnect({ mode: 'PAPER', exchange: null }, { adapterDeps: deps.adapterDeps });
|
|
58
|
+
rolledBackToPaper = true;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
ok: true,
|
|
62
|
+
message: rolledBackToPaper
|
|
63
|
+
? `Credentials cleared and trading mode rolled back from ${modeBefore} to PAPER`
|
|
64
|
+
: 'Credentials cleared',
|
|
65
|
+
modeBefore,
|
|
66
|
+
mode: deps.runtime.mode,
|
|
67
|
+
rolledBackToPaper,
|
|
68
|
+
readiness: deps.runtime.adapter.readiness,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BinancePublicApi } from '../ccxt/binance-public.js';
|
|
2
|
+
import type { IExchangeAdapter } from '../exchange-adapter.js';
|
|
3
|
+
import type { CcxtOrder } from '../types.js';
|
|
4
|
+
import { type ClosePositionArgs } from './assessment-validation.js';
|
|
5
|
+
import { type AutoCaptureContext } from '../ingest/position-auto-capture.js';
|
|
6
|
+
import { type ExitGateMode } from '../config/position-review-config.js';
|
|
7
|
+
export declare function closePositionTool(args: ClosePositionArgs, deps: {
|
|
8
|
+
binanceApi: BinancePublicApi;
|
|
9
|
+
adapter: IExchangeAdapter;
|
|
10
|
+
autoCapture?: AutoCaptureContext;
|
|
11
|
+
/** Override for tests — production reads from plugin-config.json on each
|
|
12
|
+
* call so the flag can be flipped without a restart. */
|
|
13
|
+
exitGateMode?: ExitGateMode;
|
|
14
|
+
}): Promise<CcxtOrder | {
|
|
15
|
+
error: string;
|
|
16
|
+
}>;
|
|
17
|
+
/** Test seam — clears the circuit-breaker state between unit tests. */
|
|
18
|
+
export declare const __testing__: {
|
|
19
|
+
resetCircuitBreaker(): void;
|
|
20
|
+
/** Inspect current circuit-breaker state — for assertions. */
|
|
21
|
+
getCircuitBreakerCount(): number;
|
|
22
|
+
};
|