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
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified market data feeds for CLI streaming commands.
|
|
3
|
+
*
|
|
4
|
+
* - Hyperliquid: native WebSocket (allMids, l2Book, trades, candle)
|
|
5
|
+
* - Lighter: REST polling (no public market data WS)
|
|
6
|
+
* - Pacifica: handled via existing PacificaWSClient in stream.ts
|
|
7
|
+
*/
|
|
8
|
+
import { EventEmitter } from "events";
|
|
9
|
+
export interface PriceUpdate {
|
|
10
|
+
symbol: string;
|
|
11
|
+
mid: number;
|
|
12
|
+
funding?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface BookUpdate {
|
|
15
|
+
bids: [string, string][];
|
|
16
|
+
asks: [string, string][];
|
|
17
|
+
}
|
|
18
|
+
export interface TradeUpdate {
|
|
19
|
+
side: string;
|
|
20
|
+
price: string;
|
|
21
|
+
size: string;
|
|
22
|
+
time: number;
|
|
23
|
+
}
|
|
24
|
+
export interface CandleUpdate {
|
|
25
|
+
o: string;
|
|
26
|
+
h: string;
|
|
27
|
+
l: string;
|
|
28
|
+
c: string;
|
|
29
|
+
v: string;
|
|
30
|
+
t: number;
|
|
31
|
+
}
|
|
32
|
+
export declare class HyperliquidMarketFeed extends EventEmitter {
|
|
33
|
+
private ws;
|
|
34
|
+
private closed;
|
|
35
|
+
private reconnectTimer;
|
|
36
|
+
private subs;
|
|
37
|
+
get wsUrl(): string;
|
|
38
|
+
connect(): Promise<void>;
|
|
39
|
+
private send;
|
|
40
|
+
private sub;
|
|
41
|
+
private scheduleReconnect;
|
|
42
|
+
subscribePrices(): void;
|
|
43
|
+
subscribeBook(symbol: string): void;
|
|
44
|
+
subscribeTrades(symbol: string): void;
|
|
45
|
+
subscribeCandle(symbol: string, interval: string): void;
|
|
46
|
+
private handleMessage;
|
|
47
|
+
close(): void;
|
|
48
|
+
}
|
|
49
|
+
export interface LighterFeedOpts {
|
|
50
|
+
/** Polling interval for prices in ms (default: 3000) */
|
|
51
|
+
pricesIntervalMs?: number;
|
|
52
|
+
/** Polling interval for book/trades in ms (default: 2000) */
|
|
53
|
+
bookIntervalMs?: number;
|
|
54
|
+
/** Polling interval for candles in ms (default: 5000) */
|
|
55
|
+
candleIntervalMs?: number;
|
|
56
|
+
}
|
|
57
|
+
export declare class LighterMarketFeed extends EventEmitter {
|
|
58
|
+
private closed;
|
|
59
|
+
private timers;
|
|
60
|
+
private marketMap;
|
|
61
|
+
private pricesMs;
|
|
62
|
+
private bookMs;
|
|
63
|
+
private candleMs;
|
|
64
|
+
constructor(opts?: LighterFeedOpts);
|
|
65
|
+
connect(): Promise<void>;
|
|
66
|
+
private getMarketId;
|
|
67
|
+
private poll;
|
|
68
|
+
subscribePrices(): void;
|
|
69
|
+
subscribeBook(symbol: string): void;
|
|
70
|
+
subscribeTrades(symbol: string): void;
|
|
71
|
+
subscribeCandle(symbol: string, interval: string): void;
|
|
72
|
+
close(): void;
|
|
73
|
+
}
|
|
74
|
+
export declare function createMarketFeed(exchange: string): HyperliquidMarketFeed | LighterMarketFeed;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified market data feeds for CLI streaming commands.
|
|
3
|
+
*
|
|
4
|
+
* - Hyperliquid: native WebSocket (allMids, l2Book, trades, candle)
|
|
5
|
+
* - Lighter: REST polling (no public market data WS)
|
|
6
|
+
* - Pacifica: handled via existing PacificaWSClient in stream.ts
|
|
7
|
+
*/
|
|
8
|
+
import { EventEmitter } from "events";
|
|
9
|
+
// ── Hyperliquid Market Feed (native WebSocket) ──
|
|
10
|
+
export class HyperliquidMarketFeed extends EventEmitter {
|
|
11
|
+
ws = null;
|
|
12
|
+
closed = false;
|
|
13
|
+
reconnectTimer = null;
|
|
14
|
+
subs = [];
|
|
15
|
+
get wsUrl() { return "wss://api.hyperliquid.xyz/ws"; }
|
|
16
|
+
async connect() {
|
|
17
|
+
const { WebSocket } = await import("ws");
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
this.ws = new WebSocket(this.wsUrl);
|
|
20
|
+
this.ws.on("open", () => {
|
|
21
|
+
// Re-subscribe on reconnect
|
|
22
|
+
for (const sub of this.subs)
|
|
23
|
+
this.send({ method: "subscribe", subscription: sub });
|
|
24
|
+
this.emit("connected");
|
|
25
|
+
resolve();
|
|
26
|
+
});
|
|
27
|
+
this.ws.on("error", (err) => {
|
|
28
|
+
if (!this.closed)
|
|
29
|
+
reject(err);
|
|
30
|
+
});
|
|
31
|
+
this.ws.on("close", () => {
|
|
32
|
+
if (!this.closed) {
|
|
33
|
+
this.emit("disconnected");
|
|
34
|
+
this.scheduleReconnect();
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
this.ws.on("message", (raw) => {
|
|
38
|
+
try {
|
|
39
|
+
this.handleMessage(JSON.parse(String(raw)));
|
|
40
|
+
}
|
|
41
|
+
catch { /* ignore */ }
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
send(data) {
|
|
46
|
+
if (this.ws?.readyState === 1)
|
|
47
|
+
this.ws.send(JSON.stringify(data));
|
|
48
|
+
}
|
|
49
|
+
sub(subscription) {
|
|
50
|
+
this.subs.push(subscription);
|
|
51
|
+
this.send({ method: "subscribe", subscription });
|
|
52
|
+
}
|
|
53
|
+
scheduleReconnect() {
|
|
54
|
+
if (this.closed)
|
|
55
|
+
return;
|
|
56
|
+
this.reconnectTimer = setTimeout(async () => {
|
|
57
|
+
try {
|
|
58
|
+
await this.connect();
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
this.scheduleReconnect();
|
|
62
|
+
}
|
|
63
|
+
}, 3000);
|
|
64
|
+
}
|
|
65
|
+
subscribePrices() { this.sub({ type: "allMids" }); }
|
|
66
|
+
subscribeBook(symbol) { this.sub({ type: "l2Book", coin: symbol.toUpperCase() }); }
|
|
67
|
+
subscribeTrades(symbol) { this.sub({ type: "trades", coin: symbol.toUpperCase() }); }
|
|
68
|
+
subscribeCandle(symbol, interval) {
|
|
69
|
+
this.sub({ type: "candle", coin: symbol.toUpperCase(), interval });
|
|
70
|
+
}
|
|
71
|
+
handleMessage(msg) {
|
|
72
|
+
const channel = String(msg.channel ?? "");
|
|
73
|
+
const data = msg.data;
|
|
74
|
+
if (!data)
|
|
75
|
+
return;
|
|
76
|
+
if (channel === "allMids") {
|
|
77
|
+
const mids = (data.mids ?? data);
|
|
78
|
+
const updates = Object.entries(mids).map(([symbol, mid]) => ({
|
|
79
|
+
symbol, mid: Number(mid),
|
|
80
|
+
}));
|
|
81
|
+
this.emit("prices", updates);
|
|
82
|
+
}
|
|
83
|
+
else if (channel === "l2Book") {
|
|
84
|
+
const d = data;
|
|
85
|
+
const levels = d.levels;
|
|
86
|
+
if (levels) {
|
|
87
|
+
this.emit("book", {
|
|
88
|
+
bids: levels[0].map((l) => [l.px, l.sz]),
|
|
89
|
+
asks: levels[1].map((l) => [l.px, l.sz]),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (channel === "trades") {
|
|
94
|
+
const trades = Array.isArray(data) ? data : [];
|
|
95
|
+
for (const t of trades) {
|
|
96
|
+
// HL side: "A" = sell (ask), "B" = buy (bid)
|
|
97
|
+
const rawSide = String(t.side ?? "");
|
|
98
|
+
this.emit("trade", {
|
|
99
|
+
side: rawSide === "A" ? "sell" : rawSide === "B" ? "buy" : rawSide,
|
|
100
|
+
price: String(t.px ?? ""),
|
|
101
|
+
size: String(t.sz ?? ""),
|
|
102
|
+
time: Number(t.time ?? Date.now()),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (channel === "candle") {
|
|
107
|
+
const d = data;
|
|
108
|
+
this.emit("candle", {
|
|
109
|
+
o: String(d.o ?? ""), h: String(d.h ?? ""), l: String(d.l ?? ""),
|
|
110
|
+
c: String(d.c ?? ""), v: String(d.v ?? ""), t: Number(d.t ?? 0),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
close() {
|
|
115
|
+
this.closed = true;
|
|
116
|
+
if (this.reconnectTimer)
|
|
117
|
+
clearTimeout(this.reconnectTimer);
|
|
118
|
+
if (this.ws) {
|
|
119
|
+
this.ws.close();
|
|
120
|
+
this.ws = null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// ── Lighter Market Feed (REST polling) ──
|
|
125
|
+
const LIGHTER_BASE = "https://mainnet.zklighter.elliot.ai/api/v1";
|
|
126
|
+
export class LighterMarketFeed extends EventEmitter {
|
|
127
|
+
closed = false;
|
|
128
|
+
timers = [];
|
|
129
|
+
marketMap = new Map();
|
|
130
|
+
pricesMs;
|
|
131
|
+
bookMs;
|
|
132
|
+
candleMs;
|
|
133
|
+
constructor(opts) {
|
|
134
|
+
super();
|
|
135
|
+
this.pricesMs = opts?.pricesIntervalMs ?? 3000;
|
|
136
|
+
this.bookMs = opts?.bookIntervalMs ?? 2000;
|
|
137
|
+
this.candleMs = opts?.candleIntervalMs ?? 5000;
|
|
138
|
+
}
|
|
139
|
+
async connect() {
|
|
140
|
+
const res = await fetch(`${LIGHTER_BASE}/orderBookDetails`);
|
|
141
|
+
const json = await res.json();
|
|
142
|
+
for (const m of json.order_book_details ?? []) {
|
|
143
|
+
if (m.market_type === "perp")
|
|
144
|
+
this.marketMap.set(m.symbol.toUpperCase(), m.market_id);
|
|
145
|
+
}
|
|
146
|
+
this.emit("connected");
|
|
147
|
+
}
|
|
148
|
+
getMarketId(symbol) {
|
|
149
|
+
const id = this.marketMap.get(symbol.toUpperCase());
|
|
150
|
+
if (id === undefined)
|
|
151
|
+
throw new Error(`Unknown Lighter market: ${symbol}`);
|
|
152
|
+
return id;
|
|
153
|
+
}
|
|
154
|
+
poll(fn, intervalMs) {
|
|
155
|
+
fn().catch(() => { });
|
|
156
|
+
this.timers.push(setInterval(() => { if (!this.closed)
|
|
157
|
+
fn().catch(() => { }); }, intervalMs));
|
|
158
|
+
}
|
|
159
|
+
subscribePrices() {
|
|
160
|
+
this.poll(async () => {
|
|
161
|
+
const res = await fetch(`${LIGHTER_BASE}/orderBookDetails`);
|
|
162
|
+
const json = await res.json();
|
|
163
|
+
const updates = (json.order_book_details ?? [])
|
|
164
|
+
.filter(m => m.market_type === "perp")
|
|
165
|
+
.map(m => ({ symbol: m.symbol, mid: m.last_trade_price }));
|
|
166
|
+
this.emit("prices", updates);
|
|
167
|
+
}, this.pricesMs);
|
|
168
|
+
}
|
|
169
|
+
subscribeBook(symbol) {
|
|
170
|
+
const marketId = this.getMarketId(symbol);
|
|
171
|
+
this.poll(async () => {
|
|
172
|
+
const res = await fetch(`${LIGHTER_BASE}/orderBookOrders?market_id=${marketId}&limit=20`);
|
|
173
|
+
const json = await res.json();
|
|
174
|
+
this.emit("book", {
|
|
175
|
+
bids: (json.bids ?? []).map(b => [b.price, b.remaining_base_amount]),
|
|
176
|
+
asks: (json.asks ?? []).map(a => [a.price, a.remaining_base_amount]),
|
|
177
|
+
});
|
|
178
|
+
}, this.bookMs);
|
|
179
|
+
}
|
|
180
|
+
subscribeTrades(symbol) {
|
|
181
|
+
const marketId = this.getMarketId(symbol);
|
|
182
|
+
let lastTid = 0;
|
|
183
|
+
this.poll(async () => {
|
|
184
|
+
const res = await fetch(`${LIGHTER_BASE}/recentTrades?market_id=${marketId}&limit=20`);
|
|
185
|
+
const json = await res.json();
|
|
186
|
+
for (const t of json.trades ?? []) {
|
|
187
|
+
if (t.timestamp > lastTid) {
|
|
188
|
+
lastTid = t.timestamp;
|
|
189
|
+
this.emit("trade", {
|
|
190
|
+
side: t.is_maker_ask ? "buy" : "sell",
|
|
191
|
+
price: t.price,
|
|
192
|
+
size: t.size,
|
|
193
|
+
time: t.timestamp,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}, this.bookMs);
|
|
198
|
+
}
|
|
199
|
+
subscribeCandle(symbol, interval) {
|
|
200
|
+
const marketId = this.getMarketId(symbol);
|
|
201
|
+
this.poll(async () => {
|
|
202
|
+
const now = Math.floor(Date.now() / 1000);
|
|
203
|
+
const res = await fetch(`${LIGHTER_BASE}/candles?market_id=${marketId}&resolution=${interval}&count_back=1&end_timestamp=${now}`);
|
|
204
|
+
const json = await res.json();
|
|
205
|
+
const c = json.candles?.[0];
|
|
206
|
+
if (c) {
|
|
207
|
+
this.emit("candle", {
|
|
208
|
+
o: c.open, h: c.high, l: c.low, c: c.close, v: c.volume, t: c.timestamp,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}, this.candleMs);
|
|
212
|
+
}
|
|
213
|
+
close() {
|
|
214
|
+
this.closed = true;
|
|
215
|
+
for (const t of this.timers)
|
|
216
|
+
clearInterval(t);
|
|
217
|
+
this.timers = [];
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// ── Factory ──
|
|
221
|
+
export function createMarketFeed(exchange) {
|
|
222
|
+
if (exchange === "hyperliquid")
|
|
223
|
+
return new HyperliquidMarketFeed();
|
|
224
|
+
if (exchange === "lighter")
|
|
225
|
+
return new LighterMarketFeed();
|
|
226
|
+
throw new Error(`Use PacificaWSClient for pacifica, not createMarketFeed`);
|
|
227
|
+
}
|
package/package.json
CHANGED
package/skills/perp-cli/SKILL.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: perp-cli
|
|
3
|
-
description: "Multi-DEX perpetual futures trading CLI for Pacifica (Solana), Hyperliquid (EVM), and Lighter (Ethereum). Use when user asks to trade perps, check funding rates, bridge USDC, manage positions,
|
|
3
|
+
description: "Multi-DEX perpetual futures trading CLI for Pacifica (Solana), Hyperliquid (EVM), and Lighter (Ethereum). Use when user asks to: trade perps, check funding rates, scan arbitrage (perp-perp or spot-perp), delta-neutral strategies, bridge USDC, manage positions/orders, deposit/withdraw, spot+perp hedge, or mentions perp-cli, hypurrquant, Pacifica, Hyperliquid, Lighter, HyperEVM, funding arb, U-token (UBTC/UETH/USOL)."
|
|
4
4
|
allowed-tools: "Bash(perp:*), Bash(npx perp-cli:*), Bash(npx -y perp-cli:*)"
|
|
5
5
|
license: MIT
|
|
6
6
|
metadata:
|
|
7
7
|
author: hypurrquant
|
|
8
|
-
version: "0.4.
|
|
8
|
+
version: "0.4.9"
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# perp-cli Agent Guide
|
|
@@ -60,6 +60,8 @@ perp --json arb exec <SYM> <longEx> <shortEx> <$> --leverage <N> --isolated # e
|
|
|
60
60
|
# Single exchange trading (when not doing arb)
|
|
61
61
|
perp --json -e <EX> trade market <SYM> buy <SIZE>
|
|
62
62
|
perp --json -e <EX> trade market <SYM> buy <SIZE> --smart # IOC limit at best ask + 1 tick (less slippage)
|
|
63
|
+
perp --json -e <EX> trade market <SYM> buy <SIZE> --split # orderbook-aware split for large orders
|
|
64
|
+
perp --json -e <EX> trade split <SYM> buy 5000 # dedicated split command (USD notional)
|
|
63
65
|
perp --json -e <EX> trade close <SYM>
|
|
64
66
|
perp --json -e <EX> trade close <SYM> --smart # smart close at best bid/ask
|
|
65
67
|
|
|
@@ -96,11 +98,17 @@ perp --json -e <EX> trade market <SYM> buy <SIZE> --smart
|
|
|
96
98
|
perp --json -e <EX> trade close <SYM> --smart
|
|
97
99
|
perp --json arb exec <SYM> <longEx> <shortEx> <$> --smart # smart arb entry
|
|
98
100
|
perp --json arb close <SYM> --smart # smart arb close
|
|
101
|
+
|
|
102
|
+
# Split order: orderbook-aware execution for large orders
|
|
103
|
+
# Reads depth before each slice, IOC limit within slippage tolerance
|
|
104
|
+
perp --json -e <EX> trade split <SYM> buy 5000 # split $5000 into depth-based slices
|
|
105
|
+
perp --json -e <EX> trade split <SYM> sell 10000 --max-slices 5 --delay 2000
|
|
106
|
+
perp --json -e <EX> trade market <SYM> buy <SIZE> --split # split via market command flag
|
|
99
107
|
```
|
|
100
108
|
|
|
101
109
|
All string outputs are auto-sanitized (control chars stripped, prompt injection patterns blocked).
|
|
102
110
|
|
|
103
|
-
## Arb Workflow
|
|
111
|
+
## Arb Workflow (Perp-Perp)
|
|
104
112
|
|
|
105
113
|
```
|
|
106
114
|
1. perp --json portfolio → check balances across all exchanges
|
|
@@ -119,6 +127,39 @@ All string outputs are auto-sanitized (control chars stripped, prompt injection
|
|
|
119
127
|
→ --pair <longEx>:<shortEx>: specify which pair if multiple
|
|
120
128
|
```
|
|
121
129
|
|
|
130
|
+
## Spot+Perp Arb Workflow
|
|
131
|
+
|
|
132
|
+
Spot has 0 funding cost → spread = |perp funding rate|. Only needs 1 exchange with spot + any exchange with perp.
|
|
133
|
+
|
|
134
|
+
**Spot exchanges:** HL (Hyperliquid), LT (Lighter). Pacifica is perp-only.
|
|
135
|
+
**U-token mapping:** HL spot uses Unit protocol bridged tokens — UBTC=BTC, UETH=ETH, USOL=SOL, UFART=FARTCOIN. Resolved automatically.
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
1. perp --json arb scan --mode spot-perp → find spot+perp opportunities
|
|
139
|
+
perp --json arb scan --mode all → perp-perp + spot-perp combined
|
|
140
|
+
2. [Show opportunity to user, get confirmation]
|
|
141
|
+
3. perp --json arb spot-exec <SYM> <spotEx> <perpEx> <$>
|
|
142
|
+
Examples:
|
|
143
|
+
perp --json arb spot-exec ETH hl hl 100 # ETH spot(HL/UETH) + perp(HL)
|
|
144
|
+
perp --json arb spot-exec BTC hl lt 50 # BTC spot(HL/UBTC) + perp(LT)
|
|
145
|
+
perp --json arb spot-exec LINK lt hl 100 # LINK spot(LT) + perp(HL)
|
|
146
|
+
→ cross-validates spot vs perp price (>5% deviation = abort, wrong token)
|
|
147
|
+
→ sequential execution if same exchange (nonce collision avoidance)
|
|
148
|
+
→ parallel execution if different exchanges
|
|
149
|
+
→ auto-rollback if one leg fails
|
|
150
|
+
Options:
|
|
151
|
+
--leverage <N> set perp leverage before entry
|
|
152
|
+
--isolated use isolated margin on perp side
|
|
153
|
+
4. perp --json arb status → shows spot-perp positions (spot leg labeled)
|
|
154
|
+
5. perp --json arb spot-close <SYM> --spot-exch <hl|lt>
|
|
155
|
+
→ sells spot + buys back perp simultaneously
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**Available spot+perp pairs (13):**
|
|
159
|
+
- HL spot: BTC (UBTC), ETH (UETH), SOL (USOL), FARTCOIN (UFART), HYPE, AZTEC, STABLE
|
|
160
|
+
- LT spot: ETH, AZTEC, AAVE, LINK, UNI, LIT, LDO, SKY
|
|
161
|
+
- All have perps on HL and LT. Pacifica perps available when API is up.
|
|
162
|
+
|
|
122
163
|
## Position Sizing
|
|
123
164
|
|
|
124
165
|
- Single position < **80%** of that exchange's available balance
|
|
@@ -165,7 +206,7 @@ If `error.retryable` is `false`, do NOT retry — fix the cause first.
|
|
|
165
206
|
|
|
166
207
|
| Error | Action |
|
|
167
208
|
|-------|--------|
|
|
168
|
-
| `RATE_LIMITED` | wait
|
|
209
|
+
| `RATE_LIMITED` | wait 5-10s, retry (max 3). Lighter rate limits are strict — space commands 3s+ apart |
|
|
169
210
|
| `EXCHANGE_UNREACHABLE` | wait 10s, retry. 3x fail → skip that exchange |
|
|
170
211
|
| `TIMEOUT` | wait 5s, retry (max 3) |
|
|
171
212
|
| `INSUFFICIENT_BALANCE` | reduce size or bridge funds to that exchange |
|
|
@@ -175,6 +216,41 @@ If `error.retryable` is `false`, do NOT retry — fix the cause first.
|
|
|
175
216
|
| `MARGIN_INSUFFICIENT` | reduce leverage or close existing positions |
|
|
176
217
|
| `DUPLICATE_ORDER` | already submitted — check positions, don't retry |
|
|
177
218
|
| Lighter `invalid signature` | check ~/.perp/.env or `perp --json -e lighter manage setup-api-key` |
|
|
219
|
+
| Lighter `invalid account index` | rate limit caused init failure — wait 10s and retry the command |
|
|
220
|
+
| Lighter `--smart` not filling | Lighter IOC limit orders may not fill — use regular market order (without `--smart`) |
|
|
221
|
+
|
|
222
|
+
## Examples
|
|
223
|
+
|
|
224
|
+
**User: "펀딩레이트 아비트라지 기회 찾아줘"**
|
|
225
|
+
```bash
|
|
226
|
+
perp --json portfolio # check balances
|
|
227
|
+
perp --json arb scan --mode all --min 5 # scan perp-perp + spot-perp
|
|
228
|
+
# → show results, recommend best opportunity, ask for confirmation
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**User: "ETH spot-perp 아비트라지 실행해줘 $100"**
|
|
232
|
+
```bash
|
|
233
|
+
perp --json arb scan --mode spot-perp # verify opportunity exists
|
|
234
|
+
perp --json --dry-run arb spot-exec ETH hl hl 100 # dry-run first
|
|
235
|
+
# → show dry-run result, ask for confirmation
|
|
236
|
+
perp --json arb spot-exec ETH hl hl 100 # execute after confirmation
|
|
237
|
+
perp --json arb status # verify positions
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**User: "내 포지션 상태 확인해줘"**
|
|
241
|
+
```bash
|
|
242
|
+
perp --json portfolio # balances + positions + risk
|
|
243
|
+
perp --json arb status # arb-specific PnL + funding
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**User: "Hyperliquid에서 SOL 롱 0.5개"**
|
|
247
|
+
```bash
|
|
248
|
+
perp --json -e hl market mid SOL # current price
|
|
249
|
+
perp --json -e hl trade check SOL buy 0.5 # pre-validate
|
|
250
|
+
perp --json --dry-run -e hl trade market SOL buy 0.5 # dry-run
|
|
251
|
+
# → show cost estimate, ask for confirmation
|
|
252
|
+
perp --json -e hl trade market SOL buy 0.5 --smart # execute with smart order
|
|
253
|
+
```
|
|
178
254
|
|
|
179
255
|
## Referrals (Optional)
|
|
180
256
|
|
|
@@ -123,27 +123,28 @@ perp --json -e hl account info # USDC deposited on exchange
|
|
|
123
123
|
### Deposit to Exchange
|
|
124
124
|
```bash
|
|
125
125
|
# Hyperliquid (from Arbitrum wallet)
|
|
126
|
-
perp --json deposit hyperliquid 100
|
|
126
|
+
perp --json funds deposit hyperliquid 100
|
|
127
127
|
|
|
128
128
|
# Pacifica (from Solana wallet)
|
|
129
|
-
perp --json deposit pacifica 100
|
|
129
|
+
perp --json funds deposit pacifica 100
|
|
130
130
|
|
|
131
131
|
# Lighter (multiple routes)
|
|
132
|
-
perp --json deposit lighter info # show all available routes
|
|
133
|
-
perp --json deposit lighter cctp
|
|
132
|
+
perp --json funds deposit lighter info # show all available routes
|
|
133
|
+
perp --json funds deposit lighter cctp arbitrum 100 # via CCTP from Arbitrum
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
### Withdraw from Exchange
|
|
137
137
|
```bash
|
|
138
|
-
perp --json withdraw hyperliquid 100
|
|
139
|
-
perp --json withdraw pacifica 100
|
|
138
|
+
perp --json funds withdraw hyperliquid 100
|
|
139
|
+
perp --json funds withdraw pacifica 100
|
|
140
|
+
perp --json funds withdraw lighter 100
|
|
140
141
|
```
|
|
141
142
|
|
|
142
143
|
### Bridge Between Chains
|
|
143
144
|
When you need to move USDC between exchanges on different chains:
|
|
144
145
|
```bash
|
|
145
146
|
# 1. Withdraw from source exchange
|
|
146
|
-
perp --json withdraw pacifica 500
|
|
147
|
+
perp --json funds withdraw pacifica 500
|
|
147
148
|
|
|
148
149
|
# 2. Quote the bridge
|
|
149
150
|
perp --json bridge quote --from solana --to arbitrum --amount 500
|
|
@@ -155,7 +156,7 @@ perp --json bridge send --from solana --to arbitrum --amount 500
|
|
|
155
156
|
perp --json bridge status <orderId>
|
|
156
157
|
|
|
157
158
|
# 5. Deposit to destination exchange
|
|
158
|
-
perp --json deposit hyperliquid 500
|
|
159
|
+
perp --json funds deposit hyperliquid 500
|
|
159
160
|
```
|
|
160
161
|
|
|
161
162
|
## Order Types & Execution
|
|
@@ -168,6 +169,15 @@ perp --json -e hl trade buy BTC 0.01 # shorthand
|
|
|
168
169
|
perp --json -e hl trade sell BTC 0.01 # shorthand
|
|
169
170
|
```
|
|
170
171
|
|
|
172
|
+
### Split Orders (orderbook-aware, for large orders)
|
|
173
|
+
```bash
|
|
174
|
+
perp --json -e hl trade split BTC buy 5000 # split $5000 into depth-based slices
|
|
175
|
+
perp --json -e hl trade split BTC sell 10000 --max-slippage 0.5 --max-slices 5
|
|
176
|
+
perp --json -e hl trade market BTC buy 0.5 --split # split via market command flag
|
|
177
|
+
```
|
|
178
|
+
Returns `{ slices[], filledUsd, avgPrice, totalSlippagePct, status }`.
|
|
179
|
+
Status: `complete` (all filled), `partial` (some filled), `failed` (none filled).
|
|
180
|
+
|
|
171
181
|
### Limit Orders (execute at specific price)
|
|
172
182
|
```bash
|
|
173
183
|
perp --json -e hl trade buy BTC 0.01 -p 60000 # buy at $60,000
|
|
@@ -238,7 +248,7 @@ Error case:
|
|
|
238
248
|
- `trade market`, `trade buy`, `trade sell` — will open duplicate positions
|
|
239
249
|
- `trade close` — may error if already closed, but harmless
|
|
240
250
|
- `bridge send` — will send duplicate transfers
|
|
241
|
-
- `deposit`, `withdraw` — will move funds twice
|
|
251
|
+
- `funds deposit`, `funds withdraw` — will move funds twice
|
|
242
252
|
|
|
243
253
|
**For non-idempotent commands:** always verify the result before retrying. Check positions or balances to confirm whether the first attempt succeeded.
|
|
244
254
|
|
|
@@ -7,16 +7,17 @@ All commands support `--json` for structured output. Always use `--json` when ca
|
|
|
7
7
|
perp --json market list # all markets with prices, funding, volume
|
|
8
8
|
perp --json market prices # cross-exchange price comparison
|
|
9
9
|
perp --json market mid <SYMBOL> # mid price (fast)
|
|
10
|
-
perp --json market info <SYMBOL> #
|
|
10
|
+
perp --json market info <SYMBOL> # mark/index price, funding, volume, OI, max leverage
|
|
11
11
|
perp --json market book <SYMBOL> # orderbook (bids/asks)
|
|
12
12
|
perp --json market trades <SYMBOL> # recent trades
|
|
13
13
|
perp --json market funding <SYMBOL> # funding rate history
|
|
14
14
|
perp --json market kline <SYM> <INTERVAL> # OHLCV candles (1m,5m,15m,1h,4h,1d)
|
|
15
|
+
perp --json market hip3 # list HIP-3 deployed perp dexes (Hyperliquid only)
|
|
15
16
|
```
|
|
16
17
|
|
|
17
18
|
## Account (read-only, safe)
|
|
18
19
|
```bash
|
|
19
|
-
perp --json account
|
|
20
|
+
perp --json account balance # perp balance + spot holdings + 24h funding (alias: account info)
|
|
20
21
|
perp --json account positions # open positions
|
|
21
22
|
perp --json account orders # open/pending orders
|
|
22
23
|
perp --json account history # order history
|
|
@@ -24,7 +25,6 @@ perp --json account trades # trade fill history
|
|
|
24
25
|
perp --json account funding-history # funding payments
|
|
25
26
|
perp --json account pnl # profit & loss
|
|
26
27
|
perp --json account margin <SYMBOL> # position margin info
|
|
27
|
-
perp --json status # combined: balance + positions + orders
|
|
28
28
|
perp --json portfolio # cross-exchange unified view
|
|
29
29
|
```
|
|
30
30
|
|
|
@@ -60,22 +60,29 @@ perp --json trade leverage <SYMBOL> <N> # set leverage
|
|
|
60
60
|
# Advanced orders
|
|
61
61
|
perp --json trade scale-tp <SYMBOL> --levels '<PRICE1>:<PCT>,<PRICE2>:<PCT>'
|
|
62
62
|
perp --json trade scale-in <SYMBOL> <SIDE> --levels '<PRICE1>:<SIZE>,<PRICE2>:<SIZE>'
|
|
63
|
-
perp --json trade trailing-stop <SYMBOL> # trailing stop with callback %
|
|
64
|
-
perp --json trade twap <SYMBOL> <SIDE> <SIZE> <DURATION>
|
|
65
63
|
perp --json trade pnl-track # real-time PnL tracker
|
|
64
|
+
|
|
65
|
+
# Split execution (orderbook-aware)
|
|
66
|
+
perp --json trade split <SYMBOL> <buy|sell> <USD> # split large order into depth-based slices
|
|
67
|
+
perp --json trade split <SYM> buy 5000 --max-slippage 0.5 --max-slices 5 --delay 2000 --min-slice 200
|
|
68
|
+
perp --json trade market <SYM> buy <SIZE> --split # split via market command flag
|
|
69
|
+
perp --json trade market <SYM> buy <SIZE> --split --max-slippage 0.5
|
|
66
70
|
```
|
|
67
71
|
|
|
68
|
-
## Deposit
|
|
72
|
+
## Funds (Deposit, Withdraw, Transfer, Bridge)
|
|
69
73
|
```bash
|
|
70
|
-
perp --json deposit pacifica <AMOUNT>
|
|
71
|
-
perp --json deposit hyperliquid <AMOUNT>
|
|
72
|
-
perp --json deposit lighter ethereum <AMOUNT> # L1 direct (min 1 USDC)
|
|
73
|
-
perp --json deposit lighter cctp arbitrum <AMOUNT> # CCTP (min 5 USDC)
|
|
74
|
-
perp --json deposit lighter info # all Lighter deposit routes
|
|
75
|
-
perp --json withdraw pacifica <AMOUNT>
|
|
76
|
-
perp --json withdraw hyperliquid <AMOUNT>
|
|
77
|
-
perp --json
|
|
78
|
-
perp --json
|
|
74
|
+
perp --json funds deposit pacifica <AMOUNT>
|
|
75
|
+
perp --json funds deposit hyperliquid <AMOUNT>
|
|
76
|
+
perp --json funds deposit lighter ethereum <AMOUNT> # L1 direct (min 1 USDC)
|
|
77
|
+
perp --json funds deposit lighter cctp arbitrum <AMOUNT> # CCTP (min 5 USDC)
|
|
78
|
+
perp --json funds deposit lighter info # all Lighter deposit routes
|
|
79
|
+
perp --json funds withdraw pacifica <AMOUNT>
|
|
80
|
+
perp --json funds withdraw hyperliquid <AMOUNT>
|
|
81
|
+
perp --json funds withdraw lighter <AMOUNT>
|
|
82
|
+
perp --json funds transfer <AMOUNT> <ADDRESS> # HL internal transfer (instant)
|
|
83
|
+
perp --json funds bridge --from <CHAIN> --to <CHAIN> --amount <AMT> --recipient <ADDR> # CCTP bridge
|
|
84
|
+
perp --json funds bridge-status --hash <HASH> # check CCTP bridge status
|
|
85
|
+
perp --json funds info # combined deposit & withdrawal info
|
|
79
86
|
```
|
|
80
87
|
|
|
81
88
|
## Bridge (Cross-chain USDC)
|
|
@@ -89,11 +96,26 @@ perp --json bridge status <ORDER_ID>
|
|
|
89
96
|
|
|
90
97
|
## Arbitrage
|
|
91
98
|
```bash
|
|
99
|
+
# Perp-Perp arb
|
|
92
100
|
perp --json arb scan --min <BPS> # find opportunities (>N bps spread) — PRIMARY command
|
|
93
|
-
perp --json arb
|
|
101
|
+
perp --json arb exec <SYM> <longEx> <shortEx> <$> # execute perp-perp arb
|
|
102
|
+
perp --json arb close <SYM> # close perp-perp arb
|
|
103
|
+
perp --json arb status # monitor open arb positions
|
|
104
|
+
perp --json arb funding-earned # actual funding payments
|
|
105
|
+
|
|
106
|
+
# Spot+Perp arb (spot funding = 0, spread = |perp funding|)
|
|
107
|
+
perp --json arb scan --mode spot-perp # scan spot+perp opportunities
|
|
108
|
+
perp --json arb scan --mode all # both perp-perp + spot-perp
|
|
109
|
+
perp --json arb spot-exec <SYM> <spotEx> <perpEx> <$> # execute spot+perp arb
|
|
110
|
+
perp --json arb spot-close <SYM> --spot-exch <hl|lt> # close spot+perp arb
|
|
111
|
+
# spotEx: hl (Hyperliquid) or lt (Lighter). perpEx: hl, lt, pac.
|
|
112
|
+
# HL spot uses U-tokens: BTC→UBTC, ETH→UETH, SOL→USOL (auto-resolved)
|
|
113
|
+
|
|
114
|
+
# Other arb tools
|
|
115
|
+
perp --json arb rates # funding rates across all DEXs (detailed)
|
|
116
|
+
perp --json arb prices # cross-exchange price gaps
|
|
94
117
|
perp --json arb dex # HIP-3 cross-dex arb (Hyperliquid)
|
|
95
|
-
|
|
96
|
-
# NOTE: 'arb rates' is deprecated — use 'arb scan' instead
|
|
118
|
+
# Deprecated: 'gap show' → use 'arb prices'; 'funding rates/spread' → use 'arb rates/scan'
|
|
97
119
|
```
|
|
98
120
|
|
|
99
121
|
## Wallet Management
|
|
@@ -115,30 +137,30 @@ perp --json risk liquidation-distance # % distance from liquidation for AL
|
|
|
115
137
|
perp --json risk limits # view current risk limits
|
|
116
138
|
perp --json risk limits --min-liq-distance 30 --max-leverage 5 # set risk limits
|
|
117
139
|
perp --json risk check --notional 1000 --leverage 3 # pre-trade risk check
|
|
118
|
-
perp --json
|
|
119
|
-
perp --json
|
|
120
|
-
perp --json
|
|
140
|
+
perp --json agent ping # exchange connectivity & latency
|
|
141
|
+
perp --json history summary # trading performance
|
|
142
|
+
perp --json history pnl # P&L breakdown by exchange
|
|
143
|
+
perp --json history funding # funding payment aggregation
|
|
144
|
+
perp --json history report # full performance report (summary + pnl + funding)
|
|
145
|
+
perp --json history perf --period daily # daily PnL breakdown (replaces daily-pnl)
|
|
146
|
+
perp --json history perf --period weekly # weekly PnL breakdown (replaces weekly-pnl)
|
|
147
|
+
perp --json history perf --period summary # performance summary stats
|
|
121
148
|
perp --json history list # execution audit trail
|
|
122
149
|
```
|
|
123
150
|
|
|
124
|
-
## Automated Strategies
|
|
151
|
+
## Automated Strategies (bot)
|
|
125
152
|
```bash
|
|
126
|
-
perp --json
|
|
127
|
-
perp --json
|
|
128
|
-
perp --json
|
|
153
|
+
perp --json bot twap <SYMBOL> <SIDE> <SIZE> <DURATION> # TWAP execution
|
|
154
|
+
perp --json bot grid <SYMBOL> --range <PCT> --grids <N> --size <USD>
|
|
155
|
+
perp --json bot dca <SYMBOL> <SIDE> <AMOUNT> <INTERVAL>
|
|
156
|
+
perp --json bot trailing-stop <SYMBOL> # trailing stop with callback %
|
|
157
|
+
perp --json bot funding-arb # auto funding arb
|
|
129
158
|
perp --json bot quick-grid <SYMBOL> # quick grid bot
|
|
130
159
|
perp --json bot quick-arb # quick arb bot
|
|
131
160
|
perp --json jobs list # list running jobs
|
|
132
161
|
perp --json jobs stop <ID> # stop a job
|
|
133
162
|
```
|
|
134
163
|
|
|
135
|
-
## Alerts
|
|
136
|
-
```bash
|
|
137
|
-
perp --json alert add # add price/funding/pnl/liquidation alert
|
|
138
|
-
perp --json alert list # list active alerts
|
|
139
|
-
perp --json alert remove <ID> # remove alert
|
|
140
|
-
```
|
|
141
|
-
|
|
142
164
|
## Command Discovery
|
|
143
165
|
```bash
|
|
144
166
|
perp schema # Full CLI schema as JSON
|