perp-cli 0.7.16 → 0.7.17

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.
@@ -86,10 +86,51 @@ export class FundingArbStrategy {
86
86
  }
87
87
  }
88
88
  }
89
+ // ── Same-exchange spot-perp hedges (e.g. PURR spot + PURR-PERP short on HL) ──
90
+ for (const [name, a] of adapters) {
91
+ try {
92
+ const spotState = await a._getSpotClearinghouseState?.();
93
+ if (!spotState?.balances)
94
+ continue;
95
+ const spotBalances = spotState.balances
96
+ .filter(b => Number(b.total) > 0 && b.coin.toUpperCase() !== "USDC");
97
+ const perpPositions = positionsByExchange.get(name) ?? [];
98
+ for (const perp of perpPositions) {
99
+ const perpKey = `${name}:${perp.symbol}`;
100
+ if (used.has(perpKey))
101
+ continue;
102
+ const base = perp.symbol.replace(/-PERP$/, "").toUpperCase();
103
+ const spotBal = spotBalances.find(b => b.coin.toUpperCase() === base);
104
+ if (spotBal && perp.side === "short") {
105
+ recovered.push({ symbol: base, longExchange: `${name}-spot`, shortExchange: name, entrySpread: 0, size: perp.size });
106
+ used.add(perpKey);
107
+ ctx.log(` [ARB] Detected spot-perp hedge: ${base} ${name}-spot↔${name}`);
108
+ }
109
+ }
110
+ }
111
+ catch { /* adapter doesn't support spot */ }
112
+ }
89
113
  if (recovered.length > 0) {
90
114
  ctx.state.set("arbOpenPositions", recovered);
91
115
  ctx.state.set("arbPositions", recovered.length);
92
- ctx.log(` [ARB] Recovered ${recovered.length} existing position(s): ${recovered.map(p => `${p.symbol} ${p.longExchange}↔${p.shortExchange}`).join(", ")}`);
116
+ ctx.log(` [ARB] Recovered ${recovered.length} position(s): ${recovered.map(p => `${p.symbol} ${p.longExchange}↔${p.shortExchange}`).join(", ")}`);
117
+ }
118
+ // ── Load historical funding income ──
119
+ let historicalFunding = 0;
120
+ for (const [name, a] of adapters) {
121
+ try {
122
+ const payments = await a.getFundingPayments(200);
123
+ const sum = payments.reduce((s, p) => s + parseFloat(p.payment), 0);
124
+ if (Math.abs(sum) > 0.001) {
125
+ historicalFunding += sum;
126
+ ctx.log(` [FUND] ${name}: $${sum.toFixed(4)} historical funding`);
127
+ }
128
+ }
129
+ catch { /* not all adapters support this */ }
130
+ }
131
+ if (Math.abs(historicalFunding) > 0.001) {
132
+ ctx.state.set("fundingIncome", historicalFunding);
133
+ ctx.log(` [FUND] Total historical funding: $${historicalFunding.toFixed(4)}`);
93
134
  }
94
135
  }
95
136
  catch (err) {
@@ -131,8 +172,8 @@ export class FundingArbStrategy {
131
172
  try {
132
173
  const payments = await a.getFundingPayments(50);
133
174
  const startTime = ctx.state.get("fundingLastCheck");
134
- const recent = payments.filter(p => p.timestamp > startTime - 5 * 60 * 1000);
135
- const sum = recent.reduce((s, p) => s + parseFloat(p.amount), 0);
175
+ const recent = payments.filter(p => p.time > startTime - 5 * 60 * 1000);
176
+ const sum = recent.reduce((s, p) => s + parseFloat(p.payment), 0);
136
177
  totalFunding += sum;
137
178
  if (Math.abs(sum) > 0.001) {
138
179
  ctx.log(` [FUND] ${name}: $${sum.toFixed(4)} funding received`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perp-cli",
3
- "version": "0.7.16",
3
+ "version": "0.7.17",
4
4
  "description": "Multi-DEX Perpetual Futures CLI - Pacifica, Hyperliquid, Lighter, Aster",
5
5
  "bin": {
6
6
  "perp": "dist/index.js",