mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-10 00:38:07 +00:00
refactor: enhance order handling and tracking in GridEngine
- Introduced a clientOrderId system for better order identification. - Updated order creation logic to ensure unique clientOrderIds. - Improved order cancellation methods to maintain accurate current orders. - Added tests for new clientOrderId functionality and level state tracking. - Ensured that desired orders have an intent field set for clarity. - Enhanced snapshot functionality to include level states for grid lines.
This commit is contained in:
@@ -134,6 +134,7 @@ type PlaceOrderOptions = {
|
||||
skipDedupe?: boolean;
|
||||
slPrice?: number;
|
||||
tpPrice?: number;
|
||||
clientOrderId?: string;
|
||||
};
|
||||
|
||||
export async function placeOrder(
|
||||
@@ -180,6 +181,7 @@ export async function placeOrder(
|
||||
closePosition,
|
||||
slPrice: opts?.slPrice,
|
||||
tpPrice: opts?.tpPrice,
|
||||
clientOrderId: opts?.clientOrderId,
|
||||
});
|
||||
pendings[type] = String(order.orderId);
|
||||
log("order", `挂限价单: ${side} @ ${priceNum} 数量 ${quantity} reduceOnly=${reduceOnly}${opts?.slPrice ? ` sl=${opts.slPrice}` : ""}`);
|
||||
|
||||
@@ -815,6 +815,7 @@ export class AsterRestClient {
|
||||
if (params.activationPrice !== undefined) payload.activationPrice = params.activationPrice;
|
||||
if (params.callbackRate !== undefined) payload.callbackRate = params.callbackRate;
|
||||
if (params.quantity !== undefined) payload.quantity = Math.abs(params.quantity);
|
||||
if (params.clientOrderId !== undefined) payload.newClientOrderId = params.clientOrderId;
|
||||
|
||||
// Aster rejects reduceOnly/closePosition for certain order types (e.g. STOP/TRAILING).
|
||||
// Keep the behavior exchange-specific by stripping them here for Aster.
|
||||
|
||||
@@ -487,6 +487,9 @@ export class BinanceGateway {
|
||||
if (params.callbackRate != null) {
|
||||
extra.callbackRate = params.callbackRate;
|
||||
}
|
||||
if (params.clientOrderId != null) {
|
||||
extra.newClientOrderId = params.clientOrderId;
|
||||
}
|
||||
|
||||
if (market.kind === "perp") {
|
||||
if (params.reduceOnly != null) {
|
||||
|
||||
@@ -130,10 +130,10 @@ export class DryRunExchangeAdapter implements ExchangeAdapter {
|
||||
|
||||
function createSyntheticOrder(params: CreateOrderParams, counter: number): Order {
|
||||
const now = Date.now();
|
||||
const orderId = `dry-run-${now}-${counter}`;
|
||||
const orderId = params.clientOrderId ?? `dry-run-${now}-${counter}`;
|
||||
return {
|
||||
orderId,
|
||||
clientOrderId: orderId,
|
||||
clientOrderId: params.clientOrderId ?? orderId,
|
||||
symbol: params.symbol,
|
||||
side: params.side,
|
||||
type: params.type,
|
||||
|
||||
@@ -45,6 +45,9 @@ function applyCommonFields(params: CreateOrderParams, intent: BaseOrderIntent):
|
||||
if (intent.closePosition !== undefined) {
|
||||
params.closePosition = toStringBoolean(intent.closePosition);
|
||||
}
|
||||
if (intent.clientOrderId !== undefined) {
|
||||
params.clientOrderId = intent.clientOrderId;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface BaseOrderIntent {
|
||||
reduceOnly?: boolean;
|
||||
closePosition?: boolean;
|
||||
timeInForce?: TimeInForce | "GTX";
|
||||
clientOrderId?: string;
|
||||
}
|
||||
|
||||
export interface LimitOrderIntent extends BaseOrderIntent {
|
||||
|
||||
@@ -27,6 +27,7 @@ export interface CreateOrderParams {
|
||||
triggerType?: "UNSPECIFIED" | "TAKE_PROFIT" | "STOP_LOSS";
|
||||
slPrice?: number;
|
||||
tpPrice?: number;
|
||||
clientOrderId?: string;
|
||||
}
|
||||
|
||||
export interface AccountPosition {
|
||||
|
||||
@@ -5,6 +5,19 @@ import type { GridDirection } from "../../config";
|
||||
const DATA_DIR = process.env.GRID_DATA_DIR?.trim() || path.resolve("data");
|
||||
const GRID_FILE = path.resolve(DATA_DIR, "grid-record.json");
|
||||
|
||||
/** State of a single grid level */
|
||||
export type LevelState = "idle" | "filled" | "exit_placed";
|
||||
|
||||
export interface StoredLevelInfo {
|
||||
state: LevelState;
|
||||
/** The grid level index where ENTRY was filled */
|
||||
sourceLevel: number;
|
||||
/** The grid level index where EXIT is targeted (closeTarget) */
|
||||
targetLevel: number | null;
|
||||
/** The orderId of the EXIT order on exchange (if exit_placed) */
|
||||
exitOrderId?: string;
|
||||
}
|
||||
|
||||
export interface StoredGridState {
|
||||
symbol: string;
|
||||
lowerPrice: number;
|
||||
@@ -13,8 +26,8 @@ export interface StoredGridState {
|
||||
orderSize: number;
|
||||
maxPositionSize: number;
|
||||
direction: GridDirection;
|
||||
longExposure: Record<string, number>;
|
||||
shortExposure: Record<string, number>;
|
||||
/** Per-level state: key is level index string */
|
||||
levels: Record<string, StoredLevelInfo>;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
|
||||
+678
-532
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user