From 628b428b466331429f7f9dc4d5a004b824e6828a Mon Sep 17 00:00:00 2001 From: discountry Date: Wed, 24 Sep 2025 01:44:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20TrendEngine=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8C=81=E4=BB=93=E5=9D=87=E4=BB=B7=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=97=A5=E5=BF=97=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E9=A3=8E=E6=8E=A7=E9=80=BB=E8=BE=91=E4=BB=A5=E5=A4=84?= =?UTF-8?q?=E7=90=86=E6=9C=AA=E5=90=8C=E6=AD=A5=E7=9A=84=E6=8C=81=E4=BB=93?= =?UTF-8?q?=E5=9D=87=E4=BB=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/trend-engine.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/core/trend-engine.ts b/src/core/trend-engine.ts index 08399d5..dc8b914 100644 --- a/src/core/trend-engine.ts +++ b/src/core/trend-engine.ts @@ -83,6 +83,7 @@ export class TrendEngine { private ordersSnapshotReady = false; private startupLogged = false; + private entryPricePendingLogged = false; private readonly listeners = new Map>(); @@ -242,6 +243,7 @@ export class TrendEngine { } private async handleOpenPosition(currentPrice: number, currentSma: number): Promise { + this.entryPricePendingLogged = false; if (this.lastPrice == null) { this.lastPrice = currentPrice; return; @@ -291,11 +293,23 @@ export class TrendEngine { position: PositionSnapshot, price: number ): Promise<{ closed: boolean; pnl: number }> { + const hasEntryPrice = Number.isFinite(position.entryPrice) && Math.abs(position.entryPrice) > 1e-8; + if (!hasEntryPrice) { + if (!this.entryPricePendingLogged) { + this.tradeLog.push("info", "持仓均价尚未同步,等待交易所账户快照更新后再执行风控"); + this.entryPricePendingLogged = true; + } + return { closed: false, pnl: position.unrealizedProfit }; + } + this.entryPricePendingLogged = false; const direction = position.positionAmt > 0 ? "long" : "short"; const pnl = (direction === "long" ? price - position.entryPrice : position.entryPrice - price) * Math.abs(position.positionAmt); + const unrealized = Number.isFinite(position.unrealizedProfit) + ? position.unrealizedProfit + : null; const stopSide = direction === "long" ? "SELL" : "BUY"; const stopPrice = calcStopLossPrice( position.entryPrice, @@ -348,7 +362,14 @@ export class TrendEngine { ); } - if (pnl < -this.config.lossLimit || position.unrealizedProfit < -this.config.lossLimit) { + const derivedLoss = pnl < -this.config.lossLimit; + const snapshotLoss = Boolean( + unrealized != null && + unrealized < -this.config.lossLimit && + Math.sign(unrealized) === Math.sign(pnl) + ); + + if (derivedLoss || snapshotLoss) { try { if (this.openOrders.length > 0) { const orderIdList = this.openOrders.map((order) => order.orderId);