From 640f1bfb4e0d26acb6508456b7ce5b4ab0f6fa64 Mon Sep 17 00:00:00 2001 From: discountry Date: Wed, 8 Oct 2025 03:43:47 +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=E5=A2=9E=E5=BC=BA=E5=85=A5=E5=8F=A3?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E9=99=90=E5=88=B6=E9=80=BB=E8=BE=91=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=8C=89=E4=B9=B0=E5=8D=96=E6=96=B9=E5=90=91?= =?UTF-8?q?=E5=88=86=E5=88=AB=E8=AE=A1=E7=AE=97=E5=BE=85=E5=A4=84=E7=90=86?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/strategy/grid-engine.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/strategy/grid-engine.ts b/src/strategy/grid-engine.ts index 0407f70..5d5c361 100644 --- a/src/strategy/grid-engine.ts +++ b/src/strategy/grid-engine.ts @@ -680,12 +680,12 @@ export class GridEngine { if (capped <= EPSILON) continue; d.amount = capped; } else { - const capped = this.capEntryQty(d.amount); + const capped = this.capEntryQty(d.amount, d.side); if (capped <= EPSILON) continue; d.amount = capped; } const key = this.getOrderKey(d.side, d.price, intent); - if ((plannedKeyCounts.get(key) ?? 0) >= 1) continue; + if ((activeKeyCounts.get(key) ?? 0) >= 1) continue; try { const placed = await placeOrder( this.exchange, @@ -704,6 +704,7 @@ export class GridEngine { ); if (placed) { plannedKeyCounts.set(key, (plannedKeyCounts.get(key) ?? 0) + 1); + activeKeyCounts.set(key, (activeKeyCounts.get(key) ?? 0) + 1); if (placed.orderId != null) { const record: { side: "BUY" | "SELL"; price: string; level: number; intent: "ENTRY" | "EXIT"; sourceLevel?: number } = { side: d.side, @@ -751,10 +752,11 @@ export class GridEngine { return Math.min(desiredQty, remain); } - private estimatePendingEntryQty(): number { + private estimatePendingEntryQty(side: "BUY" | "SELL"): number { let sum = 0; for (const o of this.openOrders) { if (!this.isActiveLimitOrder(o)) continue; + if (o.side !== side) continue; const meta = this.orderIntentById.get(String(o.orderId)); if (!meta || meta.intent !== "ENTRY") continue; const orig = Number(o.origQty || 0); @@ -764,10 +766,11 @@ export class GridEngine { return sum; } - private capEntryQty(desiredQty: number): number { + private capEntryQty(desiredQty: number, side: "BUY" | "SELL"): number { + // Cap per side to allow simultaneous BUY/SELL grids without mutual blocking const absPos = Math.abs(this.position.positionAmt); - const pendingEntry = this.estimatePendingEntryQty(); - const remain = Math.max(this.config.maxPositionSize - absPos - pendingEntry, 0); + const pendingEntrySameSide = this.estimatePendingEntryQty(side); + const remain = Math.max(this.config.maxPositionSize - absPos - pendingEntrySameSide, 0); return Math.min(desiredQty, remain); }