perp-cli 0.4.2 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +46 -5
- package/dist/arb/reconcile.d.ts +28 -0
- package/dist/arb/reconcile.js +162 -0
- package/dist/arb/sizing.d.ts +12 -1
- package/dist/arb/sizing.js +38 -5
- package/dist/arb/state.d.ts +6 -0
- package/dist/cli-spec.d.ts +0 -4
- package/dist/cli-spec.js +8 -1
- package/dist/commands/account.d.ts +1 -1
- package/dist/commands/account.js +300 -63
- package/dist/commands/agent.js +16 -9
- package/dist/commands/arb/index.js +243 -49
- package/dist/commands/arb-auto.js +696 -9
- package/dist/commands/arb.d.ts +2 -1
- package/dist/commands/arb.js +535 -131
- package/dist/commands/bot.js +207 -0
- package/dist/commands/dex.js +7 -1
- package/dist/commands/funding.d.ts +2 -1
- package/dist/commands/funding.js +211 -4
- package/dist/commands/funds.d.ts +4 -0
- package/dist/commands/funds.js +741 -0
- package/dist/commands/history.d.ts +2 -1
- package/dist/commands/history.js +508 -5
- package/dist/commands/manage.js +6 -4
- package/dist/commands/market.js +35 -2
- package/dist/commands/multileg.d.ts +16 -0
- package/dist/commands/multileg.js +174 -0
- package/dist/commands/pnl.d.ts +12 -0
- package/dist/commands/pnl.js +243 -0
- package/dist/commands/risk.d.ts +2 -0
- package/dist/commands/risk.js +56 -0
- package/dist/commands/settings.js +147 -0
- package/dist/commands/stream.js +132 -55
- package/dist/commands/trade.d.ts +1 -1
- package/dist/commands/trade.js +270 -267
- package/dist/commands/wallet.d.ts +4 -0
- package/dist/commands/wallet.js +11 -1
- package/dist/config.d.ts +6 -1
- package/dist/config.js +21 -1
- package/dist/dashboard/ws-feeds.js +1 -1
- package/dist/equity-tracker.d.ts +57 -0
- package/dist/equity-tracker.js +209 -0
- package/dist/exchanges/hyperliquid-spot.d.ts +69 -0
- package/dist/exchanges/hyperliquid-spot.js +309 -0
- package/dist/exchanges/hyperliquid.d.ts +26 -5
- package/dist/exchanges/hyperliquid.js +171 -73
- package/dist/exchanges/interface.d.ts +1 -1
- package/dist/exchanges/lighter-spot.d.ts +55 -0
- package/dist/exchanges/lighter-spot.js +415 -0
- package/dist/exchanges/lighter.d.ts +10 -2
- package/dist/exchanges/lighter.js +210 -56
- package/dist/exchanges/pacifica.d.ts +11 -4
- package/dist/exchanges/pacifica.js +64 -37
- package/dist/exchanges/spot-interface.d.ts +45 -0
- package/dist/exchanges/spot-interface.js +22 -0
- package/dist/execution-log.d.ts +2 -2
- package/dist/funding/rates.d.ts +36 -0
- package/dist/funding/rates.js +146 -0
- package/dist/index.js +126 -161
- package/dist/liquidity.d.ts +12 -0
- package/dist/liquidity.js +43 -0
- package/dist/mcp-server.js +43 -96
- package/dist/signer/evm-local.d.ts +12 -0
- package/dist/signer/evm-local.js +19 -0
- package/dist/signer/index.d.ts +3 -0
- package/dist/signer/index.js +2 -0
- package/dist/signer/interface.d.ts +31 -0
- package/dist/signer/interface.js +7 -0
- package/dist/signer/solana-local.d.ts +13 -0
- package/dist/signer/solana-local.js +19 -0
- package/dist/smart-order.js +14 -3
- package/dist/strategies/split-order.d.ts +49 -0
- package/dist/strategies/split-order.js +138 -0
- package/dist/utils.js +7 -1
- package/dist/ws/market-feed.d.ts +74 -0
- package/dist/ws/market-feed.js +227 -0
- package/package.json +1 -1
- package/skills/perp-cli/SKILL.md +80 -4
- package/skills/perp-cli/references/agent-operations.md +19 -9
- package/skills/perp-cli/references/commands.md +54 -32
- package/skills/perp-cli/references/strategies.md +27 -17
- package/skills/perp-cli/scripts/arb-monitor.sh +74 -0
- package/skills/perp-cli/scripts/funding-analysis.sh +85 -0
- package/skills/perp-cli/scripts/preflight.sh +98 -0
- package/skills/perp-cli/scripts/spot-perp-scan.sh +83 -0
- package/skills/perp-cli/scripts/validate-arb.sh +112 -0
- package/skills/perp-cli/templates/arb-scan.sh +0 -15
- package/skills/perp-cli/templates/open-position.sh +0 -38
- package/skills/perp-cli/templates/wallet-setup.sh +0 -17
package/dist/commands/stream.js
CHANGED
|
@@ -1,93 +1,170 @@
|
|
|
1
1
|
import { PacificaWSClient } from "../pacifica/index.js";
|
|
2
2
|
import chalk from "chalk";
|
|
3
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
|
+
}
|
|
4
12
|
export function registerStreamCommands(program, getNetwork, getExchange, getAdapter) {
|
|
5
13
|
const stream = program.command("stream").description("Live WebSocket streams (Ctrl+C to stop)");
|
|
14
|
+
// ── stream prices ──
|
|
6
15
|
stream
|
|
7
16
|
.command("prices")
|
|
8
17
|
.description("Stream live prices")
|
|
9
18
|
.action(async () => {
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
d.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
+
}
|
|
26
49
|
await new Promise(() => { }); // keep alive
|
|
27
50
|
});
|
|
51
|
+
// ── stream book ──
|
|
28
52
|
stream
|
|
29
53
|
.command("book <symbol>")
|
|
30
54
|
.description("Stream orderbook updates")
|
|
31
55
|
.action(async (symbol) => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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`));
|
|
40
77
|
await new Promise(() => { });
|
|
41
78
|
});
|
|
79
|
+
// ── stream trades ──
|
|
42
80
|
stream
|
|
43
81
|
.command("trades <symbol>")
|
|
44
82
|
.description("Stream live trades")
|
|
45
83
|
.action(async (symbol) => {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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`));
|
|
59
109
|
await new Promise(() => { });
|
|
60
110
|
});
|
|
111
|
+
// ── stream bbo ──
|
|
61
112
|
stream
|
|
62
113
|
.command("bbo <symbol>")
|
|
63
114
|
.description("Stream best bid/offer")
|
|
64
115
|
.action(async (symbol) => {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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`));
|
|
73
138
|
await new Promise(() => { });
|
|
74
139
|
});
|
|
140
|
+
// ── stream candle ──
|
|
75
141
|
stream
|
|
76
142
|
.command("candle <symbol> <interval>")
|
|
77
143
|
.description("Stream candlestick data")
|
|
78
144
|
.action(async (symbol, interval) => {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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`));
|
|
88
165
|
await new Promise(() => { });
|
|
89
166
|
});
|
|
90
|
-
// ── stream events ── (unified account events as NDJSON)
|
|
167
|
+
// ── stream events ── (unified account events as NDJSON, already exchange-agnostic)
|
|
91
168
|
if (getAdapter) {
|
|
92
169
|
stream
|
|
93
170
|
.command("events")
|
package/dist/commands/trade.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import type { ExchangeAdapter } from "../exchanges/interface.js";
|
|
3
|
-
export declare function registerTradeCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, isJson: () => boolean, isDryRun?: () => boolean): void;
|
|
3
|
+
export declare function registerTradeCommands(program: Command, getAdapter: () => Promise<ExchangeAdapter>, isJson: () => boolean, isDryRun?: () => boolean, getAdapterForExchange?: (exchange: string) => Promise<ExchangeAdapter>): void;
|