From c6f279c51b92068ed9faec0cc12f801033b800de Mon Sep 17 00:00:00 2001 From: discountry Date: Tue, 7 Oct 2025 04:16:33 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E7=BD=91=E6=A0=BC?= =?UTF-8?q?=E5=BC=95=E6=93=8E=EF=BC=8C=E4=BC=98=E5=8C=96=E5=B9=B3=E4=BB=93?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E4=BB=A5=E5=A4=84=E7=90=86=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E6=8C=81=E4=BB=93=E6=83=85=E5=86=B5=EF=BC=8C=E7=A1=AE=E4=BF=9D?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E5=B9=B3=E4=BB=93=E6=95=B0=E9=87=8F=E8=AE=A1?= =?UTF-8?q?=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/strategy/grid-engine.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/strategy/grid-engine.ts b/src/strategy/grid-engine.ts index 260f5c0..a385b7a 100644 --- a/src/strategy/grid-engine.ts +++ b/src/strategy/grid-engine.ts @@ -724,7 +724,19 @@ export class GridEngine { const totalLongClose = toCloseLongLevels.reduce((acc, item) => acc + item.quantity, 0); const totalShortClose = toCloseShortLevels.reduce((acc, item) => acc + item.quantity, 0); - if (totalLongClose > EPSILON) { + const actualLong = Math.max(this.position.positionAmt, 0); + const actualShort = Math.max(-this.position.positionAmt, 0); + + if (actualLong <= EPSILON && totalLongClose > EPSILON) { + this.resyncLongExposure(actualLong); + } + + if (actualShort <= EPSILON && totalShortClose > EPSILON) { + this.resyncShortExposure(actualShort); + } + + const safeLongClose = Math.min(totalLongClose, Math.max(actualLong - EPSILON, 0)); + if (safeLongClose > EPSILON) { try { await placeMarketOrder( this.exchange, @@ -734,7 +746,7 @@ export class GridEngine { this.timers, this.pendings, "SELL", - totalLongClose, + safeLongClose, this.log, true, { expectedPrice: referencePrice }, @@ -743,13 +755,15 @@ export class GridEngine { for (const { level } of toCloseLongLevels) { this.longExposure.delete(level); } + this.deferPositionAlignment(); this.schedulePersist(); } catch (error) { this.log("error", `市价平仓多单失败: ${extractMessage(error)}`); } } - if (totalShortClose > EPSILON) { + const safeShortClose = Math.min(totalShortClose, Math.max(actualShort - EPSILON, 0)); + if (safeShortClose > EPSILON) { try { await placeMarketOrder( this.exchange, @@ -759,7 +773,7 @@ export class GridEngine { this.timers, this.pendings, "BUY", - totalShortClose, + safeShortClose, this.log, true, { expectedPrice: referencePrice }, @@ -768,6 +782,7 @@ export class GridEngine { for (const { level } of toCloseShortLevels) { this.shortExposure.delete(level); } + this.deferPositionAlignment(); this.schedulePersist(); } catch (error) { this.log("error", `市价平仓空单失败: ${extractMessage(error)}`);