feat: 更新订单协调器和 GRVT 适配器,添加触发类型支持,优化趋势引擎的损益计算逻辑

This commit is contained in:
discountry
2025-10-06 19:06:49 +08:00
parent e28240e799
commit d2867ba98c
4 changed files with 18 additions and 9 deletions
+1
View File
@@ -242,6 +242,7 @@ export async function placeStopLossOrder(
closePosition: "true",
timeInForce: "GTC",
quantity: roundQtyDownToStep(quantity, qtyStep),
triggerType: "STOP_LOSS",
};
// 部分交易所(例如 Paradex)要求 STOP_MARKET 同时提供 price 字段
params.price = params.stopPrice;
+1 -1
View File
@@ -1337,7 +1337,7 @@ function buildUnsignedOrder(params: {
function buildTriggerMetadata(params: CreateOrderParams): GrvtUnsignedOrder["metadata"]["trigger"] | undefined {
if (params.type === "STOP_MARKET") {
const triggerType = params.side === "BUY" ? "TAKE_PROFIT" : "STOP_LOSS";
const triggerType = params.triggerType ?? (params.side === "BUY" ? "TAKE_PROFIT" : "STOP_LOSS");
const stopPrice = params.stopPrice ?? params.activationPrice;
if (!stopPrice) {
throw new Error("GRVT stop orders require a stopPrice or activationPrice");
+1
View File
@@ -21,6 +21,7 @@ export interface CreateOrderParams {
timeInForce?: TimeInForce;
reduceOnly?: StringBoolean;
closePosition?: StringBoolean;
triggerType?: "UNSPECIFIED" | "TAKE_PROFIT" | "STOP_LOSS";
}
export interface AsterAccountPosition {
+15 -8
View File
@@ -509,10 +509,21 @@ export class TrendEngine {
}
this.entryPricePendingLogged = false;
const direction = position.positionAmt > 0 ? "long" : "short";
const qtyAbs = Math.abs(position.positionAmt);
const depthBid = Number(this.depthSnapshot?.bids?.[0]?.[0]);
const depthAsk = Number(this.depthSnapshot?.asks?.[0]?.[0]);
const closeSidePriceRaw = direction === "long" ? depthBid : depthAsk;
const effectiveClosePrice = Number.isFinite(closeSidePriceRaw)
? closeSidePriceRaw
: Number.isFinite(price)
? price
: position.entryPrice;
const pnl =
(direction === "long"
? price - position.entryPrice
: position.entryPrice - price) * Math.abs(position.positionAmt);
qtyAbs > 0
? (direction === "long"
? effectiveClosePrice - position.entryPrice
: position.entryPrice - effectiveClosePrice) * qtyAbs
: 0;
const unrealized = Number.isFinite(position.unrealizedProfit)
? position.unrealizedProfit
: null;
@@ -671,11 +682,7 @@ export class TrendEngine {
}
const derivedLoss = pnl < -this.config.lossLimit;
const snapshotLoss = Boolean(
unrealized != null &&
unrealized < -this.config.lossLimit &&
pnl <= 0
);
const snapshotLoss = derivedLoss;
if (derivedLoss || snapshotLoss) {
const result = { closed: false, pnl };