mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-09 08:18:07 +00:00
feat: enhance order error handling in OffsetMakerEngine and update LighterGateway order status types for improved robustness
This commit is contained in:
@@ -133,7 +133,7 @@ const RESOLUTION_MS: Record<string, number> = {
|
||||
"1d": 86_400_000,
|
||||
};
|
||||
|
||||
const TERMINAL_ORDER_STATUSES = new Set(["filled", "canceled", "cancelled", "expired"]);
|
||||
const TERMINAL_ORDER_STATUSES = new Set(["filled", "canceled", "cancelled", "expired", "canceled-post-only"]);
|
||||
|
||||
export interface LighterGatewayOptions {
|
||||
symbol: string; // display symbol used by strategy logging
|
||||
|
||||
@@ -29,8 +29,8 @@ export interface LighterOrder {
|
||||
time_in_force?: string;
|
||||
trigger_price?: string;
|
||||
reduce_only?: boolean;
|
||||
status?: string;
|
||||
trigger_status?: string;
|
||||
status?: string | number;
|
||||
trigger_status?: string | number;
|
||||
trigger_time?: number;
|
||||
updated_at?: number;
|
||||
created_at?: number;
|
||||
|
||||
@@ -546,7 +546,10 @@ export class OffsetMakerEngine {
|
||||
this.lastEntryOrderBySide[target.side] = { price: target.price, ts: Date.now() };
|
||||
}
|
||||
} catch (error) {
|
||||
this.tradeLog.push("error", `挂单失败(${target.side} ${target.price}): ${String(error)}`);
|
||||
const dustClosed = await this.tryDustMarketClose(target, error);
|
||||
if (!dustClosed) {
|
||||
this.tradeLog.push("error", `挂单失败(${target.side} ${target.price}): ${String(error)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -713,4 +716,52 @@ export class OffsetMakerEngine {
|
||||
private getReferencePrice(): number | null {
|
||||
return getMidOrLast(this.depthSnapshot, this.tickerSnapshot);
|
||||
}
|
||||
|
||||
private isInvalidAmountError(error: unknown): boolean {
|
||||
const message =
|
||||
typeof error === "string"
|
||||
? error
|
||||
: error instanceof Error
|
||||
? error.message
|
||||
: JSON.stringify(error);
|
||||
if (!message) return false;
|
||||
if (message.includes("\"code\":21706")) return true;
|
||||
return message.toLowerCase().includes("invalid order base or quote amount");
|
||||
}
|
||||
|
||||
private async tryDustMarketClose(target: DesiredOrder, error: unknown): Promise<boolean> {
|
||||
if (!target.reduceOnly) return false;
|
||||
if (!this.isInvalidAmountError(error)) return false;
|
||||
const position = getPosition(this.accountSnapshot, this.config.symbol);
|
||||
const absQty = Math.abs(target.amount);
|
||||
if (absQty < EPS) return false;
|
||||
const { topBid, topAsk } = getTopPrices(this.depthSnapshot);
|
||||
try {
|
||||
await marketClose(
|
||||
this.exchange,
|
||||
this.config.symbol,
|
||||
this.openOrders,
|
||||
this.locks,
|
||||
this.timers,
|
||||
this.pending,
|
||||
target.side,
|
||||
absQty,
|
||||
(type, detail) => this.tradeLog.push(type, detail),
|
||||
{
|
||||
markPrice: position.markPrice,
|
||||
expectedPrice:
|
||||
target.side === "SELL"
|
||||
? (topBid != null ? Number(topBid) : null)
|
||||
: (topAsk != null ? Number(topAsk) : null),
|
||||
maxPct: this.config.maxCloseSlippagePct,
|
||||
},
|
||||
{ qtyStep: this.qtyStep }
|
||||
);
|
||||
this.tradeLog.push("order", `小额仓位使用市价平仓 ${target.side} 数量 ${absQty.toFixed(6)}`);
|
||||
return true;
|
||||
} catch (closeError) {
|
||||
this.tradeLog.push("error", `小额市价平仓失败: ${String(closeError)}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user