perp-cli 0.3.3 → 0.3.5

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.
@@ -0,0 +1,377 @@
1
+ # Autonomous Strategy Framework
2
+
3
+ This guide helps agents make informed decisions about perpetual futures trading across exchanges.
4
+ You are not expected to follow rigid rules — use this as a decision framework and develop your own judgment over time.
5
+
6
+ ## Core Concepts
7
+
8
+ ### Funding Rate Mechanics
9
+ - Funding rates settle **every 1 hour** on all supported exchanges
10
+ - Positive rate = longs pay shorts, negative rate = shorts pay longs
11
+ - Rates are annualized in display but applied hourly: `hourly = annual / 8760`
12
+ - Scan rates: `perp --json arb rates`
13
+
14
+ ### Opportunity Cost Awareness
15
+
16
+ **This is critical.** Before switching any position, calculate the FULL cost of the switch:
17
+
18
+ ```
19
+ Switch Cost =
20
+ + close current position (trading fee + slippage)
21
+ + withdraw from exchange (gas fee + time)
22
+ + bridge to target chain (bridge fee + gas + time)
23
+ + deposit to new exchange (gas fee + time)
24
+ + open new position (trading fee + slippage)
25
+ ```
26
+
27
+ Query each component:
28
+ ```bash
29
+ perp --json -e <FROM> trade check <SYM> <SIDE> <SIZE> # close cost estimate
30
+ perp --json bridge quote --from <CHAIN> --to <CHAIN> --amount <AMT> # bridge cost
31
+ perp --json -e <TO> trade check <SYM> <SIDE> <SIZE> # open cost estimate
32
+ ```
33
+
34
+ **Only switch if:**
35
+ ```
36
+ expected_hourly_gain × expected_hours_held > total_switch_cost × safety_margin
37
+ ```
38
+
39
+ Where `safety_margin` should be at least 2x — rates can change before you finish switching.
40
+
41
+ ### Time Cost
42
+ Switching is not instant. Estimate total transition time:
43
+ - Exchange withdrawal: 1-30 minutes
44
+ - Bridge transfer: 1-20 minutes (CCTP ~2-5 min, deBridge ~5-15 min)
45
+ - Exchange deposit confirmation: 1-10 minutes
46
+
47
+ During transition, you are **unhedged**. Price can move against you. Factor this risk in.
48
+
49
+ ## Funding Rate Arbitrage
50
+
51
+ ### How It Works
52
+ 1. Find a symbol where Exchange A pays significantly more funding than Exchange B
53
+ 2. Go short on Exchange A (receive funding) and long on Exchange B (pay less funding)
54
+ 3. Net = funding received - funding paid - fees
55
+ 4. The position is market-neutral (delta-hedged) — you profit from the rate spread
56
+
57
+ ### Discovery Loop
58
+ ```bash
59
+ perp --json arb rates # compare rates across exchanges
60
+ perp --json arb scan --min 10 # find spreads > 10 bps
61
+ ```
62
+
63
+ ### Decision Framework
64
+ When evaluating an arb opportunity:
65
+
66
+ 1. **Is the spread real?** Check if rates are stable or spiking temporarily
67
+ - Query rates multiple times over 15-30 minutes
68
+ - A spike that reverts in 1 hour is not worth switching for
69
+
70
+ 2. **What's my current position earning?**
71
+ - If already in a profitable arb, switching has opportunity cost
72
+ - Calculate: `current_hourly_income vs new_hourly_income - switch_cost`
73
+
74
+ 3. **How long will the spread persist?**
75
+ - Historical funding tends to mean-revert
76
+ - Higher confidence in moderate, stable spreads (20-50 bps) than extreme spikes (>100 bps)
77
+
78
+ 4. **Can I execute both legs atomically?**
79
+ - Both positions should open near-simultaneously to minimize directional exposure
80
+ - If capital needs to bridge first, you're exposed during transit
81
+
82
+ ### Hold Duration Target
83
+
84
+ **Before entering any arb position, set a target hold duration.** This is critical for calculating whether the position is worth entering.
85
+
86
+ ```
87
+ Expected Profit = hourly_spread × target_hours
88
+ Entry/Exit Cost = open_fees + close_fees + slippage (both legs)
89
+ Net Profit = Expected Profit - Entry/Exit Cost
90
+ ```
91
+
92
+ **Only enter if Net Profit > 0 with a comfortable margin.**
93
+
94
+ Guidelines for hold duration:
95
+ - **Stable spreads (20-50 bps):** target 8-24 hours. These are reliable but low-yield — you need time for the funding to accumulate past your entry/exit costs.
96
+ - **Elevated spreads (50-100 bps):** target 4-8 hours. Higher yield, but likely to compress. Take profit earlier.
97
+ - **Spike spreads (>100 bps):** target 1-4 hours. These revert quickly. Must cover entry/exit costs within a few funding cycles.
98
+
99
+ **Re-evaluate at each funding settlement (every hour):**
100
+ 1. Is the spread still above breakeven for the remaining target hours?
101
+ 2. If spread compressed, should I exit early or extend the hold?
102
+ 3. Has a better opportunity appeared? (Remember: switching has its own cost)
103
+
104
+ **Track your actual hold durations vs targets over time.** This builds intuition for how long spreads persist on each exchange pair.
105
+
106
+ Example entry decision log:
107
+ ```
108
+ Entry: BTC HL↔PAC | Spread: 35 bps | Target hold: 12h
109
+ Expected: 35 bps × 12h = 420 bps gross
110
+ Entry/exit cost: ~80 bps (fees + slippage both legs)
111
+ Net expected: ~340 bps → ENTER
112
+ Hour 6 check: spread compressed to 15 bps → below breakeven for remaining 6h → EXIT
113
+ Actual hold: 6h | Actual net: ~130 bps
114
+ ```
115
+
116
+ ### Monitoring Active Positions
117
+ ```bash
118
+ perp --json portfolio # unified multi-exchange view
119
+ perp --json risk overview # cross-exchange risk assessment
120
+ perp --json -e <EX> account positions # per-exchange positions
121
+ perp --json arb rates # are current rates still favorable?
122
+ ```
123
+
124
+ ### Order Execution: Sequential Leg Management
125
+
126
+ **NEVER close or open both legs of an arb at once with market orders.** You must manage execution carefully.
127
+
128
+ #### Why This Matters
129
+ Orderbooks have limited depth at each price level. A large market order will eat through multiple ticks and suffer heavy slippage. Worse, if you close one leg but fail to close the other (exchange error, rate limit, network issue), you are left with naked directional exposure.
130
+
131
+ #### Pre-Execution: Check Orderbook Depth
132
+ Before executing, verify that the orderbook can absorb your size at acceptable prices on BOTH sides:
133
+ ```bash
134
+ perp --json -e <EX_A> market book <SYM> # check bids/asks depth
135
+ perp --json -e <EX_B> market book <SYM> # check bids/asks depth
136
+ ```
137
+
138
+ Look at the size available at the best tick. If your order size exceeds what's available at the best 2-3 ticks, you MUST split the order.
139
+
140
+ #### Execution Strategy
141
+ 1. **Determine executable chunk size** — the largest size both orderbooks can absorb at the best tick without excessive slippage
142
+ 2. **Execute in sequential chunks:**
143
+ ```
144
+ Chunk 1: close X on Exchange A → immediately open X on Exchange B
145
+ Chunk 2: close X on Exchange A → immediately open X on Exchange B
146
+ ... repeat until full size is executed
147
+ ```
148
+ 3. **Verify each chunk** before proceeding to the next:
149
+ ```bash
150
+ perp --json -e <EX_A> account positions # confirm partial close
151
+ perp --json -e <EX_B> account positions # confirm partial open
152
+ ```
153
+ 4. **Re-check the orderbook** between chunks — liquidity may have changed
154
+
155
+ #### Paired Execution Rule
156
+ Each chunk must be a **matched pair**: close on one side, open on the other. Never execute multiple closes without the corresponding opens. If one leg fails:
157
+ - STOP immediately
158
+ - Assess your current exposure
159
+ - Decide whether to retry the failed leg or unwind the completed leg
160
+ - Do NOT continue with remaining chunks
161
+
162
+ #### Using Limit Orders for Better Execution
163
+ For non-urgent transitions, consider limit orders at the best bid/ask instead of market orders:
164
+ ```bash
165
+ perp --json -e <EX> trade sell <SYM> <SIZE> -p <PRICE> # limit order
166
+ ```
167
+ This avoids crossing the spread, but you risk not getting filled. Set a reasonable timeout and fall back to market if not filled.
168
+
169
+ ### When to Exit
170
+ - Spread compressed below your breakeven (including fees)
171
+ - One side's funding flipped direction
172
+ - Better opportunity found (after accounting for switch cost!)
173
+ - Risk limits breached
174
+
175
+ ## Risk Management — THE MOST IMPORTANT SECTION
176
+
177
+ **Risk management is more important than profit.** A single liquidation can wipe out months of funding rate income. Every decision you make should be filtered through risk first, profit second.
178
+
179
+ ### Understanding Liquidation
180
+
181
+ When your margin drops below the maintenance requirement, the exchange force-closes your position at a loss. This is **liquidation** — it is catastrophic and must be avoided at all costs.
182
+
183
+ **Check liquidation distance for every open position:**
184
+ ```bash
185
+ perp --json risk liquidation-distance # shows % distance from liq price for ALL positions
186
+ perp --json -e <EX> account positions # shows liquidationPrice per position
187
+ perp --json -e <EX> account margin <SYM> # detailed: liquidationPrice, marginRequired, marginPctOfEquity
188
+ ```
189
+
190
+ **Liquidation distance is configurable by the user.** You MUST ask the user what risk tolerance they want:
191
+ ```bash
192
+ # Ask user: "What minimum liquidation distance do you want? (default: 30%, hard minimum: 20%)"
193
+ perp --json risk limits --min-liq-distance <USER_CHOICE>
194
+ ```
195
+
196
+ **Hard cap: 20%.** No matter what the user says, the system will NEVER allow a position to get within 20% of liquidation. This is non-negotiable and enforced at the system level. If a user tries to set it below 20%, the command will reject it.
197
+
198
+ **Action rules based on `risk liquidation-distance` output:**
199
+ - `status: "safe"` → no action needed
200
+ - `status: "warning"` → monitor more frequently (every 5 minutes)
201
+ - `status: "danger"` → alert user, recommend reducing position size
202
+ - `status: "critical"` (below 20% hard cap) → REDUCE IMMEDIATELY, `canTrade` becomes `false`
203
+
204
+ ### Leverage and Margin Mode
205
+
206
+ #### Leverage
207
+ Higher leverage = closer liquidation price = higher risk. For funding rate arb:
208
+ - **Recommended: 1x-3x leverage.** Arb profits are small but consistent — no need to amplify risk.
209
+ - **NEVER exceed 5x for arb positions.** The goal is to collect funding, not to speculate.
210
+ - For directional trades (non-arb), leverage should be set according to user's risk tolerance, but always confirm with user.
211
+
212
+ **Set leverage BEFORE opening a position:**
213
+ ```bash
214
+ perp --json -e <EX> trade leverage <SYM> <LEVERAGE>
215
+ # Example: perp --json -e hl trade leverage BTC 2
216
+ ```
217
+
218
+ #### Cross vs Isolated Margin
219
+
220
+ | Mode | Behavior | Use When |
221
+ |------|----------|----------|
222
+ | **Cross** | All positions share the same margin pool. One position's loss can liquidate everything. | Single position per exchange, or highly correlated positions |
223
+ | **Isolated** | Each position has its own margin. Liquidation of one doesn't affect others. | Multiple independent positions, recommended for arb |
224
+
225
+ **For funding rate arb, use ISOLATED margin.** Each leg should be independent — if one side gets liquidated, the other side survives.
226
+
227
+ ```bash
228
+ perp --json manage margin <SYM> isolated # set isolated margin
229
+ perp --json -e <EX> trade leverage <SYM> <LEV> --isolated # set leverage + isolated at once
230
+ ```
231
+
232
+ **Check current settings:**
233
+ ```bash
234
+ perp --json -e <EX> account settings # shows leverage and margin_mode per symbol
235
+ ```
236
+
237
+ ### Risk Limits — Configure Before Trading
238
+
239
+ Set your risk limits FIRST, before any trading activity:
240
+ ```bash
241
+ perp --json risk limits \
242
+ --max-leverage 5 \
243
+ --max-margin 60 \
244
+ --max-position 5000 \
245
+ --max-exposure 20000 \
246
+ --max-drawdown 500 \
247
+ --daily-loss 200 \
248
+ --min-liq-distance 30
249
+ ```
250
+
251
+ **IMPORTANT: Ask the user about their risk tolerance BEFORE setting limits.** Key questions:
252
+ - "How much leverage are you comfortable with?" (default: 5x for arb)
253
+ - "What's your maximum acceptable loss?" (default: $500)
254
+ - "How close to liquidation are you willing to get?" (default: 30%, minimum: 20%)
255
+
256
+ These limits are enforced by `perp risk check`. Always run it before trades:
257
+ ```bash
258
+ perp --json risk check --notional 1000 --leverage 3
259
+ # Returns: { "allowed": true/false, "reason": "...", "riskLevel": "low/medium/high/critical" }
260
+ ```
261
+
262
+ **If `allowed: false`, do NOT proceed.** Report to user why.
263
+
264
+ ### The Risk Monitoring Loop
265
+
266
+ **This is your primary responsibility.** While positions are open, run this loop continuously:
267
+
268
+ #### Every 15 minutes:
269
+ ```bash
270
+ perp --json risk status # overall risk level + violations
271
+ perp --json risk liquidation-distance # % distance from liq price for ALL positions
272
+ perp --json -e <EX> account positions # check each position's P&L
273
+ ```
274
+
275
+ Check the output:
276
+ - `risk status` returns `level` (low/medium/high/critical) and `canTrade` (boolean)
277
+ - If `level` is "high" or "critical" → take action immediately
278
+ - If `canTrade` is false → do NOT open new positions
279
+ - Check `violations[]` for specific issues
280
+
281
+ #### Every hour (at funding settlement):
282
+ ```bash
283
+ perp --json portfolio # total equity across exchanges
284
+ perp --json arb rates # are rates still favorable?
285
+ perp --json -e <EX_A> account positions # P&L on leg A
286
+ perp --json -e <EX_B> account positions # P&L on leg B
287
+ ```
288
+
289
+ Compare each position's unrealized P&L. In a perfect arb, they should roughly offset. If one side is losing significantly more than the other is gaining, investigate — the hedge may not be balanced.
290
+
291
+ #### Immediate action triggers:
292
+ | Condition | Action |
293
+ |-----------|--------|
294
+ | `risk status` level = "critical" | Reduce positions immediately |
295
+ | Liquidation price within 10% of current price | Reduce that position's size |
296
+ | `canTrade` = false | Stop all new trades, focus on reducing risk |
297
+ | One arb leg closed unexpectedly | Close the other leg IMMEDIATELY (naked exposure) |
298
+ | Unrealized loss > max-drawdown limit | Close losing positions |
299
+ | Margin utilization > 80% | Do not open new positions |
300
+
301
+ ### Position Sizing
302
+
303
+ Think in terms of total capital across all exchanges:
304
+ ```bash
305
+ perp --json portfolio # totalEquity, marginUtilization, concentration
306
+ ```
307
+
308
+ Rules of thumb:
309
+ - **Single position notional < 25% of total equity** across all exchanges
310
+ - **Total margin used < 60% of total equity** — leave buffer for adverse moves
311
+ - **Capital in transit (bridging) counts as "at risk"** — it's not available for margin
312
+
313
+ ### Stop Loss for Arb Positions
314
+
315
+ Even "market-neutral" arb can lose money if:
316
+ - One exchange goes down and you can't manage that leg
317
+ - Extreme funding spike in the wrong direction
318
+ - Slippage on entry/exit far exceeds estimates
319
+
320
+ **Always set stop losses on both legs:**
321
+ ```bash
322
+ perp --json -e <EX_A> trade sl <SYM> <PRICE> # stop loss on leg A
323
+ perp --json -e <EX_B> trade sl <SYM> <PRICE> # stop loss on leg B
324
+ ```
325
+
326
+ Or use TP/SL together:
327
+ ```bash
328
+ perp --json -e <EX> trade tp-sl <SYM> --tp <PRICE> --sl <PRICE>
329
+ ```
330
+
331
+ ### Monitoring Alerts
332
+
333
+ Set up alerts so you get notified of dangerous conditions without polling:
334
+ ```bash
335
+ perp --json alert add -t margin --margin-pct 70 # alert when margin usage > 70%
336
+ perp --json alert add -t price -s BTC --below 50000 --above 80000 # price boundaries
337
+ perp --json alert add -t funding -s ETH --spread 50 # funding spread alert
338
+ ```
339
+
340
+ ### What to Track Over Time
341
+ As you operate, build awareness of:
342
+ - Which symbols consistently have the best funding spreads
343
+ - Which exchange pairs have the lowest switching cost
344
+ - Typical bridge times for each route
345
+ - How quickly funding rate spikes mean-revert
346
+ - Your own execution quality (slippage vs estimates)
347
+ - **How close your positions have come to liquidation** — learn from near-misses
348
+
349
+ This is YOUR operational knowledge. Use it to make better decisions over time.
350
+
351
+ ## Capital Efficiency
352
+
353
+ ### Cross-Exchange Capital Allocation
354
+ Your capital is split across exchanges. Rebalancing has real costs:
355
+ ```bash
356
+ perp --json bridge quote --from solana --to arbitrum --amount 1000
357
+ ```
358
+
359
+ Before rebalancing, ask:
360
+ - Is the capital earning anything where it currently sits?
361
+ - Is the destination opportunity worth the bridge fee + downtime?
362
+ - Can I use the capital more efficiently without moving it?
363
+
364
+ ### Idle Capital
365
+ Capital sitting in an exchange wallet but not in a position is earning 0%.
366
+ Options:
367
+ - Open a low-risk funding collection position
368
+ - Bridge to where it's more useful
369
+ - Sometimes idle cash IS the right position (dry powder for opportunities)
370
+
371
+ ## Summary
372
+
373
+ Your job is not to blindly follow rules — it's to develop judgment:
374
+ - Every switch has a cost. Calculate it before acting.
375
+ - Rates change hourly. What's profitable now may not be in 2 hours.
376
+ - Build pattern recognition over time.
377
+ - The best arb is one you're already in, not one you're chasing.
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+ # Scan funding rate arbitrage opportunities
3
+ # Usage: ./arb-scan.sh [min-spread-bps]
4
+ # Example: ./arb-scan.sh 20
5
+
6
+ set -e
7
+
8
+ MIN_SPREAD="${1:-10}"
9
+
10
+ echo "=== Funding Rate Arbitrage Scanner ==="
11
+ echo "Minimum spread: ${MIN_SPREAD} bps"
12
+ echo ""
13
+
14
+ echo "1. Cross-exchange rates:"
15
+ perp --json arb rates
16
+
17
+ echo ""
18
+ echo "2. Opportunities (>= ${MIN_SPREAD} bps):"
19
+ perp --json arb scan --min "$MIN_SPREAD"
@@ -0,0 +1,38 @@
1
+ #!/bin/bash
2
+ # Open a perp position with pre-flight checks
3
+ # Usage: ./open-position.sh <exchange> <symbol> <side> <size>
4
+ # Example: ./open-position.sh hl BTC buy 0.01
5
+
6
+ set -e
7
+
8
+ EX="${1:?Usage: open-position.sh <exchange> <symbol> <side> <size>}"
9
+ SYM="${2:?Usage: open-position.sh <exchange> <symbol> <side> <size>}"
10
+ SIDE="${3:?Usage: open-position.sh <exchange> <symbol> <side> <size>}"
11
+ SIZE="${4:?Usage: open-position.sh <exchange> <symbol> <side> <size>}"
12
+
13
+ echo "=== Pre-flight checks ==="
14
+ echo "1. Account info:"
15
+ perp --json -e "$EX" account info
16
+
17
+ echo "2. Current price:"
18
+ perp --json -e "$EX" market mid "$SYM"
19
+
20
+ echo "3. Trade validation:"
21
+ perp --json -e "$EX" trade check "$SYM" "$SIDE" "$SIZE"
22
+
23
+ echo ""
24
+ echo "=== Ready to execute ==="
25
+ echo " Exchange: $EX"
26
+ echo " Symbol: $SYM"
27
+ echo " Side: $SIDE"
28
+ echo " Size: $SIZE"
29
+ echo ""
30
+ read -p "Confirm? (y/N): " CONFIRM
31
+
32
+ if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
33
+ perp --json -e "$EX" trade market "$SYM" "$SIDE" "$SIZE"
34
+ echo "=== Position verification ==="
35
+ perp --json -e "$EX" account positions
36
+ else
37
+ echo "Cancelled."
38
+ fi
@@ -0,0 +1,17 @@
1
+ #!/bin/bash
2
+ # Wallet setup for perp-cli
3
+ # Usage: ./wallet-setup.sh <exchange> <private-key>
4
+ # Exchanges: hl (Hyperliquid), pac (Pacifica), lt (Lighter)
5
+
6
+ set -e
7
+
8
+ EXCHANGE="${1:?Usage: wallet-setup.sh <exchange> <private-key>}"
9
+ KEY="${2:?Usage: wallet-setup.sh <exchange> <private-key>}"
10
+
11
+ echo "Setting up wallet for $EXCHANGE..."
12
+ perp --json wallet set "$EXCHANGE" "$KEY"
13
+
14
+ echo "Verifying..."
15
+ perp --json wallet show
16
+
17
+ echo "Done. Wallet configured for $EXCHANGE."