@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,32 @@
|
|
|
1
|
+
import type { CcxtBalance, CcxtPosition } from '../types.js';
|
|
2
|
+
/** UTC date in YYYY-MM-DD form — same shape as `closedAt.slice(0, 10)`. */
|
|
3
|
+
export declare function utcDateString(ms: number): string;
|
|
4
|
+
/** Epoch ms for the most recent 00:00:00 UTC boundary at-or-before `ms`. */
|
|
5
|
+
export declare function utcMidnightMs(ms?: number): number;
|
|
6
|
+
export declare class LiveBalanceEnricher {
|
|
7
|
+
private sessionStartNav;
|
|
8
|
+
private fills;
|
|
9
|
+
private allTimeSeed;
|
|
10
|
+
private realizedTodaySeed;
|
|
11
|
+
private realizedTodaySeedDate;
|
|
12
|
+
setSessionStartNav(nav: number): void;
|
|
13
|
+
getSessionStartNav(): number;
|
|
14
|
+
/** Seed all-time realized PnL from Intelligence DB (pre-session history). */
|
|
15
|
+
seedAllTimeRealized(total: number): void;
|
|
16
|
+
/** Seed today's realized PnL from Binance's income endpoint. The seed
|
|
17
|
+
* represents everything Binance has booked for the current UTC day. The
|
|
18
|
+
* webapp dashboard now derives Realized as (totalPnl - unrealizedPnl)
|
|
19
|
+
* for guaranteed consistency with Day P&L (see webapp trades.ts), so
|
|
20
|
+
* this seed is used only for sessionStartNav anchoring + the
|
|
21
|
+
* `realizedPnlToday` field that older consumers may still read. */
|
|
22
|
+
seedRealizedPnlToday(amount: number, dateUtc?: string): void;
|
|
23
|
+
/** Record a completed fill for realized PnL tracking. Currently unused in
|
|
24
|
+
* production (the income-endpoint seed is the sole source of Realized);
|
|
25
|
+
* retained for tests that exercise the accumulator semantics. */
|
|
26
|
+
recordFill(pnl: number, fee: number): void;
|
|
27
|
+
/**
|
|
28
|
+
* Enrich a raw CCXT balance with session PnL, equity, and sessionStartNav.
|
|
29
|
+
* Uses cached positions from the reconciler (no extra API call).
|
|
30
|
+
*/
|
|
31
|
+
enrich(rawBalance: CcxtBalance, positions: CcxtPosition[]): CcxtBalance;
|
|
32
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// LiveBalanceEnricher — attaches session PnL + equity fields to raw CCXT
|
|
2
|
+
// balance responses from the LiveAdapter, matching the enriched format that
|
|
3
|
+
// ExchangeSimulator.getBalance() produces. This lets the skill's
|
|
4
|
+
// fetchFreshBalance() process live-mode responses identically to paper mode.
|
|
5
|
+
import { getQuoteWalletBalance } from '../balance-utils.js';
|
|
6
|
+
import { logger } from '../logger.js';
|
|
7
|
+
const TAG = 'live-balance-enricher';
|
|
8
|
+
/** UTC date in YYYY-MM-DD form — same shape as `closedAt.slice(0, 10)`. */
|
|
9
|
+
export function utcDateString(ms) {
|
|
10
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
11
|
+
}
|
|
12
|
+
/** Epoch ms for the most recent 00:00:00 UTC boundary at-or-before `ms`. */
|
|
13
|
+
export function utcMidnightMs(ms = Date.now()) {
|
|
14
|
+
return new Date(new Date(ms).toISOString().slice(0, 10) + 'T00:00:00Z').getTime();
|
|
15
|
+
}
|
|
16
|
+
export class LiveBalanceEnricher {
|
|
17
|
+
sessionStartNav = 0;
|
|
18
|
+
fills = [];
|
|
19
|
+
allTimeSeed = 0; // seeded from Intelligence DB
|
|
20
|
+
// Today's realized P&L seeded from Binance income endpoint at boot. Lets the
|
|
21
|
+
// dashboard's Realized KPI exactly match Binance's "Today's Realized PNL"
|
|
22
|
+
// even after a plugin restart (without this, sessionStartNav resets to the
|
|
23
|
+
// current NAV at boot and the day's realized P&L appears as $0). Reset to 0
|
|
24
|
+
// when the enricher's day rolls over past midnight UTC; subsequent fills are
|
|
25
|
+
// accumulated via recordFill() exactly as before.
|
|
26
|
+
realizedTodaySeed = 0;
|
|
27
|
+
realizedTodaySeedDate = utcDateString(Date.now());
|
|
28
|
+
setSessionStartNav(nav) {
|
|
29
|
+
this.sessionStartNav = nav;
|
|
30
|
+
logger.info(TAG, `Session-start NAV set: ${nav}`);
|
|
31
|
+
}
|
|
32
|
+
getSessionStartNav() {
|
|
33
|
+
return this.sessionStartNav;
|
|
34
|
+
}
|
|
35
|
+
/** Seed all-time realized PnL from Intelligence DB (pre-session history). */
|
|
36
|
+
seedAllTimeRealized(total) {
|
|
37
|
+
this.allTimeSeed = total;
|
|
38
|
+
}
|
|
39
|
+
/** Seed today's realized PnL from Binance's income endpoint. The seed
|
|
40
|
+
* represents everything Binance has booked for the current UTC day. The
|
|
41
|
+
* webapp dashboard now derives Realized as (totalPnl - unrealizedPnl)
|
|
42
|
+
* for guaranteed consistency with Day P&L (see webapp trades.ts), so
|
|
43
|
+
* this seed is used only for sessionStartNav anchoring + the
|
|
44
|
+
* `realizedPnlToday` field that older consumers may still read. */
|
|
45
|
+
seedRealizedPnlToday(amount, dateUtc = utcDateString(Date.now())) {
|
|
46
|
+
this.realizedTodaySeed = amount;
|
|
47
|
+
this.realizedTodaySeedDate = dateUtc;
|
|
48
|
+
logger.info(TAG, `Today's realized PnL seeded from Binance: ${amount.toFixed(4)} (date=${dateUtc})`);
|
|
49
|
+
}
|
|
50
|
+
/** Record a completed fill for realized PnL tracking. Currently unused in
|
|
51
|
+
* production (the income-endpoint seed is the sole source of Realized);
|
|
52
|
+
* retained for tests that exercise the accumulator semantics. */
|
|
53
|
+
recordFill(pnl, fee) {
|
|
54
|
+
this.fills.push({
|
|
55
|
+
realizedPnl: pnl,
|
|
56
|
+
fee,
|
|
57
|
+
closedAt: new Date().toISOString(),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Enrich a raw CCXT balance with session PnL, equity, and sessionStartNav.
|
|
62
|
+
* Uses cached positions from the reconciler (no extra API call).
|
|
63
|
+
*/
|
|
64
|
+
enrich(rawBalance, positions) {
|
|
65
|
+
const quoteTotal = getQuoteWalletBalance(rawBalance);
|
|
66
|
+
// Compute unrealized P&L from live positions
|
|
67
|
+
let unrealizedPnl = 0;
|
|
68
|
+
for (const p of positions) {
|
|
69
|
+
unrealizedPnl += p.unrealizedPnl ?? 0;
|
|
70
|
+
}
|
|
71
|
+
// Live equity = wallet balance + unrealized P&L.
|
|
72
|
+
// Binance wallet already accounts for margin deductions.
|
|
73
|
+
const equity = quoteTotal + unrealizedPnl;
|
|
74
|
+
// Realized P&L from fills accumulated this session
|
|
75
|
+
const today = utcDateString(Date.now());
|
|
76
|
+
// UTC rollover: if the seed is from a previous day, drop it. Today's
|
|
77
|
+
// realized then comes purely from fills the WS has observed since 00:00
|
|
78
|
+
// UTC (which is correct — anything earlier belongs to yesterday).
|
|
79
|
+
if (this.realizedTodaySeedDate !== today) {
|
|
80
|
+
this.realizedTodaySeed = 0;
|
|
81
|
+
this.realizedTodaySeedDate = today;
|
|
82
|
+
}
|
|
83
|
+
let realizedPnlToday = this.realizedTodaySeed;
|
|
84
|
+
let sessionRealized = 0;
|
|
85
|
+
let totalFees = 0;
|
|
86
|
+
for (const f of this.fills) {
|
|
87
|
+
const net = f.realizedPnl - f.fee;
|
|
88
|
+
sessionRealized += net;
|
|
89
|
+
totalFees += f.fee;
|
|
90
|
+
if (f.closedAt.slice(0, 10) === today) {
|
|
91
|
+
realizedPnlToday += net;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const realizedPnlAllTime = this.allTimeSeed + sessionRealized;
|
|
95
|
+
const round4 = (n) => +n.toFixed(4);
|
|
96
|
+
const enriched = { ...rawBalance };
|
|
97
|
+
enriched.realizedPnlAllTime = round4(realizedPnlAllTime);
|
|
98
|
+
enriched.realizedPnlToday = round4(realizedPnlToday);
|
|
99
|
+
enriched.totalRoundtripFees = round4(totalFees);
|
|
100
|
+
enriched.equity = round4(equity);
|
|
101
|
+
enriched.sessionStartNav = round4(this.sessionStartNav);
|
|
102
|
+
return enriched;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { BinancePrivateApi } from '../ccxt/binance-private.js';
|
|
2
|
+
import type { CcxtOrder } from '../types.js';
|
|
3
|
+
import type { BracketApi } from './bracket-manager.js';
|
|
4
|
+
import type { BracketLegParams } from './bracket-params.js';
|
|
5
|
+
export declare class LiveBracketApi implements BracketApi {
|
|
6
|
+
private readonly api;
|
|
7
|
+
constructor(api: BinancePrivateApi);
|
|
8
|
+
submitBracketLeg(leg: BracketLegParams): Promise<CcxtOrder>;
|
|
9
|
+
cancelOrderByClientId(clientOrderId: string, symbol: string): Promise<void>;
|
|
10
|
+
/** ROOT-CAUSE FIX 2026-05-16: disable the per-symbol countdownCancelAll
|
|
11
|
+
* dead-man's-switch before bracket placement (see BinancePrivateApi). */
|
|
12
|
+
disableCountdownCancelAll(symbol: string): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Thin BracketApi implementation backed by BinancePrivateApi. Kept separate
|
|
2
|
+
// from BracketManager so tests can mock the minimal surface without pulling
|
|
3
|
+
// in CCXT.
|
|
4
|
+
export class LiveBracketApi {
|
|
5
|
+
api;
|
|
6
|
+
constructor(api) {
|
|
7
|
+
this.api = api;
|
|
8
|
+
}
|
|
9
|
+
async submitBracketLeg(leg) {
|
|
10
|
+
return this.api.createBracketOrder(leg.symbol, leg.type, leg.side, leg.amount, leg.params);
|
|
11
|
+
}
|
|
12
|
+
async cancelOrderByClientId(clientOrderId, symbol) {
|
|
13
|
+
await this.api.cancelOrderByClientId(clientOrderId, symbol);
|
|
14
|
+
}
|
|
15
|
+
/** ROOT-CAUSE FIX 2026-05-16: disable the per-symbol countdownCancelAll
|
|
16
|
+
* dead-man's-switch before bracket placement (see BinancePrivateApi). */
|
|
17
|
+
async disableCountdownCancelAll(symbol) {
|
|
18
|
+
await this.api.disableCountdownCancelAll(symbol);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { CcxtPosition, CcxtBalance, CcxtOrder } from '../types.js';
|
|
3
|
+
/** A single position line in an ACCOUNT_UPDATE event. */
|
|
4
|
+
export interface ParsedPositionUpdate {
|
|
5
|
+
symbol: string;
|
|
6
|
+
/** 'long' | 'short' — collapsed from Binance's {LONG, SHORT, BOTH} where
|
|
7
|
+
* BOTH is resolved from the sign of `quantity` (positive = long, negative = short).
|
|
8
|
+
* Zero quantity → 'flat', meaning the position should be removed. */
|
|
9
|
+
side: 'long' | 'short' | 'flat';
|
|
10
|
+
quantity: number;
|
|
11
|
+
entryPrice: number;
|
|
12
|
+
unrealizedPnl: number;
|
|
13
|
+
marginType?: 'cross' | 'isolated';
|
|
14
|
+
/** Raw positionSide from Binance — used to sanity-check one-way mode.
|
|
15
|
+
* On a one-way account, this is always 'BOTH'. */
|
|
16
|
+
positionSide?: 'LONG' | 'SHORT' | 'BOTH';
|
|
17
|
+
}
|
|
18
|
+
/** A single balance line in an ACCOUNT_UPDATE event. */
|
|
19
|
+
export interface ParsedBalanceUpdate {
|
|
20
|
+
asset: string;
|
|
21
|
+
walletBalance: number;
|
|
22
|
+
crossWallet: number;
|
|
23
|
+
balanceChange: number;
|
|
24
|
+
}
|
|
25
|
+
/** The full payload of an ACCOUNT_UPDATE event (after parsing). */
|
|
26
|
+
export interface ParsedAccountUpdate {
|
|
27
|
+
eventTime: number;
|
|
28
|
+
transactionTime: number;
|
|
29
|
+
reason: string;
|
|
30
|
+
positions: ParsedPositionUpdate[];
|
|
31
|
+
balances: ParsedBalanceUpdate[];
|
|
32
|
+
}
|
|
33
|
+
/** The payload of an ORDER_TRADE_UPDATE event (after parsing). */
|
|
34
|
+
export interface ParsedOrderUpdate {
|
|
35
|
+
eventTime: number;
|
|
36
|
+
transactionTime: number;
|
|
37
|
+
symbol: string;
|
|
38
|
+
orderId: string;
|
|
39
|
+
clientOrderId?: string;
|
|
40
|
+
side: 'buy' | 'sell';
|
|
41
|
+
type: 'market' | 'limit' | 'stop_market' | 'take_profit_market' | 'other';
|
|
42
|
+
status: 'open' | 'closed' | 'canceled';
|
|
43
|
+
executionType: string;
|
|
44
|
+
origQuantity: number;
|
|
45
|
+
cumulativeFilled: number;
|
|
46
|
+
lastFilledQty: number;
|
|
47
|
+
avgPrice: number | null;
|
|
48
|
+
origPrice: number | null;
|
|
49
|
+
lastFillPrice: number | null;
|
|
50
|
+
commission: number;
|
|
51
|
+
commissionAsset: string;
|
|
52
|
+
/** Raw Binance timeInForce (GTC, IOC, etc.) — preserved for round-trip. */
|
|
53
|
+
timeInForce: string;
|
|
54
|
+
/** Stable Binance trade id from `o.t`. The idempotency key for the audit
|
|
55
|
+
* trail. Present only on executionType='TRADE'; null on NEW/CANCELED. */
|
|
56
|
+
tradeId: string | null;
|
|
57
|
+
/** Reduce-only flag from `o.R`. True for bracket SL/TP fills + manual
|
|
58
|
+
* reduce-only orders. */
|
|
59
|
+
reduceOnly: boolean;
|
|
60
|
+
/** Maker flag from `o.m`. True if this fill matched a resting order. */
|
|
61
|
+
maker: boolean;
|
|
62
|
+
/** Realised PnL on this specific fill, from `o.rp`. Negative on losses. */
|
|
63
|
+
realizedPnl: number;
|
|
64
|
+
}
|
|
65
|
+
/** A REST snapshot used to seed the store on connect + reconcile drift. */
|
|
66
|
+
export interface RestSnapshot {
|
|
67
|
+
timestamp: number;
|
|
68
|
+
positions: CcxtPosition[];
|
|
69
|
+
balance: CcxtBalance | null;
|
|
70
|
+
openOrders: CcxtOrder[];
|
|
71
|
+
}
|
|
72
|
+
export type DriftSeverity = 'none' | 'minor' | 'major';
|
|
73
|
+
export interface PositionDriftDetail {
|
|
74
|
+
symbol: string;
|
|
75
|
+
localContracts: number;
|
|
76
|
+
restContracts: number;
|
|
77
|
+
localSide: string | null;
|
|
78
|
+
restSide: string | null;
|
|
79
|
+
kind: 'new' | 'closed' | 'size_changed' | 'side_changed';
|
|
80
|
+
}
|
|
81
|
+
export interface BalanceDriftDetail {
|
|
82
|
+
asset: string;
|
|
83
|
+
localTotal: number;
|
|
84
|
+
restTotal: number;
|
|
85
|
+
deltaBps: number;
|
|
86
|
+
}
|
|
87
|
+
export interface OrderDriftDetail {
|
|
88
|
+
orderId: string;
|
|
89
|
+
symbol: string;
|
|
90
|
+
kind: 'missing_locally' | 'missing_on_rest';
|
|
91
|
+
}
|
|
92
|
+
export interface StateDrift {
|
|
93
|
+
severity: DriftSeverity;
|
|
94
|
+
positions: PositionDriftDetail[];
|
|
95
|
+
balance: BalanceDriftDetail[];
|
|
96
|
+
orders: OrderDriftDetail[];
|
|
97
|
+
summary: string;
|
|
98
|
+
}
|
|
99
|
+
/** Thresholds for drift classification. All tuned conservatively — minor
|
|
100
|
+
* drifts are expected background noise (in-flight events); major drifts
|
|
101
|
+
* are structural and trigger a forced resync. */
|
|
102
|
+
export interface DriftThresholds {
|
|
103
|
+
/** Balance delta below this (basis points of the REST value) is minor. */
|
|
104
|
+
balanceMinorBps: number;
|
|
105
|
+
/** Position contract delta below this is minor. */
|
|
106
|
+
positionMinorContracts: number;
|
|
107
|
+
}
|
|
108
|
+
export type LiveStateStoreEvents = {
|
|
109
|
+
/** Emitted on every successful apply. Useful for observability / push-to-skill. */
|
|
110
|
+
stateChanged: (kind: 'snapshot' | 'account_update' | 'order_update' | 'algo_refresh' | 'mark_refresh') => void;
|
|
111
|
+
/** Emitted when apply fails (parse error, hedge-mode event, etc.). */
|
|
112
|
+
applyError: (kind: string, reason: string) => void;
|
|
113
|
+
};
|
|
114
|
+
export declare class LiveStateStore extends EventEmitter {
|
|
115
|
+
private positions;
|
|
116
|
+
private balances;
|
|
117
|
+
private orders;
|
|
118
|
+
private lastSnapshotAt;
|
|
119
|
+
private lastAccountUpdateAt;
|
|
120
|
+
private lastOrderUpdateAt;
|
|
121
|
+
private readonly thresholds;
|
|
122
|
+
constructor(thresholds?: Partial<DriftThresholds>);
|
|
123
|
+
/** Get positions, optionally filtered by symbol. Returns clones. */
|
|
124
|
+
getPositions(symbol?: string): CcxtPosition[];
|
|
125
|
+
/** Get the current balance view. Matches the CCXT shape. */
|
|
126
|
+
getBalance(): CcxtBalance;
|
|
127
|
+
/** Get open orders, optionally filtered by symbol. Returns clones. */
|
|
128
|
+
getOpenOrders(symbol?: string): CcxtOrder[];
|
|
129
|
+
/** Observability — last-apply timestamps for each write path. */
|
|
130
|
+
getHealth(): {
|
|
131
|
+
lastSnapshotAt: number | null;
|
|
132
|
+
lastAccountUpdateAt: number | null;
|
|
133
|
+
lastOrderUpdateAt: number | null;
|
|
134
|
+
positionCount: number;
|
|
135
|
+
orderCount: number;
|
|
136
|
+
balanceAssetCount: number;
|
|
137
|
+
};
|
|
138
|
+
/** Replace state with a REST snapshot. Called on connect + reconnect + forced resync.
|
|
139
|
+
* Idempotent: a duplicate snapshot produces identical state. */
|
|
140
|
+
applySnapshot(snap: RestSnapshot): void;
|
|
141
|
+
/** Replace the algo-order subset of the store with a fresh REST list.
|
|
142
|
+
*
|
|
143
|
+
* Binance's user-data WS does NOT emit ORDER_TRADE_UPDATE for algo orders
|
|
144
|
+
* (STOP_MARKET / TAKE_PROFIT_MARKET) until they trigger — only the resulting
|
|
145
|
+
* regular order fires the event. As a result, the store cannot observe algo
|
|
146
|
+
* add/cancel/modify events via WS alone and diverges from REST whenever
|
|
147
|
+
* brackets are touched.
|
|
148
|
+
*
|
|
149
|
+
* This method closes that gap: callers (the controller's refresh loop) hand
|
|
150
|
+
* it the current REST view of algo orders, and we swap them in wholesale
|
|
151
|
+
* while leaving regular orders (WS-tracked) untouched. An order is classed
|
|
152
|
+
* as "algo" iff its clientOrderId parses as a reefclaw bracket cid with
|
|
153
|
+
* role stop or target. External algo orders (manual STOP_MARKET placed via
|
|
154
|
+
* Binance UI with no rc- prefix) are NOT tracked by this path — the 60s
|
|
155
|
+
* reconciler snapshot still covers them. */
|
|
156
|
+
replaceAlgoOrders(freshAlgoOrders: CcxtOrder[]): void;
|
|
157
|
+
/** Refresh ONLY the mark-derived soft fields (markPrice + unrealizedPnl) of
|
|
158
|
+
* positions that already exist in the store, from a fresh REST snapshot.
|
|
159
|
+
*
|
|
160
|
+
* Why this exists: Binance's user-data `ACCOUNT_UPDATE` is event-driven
|
|
161
|
+
* (fills / funding / transfers) and carries NO per-tick mark price, so a
|
|
162
|
+
* quiet open position's `unrealizedPnl` in this store is FROZEN at the last
|
|
163
|
+
* event's value while the Binance app recomputes uPnl every mark tick. In
|
|
164
|
+
* enforce/observe mode this store is the authoritative read path, so the
|
|
165
|
+
* dashboard's Unrealized cell froze between events ("close but lags/frozen"
|
|
166
|
+
* — 2026-05-16). The controller's 60s truth-check already fetches a fresh
|
|
167
|
+
* REST snapshot (with live uPnl + mark) but DISCARDS it unless position
|
|
168
|
+
* structure drifts (diffPositions ignores uPnl entirely). This method lets
|
|
169
|
+
* the truth-check spend that already-paid REST read on a uPnl refresh
|
|
170
|
+
* instead of throwing it away — bounding uPnl staleness to the 60s interval
|
|
171
|
+
* rather than "until the next trade/funding event".
|
|
172
|
+
*
|
|
173
|
+
* Strictly bounded — this is NOT applySnapshot:
|
|
174
|
+
* - only mutates positions present in BOTH the store and the fresh REST
|
|
175
|
+
* list with the SAME symbol AND side (structural changes are the
|
|
176
|
+
* truth-check's job, not this method's);
|
|
177
|
+
* - never adds, never removes, never touches balance or orders;
|
|
178
|
+
* - so it cannot reintroduce the null≠empty / stale-as-truth collapse
|
|
179
|
+
* class (callers only reach here with a non-null REST snapshot anyway —
|
|
180
|
+
* buildSnapshot throws UntrustedSnapshotError on a failed fetch). */
|
|
181
|
+
refreshDerivedMarkFields(restPositions: CcxtPosition[]): void;
|
|
182
|
+
/** Apply an ACCOUNT_UPDATE event (positions + balance deltas). */
|
|
183
|
+
applyAccountUpdate(ev: ParsedAccountUpdate): void;
|
|
184
|
+
/** Apply an ORDER_TRADE_UPDATE event (single order state transition). */
|
|
185
|
+
applyOrderUpdate(ev: ParsedOrderUpdate): void;
|
|
186
|
+
/** Clear all state. Used on shutdown/reset. */
|
|
187
|
+
reset(): void;
|
|
188
|
+
/** Diff local state vs a fresh REST snapshot. Classifies drifts by severity
|
|
189
|
+
* so the parent reconciler can decide: log-only (minor) vs forced resync (major). */
|
|
190
|
+
diffAgainstSnapshot(rest: RestSnapshot): StateDrift;
|
|
191
|
+
private diffPositions;
|
|
192
|
+
private diffBalance;
|
|
193
|
+
private diffOrders;
|
|
194
|
+
}
|