perp-cli 0.9.8 → 0.12.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 (254) hide show
  1. package/README.md +30 -25
  2. package/dist/_stderr-filter.d.ts +0 -0
  3. package/dist/_stderr-filter.js +30 -0
  4. package/dist/agent-wallet/expiry.d.ts +15 -0
  5. package/dist/agent-wallet/expiry.js +26 -0
  6. package/dist/agent-wallet/lighter-keystore.d.ts +34 -0
  7. package/dist/agent-wallet/lighter-keystore.js +232 -0
  8. package/dist/agent-wallet/passphrase.d.ts +13 -0
  9. package/dist/agent-wallet/passphrase.js +54 -0
  10. package/dist/agent-wallet/signing-strategy.d.ts +67 -0
  11. package/dist/agent-wallet/signing-strategy.js +51 -0
  12. package/dist/agent-wallet/store.d.ts +37 -0
  13. package/dist/agent-wallet/store.js +172 -0
  14. package/dist/api/public/_http.d.ts +15 -0
  15. package/dist/api/public/_http.js +24 -0
  16. package/dist/api/public/hyperliquid.js +36 -24
  17. package/dist/api/public/lighter.d.ts +7 -1
  18. package/dist/api/public/lighter.js +85 -37
  19. package/dist/api/public/pacifica.js +47 -18
  20. package/dist/bot/engine.js +23 -4
  21. package/dist/bot/presets.js +3 -3
  22. package/dist/bot/strategies/funding-arb-strategy.d.ts +0 -23
  23. package/dist/bot/strategies/funding-arb-strategy.js +41 -176
  24. package/dist/bot/strategies/funding-auto.js +2 -2
  25. package/dist/bridge-engine.js +102 -49
  26. package/dist/cli-spec.js +1 -2
  27. package/dist/commands/account.js +2 -500
  28. package/dist/commands/agent.d.ts +8 -2
  29. package/dist/commands/agent.js +1903 -366
  30. package/dist/commands/alerts.js +3 -1
  31. package/dist/commands/arb/index.js +37 -7
  32. package/dist/commands/arb-auto.js +44 -11
  33. package/dist/commands/arb.js +83 -34
  34. package/dist/commands/bot.d.ts +1 -1
  35. package/dist/commands/bot.js +20 -16
  36. package/dist/commands/bridge.d.ts +1 -1
  37. package/dist/commands/bridge.js +4 -4
  38. package/dist/commands/funds.d.ts +1 -1
  39. package/dist/commands/funds.js +18 -68
  40. package/dist/commands/jobs.d.ts +1 -1
  41. package/dist/commands/jobs.js +2 -2
  42. package/dist/commands/manage.d.ts +1 -1
  43. package/dist/commands/manage.js +12 -84
  44. package/dist/commands/plan.d.ts +1 -1
  45. package/dist/commands/plan.js +2 -2
  46. package/dist/commands/portfolio.d.ts +19 -3
  47. package/dist/commands/portfolio.js +747 -163
  48. package/dist/commands/rebalance.d.ts +1 -1
  49. package/dist/commands/rebalance.js +18 -12
  50. package/dist/commands/risk.js +2 -6
  51. package/dist/commands/settings.js +30 -53
  52. package/dist/commands/trade.js +16 -15
  53. package/dist/commands/wallet.d.ts +2 -1
  54. package/dist/commands/wallet.js +1122 -176
  55. package/dist/config.d.ts +9 -0
  56. package/dist/config.js +55 -9
  57. package/dist/errors.d.ts +64 -0
  58. package/dist/errors.js +82 -2
  59. package/dist/event-stream.js +12 -1
  60. package/dist/exchanges/aster-typed-data.d.ts +156 -0
  61. package/dist/exchanges/aster-typed-data.js +189 -0
  62. package/dist/exchanges/aster.d.ts +60 -11
  63. package/dist/exchanges/aster.js +278 -136
  64. package/dist/exchanges/hyperliquid.d.ts +14 -0
  65. package/dist/exchanges/hyperliquid.js +88 -34
  66. package/dist/exchanges/lighter-spot.js +19 -5
  67. package/dist/exchanges/lighter.d.ts +66 -0
  68. package/dist/exchanges/lighter.js +213 -31
  69. package/dist/exchanges/pacifica-typed-data.d.ts +75 -0
  70. package/dist/exchanges/pacifica-typed-data.js +74 -0
  71. package/dist/exchanges/pacifica.d.ts +29 -1
  72. package/dist/exchanges/pacifica.js +94 -6
  73. package/dist/funding/rates.js +59 -21
  74. package/dist/guardrail/contracts.d.ts +14 -0
  75. package/dist/guardrail/contracts.js +72 -0
  76. package/dist/guardrail/perp-guardrail.d.ts +21 -0
  77. package/dist/guardrail/perp-guardrail.js +145 -0
  78. package/dist/index.d.ts +1 -1
  79. package/dist/index.js +307 -362
  80. package/dist/jobs.js +3 -1
  81. package/dist/mcp-server.js +92 -88
  82. package/dist/position-history.js +47 -4
  83. package/dist/settings.d.ts +69 -3
  84. package/dist/settings.js +3 -2
  85. package/dist/signer/index.d.ts +2 -0
  86. package/dist/signer/index.js +2 -0
  87. package/dist/signer/ows-evm.d.ts +32 -0
  88. package/dist/signer/ows-evm.js +86 -0
  89. package/dist/signer/ows-loader.d.ts +2 -0
  90. package/dist/signer/ows-loader.js +6 -0
  91. package/dist/signer/ows-solana.d.ts +25 -0
  92. package/dist/signer/ows-solana.js +56 -0
  93. package/dist/smart-order.d.ts +8 -2
  94. package/dist/smart-order.js +46 -11
  95. package/dist/strategies/funding-arb.js +29 -8
  96. package/dist/trade-validator.js +30 -5
  97. package/dist/utils.d.ts +10 -0
  98. package/dist/utils.js +19 -0
  99. package/package.json +4 -2
  100. package/skills/perp-cli/SKILL.md +23 -14
  101. package/skills/perp-cli/references/agent-operations.md +6 -4
  102. package/skills/perp-cli/references/commands.md +55 -34
  103. package/skills/perp-cli/scripts/preflight.sh +4 -4
  104. package/skills/perp-cli/scripts/spot-perp-scan.sh +2 -2
  105. package/dist/__tests__/alert-logic.test.d.ts +0 -1
  106. package/dist/__tests__/alert-logic.test.js +0 -107
  107. package/dist/__tests__/arb-auto-3dex.test.d.ts +0 -1
  108. package/dist/__tests__/arb-auto-3dex.test.js +0 -397
  109. package/dist/__tests__/arb-history-stats.test.d.ts +0 -1
  110. package/dist/__tests__/arb-history-stats.test.js +0 -176
  111. package/dist/__tests__/arb-logic.test.d.ts +0 -1
  112. package/dist/__tests__/arb-logic.test.js +0 -84
  113. package/dist/__tests__/arb-manage.test.d.ts +0 -1
  114. package/dist/__tests__/arb-manage.test.js +0 -253
  115. package/dist/__tests__/arb-new-features.test.d.ts +0 -1
  116. package/dist/__tests__/arb-new-features.test.js +0 -457
  117. package/dist/__tests__/arb-sizing.test.d.ts +0 -1
  118. package/dist/__tests__/arb-sizing.test.js +0 -48
  119. package/dist/__tests__/arb-state.test.d.ts +0 -1
  120. package/dist/__tests__/arb-state.test.js +0 -284
  121. package/dist/__tests__/arb-userflow.test.d.ts +0 -1
  122. package/dist/__tests__/arb-userflow.test.js +0 -945
  123. package/dist/__tests__/arb-utils.test.d.ts +0 -1
  124. package/dist/__tests__/arb-utils.test.js +0 -264
  125. package/dist/__tests__/bot-conditions.test.d.ts +0 -1
  126. package/dist/__tests__/bot-conditions.test.js +0 -341
  127. package/dist/__tests__/client-id-tracker.test.d.ts +0 -1
  128. package/dist/__tests__/client-id-tracker.test.js +0 -137
  129. package/dist/__tests__/commands/new-atomic-commands.test.d.ts +0 -1
  130. package/dist/__tests__/commands/new-atomic-commands.test.js +0 -502
  131. package/dist/__tests__/commands/order-intent.test.d.ts +0 -1
  132. package/dist/__tests__/commands/order-intent.test.js +0 -600
  133. package/dist/__tests__/commands/trade-commands.test.d.ts +0 -1
  134. package/dist/__tests__/commands/trade-commands.test.js +0 -821
  135. package/dist/__tests__/config.test.d.ts +0 -1
  136. package/dist/__tests__/config.test.js +0 -86
  137. package/dist/__tests__/cross-chain-margin.test.d.ts +0 -1
  138. package/dist/__tests__/cross-chain-margin.test.js +0 -287
  139. package/dist/__tests__/dex-asset-map.test.d.ts +0 -1
  140. package/dist/__tests__/dex-asset-map.test.js +0 -191
  141. package/dist/__tests__/errors.test.d.ts +0 -1
  142. package/dist/__tests__/errors.test.js +0 -110
  143. package/dist/__tests__/event-stream.test.d.ts +0 -1
  144. package/dist/__tests__/event-stream.test.js +0 -276
  145. package/dist/__tests__/exchanges/interface.test.d.ts +0 -1
  146. package/dist/__tests__/exchanges/interface.test.js +0 -132
  147. package/dist/__tests__/exchanges/mock-adapter.d.ts +0 -69
  148. package/dist/__tests__/exchanges/mock-adapter.js +0 -137
  149. package/dist/__tests__/execution-log.test.d.ts +0 -1
  150. package/dist/__tests__/execution-log.test.js +0 -106
  151. package/dist/__tests__/funding-calc.test.d.ts +0 -1
  152. package/dist/__tests__/funding-calc.test.js +0 -71
  153. package/dist/__tests__/funding-history.test.d.ts +0 -1
  154. package/dist/__tests__/funding-history.test.js +0 -343
  155. package/dist/__tests__/funding-rates.test.d.ts +0 -1
  156. package/dist/__tests__/funding-rates.test.js +0 -342
  157. package/dist/__tests__/funding.test.d.ts +0 -1
  158. package/dist/__tests__/funding.test.js +0 -173
  159. package/dist/__tests__/gap-logic.test.d.ts +0 -1
  160. package/dist/__tests__/gap-logic.test.js +0 -43
  161. package/dist/__tests__/hip3-dex.test.d.ts +0 -1
  162. package/dist/__tests__/hip3-dex.test.js +0 -234
  163. package/dist/__tests__/integration/agent-features.integration.test.d.ts +0 -1
  164. package/dist/__tests__/integration/agent-features.integration.test.js +0 -553
  165. package/dist/__tests__/integration/atomic-commands.integration.test.d.ts +0 -13
  166. package/dist/__tests__/integration/atomic-commands.integration.test.js +0 -246
  167. package/dist/__tests__/integration/bridge-simulation.integration.test.d.ts +0 -1
  168. package/dist/__tests__/integration/bridge-simulation.integration.test.js +0 -453
  169. package/dist/__tests__/integration/bridge-strict.integration.test.d.ts +0 -1
  170. package/dist/__tests__/integration/bridge-strict.integration.test.js +0 -812
  171. package/dist/__tests__/integration/bridge.integration.test.d.ts +0 -1
  172. package/dist/__tests__/integration/bridge.integration.test.js +0 -309
  173. package/dist/__tests__/integration/cli-e2e.integration.test.d.ts +0 -1
  174. package/dist/__tests__/integration/cli-e2e.integration.test.js +0 -202
  175. package/dist/__tests__/integration/dex-arb.integration.test.d.ts +0 -1
  176. package/dist/__tests__/integration/dex-arb.integration.test.js +0 -116
  177. package/dist/__tests__/integration/envelope-consistency.integration.test.d.ts +0 -13
  178. package/dist/__tests__/integration/envelope-consistency.integration.test.js +0 -205
  179. package/dist/__tests__/integration/hip3-dex.integration.test.d.ts +0 -1
  180. package/dist/__tests__/integration/hip3-dex.integration.test.js +0 -147
  181. package/dist/__tests__/integration/hyperliquid.integration.test.d.ts +0 -1
  182. package/dist/__tests__/integration/hyperliquid.integration.test.js +0 -79
  183. package/dist/__tests__/integration/lighter.integration.test.d.ts +0 -1
  184. package/dist/__tests__/integration/lighter.integration.test.js +0 -53
  185. package/dist/__tests__/integration/new-commands-e2e.integration.test.d.ts +0 -9
  186. package/dist/__tests__/integration/new-commands-e2e.integration.test.js +0 -236
  187. package/dist/__tests__/integration/order-verification.integration.test.d.ts +0 -1
  188. package/dist/__tests__/integration/order-verification.integration.test.js +0 -321
  189. package/dist/__tests__/integration/pacifica.integration.test.d.ts +0 -1
  190. package/dist/__tests__/integration/pacifica.integration.test.js +0 -75
  191. package/dist/__tests__/integration/response-shapes.integration.test.d.ts +0 -1
  192. package/dist/__tests__/integration/response-shapes.integration.test.js +0 -278
  193. package/dist/__tests__/liquidity.test.d.ts +0 -1
  194. package/dist/__tests__/liquidity.test.js +0 -225
  195. package/dist/__tests__/plan-executor.test.d.ts +0 -1
  196. package/dist/__tests__/plan-executor.test.js +0 -314
  197. package/dist/__tests__/position-history.test.d.ts +0 -1
  198. package/dist/__tests__/position-history.test.js +0 -367
  199. package/dist/__tests__/retry.test.d.ts +0 -1
  200. package/dist/__tests__/retry.test.js +0 -310
  201. package/dist/__tests__/risk-assessment.test.d.ts +0 -1
  202. package/dist/__tests__/risk-assessment.test.js +0 -288
  203. package/dist/__tests__/security-adversarial.test.d.ts +0 -1
  204. package/dist/__tests__/security-adversarial.test.js +0 -574
  205. package/dist/__tests__/strategies.test.d.ts +0 -1
  206. package/dist/__tests__/strategies.test.js +0 -539
  207. package/dist/__tests__/trade-execution.test.d.ts +0 -1
  208. package/dist/__tests__/trade-execution.test.js +0 -129
  209. package/dist/__tests__/trade-validator.test.d.ts +0 -1
  210. package/dist/__tests__/trade-validator.test.js +0 -655
  211. package/dist/__tests__/utils.test.d.ts +0 -1
  212. package/dist/__tests__/utils.test.js +0 -76
  213. package/dist/arb/reconcile.d.ts +0 -28
  214. package/dist/arb/reconcile.js +0 -162
  215. package/dist/commands/alert.d.ts +0 -2
  216. package/dist/commands/alert.js +0 -421
  217. package/dist/commands/analytics.d.ts +0 -3
  218. package/dist/commands/analytics.js +0 -311
  219. package/dist/commands/arb-manage.d.ts +0 -5
  220. package/dist/commands/arb-manage.js +0 -5
  221. package/dist/commands/dashboard.d.ts +0 -3
  222. package/dist/commands/dashboard.js +0 -176
  223. package/dist/commands/deposit.d.ts +0 -4
  224. package/dist/commands/deposit.js +0 -573
  225. package/dist/commands/dex.d.ts +0 -3
  226. package/dist/commands/dex.js +0 -120
  227. package/dist/commands/env.d.ts +0 -2
  228. package/dist/commands/env.js +0 -136
  229. package/dist/commands/funding.d.ts +0 -3
  230. package/dist/commands/funding.js +0 -554
  231. package/dist/commands/gap.d.ts +0 -2
  232. package/dist/commands/gap.js +0 -305
  233. package/dist/commands/health.d.ts +0 -2
  234. package/dist/commands/health.js +0 -67
  235. package/dist/commands/multileg.d.ts +0 -16
  236. package/dist/commands/multileg.js +0 -174
  237. package/dist/commands/pnl.d.ts +0 -12
  238. package/dist/commands/pnl.js +0 -243
  239. package/dist/commands/run.d.ts +0 -3
  240. package/dist/commands/run.js +0 -202
  241. package/dist/commands/stream.d.ts +0 -5
  242. package/dist/commands/stream.js +0 -200
  243. package/dist/commands/withdraw.d.ts +0 -3
  244. package/dist/commands/withdraw.js +0 -187
  245. package/dist/exchanges/edgex.d.ts +0 -62
  246. package/dist/exchanges/edgex.js +0 -552
  247. package/dist/exchanges/nado.d.ts +0 -52
  248. package/dist/exchanges/nado.js +0 -223
  249. package/dist/funding/index.d.ts +0 -3
  250. package/dist/funding/index.js +0 -3
  251. package/dist/retry.d.ts +0 -74
  252. package/dist/retry.js +0 -129
  253. package/dist/ws/market-feed.d.ts +0 -74
  254. package/dist/ws/market-feed.js +0 -227
@@ -1,76 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { formatUsd, formatPnl, formatPercent, printJson } from "../utils.js";
3
- describe("formatUsd", () => {
4
- it("formats numeric strings", () => {
5
- expect(formatUsd("1234.5")).toBe("1,234.50");
6
- });
7
- it("formats numbers", () => {
8
- expect(formatUsd(99999.999)).toBe("100,000.00");
9
- });
10
- it("returns original string for NaN", () => {
11
- expect(formatUsd("abc")).toBe("abc");
12
- });
13
- it("formats zero", () => {
14
- expect(formatUsd(0)).toBe("0.00");
15
- });
16
- it("formats negative numbers", () => {
17
- expect(formatUsd(-42.1)).toBe("-42.10");
18
- });
19
- });
20
- describe("formatPnl", () => {
21
- it("positive PnL has + prefix", () => {
22
- const result = formatPnl(100);
23
- expect(result).toContain("+$100.00");
24
- });
25
- it("negative PnL has - prefix", () => {
26
- const result = formatPnl(-50);
27
- expect(result).toContain("-$50.00");
28
- });
29
- it("zero PnL", () => {
30
- const result = formatPnl(0);
31
- expect(result).toContain("$0.00");
32
- });
33
- it("handles string input", () => {
34
- const result = formatPnl("123.456");
35
- expect(result).toContain("$123.46");
36
- });
37
- it("handles NaN", () => {
38
- expect(formatPnl("abc")).toBe("abc");
39
- });
40
- });
41
- describe("formatPercent", () => {
42
- it("positive percent", () => {
43
- const result = formatPercent(0.0015);
44
- expect(result).toContain("+0.1500%");
45
- });
46
- it("negative percent", () => {
47
- const result = formatPercent(-0.0025);
48
- expect(result).toContain("-0.2500%");
49
- });
50
- it("zero percent", () => {
51
- const result = formatPercent(0);
52
- expect(result).toContain("0.0000%");
53
- });
54
- it("handles NaN", () => {
55
- expect(formatPercent("abc")).toBe("abc");
56
- });
57
- });
58
- describe("printJson", () => {
59
- it("outputs valid JSON to console", () => {
60
- const logs = [];
61
- const origLog = console.log;
62
- console.log = (...args) => logs.push(args.join(" "));
63
- printJson({ a: 1, b: "hello" });
64
- console.log = origLog;
65
- const parsed = JSON.parse(logs[0]);
66
- expect(parsed).toEqual({ a: 1, b: "hello" });
67
- });
68
- it("handles arrays", () => {
69
- const logs = [];
70
- const origLog = console.log;
71
- console.log = (...args) => logs.push(args.join(" "));
72
- printJson([1, 2, 3]);
73
- console.log = origLog;
74
- expect(JSON.parse(logs[0])).toEqual([1, 2, 3]);
75
- });
76
- });
@@ -1,28 +0,0 @@
1
- import type { ExchangeAdapter } from "../exchanges/interface.js";
2
- export interface ReconciliationIssue {
3
- type: "orphan" | "phantom" | "size_mismatch";
4
- symbol: string;
5
- exchange: string;
6
- side: "long" | "short";
7
- localSize: number | null;
8
- exchangeSize: number | null;
9
- severity: "warning" | "critical";
10
- suggestion: string;
11
- }
12
- export interface ReconciliationResult {
13
- issues: ReconciliationIssue[];
14
- healthy: number;
15
- fixesApplied?: string[];
16
- }
17
- /**
18
- * Reconcile local arb state with actual exchange positions.
19
- *
20
- * Detects three types of issues:
21
- * - **Orphan**: Position exists on exchange but not in local arb state (manual entry?)
22
- * - **Phantom**: Position exists in local state but not on exchange (liquidated? manually closed?)
23
- * - **Size mismatch**: Both exist but sizes differ beyond tolerance
24
- */
25
- export declare function reconcileArbPositions(adapters: Map<string, ExchangeAdapter>, opts?: {
26
- fix?: boolean;
27
- tolerancePct?: number;
28
- }): Promise<ReconciliationResult>;
@@ -1,162 +0,0 @@
1
- import { getPositions, removePosition, updatePosition } from "./state.js";
2
- /** Normalize symbol for comparison (strip -PERP suffix, uppercase) */
3
- function normalizeSymbol(symbol) {
4
- return symbol.toUpperCase().replace(/-PERP$/, "");
5
- }
6
- /** Find a matching exchange position by symbol */
7
- function findExchangePosition(positions, symbol, side) {
8
- const norm = normalizeSymbol(symbol);
9
- return positions.find(p => normalizeSymbol(p.symbol) === norm && p.side === side);
10
- }
11
- /**
12
- * Reconcile local arb state with actual exchange positions.
13
- *
14
- * Detects three types of issues:
15
- * - **Orphan**: Position exists on exchange but not in local arb state (manual entry?)
16
- * - **Phantom**: Position exists in local state but not on exchange (liquidated? manually closed?)
17
- * - **Size mismatch**: Both exist but sizes differ beyond tolerance
18
- */
19
- export async function reconcileArbPositions(adapters, opts) {
20
- const tolerancePct = opts?.tolerancePct ?? 1;
21
- const shouldFix = opts?.fix ?? false;
22
- const issues = [];
23
- const fixesApplied = [];
24
- let healthy = 0;
25
- const localPositions = getPositions();
26
- // Fetch all exchange positions
27
- const exchangePositions = new Map();
28
- for (const [name, adapter] of adapters) {
29
- try {
30
- const pos = await adapter.getPositions();
31
- exchangePositions.set(name, pos);
32
- }
33
- catch {
34
- exchangePositions.set(name, []);
35
- }
36
- }
37
- // Track which exchange positions are accounted for
38
- const accountedFor = new Set(); // "exchange:symbol:side"
39
- // Check each local arb position against exchange
40
- for (const arb of localPositions) {
41
- // Check long leg
42
- const longPositions = exchangePositions.get(arb.longExchange) ?? [];
43
- const longMatch = findExchangePosition(longPositions, arb.symbol, "long");
44
- if (!longMatch) {
45
- issues.push({
46
- type: "phantom",
47
- symbol: arb.symbol,
48
- exchange: arb.longExchange,
49
- side: "long",
50
- localSize: arb.longSize,
51
- exchangeSize: null,
52
- severity: "critical",
53
- suggestion: `Local state has long ${arb.symbol} on ${arb.longExchange} but exchange has no position. May have been liquidated or manually closed.`,
54
- });
55
- if (shouldFix) {
56
- removePosition(arb.symbol);
57
- fixesApplied.push(`Removed phantom position ${arb.symbol} (long leg missing on ${arb.longExchange})`);
58
- continue; // Skip short leg check since we removed the position
59
- }
60
- }
61
- else {
62
- accountedFor.add(`${arb.longExchange}:${normalizeSymbol(arb.symbol)}:long`);
63
- const exchangeSize = Math.abs(Number(longMatch.size));
64
- const localSize = Math.abs(arb.longSize);
65
- const diffPct = localSize > 0 ? (Math.abs(exchangeSize - localSize) / localSize) * 100 : 0;
66
- if (diffPct > tolerancePct) {
67
- issues.push({
68
- type: "size_mismatch",
69
- symbol: arb.symbol,
70
- exchange: arb.longExchange,
71
- side: "long",
72
- localSize,
73
- exchangeSize,
74
- severity: "warning",
75
- suggestion: `Long size mismatch: local ${localSize} vs exchange ${exchangeSize} (${diffPct.toFixed(1)}% diff). Partial fill or manual adjustment?`,
76
- });
77
- if (shouldFix) {
78
- updatePosition(arb.symbol, { longSize: exchangeSize });
79
- fixesApplied.push(`Updated ${arb.symbol} long size: ${localSize} → ${exchangeSize}`);
80
- }
81
- }
82
- else {
83
- healthy++;
84
- }
85
- }
86
- // Check short leg
87
- const shortPositions = exchangePositions.get(arb.shortExchange) ?? [];
88
- const shortMatch = findExchangePosition(shortPositions, arb.symbol, "short");
89
- if (!shortMatch) {
90
- // Don't double-report if we already removed via fix
91
- if (shouldFix && !getPositions().find(p => p.symbol === arb.symbol))
92
- continue;
93
- issues.push({
94
- type: "phantom",
95
- symbol: arb.symbol,
96
- exchange: arb.shortExchange,
97
- side: "short",
98
- localSize: arb.shortSize,
99
- exchangeSize: null,
100
- severity: "critical",
101
- suggestion: `Local state has short ${arb.symbol} on ${arb.shortExchange} but exchange has no position. May have been liquidated or manually closed.`,
102
- });
103
- if (shouldFix) {
104
- removePosition(arb.symbol);
105
- fixesApplied.push(`Removed phantom position ${arb.symbol} (short leg missing on ${arb.shortExchange})`);
106
- }
107
- }
108
- else {
109
- accountedFor.add(`${arb.shortExchange}:${normalizeSymbol(arb.symbol)}:short`);
110
- const exchangeSize = Math.abs(Number(shortMatch.size));
111
- const localSize = Math.abs(arb.shortSize);
112
- const diffPct = localSize > 0 ? (Math.abs(exchangeSize - localSize) / localSize) * 100 : 0;
113
- if (diffPct > tolerancePct) {
114
- issues.push({
115
- type: "size_mismatch",
116
- symbol: arb.symbol,
117
- exchange: arb.shortExchange,
118
- side: "short",
119
- localSize,
120
- exchangeSize,
121
- severity: "warning",
122
- suggestion: `Short size mismatch: local ${localSize} vs exchange ${exchangeSize} (${diffPct.toFixed(1)}% diff). Partial fill or manual adjustment?`,
123
- });
124
- if (shouldFix) {
125
- updatePosition(arb.symbol, { shortSize: exchangeSize });
126
- fixesApplied.push(`Updated ${arb.symbol} short size: ${localSize} → ${exchangeSize}`);
127
- }
128
- }
129
- else {
130
- healthy++;
131
- }
132
- }
133
- }
134
- // Check for orphan positions (on exchange but not in local state)
135
- for (const [exchangeName, positions] of exchangePositions) {
136
- for (const pos of positions) {
137
- const key = `${exchangeName}:${normalizeSymbol(pos.symbol)}:${pos.side}`;
138
- if (!accountedFor.has(key)) {
139
- // Check if this exchange is used in any arb position
140
- const isArbExchange = localPositions.some(p => p.longExchange === exchangeName || p.shortExchange === exchangeName);
141
- // Only report orphans on exchanges that are part of arb state
142
- if (isArbExchange || localPositions.length > 0) {
143
- issues.push({
144
- type: "orphan",
145
- symbol: pos.symbol,
146
- exchange: exchangeName,
147
- side: pos.side,
148
- localSize: null,
149
- exchangeSize: Math.abs(Number(pos.size)),
150
- severity: "warning",
151
- suggestion: `Position on ${exchangeName} not tracked in arb state. Manual entry or untracked strategy?`,
152
- });
153
- }
154
- }
155
- }
156
- }
157
- return {
158
- issues,
159
- healthy,
160
- ...(fixesApplied.length > 0 ? { fixesApplied } : {}),
161
- };
162
- }
@@ -1,2 +0,0 @@
1
- import { Command } from "commander";
2
- export declare function registerAlertCommands(program: Command, isJson: () => boolean, getAdapterFor?: (exchange: string) => Promise<import("../exchanges/interface.js").ExchangeAdapter>): void;