perp-cli 0.7.42 → 0.7.43
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/dist/bot/strategies/funding-arb-strategy.js +10 -9
- package/dist/exchanges/aster.d.ts +3 -1
- package/dist/exchanges/aster.js +6 -3
- package/dist/exchanges/hyperliquid.d.ts +3 -1
- package/dist/exchanges/hyperliquid.js +1 -1
- package/dist/exchanges/interface.d.ts +3 -1
- package/dist/exchanges/lighter.d.ts +3 -1
- package/dist/exchanges/lighter.js +2 -1
- package/dist/exchanges/pacifica.d.ts +3 -1
- package/dist/exchanges/pacifica.js +2 -2
- package/package.json +1 -1
|
@@ -331,7 +331,7 @@ export class FundingArbStrategy {
|
|
|
331
331
|
if (longAdapter && shortAdapter) {
|
|
332
332
|
let closeLongOk = false;
|
|
333
333
|
try {
|
|
334
|
-
const closeLongResult = await longAdapter.marketOrder(pos.symbol, "sell", pos.size);
|
|
334
|
+
const closeLongResult = await longAdapter.marketOrder(pos.symbol, "sell", pos.size, { reduceOnly: true });
|
|
335
335
|
closeLongOk = true;
|
|
336
336
|
logExecution({ type: "arb_close", exchange: pos.longExchange, symbol: pos.symbol, side: "sell", size: pos.size, status: "success", dryRun: false, meta: { mode: pos.mode, leg: "long", signedSpread: signedSpread, response: closeLongResult } });
|
|
337
337
|
}
|
|
@@ -342,9 +342,9 @@ export class FundingArbStrategy {
|
|
|
342
342
|
this._failCooldown.set(`${pos.symbol}:close`, Date.now() + 5 * 60 * 1000);
|
|
343
343
|
}
|
|
344
344
|
if (!closeLongOk)
|
|
345
|
-
continue;
|
|
345
|
+
continue;
|
|
346
346
|
try {
|
|
347
|
-
const closeShortResult = await shortAdapter.marketOrder(pos.symbol, "buy", pos.size);
|
|
347
|
+
const closeShortResult = await shortAdapter.marketOrder(pos.symbol, "buy", pos.size, { reduceOnly: true });
|
|
348
348
|
logExecution({ type: "arb_close", exchange: pos.shortExchange, symbol: pos.symbol, side: "buy", size: pos.size, status: "success", dryRun: false, meta: { mode: pos.mode, leg: "short", signedSpread: signedSpread, response: closeShortResult } });
|
|
349
349
|
}
|
|
350
350
|
catch (err) {
|
|
@@ -355,6 +355,7 @@ export class FundingArbStrategy {
|
|
|
355
355
|
try {
|
|
356
356
|
await longAdapter.marketOrder(pos.symbol, "buy", pos.size);
|
|
357
357
|
ctx.log(` [ARB] Rollback: re-opened long ${pos.size} ${pos.symbol} on ${pos.longExchange}`);
|
|
358
|
+
// Note: re-open is NOT reduceOnly (it's a new position)
|
|
358
359
|
logExecution({ type: "multi_leg_rollback", exchange: pos.longExchange, symbol: pos.symbol, side: "buy", size: pos.size, status: "success", dryRun: false });
|
|
359
360
|
}
|
|
360
361
|
catch (rbErr) {
|
|
@@ -570,7 +571,7 @@ export class FundingArbStrategy {
|
|
|
570
571
|
logExecution({ type: "arb_entry", exchange: best.shortExchange, symbol: best.symbol, side: "sell", size: matched.size, status: "failed", error: msg, dryRun: false, meta: { mode: "perp-perp", leg: "short" } });
|
|
571
572
|
// Rollback: close the long position
|
|
572
573
|
try {
|
|
573
|
-
await longAdapter.marketOrder(best.symbol, "sell", matched.size);
|
|
574
|
+
await longAdapter.marketOrder(best.symbol, "sell", matched.size, { reduceOnly: true });
|
|
574
575
|
ctx.log(` [ARB] Rollback success: closed long ${matched.size} ${best.symbol} on ${best.longExchange}`);
|
|
575
576
|
logExecution({ type: "multi_leg_rollback", exchange: best.longExchange, symbol: best.symbol, side: "sell", size: matched.size, status: "success", dryRun: false });
|
|
576
577
|
}
|
|
@@ -617,14 +618,14 @@ export class FundingArbStrategy {
|
|
|
617
618
|
logExecution({ type: "arb_entry", exchange: `${best.longExchange}↔${best.shortExchange}`, symbol: best.symbol, side: "verify", size: matched.size, status: "failed", error: `Position missing after fill: long=${longExists} short=${shortExists}`, dryRun: false });
|
|
618
619
|
if (longExists && !shortExists) {
|
|
619
620
|
try {
|
|
620
|
-
await longAdapter.marketOrder(best.symbol, "sell", matched.size);
|
|
621
|
+
await longAdapter.marketOrder(best.symbol, "sell", matched.size, { reduceOnly: true });
|
|
621
622
|
ctx.log(` [ARB] Rollback: closed phantom long ${best.symbol}`);
|
|
622
623
|
}
|
|
623
624
|
catch { /* best effort */ }
|
|
624
625
|
}
|
|
625
626
|
if (shortExists && !longExists) {
|
|
626
627
|
try {
|
|
627
|
-
await shortAdapter.marketOrder(best.symbol, "buy", matched.size);
|
|
628
|
+
await shortAdapter.marketOrder(best.symbol, "buy", matched.size, { reduceOnly: true });
|
|
628
629
|
ctx.log(` [ARB] Rollback: closed phantom short ${best.symbol}`);
|
|
629
630
|
}
|
|
630
631
|
catch { /* best effort */ }
|
|
@@ -683,7 +684,7 @@ export class FundingArbStrategy {
|
|
|
683
684
|
if (longAdapter && shortAdapter) {
|
|
684
685
|
ctx.log(` [ARB] Closing ${pos.symbol} on stop (${pos.size})`);
|
|
685
686
|
try {
|
|
686
|
-
const closeLongResult = await longAdapter.marketOrder(pos.symbol, "sell", pos.size);
|
|
687
|
+
const closeLongResult = await longAdapter.marketOrder(pos.symbol, "sell", pos.size, { reduceOnly: true });
|
|
687
688
|
logExecution({ type: "arb_close", exchange: pos.longExchange, symbol: pos.symbol, side: "sell", size: pos.size, status: "success", dryRun: false, meta: { mode: pos.mode, leg: "long", stop: true, response: closeLongResult } });
|
|
688
689
|
}
|
|
689
690
|
catch (err) {
|
|
@@ -692,7 +693,7 @@ export class FundingArbStrategy {
|
|
|
692
693
|
logExecution({ type: "arb_close", exchange: pos.longExchange, symbol: pos.symbol, side: "sell", size: pos.size, status: "failed", error: msg, dryRun: false, meta: { mode: pos.mode, leg: "long", stop: true } });
|
|
693
694
|
}
|
|
694
695
|
try {
|
|
695
|
-
const closeShortResult = await shortAdapter.marketOrder(pos.symbol, "buy", pos.size);
|
|
696
|
+
const closeShortResult = await shortAdapter.marketOrder(pos.symbol, "buy", pos.size, { reduceOnly: true });
|
|
696
697
|
logExecution({ type: "arb_close", exchange: pos.shortExchange, symbol: pos.symbol, side: "buy", size: pos.size, status: "success", dryRun: false, meta: { mode: pos.mode, leg: "short", stop: true, response: closeShortResult } });
|
|
697
698
|
}
|
|
698
699
|
catch (err) {
|
|
@@ -758,7 +759,7 @@ export class FundingArbStrategy {
|
|
|
758
759
|
// Step 3: Close perp short
|
|
759
760
|
try {
|
|
760
761
|
const perpSymbol = this.getPerpSymbol(pos.symbol, pos.shortExchange);
|
|
761
|
-
await perpAdapter.marketOrder(perpSymbol, "buy", pos.size);
|
|
762
|
+
await perpAdapter.marketOrder(perpSymbol, "buy", pos.size, { reduceOnly: true });
|
|
762
763
|
ctx.log(` [ARB] Closed perp short ${pos.size} ${perpSymbol}`);
|
|
763
764
|
}
|
|
764
765
|
catch (err) {
|
|
@@ -44,7 +44,9 @@ export declare class AsterAdapter implements ExchangeAdapter {
|
|
|
44
44
|
getOrderHistory(limit?: number): Promise<ExchangeOrder[]>;
|
|
45
45
|
getTradeHistory(limit?: number): Promise<ExchangeTrade[]>;
|
|
46
46
|
getFundingPayments(limit?: number): Promise<ExchangeFundingPayment[]>;
|
|
47
|
-
marketOrder(symbol: string, side: "buy" | "sell", size: string
|
|
47
|
+
marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
|
|
48
|
+
reduceOnly?: boolean;
|
|
49
|
+
}): Promise<unknown>;
|
|
48
50
|
limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
|
|
49
51
|
reduceOnly?: boolean;
|
|
50
52
|
tif?: string;
|
package/dist/exchanges/aster.js
CHANGED
|
@@ -283,14 +283,17 @@ export class AsterAdapter {
|
|
|
283
283
|
}));
|
|
284
284
|
}
|
|
285
285
|
// ── Trading ──
|
|
286
|
-
async marketOrder(symbol, side, size) {
|
|
286
|
+
async marketOrder(symbol, side, size, opts) {
|
|
287
287
|
const apiSymbol = this._toApi(symbol);
|
|
288
|
-
const
|
|
288
|
+
const params = {
|
|
289
289
|
symbol: apiSymbol,
|
|
290
290
|
side: side.toUpperCase(),
|
|
291
291
|
type: "MARKET",
|
|
292
292
|
quantity: size,
|
|
293
|
-
}
|
|
293
|
+
};
|
|
294
|
+
if (opts?.reduceOnly)
|
|
295
|
+
params.reduceOnly = "true";
|
|
296
|
+
const result = await this._signedPost("/fapi/v1/order", params);
|
|
294
297
|
const r = result;
|
|
295
298
|
const executedQty = Number(r.executedQty ?? 0);
|
|
296
299
|
const orderId = String(r.orderId ?? "");
|
|
@@ -55,7 +55,9 @@ export declare class HyperliquidAdapter implements ExchangeAdapter {
|
|
|
55
55
|
getPositions(): Promise<ExchangePosition[]>;
|
|
56
56
|
getOpenOrders(): Promise<ExchangeOrder[]>;
|
|
57
57
|
private _invalidateAccountCache;
|
|
58
|
-
marketOrder(symbol: string, side: "buy" | "sell", size: string
|
|
58
|
+
marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
|
|
59
|
+
reduceOnly?: boolean;
|
|
60
|
+
}): Promise<unknown>;
|
|
59
61
|
/**
|
|
60
62
|
* Place a market order on a HIP-3 deployed dex.
|
|
61
63
|
* Bypasses SDK's symbolConversion (which only knows native perps)
|
|
@@ -393,7 +393,7 @@ export class HyperliquidAdapter {
|
|
|
393
393
|
}
|
|
394
394
|
catch { /* ignore */ }
|
|
395
395
|
}
|
|
396
|
-
async marketOrder(symbol, side, size) {
|
|
396
|
+
async marketOrder(symbol, side, size, opts) {
|
|
397
397
|
this.ensureSigner();
|
|
398
398
|
if (this._dex) {
|
|
399
399
|
const r = await this._dexMarketOrder(symbol, side, size);
|
|
@@ -85,7 +85,9 @@ export interface ExchangeAdapter {
|
|
|
85
85
|
getOrderHistory(limit?: number): Promise<ExchangeOrder[]>;
|
|
86
86
|
getTradeHistory(limit?: number): Promise<ExchangeTrade[]>;
|
|
87
87
|
getFundingPayments(limit?: number): Promise<ExchangeFundingPayment[]>;
|
|
88
|
-
marketOrder(symbol: string, side: "buy" | "sell", size: string
|
|
88
|
+
marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
|
|
89
|
+
reduceOnly?: boolean;
|
|
90
|
+
}): Promise<unknown>;
|
|
89
91
|
limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
|
|
90
92
|
reduceOnly?: boolean;
|
|
91
93
|
tif?: string;
|
|
@@ -62,7 +62,9 @@ export declare class LighterAdapter implements ExchangeAdapter {
|
|
|
62
62
|
private getAuthToken;
|
|
63
63
|
private restGetAuth;
|
|
64
64
|
getOpenOrders(): Promise<ExchangeOrder[]>;
|
|
65
|
-
marketOrder(symbol: string, side: "buy" | "sell", size: string
|
|
65
|
+
marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
|
|
66
|
+
reduceOnly?: boolean;
|
|
67
|
+
}): Promise<unknown>;
|
|
66
68
|
limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
|
|
67
69
|
reduceOnly?: boolean;
|
|
68
70
|
tif?: string;
|
|
@@ -454,8 +454,9 @@ export class LighterAdapter {
|
|
|
454
454
|
return [];
|
|
455
455
|
}
|
|
456
456
|
}
|
|
457
|
-
async marketOrder(symbol, side, size) {
|
|
457
|
+
async marketOrder(symbol, side, size, opts) {
|
|
458
458
|
this.ensureSigner();
|
|
459
|
+
void opts; // lighter doesn't support reduceOnly on market orders
|
|
459
460
|
await this.ensureMarketMap();
|
|
460
461
|
const nonce = await this.getNextNonce();
|
|
461
462
|
const marketIndex = this.getMarketIndex(symbol);
|
|
@@ -33,7 +33,9 @@ export declare class PacificaAdapter implements ExchangeAdapter {
|
|
|
33
33
|
getBalance(): Promise<ExchangeBalance>;
|
|
34
34
|
getPositions(): Promise<ExchangePosition[]>;
|
|
35
35
|
getOpenOrders(): Promise<ExchangeOrder[]>;
|
|
36
|
-
marketOrder(symbol: string, side: "buy" | "sell", size: string
|
|
36
|
+
marketOrder(symbol: string, side: "buy" | "sell", size: string, opts?: {
|
|
37
|
+
reduceOnly?: boolean;
|
|
38
|
+
}): Promise<unknown>;
|
|
37
39
|
limitOrder(symbol: string, side: "buy" | "sell", price: string, size: string, opts?: {
|
|
38
40
|
reduceOnly?: boolean;
|
|
39
41
|
tif?: string;
|
|
@@ -180,9 +180,9 @@ export class PacificaAdapter {
|
|
|
180
180
|
};
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
|
-
async marketOrder(symbol, side, size) {
|
|
183
|
+
async marketOrder(symbol, side, size, opts) {
|
|
184
184
|
this.ensureSigner();
|
|
185
|
-
return this.client.createMarketOrder({ symbol, amount: size, side: side === "buy" ? "bid" : "ask", reduce_only: false, slippage_percent: "1" }, this.account, this.signMessage);
|
|
185
|
+
return this.client.createMarketOrder({ symbol, amount: size, side: side === "buy" ? "bid" : "ask", reduce_only: opts?.reduceOnly ?? false, slippage_percent: "1" }, this.account, this.signMessage);
|
|
186
186
|
}
|
|
187
187
|
async limitOrder(symbol, side, price, size, opts) {
|
|
188
188
|
this.ensureSigner();
|