mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 09:18:08 +00:00
feat: 更新订单协调器和 GRVT 适配器,添加触发类型支持,优化趋势引擎的损益计算逻辑
This commit is contained in:
@@ -242,6 +242,7 @@ export async function placeStopLossOrder(
|
|||||||
closePosition: "true",
|
closePosition: "true",
|
||||||
timeInForce: "GTC",
|
timeInForce: "GTC",
|
||||||
quantity: roundQtyDownToStep(quantity, qtyStep),
|
quantity: roundQtyDownToStep(quantity, qtyStep),
|
||||||
|
triggerType: "STOP_LOSS",
|
||||||
};
|
};
|
||||||
// 部分交易所(例如 Paradex)要求 STOP_MARKET 同时提供 price 字段
|
// 部分交易所(例如 Paradex)要求 STOP_MARKET 同时提供 price 字段
|
||||||
params.price = params.stopPrice;
|
params.price = params.stopPrice;
|
||||||
|
|||||||
@@ -1337,7 +1337,7 @@ function buildUnsignedOrder(params: {
|
|||||||
|
|
||||||
function buildTriggerMetadata(params: CreateOrderParams): GrvtUnsignedOrder["metadata"]["trigger"] | undefined {
|
function buildTriggerMetadata(params: CreateOrderParams): GrvtUnsignedOrder["metadata"]["trigger"] | undefined {
|
||||||
if (params.type === "STOP_MARKET") {
|
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;
|
const stopPrice = params.stopPrice ?? params.activationPrice;
|
||||||
if (!stopPrice) {
|
if (!stopPrice) {
|
||||||
throw new Error("GRVT stop orders require a stopPrice or activationPrice");
|
throw new Error("GRVT stop orders require a stopPrice or activationPrice");
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export interface CreateOrderParams {
|
|||||||
timeInForce?: TimeInForce;
|
timeInForce?: TimeInForce;
|
||||||
reduceOnly?: StringBoolean;
|
reduceOnly?: StringBoolean;
|
||||||
closePosition?: StringBoolean;
|
closePosition?: StringBoolean;
|
||||||
|
triggerType?: "UNSPECIFIED" | "TAKE_PROFIT" | "STOP_LOSS";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AsterAccountPosition {
|
export interface AsterAccountPosition {
|
||||||
|
|||||||
@@ -509,10 +509,21 @@ export class TrendEngine {
|
|||||||
}
|
}
|
||||||
this.entryPricePendingLogged = false;
|
this.entryPricePendingLogged = false;
|
||||||
const direction = position.positionAmt > 0 ? "long" : "short";
|
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 =
|
const pnl =
|
||||||
(direction === "long"
|
qtyAbs > 0
|
||||||
? price - position.entryPrice
|
? (direction === "long"
|
||||||
: position.entryPrice - price) * Math.abs(position.positionAmt);
|
? effectiveClosePrice - position.entryPrice
|
||||||
|
: position.entryPrice - effectiveClosePrice) * qtyAbs
|
||||||
|
: 0;
|
||||||
const unrealized = Number.isFinite(position.unrealizedProfit)
|
const unrealized = Number.isFinite(position.unrealizedProfit)
|
||||||
? position.unrealizedProfit
|
? position.unrealizedProfit
|
||||||
: null;
|
: null;
|
||||||
@@ -671,11 +682,7 @@ export class TrendEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const derivedLoss = pnl < -this.config.lossLimit;
|
const derivedLoss = pnl < -this.config.lossLimit;
|
||||||
const snapshotLoss = Boolean(
|
const snapshotLoss = derivedLoss;
|
||||||
unrealized != null &&
|
|
||||||
unrealized < -this.config.lossLimit &&
|
|
||||||
pnl <= 0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (derivedLoss || snapshotLoss) {
|
if (derivedLoss || snapshotLoss) {
|
||||||
const result = { closed: false, pnl };
|
const result = { closed: false, pnl };
|
||||||
|
|||||||
Reference in New Issue
Block a user