@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.
Files changed (371) hide show
  1. package/.gitignore +8 -0
  2. package/audit/mode-transition-audit.d.ts +11 -0
  3. package/audit/mode-transition-audit.js +29 -0
  4. package/balance-utils.d.ts +36 -0
  5. package/balance-utils.js +98 -0
  6. package/bridge/bridge.d.ts +109 -0
  7. package/bridge/bridge.js +1036 -0
  8. package/bridge/config.d.ts +43 -0
  9. package/bridge/config.js +176 -0
  10. package/bridge/connector.d.ts +52 -0
  11. package/bridge/connector.js +293 -0
  12. package/bridge/event-replay-buffer.d.ts +43 -0
  13. package/bridge/event-replay-buffer.js +109 -0
  14. package/bridge/gateway/event-parser.d.ts +209 -0
  15. package/bridge/gateway/event-parser.js +793 -0
  16. package/bridge/gateway/gateway-config.d.ts +39 -0
  17. package/bridge/gateway/gateway-config.js +86 -0
  18. package/bridge/gateway/gateway-http-client.d.ts +50 -0
  19. package/bridge/gateway/gateway-http-client.js +165 -0
  20. package/bridge/gateway/gateway-ws-client.d.ts +116 -0
  21. package/bridge/gateway/gateway-ws-client.js +417 -0
  22. package/bridge/gateway/poller.d.ts +146 -0
  23. package/bridge/gateway/poller.js +505 -0
  24. package/bridge/gateway/tool-discovery.d.ts +25 -0
  25. package/bridge/gateway/tool-discovery.js +198 -0
  26. package/bridge/index.d.ts +2 -0
  27. package/bridge/index.js +253 -0
  28. package/bridge/logger.d.ts +2 -0
  29. package/bridge/logger.js +2 -0
  30. package/bridge/provider.d.ts +156 -0
  31. package/bridge/provider.js +2 -0
  32. package/bridge/providers/emergency-commands.d.ts +54 -0
  33. package/bridge/providers/emergency-commands.js +235 -0
  34. package/bridge/providers/gateway.d.ts +322 -0
  35. package/bridge/providers/gateway.js +2302 -0
  36. package/bridge/providers/mock.d.ts +37 -0
  37. package/bridge/providers/mock.js +385 -0
  38. package/bridge/providers/onboarding-commands.d.ts +83 -0
  39. package/bridge/providers/onboarding-commands.js +213 -0
  40. package/bridge/providers/risk-calculator.d.ts +96 -0
  41. package/bridge/providers/risk-calculator.js +369 -0
  42. package/bridge/setup.d.ts +32 -0
  43. package/bridge/setup.js +226 -0
  44. package/bridge/types.d.ts +584 -0
  45. package/bridge/types.js +50 -0
  46. package/bridge/utils/reconnect.d.ts +6 -0
  47. package/bridge/utils/reconnect.js +6 -0
  48. package/bridge/utils/skill-signing.d.ts +51 -0
  49. package/bridge/utils/skill-signing.js +138 -0
  50. package/bridge/utils/skill-version.d.ts +17 -0
  51. package/bridge/utils/skill-version.js +74 -0
  52. package/ccxt/binance-ban-gate.d.ts +47 -0
  53. package/ccxt/binance-ban-gate.js +409 -0
  54. package/ccxt/binance-private.d.ts +325 -0
  55. package/ccxt/binance-private.js +1415 -0
  56. package/ccxt/binance-public.d.ts +18 -0
  57. package/ccxt/binance-public.js +147 -0
  58. package/config/agent-config-client.d.ts +55 -0
  59. package/config/agent-config-client.js +145 -0
  60. package/config/agent-config-poller.d.ts +25 -0
  61. package/config/agent-config-poller.js +100 -0
  62. package/config/brackets-config.d.ts +22 -0
  63. package/config/brackets-config.js +58 -0
  64. package/config/gate-store.d.ts +18 -0
  65. package/config/gate-store.js +61 -0
  66. package/config/plugin-config-io.d.ts +181 -0
  67. package/config/plugin-config-io.js +84 -0
  68. package/config/position-review-config.d.ts +35 -0
  69. package/config/position-review-config.js +105 -0
  70. package/config/tool-gate.d.ts +53 -0
  71. package/config/tool-gate.js +125 -0
  72. package/config/user-data-stream-config.d.ts +85 -0
  73. package/config/user-data-stream-config.js +224 -0
  74. package/connector-supervisor.d.ts +36 -0
  75. package/connector-supervisor.js +149 -0
  76. package/exchange-adapter.d.ts +49 -0
  77. package/exchange-adapter.js +4 -0
  78. package/index.d.ts +30 -0
  79. package/index.js +2030 -0
  80. package/ingest/pending-entry-metadata.d.ts +52 -0
  81. package/ingest/pending-entry-metadata.js +182 -0
  82. package/ingest/position-auto-capture.d.ts +98 -0
  83. package/ingest/position-auto-capture.js +394 -0
  84. package/ingest/position-decisions-client.d.ts +318 -0
  85. package/ingest/position-decisions-client.js +296 -0
  86. package/ingest/reconcile-db-vs-exchange.d.ts +13 -0
  87. package/ingest/reconcile-db-vs-exchange.js +114 -0
  88. package/ingest/reconciler-cleanup.d.ts +37 -0
  89. package/ingest/reconciler-cleanup.js +147 -0
  90. package/ingest/rest-gap-filler.d.ts +191 -0
  91. package/ingest/rest-gap-filler.js +565 -0
  92. package/ingest/touched-symbols-store.d.ts +25 -0
  93. package/ingest/touched-symbols-store.js +96 -0
  94. package/ingest/trade-store-client.d.ts +40 -0
  95. package/ingest/trade-store-client.js +125 -0
  96. package/ingest/ws-ingest.d.ts +43 -0
  97. package/ingest/ws-ingest.js +126 -0
  98. package/learning/setup-family.d.ts +21 -0
  99. package/learning/setup-family.js +103 -0
  100. package/lifecycle/install-signal-handlers.d.ts +33 -0
  101. package/lifecycle/install-signal-handlers.js +112 -0
  102. package/lifecycle/shutdown-coordinator.d.ts +43 -0
  103. package/lifecycle/shutdown-coordinator.js +131 -0
  104. package/live/bracket-id.d.ts +18 -0
  105. package/live/bracket-id.js +81 -0
  106. package/live/bracket-ledger.d.ts +54 -0
  107. package/live/bracket-ledger.js +267 -0
  108. package/live/bracket-manager.d.ts +82 -0
  109. package/live/bracket-manager.js +478 -0
  110. package/live/bracket-params.d.ts +22 -0
  111. package/live/bracket-params.js +124 -0
  112. package/live/bracket-reconciler.d.ts +95 -0
  113. package/live/bracket-reconciler.js +573 -0
  114. package/live/bracket-types.d.ts +102 -0
  115. package/live/bracket-types.js +8 -0
  116. package/live/deposit-tracker.d.ts +62 -0
  117. package/live/deposit-tracker.js +97 -0
  118. package/live/emergency-controls.d.ts +32 -0
  119. package/live/emergency-controls.js +226 -0
  120. package/live/exchange-errors.d.ts +12 -0
  121. package/live/exchange-errors.js +130 -0
  122. package/live/exchange-info-cache.d.ts +35 -0
  123. package/live/exchange-info-cache.js +119 -0
  124. package/live/fact-subscriber.d.ts +78 -0
  125. package/live/fact-subscriber.js +182 -0
  126. package/live/intent-journal.d.ts +42 -0
  127. package/live/intent-journal.js +122 -0
  128. package/live/listen-key-manager.d.ts +70 -0
  129. package/live/listen-key-manager.js +169 -0
  130. package/live/live-adapter.d.ts +264 -0
  131. package/live/live-adapter.js +1665 -0
  132. package/live/live-balance-enricher.d.ts +32 -0
  133. package/live/live-balance-enricher.js +104 -0
  134. package/live/live-bracket-api.d.ts +13 -0
  135. package/live/live-bracket-api.js +20 -0
  136. package/live/live-state-store.d.ts +194 -0
  137. package/live/live-state-store.js +450 -0
  138. package/live/local-signal-service.d.ts +57 -0
  139. package/live/local-signal-service.js +146 -0
  140. package/live/local-strategy-evaluator.d.ts +62 -0
  141. package/live/local-strategy-evaluator.js +127 -0
  142. package/live/microstructure-assembler.d.ts +54 -0
  143. package/live/microstructure-assembler.js +148 -0
  144. package/live/order-poller.d.ts +29 -0
  145. package/live/order-poller.js +125 -0
  146. package/live/position-state-store.d.ts +83 -0
  147. package/live/position-state-store.js +237 -0
  148. package/live/proposal-decision-listener.d.ts +64 -0
  149. package/live/proposal-decision-listener.js +288 -0
  150. package/live/proposal-manager.d.ts +76 -0
  151. package/live/proposal-manager.js +140 -0
  152. package/live/rate-limiter.d.ts +47 -0
  153. package/live/rate-limiter.js +159 -0
  154. package/live/reconciler.d.ts +39 -0
  155. package/live/reconciler.js +175 -0
  156. package/live/setup-buckets.d.ts +7 -0
  157. package/live/setup-buckets.js +33 -0
  158. package/live/slippage-tracker.d.ts +45 -0
  159. package/live/slippage-tracker.js +78 -0
  160. package/live/stop-watcher.d.ts +34 -0
  161. package/live/stop-watcher.js +158 -0
  162. package/live/user-data-active-probe.d.ts +54 -0
  163. package/live/user-data-active-probe.js +180 -0
  164. package/live/user-data-stream-controller.d.ts +200 -0
  165. package/live/user-data-stream-controller.js +579 -0
  166. package/live/user-data-stream-ws.d.ts +22 -0
  167. package/live/user-data-stream-ws.js +63 -0
  168. package/live/user-data-stream.d.ts +243 -0
  169. package/live/user-data-stream.js +704 -0
  170. package/logger.d.ts +2 -0
  171. package/logger.js +2 -0
  172. package/mfe.d.ts +21 -0
  173. package/mfe.js +68 -0
  174. package/onboarding/mode-ladder.d.ts +1 -0
  175. package/onboarding/mode-ladder.js +3 -0
  176. package/onboarding/runtime.d.ts +71 -0
  177. package/onboarding/runtime.js +153 -0
  178. package/openclaw.plugin.json +94 -0
  179. package/package.json +27 -0
  180. package/paper-adapter.d.ts +24 -0
  181. package/paper-adapter.js +91 -0
  182. package/persistence/state-manager.d.ts +42 -0
  183. package/persistence/state-manager.js +164 -0
  184. package/pinned-plan.d.ts +9 -0
  185. package/pinned-plan.js +23 -0
  186. package/risk/pre-trade-check.d.ts +38 -0
  187. package/risk/pre-trade-check.js +345 -0
  188. package/risk/pre-trade-types.d.ts +60 -0
  189. package/risk/pre-trade-types.js +3 -0
  190. package/scripts/assemble.mjs +114 -0
  191. package/shadow/shadow-tracker.d.ts +36 -0
  192. package/shadow/shadow-tracker.js +151 -0
  193. package/shadow/types.d.ts +42 -0
  194. package/shadow/types.js +20 -0
  195. package/shared/indicators-extended.d.ts +52 -0
  196. package/shared/indicators-extended.js +291 -0
  197. package/shared/indicators.d.ts +15 -0
  198. package/shared/indicators.js +114 -0
  199. package/signals/conditions/registry.d.ts +16 -0
  200. package/signals/conditions/registry.js +1274 -0
  201. package/signals/conditions/types.d.ts +1 -0
  202. package/signals/conditions/types.js +4 -0
  203. package/signals/direction-rules.d.ts +3 -0
  204. package/signals/direction-rules.js +24 -0
  205. package/signals/entry-rules.d.ts +6 -0
  206. package/signals/entry-rules.js +33 -0
  207. package/signals/serialize-context.d.ts +4 -0
  208. package/signals/serialize-context.js +39 -0
  209. package/signals/stop-rules.d.ts +3 -0
  210. package/signals/stop-rules.js +48 -0
  211. package/signals/strategy-adapter.d.ts +14 -0
  212. package/signals/strategy-adapter.js +122 -0
  213. package/signals/types.d.ts +1 -0
  214. package/signals/types.js +8 -0
  215. package/simulator/exchange-simulator.d.ts +93 -0
  216. package/simulator/exchange-simulator.js +684 -0
  217. package/simulator/fill-engine.d.ts +53 -0
  218. package/simulator/fill-engine.js +276 -0
  219. package/simulator/paper-market-feed.d.ts +26 -0
  220. package/simulator/paper-market-feed.js +104 -0
  221. package/simulator/realistic-fills.d.ts +59 -0
  222. package/simulator/realistic-fills.js +175 -0
  223. package/simulator/types.d.ts +219 -0
  224. package/simulator/types.js +43 -0
  225. package/skills/reefclaw/SKILL.md +97 -0
  226. package/strategy/builtin-strategies.d.ts +2 -0
  227. package/strategy/builtin-strategies.js +109 -0
  228. package/strategy/condition-registry.d.ts +3 -0
  229. package/strategy/condition-registry.js +153 -0
  230. package/strategy/evaluator.d.ts +67 -0
  231. package/strategy/evaluator.js +93 -0
  232. package/tools/assessment-validation.d.ts +118 -0
  233. package/tools/assessment-validation.js +415 -0
  234. package/tools/attach-brackets.d.ts +34 -0
  235. package/tools/attach-brackets.js +363 -0
  236. package/tools/audit-bracket-protection.d.ts +49 -0
  237. package/tools/audit-bracket-protection.js +527 -0
  238. package/tools/cancel-all-orders.d.ts +7 -0
  239. package/tools/cancel-all-orders.js +5 -0
  240. package/tools/cancel-order.d.ts +10 -0
  241. package/tools/cancel-order.js +14 -0
  242. package/tools/check-position-health.d.ts +46 -0
  243. package/tools/check-position-health.js +194 -0
  244. package/tools/clear-exchange-credentials.d.ts +24 -0
  245. package/tools/clear-exchange-credentials.js +70 -0
  246. package/tools/close-position.d.ts +22 -0
  247. package/tools/close-position.js +449 -0
  248. package/tools/create-order.d.ts +54 -0
  249. package/tools/create-order.js +338 -0
  250. package/tools/exit-gate.d.ts +58 -0
  251. package/tools/exit-gate.js +162 -0
  252. package/tools/fetch-balance.d.ts +5 -0
  253. package/tools/fetch-balance.js +4 -0
  254. package/tools/fetch-ohlcv.d.ts +11 -0
  255. package/tools/fetch-ohlcv.js +8 -0
  256. package/tools/fetch-open-orders.d.ts +7 -0
  257. package/tools/fetch-open-orders.js +4 -0
  258. package/tools/fetch-positions.d.ts +7 -0
  259. package/tools/fetch-positions.js +4 -0
  260. package/tools/fetch-ticker.d.ts +11 -0
  261. package/tools/fetch-ticker.js +5 -0
  262. package/tools/get-agent-profile.d.ts +4 -0
  263. package/tools/get-agent-profile.js +6 -0
  264. package/tools/get-analytics.d.ts +6 -0
  265. package/tools/get-analytics.js +7 -0
  266. package/tools/get-backtest.d.ts +12 -0
  267. package/tools/get-backtest.js +91 -0
  268. package/tools/get-basis.d.ts +7 -0
  269. package/tools/get-basis.js +7 -0
  270. package/tools/get-bracket-config.d.ts +11 -0
  271. package/tools/get-bracket-config.js +24 -0
  272. package/tools/get-cascade-risk.d.ts +7 -0
  273. package/tools/get-cascade-risk.js +8 -0
  274. package/tools/get-crypto-metrics.d.ts +18 -0
  275. package/tools/get-crypto-metrics.js +45 -0
  276. package/tools/get-cvd.d.ts +6 -0
  277. package/tools/get-cvd.js +6 -0
  278. package/tools/get-divergences.d.ts +6 -0
  279. package/tools/get-divergences.js +6 -0
  280. package/tools/get-funding-context.d.ts +6 -0
  281. package/tools/get-funding-context.js +16 -0
  282. package/tools/get-liquidation-levels.d.ts +7 -0
  283. package/tools/get-liquidation-levels.js +7 -0
  284. package/tools/get-liquidation-pulse.d.ts +9 -0
  285. package/tools/get-liquidation-pulse.js +22 -0
  286. package/tools/get-market-breadth.d.ts +6 -0
  287. package/tools/get-market-breadth.js +8 -0
  288. package/tools/get-market-intel.d.ts +19 -0
  289. package/tools/get-market-intel.js +116 -0
  290. package/tools/get-market-structure.d.ts +47 -0
  291. package/tools/get-market-structure.js +198 -0
  292. package/tools/get-my-mined-patterns.d.ts +20 -0
  293. package/tools/get-my-mined-patterns.js +61 -0
  294. package/tools/get-my-proposed-learnings.d.ts +20 -0
  295. package/tools/get-my-proposed-learnings.js +55 -0
  296. package/tools/get-my-recent-reviews.d.ts +22 -0
  297. package/tools/get-my-recent-reviews.js +66 -0
  298. package/tools/get-orderbook.d.ts +21 -0
  299. package/tools/get-orderbook.js +32 -0
  300. package/tools/get-pattern-scan.d.ts +7 -0
  301. package/tools/get-pattern-scan.js +8 -0
  302. package/tools/get-regime.d.ts +6 -0
  303. package/tools/get-regime.js +7 -0
  304. package/tools/get-relevant-learnings.d.ts +21 -0
  305. package/tools/get-relevant-learnings.js +65 -0
  306. package/tools/get-resting-liquidity.d.ts +6 -0
  307. package/tools/get-resting-liquidity.js +11 -0
  308. package/tools/get-risk-scenario.d.ts +29 -0
  309. package/tools/get-risk-scenario.js +47 -0
  310. package/tools/get-risk-summary.d.ts +51 -0
  311. package/tools/get-risk-summary.js +118 -0
  312. package/tools/get-sentiment.d.ts +4 -0
  313. package/tools/get-sentiment.js +6 -0
  314. package/tools/get-session-review.d.ts +7 -0
  315. package/tools/get-session-review.js +8 -0
  316. package/tools/get-setup-detail.d.ts +7 -0
  317. package/tools/get-setup-detail.js +303 -0
  318. package/tools/get-signals.d.ts +15 -0
  319. package/tools/get-signals.js +54 -0
  320. package/tools/get-sizing.d.ts +6 -0
  321. package/tools/get-sizing.js +6 -0
  322. package/tools/get-trade-feedback.d.ts +7 -0
  323. package/tools/get-trade-feedback.js +8 -0
  324. package/tools/get-trade-flow.d.ts +7 -0
  325. package/tools/get-trade-flow.js +7 -0
  326. package/tools/get-volume-analysis.d.ts +21 -0
  327. package/tools/get-volume-analysis.js +74 -0
  328. package/tools/get-volume-profile.d.ts +7 -0
  329. package/tools/get-volume-profile.js +7 -0
  330. package/tools/helpers.d.ts +25 -0
  331. package/tools/helpers.js +38 -0
  332. package/tools/intel-api.d.ts +14 -0
  333. package/tools/intel-api.js +52 -0
  334. package/tools/intel-cache.d.ts +25 -0
  335. package/tools/intel-cache.js +133 -0
  336. package/tools/list-strategies.d.ts +7 -0
  337. package/tools/list-strategies.js +6 -0
  338. package/tools/modify-stop.d.ts +17 -0
  339. package/tools/modify-stop.js +81 -0
  340. package/tools/modify-target.d.ts +17 -0
  341. package/tools/modify-target.js +71 -0
  342. package/tools/propose-learning.d.ts +22 -0
  343. package/tools/propose-learning.js +65 -0
  344. package/tools/query-review-outcomes.d.ts +30 -0
  345. package/tools/query-review-outcomes.js +64 -0
  346. package/tools/query-trades.d.ts +21 -0
  347. package/tools/query-trades.js +37 -0
  348. package/tools/record-position-reviews.d.ts +38 -0
  349. package/tools/record-position-reviews.js +147 -0
  350. package/tools/save-strategy.d.ts +16 -0
  351. package/tools/save-strategy.js +46 -0
  352. package/tools/scan-pairs.d.ts +18 -0
  353. package/tools/scan-pairs.js +220 -0
  354. package/tools/score-setup.d.ts +31 -0
  355. package/tools/score-setup.js +268 -0
  356. package/tools/set-bracket-requirement.d.ts +18 -0
  357. package/tools/set-bracket-requirement.js +81 -0
  358. package/tools/set-exchange-credentials.d.ts +25 -0
  359. package/tools/set-exchange-credentials.js +80 -0
  360. package/tools/set-trading-mode.d.ts +26 -0
  361. package/tools/set-trading-mode.js +135 -0
  362. package/tools/test-exchange-credentials.d.ts +16 -0
  363. package/tools/test-exchange-credentials.js +100 -0
  364. package/tools/toggle-strategy.d.ts +8 -0
  365. package/tools/toggle-strategy.js +8 -0
  366. package/trading-params-cache.d.ts +26 -0
  367. package/trading-params-cache.js +52 -0
  368. package/types.d.ts +110 -0
  369. package/types.js +7 -0
  370. package/util/plugin-paths.d.ts +3 -0
  371. 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
+ }