From 4915dc574e41da384cd8cfbf94e889884972a778 Mon Sep 17 00:00:00 2001 From: discountry Date: Tue, 13 Jan 2026 20:23:18 +0800 Subject: [PATCH] Implement precision error handling in MakerPointsEngine - Added a new `isPrecisionError` function to identify precision-related errors in the error utility module. - Updated the MakerPointsEngine to handle precision errors by logging warnings and synchronizing precision when such errors occur during order processing and stop-loss execution. - Enhanced the `syncPrecision` method to allow forced synchronization, improving the handling of precision-related issues. --- src/strategy/maker-points-engine.ts | 14 +++++++++++--- src/utils/errors.ts | 24 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/strategy/maker-points-engine.ts b/src/strategy/maker-points-engine.ts index ce39d2d..5ed9978 100644 --- a/src/strategy/maker-points-engine.ts +++ b/src/strategy/maker-points-engine.ts @@ -8,7 +8,7 @@ import type { } from "../exchanges/types"; import { formatPriceToString } from "../utils/math"; import { createTradeLog, type TradeLogEntry } from "../logging/trade-log"; -import { extractMessage, isInsufficientBalanceError, isRateLimitError, isUnknownOrderError } from "../utils/errors"; +import { extractMessage, isInsufficientBalanceError, isPrecisionError, isRateLimitError, isUnknownOrderError } from "../utils/errors"; import { isOrderActiveStatus } from "../utils/order-status"; import { getPosition, parseSymbolParts } from "../utils/strategy"; import type { PositionSnapshot } from "../utils/strategy"; @@ -617,6 +617,10 @@ export class MakerPointsEngine { this.registerInsufficientBalance(error); break; } + if (isPrecisionError(error)) { + this.tradeLog.push("warn", `检测到精度错误,重新同步: ${extractMessage(error)}`); + this.syncPrecision(true); + } this.tradeLog.push( "error", `挂单失败 ${target.side} @ ${target.price}: ${extractMessage(error)}` @@ -676,6 +680,9 @@ export class MakerPointsEngine { } catch (error) { if (isUnknownOrderError(error)) { this.tradeLog.push("order", "止损平仓时订单已不存在"); + } else if (isPrecisionError(error)) { + this.tradeLog.push("warn", `止损平仓精度错误,重新同步: ${extractMessage(error)}`); + this.syncPrecision(true); } else { this.tradeLog.push("error", `止损平仓失败: ${extractMessage(error)}`); } @@ -711,12 +718,13 @@ export class MakerPointsEngine { } } - private syncPrecision(): void { - if (this.precisionSync) return; + private syncPrecision(force = false): void { + if (this.precisionSync && !force) return; const getPrecision = this.exchange.getPrecision?.bind(this.exchange); if (!getPrecision) return; this.precisionSync = getPrecision() .then((precision) => { + this.precisionSync = null; if (!precision) return; let updated = false; if (Number.isFinite(precision.priceTick) && precision.priceTick > 0) { diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 66fe61a..3a4f668 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -61,3 +61,27 @@ export function isInsufficientBalanceError(error: unknown): boolean { message.includes("NOT ENOUGH") ); } + +export function isPrecisionError(error: unknown): boolean { + const message = extractMessage(error).toUpperCase(); + return ( + message.includes("PRECISION") || + message.includes("TICK_SIZE") || + message.includes("TICKSIZE") || + message.includes("STEP_SIZE") || + message.includes("STEPSIZE") || + message.includes("LOT_SIZE") || + message.includes("LOTSIZE") || + message.includes("INVALID_QUANTITY") || + message.includes("INVALID QUANTITY") || + message.includes("QUANTITY_INVALID") || + message.includes("INVALID_PRICE") || + message.includes("INVALID PRICE") || + message.includes("PRICE_INVALID") || + message.includes("QTY_STEP") || + message.includes("PRICE_TICK") || + message.includes("DECIMAL") || + message.includes("FILTER_FAILURE") || + message.includes("NOTIONAL") + ); +}