feat: 优化平仓订单逻辑,避免在止损订单中下调数量,确保精确传递给交易所

This commit is contained in:
discountry
2025-10-08 20:05:02 +08:00
parent b36c1dce0f
commit 6a3b842a3b
2 changed files with 18 additions and 4 deletions
+2 -1
View File
@@ -249,7 +249,8 @@ export async function placeStopLossOrder(
reduceOnly: "true",
closePosition: "true",
timeInForce: "GTC",
quantity: roundQtyDownToStep(quantity, qtyStep),
// Do not round down stop quantity here to avoid underflow to exchange min; gateway will quantize precisely
quantity,
triggerType: "STOP_LOSS",
};
// 部分交易所(例如 Paradex)要求 STOP_MARKET 同时提供 price 字段
+16 -3
View File
@@ -566,8 +566,7 @@ export class ParadexGateway {
}
// Normalize amount for Paradex according to market precision/limits.
// Particularly important for STOP_MARKET closePosition orders where rounding
// upstream may result in 0 due to larger strategy qtyStep.
// For STOP_MARKET closePosition orders, prefer using the current position size.
try {
const market = typeof (this.exchange as any).market === "function"
? (this.exchange as any).market(symbol)
@@ -577,9 +576,13 @@ export class ParadexGateway {
// Only trust explicit exchange min limit; do NOT infer 1 from precision=0
const minAmount = Number.isFinite(limitMin) && limitMin > 0 ? limitMin : undefined;
// If closePosition is requested and amount is missing or too small, bump to minimum allowed
// If closePosition is requested and amount is missing or too small, prefer using current position size
const isClosePosition = (extraParams as any).closePosition === true;
if (isClosePosition) {
const posAbs = this.getCurrentPositionAbs();
if (Number.isFinite(posAbs) && posAbs > 0) {
amount = posAbs;
}
const current = Number(amount);
if (!Number.isFinite(current) || current <= 0 || (minAmount !== undefined && current < minAmount)) {
amount = (minAmount as number) ?? 1e-5; // fallback if market data is missing
@@ -615,6 +618,16 @@ export class ParadexGateway {
}
}
private getCurrentPositionAbs(): number | undefined {
const snapshot = this.lastBalanceSnapshot;
if (!snapshot) return undefined;
const pos = (snapshot.positions || []).find((p) => p.symbol === this.displaySymbol);
if (!pos) return undefined;
const amt = Number(pos.positionAmt);
if (!Number.isFinite(amt)) return undefined;
return Math.abs(amt);
}
async cancelOrder(params: { symbol: string; orderId: number | string }): Promise<void> {
await this.ensureInitialized(params.symbol);
try {