|
|
@@ -66,6 +66,7 @@ export class GridMaker {
|
|
|
private resetting = false;
|
|
|
private consecutivePlaceFailures = 0;
|
|
|
private needsReinit = false;
|
|
|
+ private readonly pendingCancellations = new Set<string>();
|
|
|
|
|
|
constructor(
|
|
|
private config: GridConfig,
|
|
|
@@ -134,12 +135,16 @@ export class GridMaker {
|
|
|
|
|
|
// 从网格中删除这个层级
|
|
|
this.grids.delete(index);
|
|
|
-
|
|
|
+ this.pendingCancellations.delete(orderId);
|
|
|
// 标记需要重新初始化(在下次 tick 时补单)
|
|
|
this.needsReinit = true;
|
|
|
- break;
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
+ if (this.pendingCancellations.delete(orderId)) {
|
|
|
+ this.logger.debug({ orderId }, 'Cancellation confirmed for order not present in grid (likely pre-removed)');
|
|
|
+ }
|
|
|
+ return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -404,7 +409,12 @@ export class GridMaker {
|
|
|
const tolerancePx = this.tickSize > 0 ? this.tickSize : levels.length > 0 ? Math.abs(levels[0].px) * 1e-6 : 1e-6;
|
|
|
const sizeToleranceBase = this.lotSize > 0 ? this.lotSize : 1e-8;
|
|
|
|
|
|
- const activeLevels = Array.from(this.grids.values()).filter(level => level.orderId && !level.filled);
|
|
|
+ const activeLevels = Array.from(this.grids.values()).filter(
|
|
|
+ level =>
|
|
|
+ level.orderId &&
|
|
|
+ !level.filled &&
|
|
|
+ !this.pendingCancellations.has(level.orderId)
|
|
|
+ );
|
|
|
|
|
|
for (const level of activeLevels) {
|
|
|
const target = targetMap.get(level.index);
|
|
|
@@ -885,8 +895,15 @@ export class GridMaker {
|
|
|
private async cancelGridLevel(level: GridLevel): Promise<void> {
|
|
|
const orderId = level.orderId;
|
|
|
if (!orderId) return;
|
|
|
+ if (this.pendingCancellations.has(orderId)) {
|
|
|
+ this.logger.debug({ orderId }, 'Cancel request skipped because it is already pending');
|
|
|
+ return;
|
|
|
+ }
|
|
|
this.logger.debug({ orderId }, 'Canceling grid order');
|
|
|
let cancelled = false;
|
|
|
+ const snapshot = { ...level };
|
|
|
+ this.pendingCancellations.add(orderId);
|
|
|
+ this.grids.delete(level.index);
|
|
|
try {
|
|
|
await this.router.cancel(orderId);
|
|
|
cancelled = true;
|
|
|
@@ -920,11 +937,13 @@ export class GridMaker {
|
|
|
cancelled = true;
|
|
|
}
|
|
|
if (!cancelled) {
|
|
|
+ // 还原本地状态,等待下次重试
|
|
|
+ this.grids.set(snapshot.index, snapshot);
|
|
|
throw error;
|
|
|
}
|
|
|
} finally {
|
|
|
+ this.pendingCancellations.delete(orderId);
|
|
|
if (cancelled) {
|
|
|
- this.grids.delete(level.index);
|
|
|
this.releaseOrder(orderId, level.clientId);
|
|
|
this.logger.debug({ orderId }, 'Grid order cancel confirmed');
|
|
|
}
|