feat: 更新网格引擎,重构订单管理逻辑,添加持仓水平和关闭目标管理,优化订单计算和曝光对齐处理

This commit is contained in:
discountry
2025-10-07 03:24:09 +08:00
parent ccb23ecf44
commit 5878a3dc0b
2 changed files with 295 additions and 123 deletions
+48 -1
View File
@@ -206,7 +206,7 @@ describe("GridEngine", () => {
expect(nearestBuy).toBeTruthy();
const targetLevel = nearestBuy!.level;
(engine as any).levelExposure.set(targetLevel, baseConfig.orderSize);
(engine as any).longExposure.set(targetLevel, baseConfig.orderSize);
adapter.emitAccount(createAccountSnapshot(baseConfig.symbol, baseConfig.orderSize));
const desiredAfterFill = (engine as any).computeDesiredOrders(150) as Array<{ level: number; side: string }>;
@@ -241,6 +241,53 @@ describe("GridEngine", () => {
engine.stop();
});
it("limits active sell orders by remaining short headroom", () => {
const adapter = new StubAdapter();
const engine = new GridEngine(baseConfig, adapter, { now: () => 0 });
adapter.emitAccount(createAccountSnapshot(baseConfig.symbol, 0));
adapter.emitOrders([]);
const desiredFull = (engine as any).computeDesiredOrders(2.1) as Array<{ level: number; side: string }>;
const sellCountFull = desiredFull.filter((order) => order.side === "SELL").length;
expect(sellCountFull).toBeGreaterThan(0);
const limitedHeadroomConfig = { ...baseConfig, maxPositionSize: baseConfig.orderSize * 2 };
const limitedEngine = new GridEngine(limitedHeadroomConfig, adapter as any, { now: () => 0 });
(limitedEngine as any).shortExposure.set(12, baseConfig.orderSize * 2);
const desiredLimited = (limitedEngine as any).computeDesiredOrders(2.1) as Array<{ level: number; side: string }>;
const sellCountLimited = desiredLimited.filter((order) => order.side === "SELL").length;
expect(sellCountLimited).toBeLessThanOrEqual(1);
engine.stop();
limitedEngine.stop();
});
it("places reduce-only orders to close existing exposures", () => {
const adapter = new StubAdapter();
const engine = new GridEngine(baseConfig, adapter, { now: () => 0 });
adapter.emitAccount(createAccountSnapshot(baseConfig.symbol, baseConfig.orderSize));
adapter.emitOrders([]);
const buyLevel = (engine as any).buyLevelIndices.slice(-1)[0];
(engine as any).longExposure.set(buyLevel, baseConfig.orderSize);
const desired = (engine as any).computeDesiredOrders(2.05) as Array<{
level: number;
side: string;
reduceOnly: boolean;
amount: number;
}>;
const closeOrder = desired.find((order) => order.reduceOnly && order.side === "SELL");
expect(closeOrder).toBeTruthy();
expect(closeOrder!.amount).toBeCloseTo(baseConfig.orderSize);
engine.stop();
});
it("halts the grid and closes positions when stop loss triggers", async () => {
const adapter = new StubAdapter();
const engine = new GridEngine(baseConfig, adapter, { now: () => 0 });