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
|
@@ -173,7 +173,7 @@ Desired size: 1.0
|
|
|
173
173
|
|
|
174
174
|
**CRITICAL: Each exchange has its own minimum order size and step size.**
|
|
175
175
|
```bash
|
|
176
|
-
perp --json -e <EX> market info <SYM> # check
|
|
176
|
+
perp --json -e <EX> market info <SYM> # check maxLeverage, volume, openInterest
|
|
177
177
|
```
|
|
178
178
|
Round `ORDER_SIZE` to the coarser step size of the two exchanges. If the matched size falls below either exchange's minimum, the arb is NOT executable at this size — reduce target or skip.
|
|
179
179
|
|
|
@@ -202,19 +202,38 @@ perp --json -e <SHORT_EX> account positions # size must = X
|
|
|
202
202
|
```
|
|
203
203
|
If sizes differ (partial fill, rounding), immediately adjust the larger position to match the smaller one.
|
|
204
204
|
|
|
205
|
-
#### Step 3: Split Large Orders
|
|
205
|
+
#### Step 3: Split Large Orders with `trade split`
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
For large orders, use the built-in orderbook-aware split execution instead of manual chunking:
|
|
208
208
|
|
|
209
|
+
```bash
|
|
210
|
+
# Single exchange: split $5000 buy into depth-based slices
|
|
211
|
+
perp --json -e <EX> trade split <SYM> buy 5000
|
|
212
|
+
|
|
213
|
+
# With options
|
|
214
|
+
perp --json -e <EX> trade split <SYM> buy 5000 --max-slippage 0.5 --max-slices 5 --delay 2000
|
|
215
|
+
|
|
216
|
+
# Or use --split flag on market command
|
|
217
|
+
perp --json -e <EX> trade market <SYM> buy <SIZE> --split
|
|
209
218
|
```
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
219
|
+
|
|
220
|
+
How it works:
|
|
221
|
+
1. Fetches fresh orderbook before each slice
|
|
222
|
+
2. Walks levels via `computeExecutableSize` to find fillable amount at target slippage
|
|
223
|
+
3. Places IOC limit at worst acceptable price within slippage tolerance
|
|
224
|
+
4. Waits for book to refresh, repeats until target filled or max slices reached
|
|
225
|
+
|
|
226
|
+
**For arb, both legs must still match.** Use `trade split` on each side independently with the same total USD, then verify sizes match:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
Leg A: perp --json -e <LONG_EX> trade split <SYM> buy 5000
|
|
230
|
+
Leg B: perp --json -e <SHORT_EX> trade split <SYM> sell 5000
|
|
231
|
+
→ Verify positions, adjust if sizes differ
|
|
213
232
|
```
|
|
214
233
|
|
|
215
234
|
**Rules:**
|
|
216
|
-
1.
|
|
217
|
-
2.
|
|
235
|
+
1. Each chunk re-checks orderbook depth — liquidity changes between slices
|
|
236
|
+
2. For arb: same total USD on both sides, verify matched sizes after execution
|
|
218
237
|
3. If one leg fails → STOP immediately, do NOT continue
|
|
219
238
|
4. Assess exposure: retry the failed leg, or unwind the completed leg
|
|
220
239
|
5. NEVER execute multiple orders on one side without matching the other
|
|
@@ -418,15 +437,6 @@ Or use TP/SL together:
|
|
|
418
437
|
perp --json -e <EX> trade tp-sl <SYM> --tp <PRICE> --sl <PRICE>
|
|
419
438
|
```
|
|
420
439
|
|
|
421
|
-
### Monitoring Alerts
|
|
422
|
-
|
|
423
|
-
Set up alerts so you get notified of dangerous conditions without polling:
|
|
424
|
-
```bash
|
|
425
|
-
perp --json alert add -t margin --margin-pct 70 # alert when margin usage > 70%
|
|
426
|
-
perp --json alert add -t price -s BTC --below 50000 --above 80000 # price boundaries
|
|
427
|
-
perp --json alert add -t funding -s ETH --spread 50 # funding spread alert
|
|
428
|
-
```
|
|
429
|
-
|
|
430
440
|
### What to Track Over Time
|
|
431
441
|
As you operate, build awareness of:
|
|
432
442
|
- Which symbols consistently have the best funding spreads
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Monitor open arb positions and evaluate exit conditions
|
|
3
|
+
# Usage: ./arb-monitor.sh [--json] [--min-spread 5]
|
|
4
|
+
# Checks: current spread vs entry, funding earned, PnL, liquidation distance
|
|
5
|
+
# Returns JSON with position health + actionable recommendations
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Auto-detect perp command (supports npx fallback for agents without install permissions)
|
|
10
|
+
if command -v perp &>/dev/null; then
|
|
11
|
+
PERP="perp"
|
|
12
|
+
else
|
|
13
|
+
PERP="npx -y perp-cli@latest"
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
JSON_MODE=false
|
|
17
|
+
MIN_SPREAD=5
|
|
18
|
+
while [[ $# -gt 0 ]]; do
|
|
19
|
+
case "$1" in
|
|
20
|
+
--json) JSON_MODE=true; shift ;;
|
|
21
|
+
--min-spread) MIN_SPREAD="$2"; shift 2 ;;
|
|
22
|
+
*) shift ;;
|
|
23
|
+
esac
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
# 1. Get current arb status
|
|
27
|
+
ARB_STATUS=$($PERP --json arb status 2>/dev/null || echo '{"ok":false}')
|
|
28
|
+
if ! echo "$ARB_STATUS" | grep -q '"ok":true'; then
|
|
29
|
+
if $JSON_MODE; then
|
|
30
|
+
echo '{"ok":false,"error":"No arb positions or arb status unavailable"}'
|
|
31
|
+
else
|
|
32
|
+
echo "No open arb positions found."
|
|
33
|
+
fi
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# 2. Get current spreads
|
|
38
|
+
ARB_SCAN=$($PERP --json arb scan --min 0 2>/dev/null || echo '{"ok":false,"data":{"opportunities":[]}}')
|
|
39
|
+
|
|
40
|
+
# 3. Get funding earned
|
|
41
|
+
FUNDING=$($PERP --json arb funding-earned 2>/dev/null || echo '{"ok":false}')
|
|
42
|
+
|
|
43
|
+
# 4. Get liquidation distances
|
|
44
|
+
LIQ_DIST=$($PERP --json risk liquidation-distance 2>/dev/null || echo '{"ok":false}')
|
|
45
|
+
|
|
46
|
+
# 5. Output combined analysis
|
|
47
|
+
if $JSON_MODE; then
|
|
48
|
+
cat <<EOF
|
|
49
|
+
{
|
|
50
|
+
"ok": true,
|
|
51
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
52
|
+
"positions": $ARB_STATUS,
|
|
53
|
+
"currentSpreads": $ARB_SCAN,
|
|
54
|
+
"fundingEarned": $FUNDING,
|
|
55
|
+
"liquidationDistance": $LIQ_DIST,
|
|
56
|
+
"minSpreadThreshold": $MIN_SPREAD
|
|
57
|
+
}
|
|
58
|
+
EOF
|
|
59
|
+
else
|
|
60
|
+
echo "=== Arb Position Monitor ==="
|
|
61
|
+
echo "Timestamp: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
62
|
+
echo ""
|
|
63
|
+
echo "--- Positions ---"
|
|
64
|
+
echo "$ARB_STATUS" | jq -r '.data // empty'
|
|
65
|
+
echo ""
|
|
66
|
+
echo "--- Funding Earned ---"
|
|
67
|
+
echo "$FUNDING" | jq -r '.data // empty'
|
|
68
|
+
echo ""
|
|
69
|
+
echo "--- Liquidation Distance ---"
|
|
70
|
+
echo "$LIQ_DIST" | jq -r '.data // empty'
|
|
71
|
+
echo ""
|
|
72
|
+
echo "Min spread threshold: ${MIN_SPREAD} bps"
|
|
73
|
+
echo "Recommendation: Check if current spreads exceed ${MIN_SPREAD} bps to continue holding."
|
|
74
|
+
fi
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Funding rate analysis across all exchanges
|
|
3
|
+
# Usage: ./funding-analysis.sh [--json] [--symbol ETH] [--top 10]
|
|
4
|
+
# Fetches current + historical funding data for comparison
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Auto-detect perp command (supports npx fallback for agents without install permissions)
|
|
9
|
+
if command -v perp &>/dev/null; then
|
|
10
|
+
PERP="perp"
|
|
11
|
+
else
|
|
12
|
+
PERP="npx -y perp-cli@latest"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
JSON_MODE=false
|
|
16
|
+
SYMBOL=""
|
|
17
|
+
TOP=10
|
|
18
|
+
while [[ $# -gt 0 ]]; do
|
|
19
|
+
case "$1" in
|
|
20
|
+
--json) JSON_MODE=true; shift ;;
|
|
21
|
+
--symbol) SYMBOL="$2"; shift 2 ;;
|
|
22
|
+
--top) TOP="$2"; shift 2 ;;
|
|
23
|
+
*) shift ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
if [[ -n "$SYMBOL" ]]; then
|
|
28
|
+
# Single symbol detailed analysis
|
|
29
|
+
FUNDING=$($PERP --json market funding "$SYMBOL" 2>/dev/null || echo '{"ok":false}')
|
|
30
|
+
SCAN=$($PERP --json arb scan --min 0 2>/dev/null || echo '{"ok":false}')
|
|
31
|
+
SPOT_SCAN=$($PERP --json arb scan --mode spot-perp --min 0 2>/dev/null || echo '{"ok":false}')
|
|
32
|
+
|
|
33
|
+
if $JSON_MODE; then
|
|
34
|
+
cat <<EOF
|
|
35
|
+
{
|
|
36
|
+
"ok": true,
|
|
37
|
+
"symbol": "$SYMBOL",
|
|
38
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
39
|
+
"funding": $FUNDING,
|
|
40
|
+
"perpPerpArb": $SCAN,
|
|
41
|
+
"spotPerpArb": $SPOT_SCAN
|
|
42
|
+
}
|
|
43
|
+
EOF
|
|
44
|
+
else
|
|
45
|
+
echo "=== Funding Analysis: $SYMBOL ==="
|
|
46
|
+
echo ""
|
|
47
|
+
echo "--- Current Funding Rates ---"
|
|
48
|
+
echo "$FUNDING" | jq -r '.data // empty' 2>/dev/null || echo "(unavailable)"
|
|
49
|
+
echo ""
|
|
50
|
+
echo "--- Perp-Perp Arb ---"
|
|
51
|
+
echo "$SCAN" | jq -r '
|
|
52
|
+
.data // [] | map(select(.symbol == "'"$SYMBOL"'")) | .[] |
|
|
53
|
+
" \(.longExch // .longExchange)→\(.shortExch // .shortExchange): \(.netSpread // .spread)bps"
|
|
54
|
+
' 2>/dev/null || echo " (no opportunity)"
|
|
55
|
+
echo ""
|
|
56
|
+
echo "--- Spot+Perp Arb ---"
|
|
57
|
+
echo "$SPOT_SCAN" | jq -r '
|
|
58
|
+
.data // [] | map(select(.symbol == "'"$SYMBOL"'")) | .[] |
|
|
59
|
+
" \(.direction): \(.annualSpreadPct // .spread)% annual"
|
|
60
|
+
' 2>/dev/null || echo " (no opportunity)"
|
|
61
|
+
fi
|
|
62
|
+
else
|
|
63
|
+
# All symbols scan
|
|
64
|
+
SCAN=$($PERP --json arb scan --mode all --min 0 2>/dev/null || echo '{"ok":false}')
|
|
65
|
+
FUNDING_DETAIL=$($PERP --json arb rates 2>/dev/null || echo '{"ok":false}')
|
|
66
|
+
|
|
67
|
+
if $JSON_MODE; then
|
|
68
|
+
cat <<EOF
|
|
69
|
+
{
|
|
70
|
+
"ok": true,
|
|
71
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
72
|
+
"topN": $TOP,
|
|
73
|
+
"allOpportunities": $SCAN,
|
|
74
|
+
"ratesDetail": $FUNDING_DETAIL
|
|
75
|
+
}
|
|
76
|
+
EOF
|
|
77
|
+
else
|
|
78
|
+
echo "=== Funding Rate Overview (top $TOP) ==="
|
|
79
|
+
echo ""
|
|
80
|
+
echo "$SCAN" | jq -r "
|
|
81
|
+
.data // [] | .[0:$TOP] | .[] |
|
|
82
|
+
\" \(.symbol) | \(.mode // \"perp\") | \(.netSpread // .spread)bps | \(.longExch // .longExchange)→\(.shortExch // .shortExchange)\"
|
|
83
|
+
" 2>/dev/null || echo "(no data)"
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Pre-flight validation for perp-cli operations
|
|
3
|
+
# Checks: install, wallet, connectivity, balances, risk
|
|
4
|
+
# Usage: ./preflight.sh [--json]
|
|
5
|
+
# Returns JSON with { ready: bool, checks: [...], issues: [...] }
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Auto-detect perp command (supports npx fallback for agents without install permissions)
|
|
10
|
+
if command -v perp &>/dev/null; then
|
|
11
|
+
PERP="perp"
|
|
12
|
+
else
|
|
13
|
+
PERP="npx -y perp-cli@latest"
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
JSON_MODE=false
|
|
17
|
+
[[ "${1:-}" == "--json" ]] && JSON_MODE=true
|
|
18
|
+
|
|
19
|
+
issues=()
|
|
20
|
+
checks=()
|
|
21
|
+
|
|
22
|
+
add_check() {
|
|
23
|
+
local name="$1" status="$2" detail="$3"
|
|
24
|
+
checks+=("{\"name\":\"$name\",\"status\":\"$status\",\"detail\":\"$detail\"}")
|
|
25
|
+
[[ "$status" == "fail" ]] && issues+=("$name: $detail")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# 1. perp-cli installed and version check
|
|
29
|
+
VERSION=$($PERP --version 2>/dev/null || echo "unknown")
|
|
30
|
+
if [[ "$VERSION" != "unknown" ]]; then
|
|
31
|
+
add_check "install" "pass" "perp-cli $VERSION ($(command -v perp &>/dev/null && echo 'global' || echo 'npx'))"
|
|
32
|
+
else
|
|
33
|
+
add_check "install" "fail" "perp-cli not found — run: npm i -g perp-cli@latest or use npx"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# 2. Wallet configured
|
|
37
|
+
WALLET_OUT=$($PERP --json wallet show 2>/dev/null || echo '{"ok":false}')
|
|
38
|
+
if echo "$WALLET_OUT" | grep -q '"ok":true'; then
|
|
39
|
+
add_check "wallet" "pass" "Wallet configured"
|
|
40
|
+
else
|
|
41
|
+
add_check "wallet" "fail" "No wallet configured — run: perp wallet set <exchange> <key>"
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# 3. Exchange connectivity
|
|
45
|
+
HEALTH_OUT=$($PERP --json agent ping 2>/dev/null || echo '{"ok":false}')
|
|
46
|
+
if echo "$HEALTH_OUT" | grep -q '"ok":true'; then
|
|
47
|
+
add_check "connectivity" "pass" "Exchanges reachable"
|
|
48
|
+
else
|
|
49
|
+
add_check "connectivity" "warn" "Some exchanges unreachable"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# 4. Portfolio & balances
|
|
53
|
+
PORTFOLIO_OUT=$($PERP --json portfolio 2>/dev/null || echo '{"ok":false}')
|
|
54
|
+
if echo "$PORTFOLIO_OUT" | grep -q '"ok":true'; then
|
|
55
|
+
add_check "portfolio" "pass" "Portfolio accessible"
|
|
56
|
+
else
|
|
57
|
+
add_check "portfolio" "warn" "Could not fetch portfolio"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# 5. Risk status
|
|
61
|
+
RISK_OUT=$($PERP --json risk status 2>/dev/null || echo '{"ok":false}')
|
|
62
|
+
if echo "$RISK_OUT" | grep -q '"canTrade":true'; then
|
|
63
|
+
add_check "risk" "pass" "Trading allowed (canTrade=true)"
|
|
64
|
+
elif echo "$RISK_OUT" | grep -q '"canTrade":false'; then
|
|
65
|
+
add_check "risk" "fail" "Trading blocked — check risk violations"
|
|
66
|
+
else
|
|
67
|
+
add_check "risk" "warn" "Could not check risk status"
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# Output
|
|
71
|
+
READY=true
|
|
72
|
+
[[ ${#issues[@]} -gt 0 ]] && READY=false
|
|
73
|
+
|
|
74
|
+
if $JSON_MODE; then
|
|
75
|
+
CHECKS_JSON=$(IFS=,; echo "${checks[*]}")
|
|
76
|
+
ISSUES_JSON=$(printf '%s\n' "${issues[@]}" | jq -R . | jq -s .)
|
|
77
|
+
echo "{\"ready\":$READY,\"checks\":[$CHECKS_JSON],\"issues\":$ISSUES_JSON}"
|
|
78
|
+
else
|
|
79
|
+
echo "=== perp-cli Pre-flight Check ==="
|
|
80
|
+
for c in "${checks[@]}"; do
|
|
81
|
+
name=$(echo "$c" | jq -r .name)
|
|
82
|
+
status=$(echo "$c" | jq -r .status)
|
|
83
|
+
detail=$(echo "$c" | jq -r .detail)
|
|
84
|
+
case "$status" in
|
|
85
|
+
pass) icon="✓" ;;
|
|
86
|
+
warn) icon="⚠" ;;
|
|
87
|
+
fail) icon="✗" ;;
|
|
88
|
+
esac
|
|
89
|
+
printf " %s %-15s %s\n" "$icon" "$name" "$detail"
|
|
90
|
+
done
|
|
91
|
+
echo ""
|
|
92
|
+
if $READY; then
|
|
93
|
+
echo "Ready to trade."
|
|
94
|
+
else
|
|
95
|
+
echo "Issues found:"
|
|
96
|
+
for i in "${issues[@]}"; do echo " - $i"; done
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Scan spot+perp funding rate arbitrage opportunities
|
|
3
|
+
# Usage: ./spot-perp-scan.sh [--json] [--mode all|spot-perp|perp-perp] [--min 10]
|
|
4
|
+
# Combines perp-perp and spot-perp scans with validation
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Auto-detect perp command (supports npx fallback for agents without install permissions)
|
|
9
|
+
if command -v perp &>/dev/null; then
|
|
10
|
+
PERP="perp"
|
|
11
|
+
else
|
|
12
|
+
PERP="npx -y perp-cli@latest"
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
JSON_MODE=false
|
|
16
|
+
MODE="all"
|
|
17
|
+
MIN_SPREAD=10
|
|
18
|
+
while [[ $# -gt 0 ]]; do
|
|
19
|
+
case "$1" in
|
|
20
|
+
--json) JSON_MODE=true; shift ;;
|
|
21
|
+
--mode) MODE="$2"; shift 2 ;;
|
|
22
|
+
--min) MIN_SPREAD="$2"; shift 2 ;;
|
|
23
|
+
*) shift ;;
|
|
24
|
+
esac
|
|
25
|
+
done
|
|
26
|
+
|
|
27
|
+
# 1. Portfolio check (ensure we have balances)
|
|
28
|
+
PORTFOLIO=$($PERP --json portfolio 2>/dev/null || echo '{"ok":false}')
|
|
29
|
+
if ! echo "$PORTFOLIO" | grep -q '"ok":true'; then
|
|
30
|
+
if $JSON_MODE; then
|
|
31
|
+
echo '{"ok":false,"error":"Cannot fetch portfolio — check wallet setup"}'
|
|
32
|
+
else
|
|
33
|
+
echo "ERROR: Cannot fetch portfolio. Check wallet setup first."
|
|
34
|
+
fi
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# 2. Run appropriate scan
|
|
39
|
+
SCAN_RESULT=$($PERP --json arb scan --mode "$MODE" --min "$MIN_SPREAD" 2>/dev/null || echo '{"ok":false}')
|
|
40
|
+
|
|
41
|
+
# 3. Get exchange health for context
|
|
42
|
+
HEALTH=$($PERP --json agent ping 2>/dev/null || echo '{"ok":false}')
|
|
43
|
+
|
|
44
|
+
if $JSON_MODE; then
|
|
45
|
+
cat <<EOF
|
|
46
|
+
{
|
|
47
|
+
"ok": true,
|
|
48
|
+
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
49
|
+
"mode": "$MODE",
|
|
50
|
+
"minSpread": $MIN_SPREAD,
|
|
51
|
+
"portfolio": $PORTFOLIO,
|
|
52
|
+
"scan": $SCAN_RESULT,
|
|
53
|
+
"health": $HEALTH
|
|
54
|
+
}
|
|
55
|
+
EOF
|
|
56
|
+
else
|
|
57
|
+
echo "=== Spot+Perp Arb Scanner ==="
|
|
58
|
+
echo "Mode: $MODE | Min spread: ${MIN_SPREAD} bps"
|
|
59
|
+
echo ""
|
|
60
|
+
|
|
61
|
+
# Show balances
|
|
62
|
+
echo "--- Balances ---"
|
|
63
|
+
echo "$PORTFOLIO" | jq -r '
|
|
64
|
+
.data.exchanges // [] | .[] |
|
|
65
|
+
" \(.exchange): $\(.balance // .equity // "N/A")"
|
|
66
|
+
' 2>/dev/null || echo " (unable to parse)"
|
|
67
|
+
echo ""
|
|
68
|
+
|
|
69
|
+
# Show opportunities
|
|
70
|
+
echo "--- Opportunities ---"
|
|
71
|
+
echo "$SCAN_RESULT" | jq -r '
|
|
72
|
+
.data // [] | .[] |
|
|
73
|
+
" \(.symbol) | \(.mode // "perp-perp") | spread: \(.netSpread // .spread)bps | \(.longExch // .longExchange)→\(.shortExch // .shortExchange)"
|
|
74
|
+
' 2>/dev/null || echo " (no opportunities or parse error)"
|
|
75
|
+
|
|
76
|
+
# Show exchange health
|
|
77
|
+
echo ""
|
|
78
|
+
echo "--- Exchange Health ---"
|
|
79
|
+
echo "$HEALTH" | jq -r '
|
|
80
|
+
.data // {} | to_entries[] |
|
|
81
|
+
" \(.key): \(.value.status // .value // "unknown")"
|
|
82
|
+
' 2>/dev/null || echo " (unable to check)"
|
|
83
|
+
fi
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Validate an arb opportunity before execution
|
|
3
|
+
# Usage: ./validate-arb.sh <SYMBOL> <LONG_EX> <SHORT_EX> <SIZE_USD> [--leverage N]
|
|
4
|
+
# Performs: price check, liquidity check, balance check, risk check, slippage estimate
|
|
5
|
+
# Returns JSON validation report
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Auto-detect perp command (supports npx fallback for agents without install permissions)
|
|
10
|
+
if command -v perp &>/dev/null; then
|
|
11
|
+
PERP="perp"
|
|
12
|
+
else
|
|
13
|
+
PERP="npx -y perp-cli@latest"
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
SYM="${1:?Usage: validate-arb.sh <SYMBOL> <LONG_EX> <SHORT_EX> <SIZE_USD> [--leverage N]}"
|
|
17
|
+
LONG_EX="${2:?Usage: validate-arb.sh <SYMBOL> <LONG_EX> <SHORT_EX> <SIZE_USD>}"
|
|
18
|
+
SHORT_EX="${3:?Usage: validate-arb.sh <SYMBOL> <LONG_EX> <SHORT_EX> <SIZE_USD>}"
|
|
19
|
+
SIZE="${4:?Usage: validate-arb.sh <SYMBOL> <LONG_EX> <SHORT_EX> <SIZE_USD>}"
|
|
20
|
+
LEVERAGE=""
|
|
21
|
+
|
|
22
|
+
shift 4
|
|
23
|
+
while [[ $# -gt 0 ]]; do
|
|
24
|
+
case "$1" in
|
|
25
|
+
--leverage) LEVERAGE="$2"; shift 2 ;;
|
|
26
|
+
*) shift ;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
checks=()
|
|
31
|
+
pass=true
|
|
32
|
+
|
|
33
|
+
add_result() {
|
|
34
|
+
local name="$1" ok="$2" detail="$3"
|
|
35
|
+
checks+=("{\"check\":\"$name\",\"ok\":$ok,\"detail\":\"$detail\"}")
|
|
36
|
+
[[ "$ok" == "false" ]] && pass=false
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# 1. Price comparison — both exchanges must report similar prices
|
|
40
|
+
LONG_PRICE=$($PERP --json -e "$LONG_EX" market mid "$SYM" 2>/dev/null | jq -r '.data.mid // "0"')
|
|
41
|
+
SHORT_PRICE=$($PERP --json -e "$SHORT_EX" market mid "$SYM" 2>/dev/null | jq -r '.data.mid // "0"')
|
|
42
|
+
|
|
43
|
+
if [[ "$LONG_PRICE" == "0" || "$SHORT_PRICE" == "0" ]]; then
|
|
44
|
+
add_result "price" "false" "Cannot fetch price: long=$LONG_PRICE short=$SHORT_PRICE"
|
|
45
|
+
else
|
|
46
|
+
# Check deviation
|
|
47
|
+
DEVIATION=$(echo "$LONG_PRICE $SHORT_PRICE" | awk '{d=($1-$2)/$2*100; print (d<0?-d:d)}')
|
|
48
|
+
if (( $(echo "$DEVIATION > 5" | bc -l) )); then
|
|
49
|
+
add_result "price" "false" "Price deviation ${DEVIATION}% > 5% — possible wrong token"
|
|
50
|
+
else
|
|
51
|
+
add_result "price" "true" "long=$LONG_PRICE short=$SHORT_PRICE dev=${DEVIATION}%"
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# 2. Balance check on both exchanges
|
|
56
|
+
LONG_BAL=$($PERP --json -e "$LONG_EX" account info 2>/dev/null | jq -r '.data.available // .data.equity // "0"')
|
|
57
|
+
SHORT_BAL=$($PERP --json -e "$SHORT_EX" account info 2>/dev/null | jq -r '.data.available // .data.equity // "0"')
|
|
58
|
+
|
|
59
|
+
NEEDED=$(echo "$SIZE" | awk '{print $1}')
|
|
60
|
+
if (( $(echo "$LONG_BAL < $NEEDED" | bc -l 2>/dev/null || echo 1) )); then
|
|
61
|
+
add_result "balance_long" "false" "$LONG_EX balance $LONG_BAL < needed $NEEDED"
|
|
62
|
+
else
|
|
63
|
+
add_result "balance_long" "true" "$LONG_EX balance=$LONG_BAL"
|
|
64
|
+
fi
|
|
65
|
+
if (( $(echo "$SHORT_BAL < $NEEDED" | bc -l 2>/dev/null || echo 1) )); then
|
|
66
|
+
add_result "balance_short" "false" "$SHORT_EX balance $SHORT_BAL < needed $NEEDED"
|
|
67
|
+
else
|
|
68
|
+
add_result "balance_short" "true" "$SHORT_EX balance=$SHORT_BAL"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# 3. Market info (symbol availability)
|
|
72
|
+
LONG_INFO=$($PERP --json -e "$LONG_EX" market info "$SYM" 2>/dev/null || echo '{"ok":false}')
|
|
73
|
+
SHORT_INFO=$($PERP --json -e "$SHORT_EX" market info "$SYM" 2>/dev/null || echo '{"ok":false}')
|
|
74
|
+
|
|
75
|
+
if echo "$LONG_INFO" | grep -q '"ok":true' && echo "$SHORT_INFO" | grep -q '"ok":true'; then
|
|
76
|
+
add_result "market_info" "true" "Both exchanges support $SYM"
|
|
77
|
+
else
|
|
78
|
+
add_result "market_info" "false" "Symbol $SYM not available on one or both exchanges"
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# 4. Risk pre-check
|
|
82
|
+
LEV_FLAG=""
|
|
83
|
+
[[ -n "$LEVERAGE" ]] && LEV_FLAG="--leverage $LEVERAGE"
|
|
84
|
+
RISK_CHECK=$($PERP --json risk check --notional "$SIZE" $LEV_FLAG 2>/dev/null || echo '{"ok":false}')
|
|
85
|
+
if echo "$RISK_CHECK" | grep -q '"ok":true'; then
|
|
86
|
+
add_result "risk" "true" "Within risk limits"
|
|
87
|
+
else
|
|
88
|
+
add_result "risk" "false" "Risk check failed — review risk limits"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# 5. Dry-run
|
|
92
|
+
DRY_RUN=$($PERP --json --dry-run arb exec "$SYM" "$LONG_EX" "$SHORT_EX" "$SIZE" $LEV_FLAG 2>/dev/null || echo '{"ok":false}')
|
|
93
|
+
if echo "$DRY_RUN" | grep -q '"ok":true'; then
|
|
94
|
+
add_result "dry_run" "true" "Dry-run succeeded"
|
|
95
|
+
else
|
|
96
|
+
DRY_ERR=$(echo "$DRY_RUN" | jq -r '.error.message // .error // "unknown"' 2>/dev/null)
|
|
97
|
+
add_result "dry_run" "false" "Dry-run failed: $DRY_ERR"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Output
|
|
101
|
+
CHECKS_JSON=$(IFS=,; echo "${checks[*]}")
|
|
102
|
+
cat <<EOF
|
|
103
|
+
{
|
|
104
|
+
"ok": true,
|
|
105
|
+
"symbol": "$SYM",
|
|
106
|
+
"longExchange": "$LONG_EX",
|
|
107
|
+
"shortExchange": "$SHORT_EX",
|
|
108
|
+
"sizeUsd": $SIZE,
|
|
109
|
+
"allPassed": $pass,
|
|
110
|
+
"checks": [$CHECKS_JSON]
|
|
111
|
+
}
|
|
112
|
+
EOF
|
|
@@ -1,15 +0,0 @@
|
|
|
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. Opportunities (>= ${MIN_SPREAD} bps):"
|
|
15
|
-
perp --json arb scan --min "$MIN_SPREAD"
|
|
@@ -1,38 +0,0 @@
|
|
|
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
|
|
@@ -1,17 +0,0 @@
|
|
|
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."
|