mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 09:18:08 +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,
|
"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 {
|
export interface LighterGatewayOptions {
|
||||||
symbol: string; // display symbol used by strategy logging
|
symbol: string; // display symbol used by strategy logging
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ export interface LighterOrder {
|
|||||||
time_in_force?: string;
|
time_in_force?: string;
|
||||||
trigger_price?: string;
|
trigger_price?: string;
|
||||||
reduce_only?: boolean;
|
reduce_only?: boolean;
|
||||||
status?: string;
|
status?: string | number;
|
||||||
trigger_status?: string;
|
trigger_status?: string | number;
|
||||||
trigger_time?: number;
|
trigger_time?: number;
|
||||||
updated_at?: number;
|
updated_at?: number;
|
||||||
created_at?: number;
|
created_at?: number;
|
||||||
|
|||||||
@@ -546,10 +546,13 @@ export class OffsetMakerEngine {
|
|||||||
this.lastEntryOrderBySide[target.side] = { price: target.price, ts: Date.now() };
|
this.lastEntryOrderBySide[target.side] = { price: target.price, ts: Date.now() };
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
const dustClosed = await this.tryDustMarketClose(target, error);
|
||||||
|
if (!dustClosed) {
|
||||||
this.tradeLog.push("error", `挂单失败(${target.side} ${target.price}): ${String(error)}`);
|
this.tradeLog.push("error", `挂单失败(${target.side} ${target.price}): ${String(error)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async checkRisk(position: PositionSnapshot, bidPrice: number, askPrice: number): Promise<void> {
|
private async checkRisk(position: PositionSnapshot, bidPrice: number, askPrice: number): Promise<void> {
|
||||||
const absPosition = Math.abs(position.positionAmt);
|
const absPosition = Math.abs(position.positionAmt);
|
||||||
@@ -713,4 +716,52 @@ export class OffsetMakerEngine {
|
|||||||
private getReferencePrice(): number | null {
|
private getReferencePrice(): number | null {
|
||||||
return getMidOrLast(this.depthSnapshot, this.tickerSnapshot);
|
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