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,243 +0,0 @@
1
- /**
2
- * PnL Tracker CLI commands.
3
- *
4
- * perp pnl snapshot — take one-time equity snapshots across exchanges
5
- * perp pnl track — continuous equity tracking (foreground)
6
- * perp pnl daily — daily PnL breakdown table
7
- * perp pnl weekly — weekly PnL breakdown table
8
- * perp pnl summary — performance summary (Sharpe, drawdown, win rate)
9
- */
10
- import chalk from "chalk";
11
- import { printJson, jsonOk, jsonError, makeTable, formatUsd, formatPnl, withJsonErrors } from "../utils.js";
12
- import { saveEquitySnapshot, readEquityHistory, computePnlMetrics, computeDailyPnl, aggregateWeekly, } from "../equity-tracker.js";
13
- const EXCHANGES = ["pacifica", "hyperliquid", "lighter"];
14
- function parseSince(since) {
15
- if (!since)
16
- return undefined;
17
- const match = since.match(/^(\d+)(h|d|w)$/);
18
- if (match) {
19
- const [, num, unit] = match;
20
- const ms = { h: 3600000, d: 86400000, w: 604800000 }[unit] ?? 86400000;
21
- return new Date(Date.now() - parseInt(num) * ms);
22
- }
23
- return new Date(since);
24
- }
25
- /** Take equity snapshot for given adapters. */
26
- async function takeSnapshot(getAdapterForExchange, exchanges) {
27
- const ts = new Date().toISOString();
28
- const snaps = [];
29
- const results = await Promise.allSettled(exchanges.map(async (ex) => {
30
- const adapter = await getAdapterForExchange(ex);
31
- const [balance, positions] = await Promise.all([
32
- adapter.getBalance(),
33
- adapter.getPositions(),
34
- ]);
35
- const snap = {
36
- ts,
37
- exchange: ex,
38
- equity: Number(balance.equity),
39
- available: Number(balance.available),
40
- marginUsed: Number(balance.marginUsed),
41
- unrealizedPnl: Number(balance.unrealizedPnl),
42
- positionCount: positions.filter(p => Number(p.size) > 0).length,
43
- };
44
- saveEquitySnapshot(snap);
45
- return snap;
46
- }));
47
- for (const r of results) {
48
- if (r.status === "fulfilled")
49
- snaps.push(r.value);
50
- }
51
- return snaps;
52
- }
53
- export function registerPnlCommands(program, getAdapterForExchange, isJson) {
54
- const pnl = program.command("pnl").description("Equity snapshot tracking & time-series performance (Sharpe, drawdown)");
55
- // ── pnl snapshot ──
56
- pnl
57
- .command("snapshot")
58
- .description("Take equity snapshot across all exchanges")
59
- .option("--exchanges <list>", "Comma-separated exchange list", EXCHANGES.join(","))
60
- .action(async (opts) => {
61
- await withJsonErrors(isJson(), async () => {
62
- const exchanges = opts.exchanges.split(",").map(e => e.trim());
63
- const snaps = await takeSnapshot(getAdapterForExchange, exchanges);
64
- if (isJson()) {
65
- printJson(jsonOk({ snapshots: snaps }));
66
- }
67
- else {
68
- const total = snaps.reduce((s, sn) => s + sn.equity, 0);
69
- console.log(chalk.cyan.bold("Equity Snapshot\n"));
70
- for (const s of snaps) {
71
- console.log(` ${s.exchange.padEnd(14)} $${formatUsd(s.equity)} ` +
72
- `avail $${formatUsd(s.available)} ` +
73
- `uPnL ${formatPnl(s.unrealizedPnl)} ` +
74
- `pos: ${s.positionCount}`);
75
- }
76
- console.log(`\n ${"Total".padEnd(14)} $${formatUsd(total)}`);
77
- console.log(chalk.gray(`\n Saved at ${snaps[0]?.ts ?? "—"}`));
78
- }
79
- });
80
- });
81
- // ── pnl track ──
82
- pnl
83
- .command("track")
84
- .description("Continuously track equity (foreground)")
85
- .option("--interval <sec>", "Snapshot interval in seconds", "300")
86
- .option("--exchanges <list>", "Comma-separated exchange list", EXCHANGES.join(","))
87
- .action(async (opts) => {
88
- const intervalMs = parseInt(opts.interval) * 1000;
89
- const exchanges = opts.exchanges.split(",").map(e => e.trim());
90
- console.log(chalk.cyan(`PnL tracker started — snapshot every ${opts.interval}s for [${exchanges.join(", ")}]`));
91
- console.log(chalk.gray("Press Ctrl+C to stop\n"));
92
- const controller = new AbortController();
93
- process.on("SIGINT", () => controller.abort());
94
- // Initial snapshot
95
- const snaps = await takeSnapshot(getAdapterForExchange, exchanges);
96
- const total = snaps.reduce((s, sn) => s + sn.equity, 0);
97
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} Total equity: $${formatUsd(total)}`);
98
- while (!controller.signal.aborted) {
99
- await new Promise((resolve) => {
100
- const timer = setTimeout(resolve, intervalMs);
101
- controller.signal.addEventListener("abort", () => { clearTimeout(timer); resolve(); }, { once: true });
102
- });
103
- if (controller.signal.aborted)
104
- break;
105
- try {
106
- const s = await takeSnapshot(getAdapterForExchange, exchanges);
107
- const t = s.reduce((sum, sn) => sum + sn.equity, 0);
108
- const delta = t - total;
109
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} ` +
110
- `Total: $${formatUsd(t)} ${formatPnl(delta)}`);
111
- }
112
- catch (err) {
113
- console.error(chalk.red(`Snapshot error: ${err instanceof Error ? err.message : err}`));
114
- }
115
- }
116
- });
117
- // ── pnl daily ──
118
- pnl
119
- .command("daily")
120
- .description("Daily PnL breakdown")
121
- .option("--exchange <name>", "Single exchange filter")
122
- .option("--days <n>", "Number of days to show", "14")
123
- .option("--since <period>", "Time range (e.g. 7d, 2w, 30d)")
124
- .action(async (opts) => {
125
- await withJsonErrors(isJson(), async () => {
126
- const since = parseSince(opts.since) ?? new Date(Date.now() - parseInt(opts.days) * 86400000);
127
- const snapshots = readEquityHistory({ exchange: opts.exchange, since });
128
- if (snapshots.length === 0) {
129
- if (isJson()) {
130
- printJson(jsonError("NO_DATA", "No equity snapshots found. Run 'perp pnl snapshot' or 'perp pnl track' first."));
131
- }
132
- else {
133
- console.log(chalk.yellow("No equity snapshots found. Run 'perp pnl snapshot' or 'perp pnl track' first."));
134
- }
135
- return;
136
- }
137
- const daily = computeDailyPnl(snapshots, opts.exchange);
138
- if (isJson()) {
139
- printJson(jsonOk({ daily }));
140
- }
141
- else {
142
- console.log(chalk.cyan.bold(`Daily PnL${opts.exchange ? ` (${opts.exchange})` : ""}\n`));
143
- const head = ["Date", "Start", "End", "PnL", "PnL %"];
144
- const rows = daily.map(d => [
145
- d.date,
146
- `$${formatUsd(d.startEquity)}`,
147
- `$${formatUsd(d.endEquity)}`,
148
- formatPnl(d.pnl),
149
- `${d.pnlPct >= 0 ? "+" : ""}${d.pnlPct.toFixed(2)}%`,
150
- ]);
151
- console.log(makeTable(head, rows));
152
- }
153
- });
154
- });
155
- // ── pnl weekly ──
156
- pnl
157
- .command("weekly")
158
- .description("Weekly PnL breakdown")
159
- .option("--exchange <name>", "Single exchange filter")
160
- .option("--weeks <n>", "Number of weeks to show", "8")
161
- .option("--since <period>", "Time range (e.g. 4w, 8w)")
162
- .action(async (opts) => {
163
- await withJsonErrors(isJson(), async () => {
164
- const since = parseSince(opts.since) ?? new Date(Date.now() - parseInt(opts.weeks) * 7 * 86400000);
165
- const snapshots = readEquityHistory({ exchange: opts.exchange, since });
166
- if (snapshots.length === 0) {
167
- if (isJson()) {
168
- printJson(jsonError("NO_DATA", "No equity snapshots found."));
169
- }
170
- else {
171
- console.log(chalk.yellow("No equity snapshots found. Run 'perp pnl snapshot' or 'perp pnl track' first."));
172
- }
173
- return;
174
- }
175
- const daily = computeDailyPnl(snapshots, opts.exchange);
176
- const weekly = aggregateWeekly(daily);
177
- if (isJson()) {
178
- printJson(jsonOk({ weekly }));
179
- }
180
- else {
181
- console.log(chalk.cyan.bold(`Weekly PnL${opts.exchange ? ` (${opts.exchange})` : ""}\n`));
182
- const head = ["Week", "Start", "End", "PnL", "PnL %"];
183
- const rows = weekly.map(w => [
184
- w.date,
185
- `$${formatUsd(w.startEquity)}`,
186
- `$${formatUsd(w.endEquity)}`,
187
- formatPnl(w.pnl),
188
- `${w.pnlPct >= 0 ? "+" : ""}${w.pnlPct.toFixed(2)}%`,
189
- ]);
190
- console.log(makeTable(head, rows));
191
- }
192
- });
193
- });
194
- // ── pnl summary ──
195
- pnl
196
- .command("summary")
197
- .description("Performance summary — Sharpe, drawdown, win rate")
198
- .option("--exchange <name>", "Single exchange filter")
199
- .option("--since <period>", "Time range (e.g. 7d, 30d, 12w)")
200
- .action(async (opts) => {
201
- await withJsonErrors(isJson(), async () => {
202
- const since = parseSince(opts.since);
203
- const snapshots = readEquityHistory({ exchange: opts.exchange, since });
204
- if (snapshots.length === 0) {
205
- if (isJson()) {
206
- printJson(jsonError("NO_DATA", "No equity snapshots found."));
207
- }
208
- else {
209
- console.log(chalk.yellow("No equity snapshots found. Run 'perp pnl snapshot' or 'perp pnl track' first."));
210
- }
211
- return;
212
- }
213
- const metrics = computePnlMetrics(snapshots, opts.exchange);
214
- if (isJson()) {
215
- printJson(jsonOk({
216
- ...metrics,
217
- dailyReturns: undefined, // omit large array from JSON
218
- dailyCount: metrics.dailyReturns.length,
219
- }));
220
- }
221
- else {
222
- console.log(chalk.cyan.bold(`Performance Summary${opts.exchange ? ` (${opts.exchange})` : ""}\n`));
223
- console.log(` Period: ${metrics.period.from} → ${metrics.period.to} (${metrics.period.days} days)`);
224
- console.log(` Total Return: ${formatPnl(metrics.totalReturn)} (${metrics.totalReturnPct >= 0 ? "+" : ""}${metrics.totalReturnPct.toFixed(2)}%)`);
225
- console.log(` Peak Equity: $${formatUsd(metrics.peakEquity)}`);
226
- console.log(` Avg Daily PnL: ${formatPnl(metrics.avgDailyPnl)}`);
227
- console.log();
228
- console.log(` Sharpe Ratio: ${metrics.sharpeRatio >= 0 ? chalk.green(metrics.sharpeRatio.toFixed(2)) : chalk.red(metrics.sharpeRatio.toFixed(2))}`);
229
- console.log(` Max Drawdown: ${chalk.red(`$${formatUsd(metrics.maxDrawdown)}`)} (${chalk.red(`-${metrics.maxDrawdownPct.toFixed(2)}%`)})`);
230
- console.log(` Current DD: $${formatUsd(metrics.currentDrawdown)} (-${metrics.currentDrawdownPct.toFixed(2)}%)`);
231
- console.log();
232
- console.log(` Win Days: ${chalk.green(String(metrics.winDays))} / ${metrics.winDays + metrics.lossDays}`);
233
- console.log(` Win Rate: ${metrics.winRate.toFixed(1)}%`);
234
- if (metrics.bestDay) {
235
- console.log(` Best Day: ${metrics.bestDay.date} ${formatPnl(metrics.bestDay.pnl)}`);
236
- }
237
- if (metrics.worstDay) {
238
- console.log(` Worst Day: ${metrics.worstDay.date} ${formatPnl(metrics.worstDay.pnl)}`);
239
- }
240
- }
241
- });
242
- });
243
- }
@@ -1,3 +0,0 @@
1
- import { Command } from "commander";
2
- import type { ExchangeAdapter } from "../exchanges/interface.js";
3
- export declare function registerRunCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, getAdapterFor: (exchange: string) => Promise<ExchangeAdapter>, isJson: () => boolean): void;
@@ -1,202 +0,0 @@
1
- import { printJson, jsonOk } from "../utils.js";
2
- import { updateJobState } from "../jobs.js";
3
- import { runTWAP } from "../strategies/twap.js";
4
- import { runFundingArb } from "../strategies/funding-arb.js";
5
- import { runGrid } from "../strategies/grid.js";
6
- import { runDCA } from "../strategies/dca.js";
7
- import { runTrailingStop } from "../strategies/trailing-stop.js";
8
- import chalk from "chalk";
9
- export function registerRunCommands(program, getAdapter, getAdapterFor, isJson) {
10
- const run = program.command("run").description("Run a strategy (foreground or as background job target)");
11
- run
12
- .command("twap <symbol> <side> <size> <duration>")
13
- .description("Run client-side TWAP (splits market orders over time)")
14
- .option("-s, --slices <n>", "Number of slices (default: auto)")
15
- .option("--job-id <id>", "Job ID (set automatically for background jobs)")
16
- .action(async (symbol, side, size, duration, opts) => {
17
- const s = side.toLowerCase();
18
- if (s !== "buy" && s !== "sell") {
19
- console.error(chalk.red("Side must be buy or sell"));
20
- process.exit(1);
21
- }
22
- const adapter = await getAdapter();
23
- const params = {
24
- symbol: symbol.toUpperCase(),
25
- side: s,
26
- totalSize: parseFloat(size),
27
- durationSec: parseInt(duration),
28
- slices: opts.slices ? parseInt(opts.slices) : undefined,
29
- };
30
- const log = (msg) => {
31
- const ts = new Date().toLocaleTimeString();
32
- console.log(`${chalk.gray(ts)} ${msg}`);
33
- };
34
- const result = await runTWAP(adapter, params, opts.jobId, log);
35
- if (isJson())
36
- printJson(jsonOk(result));
37
- if (opts.jobId) {
38
- updateJobState(opts.jobId, { status: "done" });
39
- }
40
- });
41
- run
42
- .command("funding-arb")
43
- .description("Run funding rate arbitrage monitor/executor")
44
- .option("--min-spread <pct>", "Min annual spread % to enter", "10")
45
- .option("--close-spread <pct>", "Close when spread drops below (%)", "5")
46
- .option("--size <size>", "Position size per leg (base amount)", "0.01")
47
- .option("--size-usd <usd>", "Position size per leg in USD (alternative)")
48
- .option("--symbols <list>", "Comma-separated symbol filter")
49
- .option("--interval <sec>", "Check interval in seconds", "60")
50
- .option("--auto-execute", "Actually place trades (default: monitor only)")
51
- .option("--max-positions <n>", "Max simultaneous positions", "3")
52
- .option("--exchanges <list>", "Comma-separated exchanges to use", "pacifica,hyperliquid,lighter")
53
- .option("--auto-rebalance", "Trigger rebalance alerts when exchange balance is low")
54
- .option("--rebalance-threshold <usd>", "Rebalance when available < this ($)", "100")
55
- .option("--max-drawdown <usd>", "Close all positions if total uPnL exceeds this loss ($)")
56
- .option("--job-id <id>", "Job ID (set automatically for background jobs)")
57
- .action(async (opts) => {
58
- const exchangeNames = opts.exchanges.split(",").map((e) => e.trim());
59
- const adapters = new Map();
60
- for (const name of exchangeNames) {
61
- try {
62
- const a = await getAdapterFor(name);
63
- adapters.set(name, a);
64
- }
65
- catch {
66
- if (!isJson())
67
- console.log(chalk.yellow(` Skipping ${name} (no credentials)`));
68
- }
69
- }
70
- if (adapters.size < 2) {
71
- console.error(chalk.red("Need at least 2 exchanges for arbitrage. Set credentials for 2+ exchanges."));
72
- process.exit(1);
73
- }
74
- const params = {
75
- minSpread: parseFloat(opts.minSpread),
76
- closeSpread: parseFloat(opts.closeSpread),
77
- size: opts.size,
78
- sizeUsd: opts.sizeUsd ? parseFloat(opts.sizeUsd) : undefined,
79
- symbols: opts.symbols ? opts.symbols.split(",").map((s) => s.trim().toUpperCase()) : undefined,
80
- intervalSec: parseInt(opts.interval),
81
- autoExecute: opts.autoExecute ?? false,
82
- maxPositions: parseInt(opts.maxPositions),
83
- autoRebalance: opts.autoRebalance ?? false,
84
- rebalanceThreshold: parseFloat(opts.rebalanceThreshold),
85
- maxDrawdown: opts.maxDrawdown ? parseFloat(opts.maxDrawdown) : undefined,
86
- };
87
- const log = (msg) => {
88
- const ts = new Date().toLocaleTimeString();
89
- console.log(`${chalk.gray(ts)} ${msg}`);
90
- };
91
- await runFundingArb(adapters, params, opts.jobId, log);
92
- });
93
- // ── Grid Bot ──
94
- run
95
- .command("grid <symbol>")
96
- .description("Run grid trading bot (places limit orders across a price range)")
97
- .requiredOption("--upper <price>", "Upper price bound")
98
- .requiredOption("--lower <price>", "Lower price bound")
99
- .option("--grids <n>", "Number of grid lines", "10")
100
- .option("--size <size>", "Total position size (base)", "0.1")
101
- .option("--side <side>", "Grid bias: long, short, neutral", "neutral")
102
- .option("--leverage <n>", "Leverage to set")
103
- .option("--interval <sec>", "Check interval in seconds", "10")
104
- .option("--max-runtime <sec>", "Max runtime in seconds (0 = forever)", "0")
105
- .option("--trailing-stop <pct>", "Stop if equity drops by this % from peak")
106
- .option("--job-id <id>", "Job ID (set automatically for background jobs)")
107
- .action(async (symbol, opts) => {
108
- const side = opts.side.toLowerCase();
109
- if (side !== "long" && side !== "short" && side !== "neutral") {
110
- console.error(chalk.red("Side must be long, short, or neutral"));
111
- process.exit(1);
112
- }
113
- const adapter = await getAdapter();
114
- const params = {
115
- symbol: symbol.toUpperCase(),
116
- side: side,
117
- upperPrice: parseFloat(opts.upper),
118
- lowerPrice: parseFloat(opts.lower),
119
- grids: parseInt(opts.grids),
120
- totalSize: parseFloat(opts.size),
121
- leverage: opts.leverage ? parseInt(opts.leverage) : undefined,
122
- intervalSec: parseInt(opts.interval),
123
- maxRuntime: parseInt(opts.maxRuntime),
124
- trailingStop: opts.trailingStop ? parseFloat(opts.trailingStop) : undefined,
125
- };
126
- const log = (msg) => {
127
- const ts = new Date().toLocaleTimeString();
128
- console.log(`${chalk.gray(ts)} ${msg}`);
129
- };
130
- const result = await runGrid(adapter, params, opts.jobId, log);
131
- if (isJson())
132
- printJson(jsonOk(result));
133
- if (opts.jobId) {
134
- updateJobState(opts.jobId, { status: "done" });
135
- }
136
- });
137
- // ── DCA (Dollar Cost Averaging) ──
138
- run
139
- .command("dca <symbol> <side> <amount> <interval>")
140
- .description("Run DCA strategy (periodic market orders at fixed intervals)")
141
- .option("--orders <n>", "Total number of orders (0 = unlimited)", "0")
142
- .option("--price-limit <price>", "Stop buying above / selling below this price")
143
- .option("--max-runtime <sec>", "Max runtime in seconds (0 = forever)", "0")
144
- .option("--job-id <id>", "Job ID (set automatically for background jobs)")
145
- .action(async (symbol, side, amount, interval, opts) => {
146
- const s = side.toLowerCase();
147
- if (s !== "buy" && s !== "sell") {
148
- console.error(chalk.red("Side must be buy or sell"));
149
- process.exit(1);
150
- }
151
- const adapter = await getAdapter();
152
- const params = {
153
- symbol: symbol.toUpperCase(),
154
- side: s,
155
- amountPerOrder: parseFloat(amount),
156
- intervalSec: parseInt(interval),
157
- totalOrders: parseInt(opts.orders),
158
- priceLimit: opts.priceLimit ? parseFloat(opts.priceLimit) : undefined,
159
- maxRuntime: parseInt(opts.maxRuntime),
160
- };
161
- const log = (msg) => {
162
- const ts = new Date().toLocaleTimeString();
163
- console.log(`${chalk.gray(ts)} ${msg}`);
164
- };
165
- const result = await runDCA(adapter, params, opts.jobId, log);
166
- if (isJson())
167
- printJson(jsonOk(result));
168
- if (opts.jobId) {
169
- updateJobState(opts.jobId, { status: "done" });
170
- }
171
- });
172
- // ── Trailing Stop ──
173
- run
174
- .command("trailing-stop <symbol>")
175
- .description("Run client-side trailing stop (monitors price, closes position when trail % hit)")
176
- .requiredOption("--trail <pct>", "Trail percentage")
177
- .option("--interval <sec>", "Check interval in seconds", "5")
178
- .option("--activation <price>", "Only start trailing after price reaches this level")
179
- .option("--job-id <id>", "Job ID (set automatically for background jobs)")
180
- .action(async (symbol, opts) => {
181
- const sym = symbol.toUpperCase();
182
- const trailPct = parseFloat(opts.trail);
183
- const intervalSec = parseInt(opts.interval);
184
- const activationPrice = opts.activation ? parseFloat(opts.activation) : undefined;
185
- const adapter = await getAdapter();
186
- const log = (msg) => {
187
- const ts = new Date().toLocaleTimeString();
188
- console.log(`${chalk.gray(ts)} ${msg}`);
189
- };
190
- const result = await runTrailingStop(adapter, {
191
- symbol: sym,
192
- trailPct,
193
- intervalSec,
194
- activationPrice,
195
- }, opts.jobId, log);
196
- if (isJson())
197
- printJson(jsonOk(result));
198
- if (opts.jobId) {
199
- updateJobState(opts.jobId, { status: "done" });
200
- }
201
- });
202
- }
@@ -1,5 +0,0 @@
1
- import { Command } from "commander";
2
- import { type Network } from "../pacifica/index.js";
3
- import type { Exchange } from "../config.js";
4
- import type { ExchangeAdapter } from "../exchanges/interface.js";
5
- export declare function registerStreamCommands(program: Command, getNetwork: () => Network, getExchange: () => Exchange, getAdapter?: () => Promise<ExchangeAdapter>): void;
@@ -1,200 +0,0 @@
1
- import { PacificaWSClient } from "../pacifica/index.js";
2
- import chalk from "chalk";
3
- import { formatUsd, formatPercent } from "../utils.js";
4
- /** Create an HL or Lighter market feed, connected and ready. */
5
- async function getMarketFeed(exchange) {
6
- const { createMarketFeed } = await import("../ws/market-feed.js");
7
- const feed = createMarketFeed(exchange);
8
- await feed.connect();
9
- process.on("SIGINT", () => { feed.close(); process.exit(0); });
10
- return feed;
11
- }
12
- export function registerStreamCommands(program, getNetwork, getExchange, getAdapter) {
13
- const stream = program.command("stream").description("Live WebSocket streams (Ctrl+C to stop)");
14
- // ── stream prices ──
15
- stream
16
- .command("prices")
17
- .description("Stream live prices")
18
- .action(async () => {
19
- const exchange = getExchange();
20
- if (exchange === "pacifica") {
21
- const ws = new PacificaWSClient({ network: getNetwork() });
22
- await ws.connect();
23
- ws.subscribe("prices");
24
- ws.on("prices", (msg) => {
25
- const data = msg;
26
- const d = data.data ?? data;
27
- if (Array.isArray(d)) {
28
- d.forEach((p) => {
29
- const mark = Number(p.mark ?? p.m ?? 0);
30
- const funding = Number(p.funding ?? p.f ?? 0);
31
- const sym = String(p.symbol ?? p.s ?? "").padEnd(10);
32
- console.log(`${chalk.white.bold(sym)} $${formatUsd(mark)} ${formatPercent(funding)}`);
33
- });
34
- }
35
- });
36
- console.log(chalk.cyan("Streaming pacifica prices... (Ctrl+C to stop)\n"));
37
- }
38
- else {
39
- const feed = await getMarketFeed(exchange);
40
- feed.subscribePrices();
41
- feed.on("prices", (updates) => {
42
- for (const p of updates) {
43
- const sym = p.symbol.padEnd(10);
44
- console.log(`${chalk.white.bold(sym)} $${formatUsd(p.mid)}`);
45
- }
46
- });
47
- console.log(chalk.cyan(`Streaming ${exchange} prices... (Ctrl+C to stop)\n`));
48
- }
49
- await new Promise(() => { }); // keep alive
50
- });
51
- // ── stream book ──
52
- stream
53
- .command("book <symbol>")
54
- .description("Stream orderbook updates")
55
- .action(async (symbol) => {
56
- const exchange = getExchange();
57
- const sym = symbol.toUpperCase();
58
- if (exchange === "pacifica") {
59
- const ws = new PacificaWSClient({ network: getNetwork() });
60
- await ws.connect();
61
- ws.subscribe("book", { symbol: sym });
62
- ws.on("book", (msg) => {
63
- const data = msg;
64
- console.log(`${chalk.cyan(new Date().toLocaleTimeString())} ${JSON.stringify(data.data ?? data)}`);
65
- });
66
- }
67
- else {
68
- const feed = await getMarketFeed(exchange);
69
- feed.subscribeBook(sym);
70
- feed.on("book", (data) => {
71
- const topBids = data.bids.slice(0, 5).map(([p, s]) => `${p}x${s}`).join(" ");
72
- const topAsks = data.asks.slice(0, 5).map(([p, s]) => `${p}x${s}`).join(" ");
73
- console.log(`${chalk.cyan(new Date().toLocaleTimeString())} ${chalk.green("BID")} ${topBids} ${chalk.red("ASK")} ${topAsks}`);
74
- });
75
- }
76
- console.log(chalk.cyan(`Streaming ${sym} orderbook on ${exchange}... (Ctrl+C to stop)\n`));
77
- await new Promise(() => { });
78
- });
79
- // ── stream trades ──
80
- stream
81
- .command("trades <symbol>")
82
- .description("Stream live trades")
83
- .action(async (symbol) => {
84
- const exchange = getExchange();
85
- const sym = symbol.toUpperCase();
86
- if (exchange === "pacifica") {
87
- const ws = new PacificaWSClient({ network: getNetwork() });
88
- await ws.connect();
89
- ws.subscribe("trades", { symbol: sym });
90
- ws.on("trades", (msg) => {
91
- const data = msg;
92
- const d = (data.data ?? data);
93
- const side = String(d.side ?? d.d ?? "");
94
- const price = String(d.price ?? d.p ?? "");
95
- const amount = String(d.amount ?? d.a ?? "");
96
- const color = side === "bid" || side === "buy" ? chalk.green : chalk.red;
97
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} ${color(side === "bid" ? "BUY " : "SELL")} $${formatUsd(price)} x ${amount}`);
98
- });
99
- }
100
- else {
101
- const feed = await getMarketFeed(exchange);
102
- feed.subscribeTrades(sym);
103
- feed.on("trade", (t) => {
104
- const color = t.side === "buy" ? chalk.green : chalk.red;
105
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} ${color(t.side === "buy" ? "BUY " : "SELL")} $${formatUsd(t.price)} x ${t.size}`);
106
- });
107
- }
108
- console.log(chalk.cyan(`Streaming ${sym} trades on ${exchange}... (Ctrl+C to stop)\n`));
109
- await new Promise(() => { });
110
- });
111
- // ── stream bbo ──
112
- stream
113
- .command("bbo <symbol>")
114
- .description("Stream best bid/offer")
115
- .action(async (symbol) => {
116
- const exchange = getExchange();
117
- const sym = symbol.toUpperCase();
118
- if (exchange === "pacifica") {
119
- const ws = new PacificaWSClient({ network: getNetwork() });
120
- await ws.connect();
121
- ws.subscribe("bbo", { symbol: sym });
122
- ws.on("bbo", (msg) => {
123
- const data = msg.data ?? msg;
124
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} ${JSON.stringify(data)}`);
125
- });
126
- }
127
- else {
128
- // BBO derived from orderbook (HL/Lighter don't have dedicated BBO channel)
129
- const feed = await getMarketFeed(exchange);
130
- feed.subscribeBook(sym);
131
- feed.on("book", (data) => {
132
- const bid = data.bids[0] ?? ["—", "—"];
133
- const ask = data.asks[0] ?? ["—", "—"];
134
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} ${chalk.green("bid")} ${bid[0]} (${bid[1]}) ${chalk.red("ask")} ${ask[0]} (${ask[1]})`);
135
- });
136
- }
137
- console.log(chalk.cyan(`Streaming ${sym} BBO on ${exchange}... (Ctrl+C to stop)\n`));
138
- await new Promise(() => { });
139
- });
140
- // ── stream candle ──
141
- stream
142
- .command("candle <symbol> <interval>")
143
- .description("Stream candlestick data")
144
- .action(async (symbol, interval) => {
145
- const exchange = getExchange();
146
- const sym = symbol.toUpperCase();
147
- if (exchange === "pacifica") {
148
- const ws = new PacificaWSClient({ network: getNetwork() });
149
- await ws.connect();
150
- ws.subscribe("candle", { symbol: sym, interval });
151
- ws.on("candle", (msg) => {
152
- const data = msg.data ?? msg;
153
- const d = data;
154
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} O:$${formatUsd(String(d.o ?? ""))} H:$${formatUsd(String(d.h ?? ""))} L:$${formatUsd(String(d.l ?? ""))} C:$${formatUsd(String(d.c ?? ""))} V:${d.v ?? ""}`);
155
- });
156
- }
157
- else {
158
- const feed = await getMarketFeed(exchange);
159
- feed.subscribeCandle(sym, interval);
160
- feed.on("candle", (d) => {
161
- console.log(`${chalk.gray(new Date().toLocaleTimeString())} O:$${formatUsd(d.o)} H:$${formatUsd(d.h)} L:$${formatUsd(d.l)} C:$${formatUsd(d.c)} V:${d.v}`);
162
- });
163
- }
164
- console.log(chalk.cyan(`Streaming ${sym} ${interval} candles on ${exchange}... (Ctrl+C to stop)\n`));
165
- await new Promise(() => { });
166
- });
167
- // ── stream events ── (unified account events as NDJSON, already exchange-agnostic)
168
- if (getAdapter) {
169
- stream
170
- .command("events")
171
- .description("Stream account events as NDJSON (positions, orders, balance, liquidation warnings)")
172
- .option("--interval <ms>", "Polling interval in milliseconds", "5000")
173
- .option("--liq-warn <pct>", "Liquidation warning distance %", "10")
174
- .option("--log-positions", "Log position lifecycle events to ~/.perp/positions.jsonl")
175
- .action(async (opts) => {
176
- const adapter = await getAdapter();
177
- const { startEventStream } = await import("../event-stream.js");
178
- console.error(chalk.cyan(`Streaming ${adapter.name} events... (Ctrl+C to stop)\n`));
179
- if (opts.logPositions) {
180
- console.error(chalk.gray(" Position logging enabled → ~/.perp/positions.jsonl\n"));
181
- }
182
- const controller = new AbortController();
183
- process.on("SIGINT", () => controller.abort());
184
- let onEvent = (event) => {
185
- // NDJSON: one JSON per line to stdout
186
- process.stdout.write(JSON.stringify(event) + "\n");
187
- };
188
- if (opts.logPositions) {
189
- const { attachPositionLogger } = await import("../position-history.js");
190
- onEvent = attachPositionLogger(onEvent);
191
- }
192
- await startEventStream(adapter, {
193
- intervalMs: parseInt(opts.interval),
194
- liquidationWarningPct: parseFloat(opts.liqWarn),
195
- onEvent,
196
- signal: controller.signal,
197
- });
198
- });
199
- }
200
- }
@@ -1,3 +0,0 @@
1
- import { Command } from "commander";
2
- import type { ExchangeAdapter } from "../exchanges/interface.js";
3
- export declare function registerWithdrawCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, isJson: () => boolean): void;