mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 09:18:08 +00:00
feat(maker-points): enhance configuration for maker points bands
Added new configuration options for maker points bands, including target distances and maximum distance limits. Updated the logic to handle these configurations, ensuring backward compatibility with existing defaults. Enhanced documentation and tests to cover the new features and ensure correct functionality across the system.
This commit is contained in:
@@ -45,70 +45,110 @@ afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
function buildEngine(adapter: StubAdapter, restingBuyPrice: string): MakerPointsEngine {
|
||||
const engine = new MakerPointsEngine(
|
||||
{
|
||||
symbol: "BTC-USD",
|
||||
perOrderAmount: 0.01,
|
||||
closeThreshold: 0,
|
||||
stopLossUsd: 1,
|
||||
refreshIntervalMs: 10_000,
|
||||
maxLogEntries: 20,
|
||||
maxCloseSlippagePct: 0.05,
|
||||
priceTick: 0.1,
|
||||
qtyStep: 0.001,
|
||||
enableBand0To10: true,
|
||||
enableBand10To30: false,
|
||||
enableBand30To100: false,
|
||||
band0To10Amount: 0.01,
|
||||
band10To30Amount: 0.01,
|
||||
band30To100Amount: 0.01,
|
||||
band0To10Bps: 9,
|
||||
band10To30Bps: 29,
|
||||
band30To100Bps: 40,
|
||||
maxDistanceBps: 95,
|
||||
minRepriceBps: 3,
|
||||
bandRepriceRatio: 0.15,
|
||||
slOffsetBps: 2,
|
||||
enableBinanceDepthCancel: false,
|
||||
filterMinDepth: 0,
|
||||
},
|
||||
adapter
|
||||
);
|
||||
|
||||
(engine as any).feedStatus = { account: true, depth: true, ticker: true, orders: true, binance: true };
|
||||
(engine as any).initialOrderSnapshotReady = true;
|
||||
(engine as any).defenseMode = false;
|
||||
(engine as any).reconnectResetPending = false;
|
||||
(engine as any).stopLossProcessing = false;
|
||||
(engine as any).openOrders = [
|
||||
{
|
||||
orderId: 1,
|
||||
clientOrderId: "entry-order",
|
||||
symbol: "BTC-USD",
|
||||
side: "BUY",
|
||||
type: "LIMIT",
|
||||
status: "NEW",
|
||||
price: restingBuyPrice,
|
||||
origQty: "0.01",
|
||||
executedQty: "0",
|
||||
stopPrice: "0",
|
||||
time: Date.now(),
|
||||
updateTime: Date.now(),
|
||||
reduceOnly: false,
|
||||
closePosition: false,
|
||||
},
|
||||
];
|
||||
return engine;
|
||||
}
|
||||
|
||||
// bid1 99.9 / ask1 100.9 → 中值 100.4;0-10 档目标 9 bps,容差 max(3, 9×0.15)=3
|
||||
// 所以保留窗口是距中值 6–12 bps,即 100.28–100.34
|
||||
const DEPTH = {
|
||||
lastUpdateId: 1,
|
||||
bids: [["99.9", "1"]] as Array<[string, string]>,
|
||||
asks: [["100.9", "1"]] as Array<[string, string]>,
|
||||
eventTime: Date.now(),
|
||||
symbol: "BTC-USD",
|
||||
};
|
||||
|
||||
describe("MakerPointsEngine immediate reprice", () => {
|
||||
it("triggers an immediate tick when min reprice bps threshold is reached", () => {
|
||||
it("leaves a quote alone while it is still inside its band tolerance", () => {
|
||||
vi.useFakeTimers();
|
||||
const adapter = new StubAdapter();
|
||||
|
||||
const engine = new MakerPointsEngine(
|
||||
{
|
||||
symbol: "BTC-USD",
|
||||
perOrderAmount: 0.01,
|
||||
closeThreshold: 0,
|
||||
stopLossUsd: 1,
|
||||
refreshIntervalMs: 10_000,
|
||||
maxLogEntries: 20,
|
||||
maxCloseSlippagePct: 0.05,
|
||||
priceTick: 0.1,
|
||||
qtyStep: 0.001,
|
||||
enableBand0To10: true,
|
||||
enableBand10To30: false,
|
||||
enableBand30To100: false,
|
||||
band0To10Amount: 0.01,
|
||||
band10To30Amount: 0.01,
|
||||
band30To100Amount: 0.01,
|
||||
minRepriceBps: 3,
|
||||
enableBinanceDepthCancel: false,
|
||||
filterMinDepth: 0,
|
||||
},
|
||||
adapter
|
||||
);
|
||||
|
||||
(engine as any).feedStatus = { account: true, depth: true, ticker: true, orders: true, binance: true };
|
||||
(engine as any).initialOrderSnapshotReady = true;
|
||||
(engine as any).defenseMode = false;
|
||||
(engine as any).reconnectResetPending = false;
|
||||
(engine as any).stopLossProcessing = false;
|
||||
(engine as any).lastQuoteBid1 = 100;
|
||||
(engine as any).lastQuoteAsk1 = 101;
|
||||
(engine as any).openOrders = [
|
||||
{
|
||||
orderId: 1,
|
||||
clientOrderId: "entry-order",
|
||||
symbol: "BTC-USD",
|
||||
side: "BUY",
|
||||
type: "LIMIT",
|
||||
status: "NEW",
|
||||
price: "99.0",
|
||||
origQty: "0.01",
|
||||
executedQty: "0",
|
||||
stopPrice: "0",
|
||||
time: Date.now(),
|
||||
updateTime: Date.now(),
|
||||
reduceOnly: false,
|
||||
closePosition: false,
|
||||
},
|
||||
];
|
||||
|
||||
// 100.31 距中值 8.96 bps,仍在 9±3 内 —— 不该撤挂,订单得以跨过 3 秒计分门槛
|
||||
const engine = buildEngine(adapter, "100.31");
|
||||
const tickSpy = vi.spyOn(engine as any, "tick").mockResolvedValue(undefined);
|
||||
|
||||
adapter.emitDepth({
|
||||
lastUpdateId: 1,
|
||||
bids: [["99.9", "1"]],
|
||||
asks: [["100.9", "1"]],
|
||||
eventTime: Date.now(),
|
||||
symbol: "BTC-USD",
|
||||
});
|
||||
adapter.emitDepth(DEPTH);
|
||||
|
||||
expect(tickSpy).not.toHaveBeenCalled();
|
||||
engine.stop();
|
||||
});
|
||||
|
||||
it("triggers an immediate tick once the quote drifts out of every band", () => {
|
||||
vi.useFakeTimers();
|
||||
const adapter = new StubAdapter();
|
||||
// 100.25 距中值 14.94 bps,已经掉出 9±3
|
||||
const engine = buildEngine(adapter, "100.25");
|
||||
const tickSpy = vi.spyOn(engine as any, "tick").mockResolvedValue(undefined);
|
||||
|
||||
adapter.emitDepth(DEPTH);
|
||||
|
||||
expect(tickSpy).toHaveBeenCalledTimes(1);
|
||||
engine.stop();
|
||||
});
|
||||
|
||||
it("measures drift against mark price rather than the book mid", () => {
|
||||
vi.useFakeTimers();
|
||||
const adapter = new StubAdapter();
|
||||
// 同一张单:按中值 100.4 算是安全的,但 mark 已经跌到 100.0,
|
||||
// 买单实际挂在 mark 上方 31 bps,随时会被吃 —— 必须立即重挂
|
||||
const engine = buildEngine(adapter, "100.31");
|
||||
(engine as any).tickerSnapshot = { symbol: "BTC-USD", markPrice: "100.0" };
|
||||
const tickSpy = vi.spyOn(engine as any, "tick").mockResolvedValue(undefined);
|
||||
|
||||
adapter.emitDepth(DEPTH);
|
||||
|
||||
expect(tickSpy).toHaveBeenCalledTimes(1);
|
||||
engine.stop();
|
||||
|
||||
Reference in New Issue
Block a user