mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 17:28:08 +00:00
Refactor MakerPoints configuration and depth handling
- Renamed `band0To10MinDepth` to `filterMinDepth` in `config.ts` for clarity. - Updated `MakerPointsEngine` to utilize the new `filterMinDepth` for depth checks across all bands. - Introduced a method to track depth status changes, enhancing order placement logic based on market depth. - Improved logging for depth-related order skips to provide clearer insights into trading decisions.
This commit is contained in:
+3
-3
@@ -199,8 +199,8 @@ export interface MakerPointsConfig {
|
|||||||
minRepriceBps: number;
|
minRepriceBps: number;
|
||||||
/** 是否根据 Binance 盘口深度失衡自动取消单边挂单,默认 true */
|
/** 是否根据 Binance 盘口深度失衡自动取消单边挂单,默认 true */
|
||||||
enableBinanceDepthCancel: boolean;
|
enableBinanceDepthCancel: boolean;
|
||||||
/** 0-10 bps 档位最小深度阈值 (BTC),盘口到目标价之间的挂单量低于此值则跳过该档位,默认 1 */
|
/** 各档位最小深度阈值 (BTC),盘口到目标价之间的挂单量低于此值则跳过该档位,默认 1 */
|
||||||
band0To10MinDepth: number;
|
filterMinDepth: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultMakerPointsAmount = parseNumber(process.env.MAKER_POINTS_ORDER_AMOUNT, parseNumber(process.env.TRADE_AMOUNT, 0.001));
|
const defaultMakerPointsAmount = parseNumber(process.env.MAKER_POINTS_ORDER_AMOUNT, parseNumber(process.env.TRADE_AMOUNT, 0.001));
|
||||||
@@ -226,7 +226,7 @@ export const makerPointsConfig: MakerPointsConfig = {
|
|||||||
band30To100Amount: parseNumber(process.env.MAKER_POINTS_BAND_30_100_AMOUNT, defaultMakerPointsAmount),
|
band30To100Amount: parseNumber(process.env.MAKER_POINTS_BAND_30_100_AMOUNT, defaultMakerPointsAmount),
|
||||||
minRepriceBps: parseNumber(process.env.MAKER_POINTS_MIN_REPRICE_BPS, 3),
|
minRepriceBps: parseNumber(process.env.MAKER_POINTS_MIN_REPRICE_BPS, 3),
|
||||||
enableBinanceDepthCancel: parseBoolean(process.env.MAKER_POINTS_BINANCE_DEPTH_CANCEL, true),
|
enableBinanceDepthCancel: parseBoolean(process.env.MAKER_POINTS_BINANCE_DEPTH_CANCEL, true),
|
||||||
band0To10MinDepth: parseNumber(process.env.MAKER_POINTS_BAND_0_10_MIN_DEPTH, 1),
|
filterMinDepth: parseNumber(process.env.MAKER_POINTS_FILTER_MIN_DEPTH, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface BasisArbConfig {
|
export interface BasisArbConfig {
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ export class MakerPointsEngine {
|
|||||||
private lastSkipSell = false;
|
private lastSkipSell = false;
|
||||||
private lastQuoteBid1: number | null = null;
|
private lastQuoteBid1: number | null = null;
|
||||||
private lastQuoteAsk1: number | null = null;
|
private lastQuoteAsk1: number | null = null;
|
||||||
|
// 跟踪各档位深度是否足够的状态 (按 bps 值索引)
|
||||||
|
private lastDepthOkStatus: Record<number, { buy: boolean; sell: boolean }> = {};
|
||||||
|
|
||||||
private readinessLogged = {
|
private readinessLogged = {
|
||||||
account: false,
|
account: false,
|
||||||
@@ -489,11 +491,13 @@ export class MakerPointsEngine {
|
|||||||
const closeOnlyChanged = closeOnly !== prevCloseOnly;
|
const closeOnlyChanged = closeOnly !== prevCloseOnly;
|
||||||
const skipChanged = skipBuy !== prevSkipBuy || skipSell !== prevSkipSell;
|
const skipChanged = skipBuy !== prevSkipBuy || skipSell !== prevSkipSell;
|
||||||
const repriceNeeded = closeOnly ? true : this.shouldReprice(topBid, topAsk);
|
const repriceNeeded = closeOnly ? true : this.shouldReprice(topBid, topAsk);
|
||||||
|
const depthStatusChanged = this.checkDepthStatusChanged(depth, topBid, topAsk);
|
||||||
const shouldRecompute =
|
const shouldRecompute =
|
||||||
closeOnly ||
|
closeOnly ||
|
||||||
repriceNeeded ||
|
repriceNeeded ||
|
||||||
closeOnlyChanged ||
|
closeOnlyChanged ||
|
||||||
skipChanged ||
|
skipChanged ||
|
||||||
|
depthStatusChanged ||
|
||||||
this.desiredOrders.length === 0;
|
this.desiredOrders.length === 0;
|
||||||
|
|
||||||
const desired = shouldRecompute
|
const desired = shouldRecompute
|
||||||
@@ -557,7 +561,7 @@ export class MakerPointsEngine {
|
|||||||
|
|
||||||
const priceDecimals = this.getPriceDecimals();
|
const priceDecimals = this.getPriceDecimals();
|
||||||
const desired: DesiredOrder[] = [];
|
const desired: DesiredOrder[] = [];
|
||||||
const minDepth = this.config.band0To10MinDepth;
|
const minDepth = this.config.filterMinDepth;
|
||||||
|
|
||||||
const getAmountForBps = (bps: number): number => {
|
const getAmountForBps = (bps: number): number => {
|
||||||
if (bps <= 10) return Number(this.config.band0To10Amount);
|
if (bps <= 10) return Number(this.config.band0To10Amount);
|
||||||
@@ -569,20 +573,18 @@ export class MakerPointsEngine {
|
|||||||
const amount = getAmountForBps(bps);
|
const amount = getAmountForBps(bps);
|
||||||
if (!Number.isFinite(amount) || amount <= 0) continue;
|
if (!Number.isFinite(amount) || amount <= 0) continue;
|
||||||
|
|
||||||
// 对于 0-10 bps 档位,检查深度是否足够
|
// 所有档位都检查深度
|
||||||
const isBand0To10 = bps <= 10;
|
const shouldCheckDepth = minDepth > 0;
|
||||||
|
|
||||||
if (!skipBuy) {
|
if (!skipBuy) {
|
||||||
const price = bid1 * (1 - bps / 10000);
|
const price = bid1 * (1 - bps / 10000);
|
||||||
if (Number.isFinite(price) && price > 0) {
|
if (Number.isFinite(price) && price > 0) {
|
||||||
// 0-10 bps 档位需要检查深度
|
if (shouldCheckDepth) {
|
||||||
if (isBand0To10 && minDepth > 0) {
|
|
||||||
const depthQty = getDepthBetweenPrices(depth, "BUY", price);
|
const depthQty = getDepthBetweenPrices(depth, "BUY", price);
|
||||||
if (depthQty < minDepth) {
|
if (depthQty < minDepth) {
|
||||||
this.logThinDepthSkip("BUY", bps, depthQty, minDepth);
|
this.logThinDepthSkip("BUY", bps, depthQty, minDepth);
|
||||||
// 跳过该档位的 BUY 挂单
|
|
||||||
} else {
|
} else {
|
||||||
this.resetThinDepthSkip("BUY");
|
this.resetThinDepthSkip("BUY", bps);
|
||||||
desired.push({
|
desired.push({
|
||||||
side: "BUY",
|
side: "BUY",
|
||||||
price: formatPriceToString(price, priceDecimals),
|
price: formatPriceToString(price, priceDecimals),
|
||||||
@@ -603,14 +605,12 @@ export class MakerPointsEngine {
|
|||||||
if (!skipSell) {
|
if (!skipSell) {
|
||||||
const price = ask1 * (1 + bps / 10000);
|
const price = ask1 * (1 + bps / 10000);
|
||||||
if (Number.isFinite(price) && price > 0) {
|
if (Number.isFinite(price) && price > 0) {
|
||||||
// 0-10 bps 档位需要检查深度
|
if (shouldCheckDepth) {
|
||||||
if (isBand0To10 && minDepth > 0) {
|
|
||||||
const depthQty = getDepthBetweenPrices(depth, "SELL", price);
|
const depthQty = getDepthBetweenPrices(depth, "SELL", price);
|
||||||
if (depthQty < minDepth) {
|
if (depthQty < minDepth) {
|
||||||
this.logThinDepthSkip("SELL", bps, depthQty, minDepth);
|
this.logThinDepthSkip("SELL", bps, depthQty, minDepth);
|
||||||
// 跳过该档位的 SELL 挂单
|
|
||||||
} else {
|
} else {
|
||||||
this.resetThinDepthSkip("SELL");
|
this.resetThinDepthSkip("SELL", bps);
|
||||||
desired.push({
|
desired.push({
|
||||||
side: "SELL",
|
side: "SELL",
|
||||||
price: formatPriceToString(price, priceDecimals),
|
price: formatPriceToString(price, priceDecimals),
|
||||||
@@ -633,6 +633,49 @@ export class MakerPointsEngine {
|
|||||||
return desired;
|
return desired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查各档位的深度状态是否发生变化
|
||||||
|
* 当深度从足够变为不足,或从不足变为足够时,需要触发重新计算
|
||||||
|
*/
|
||||||
|
private checkDepthStatusChanged(
|
||||||
|
depth: AsterDepth | null,
|
||||||
|
bid1: number,
|
||||||
|
ask1: number
|
||||||
|
): boolean {
|
||||||
|
const minDepth = this.config.filterMinDepth;
|
||||||
|
if (minDepth <= 0) return false;
|
||||||
|
|
||||||
|
// 获取启用的所有档位
|
||||||
|
const targets = buildBpsTargets({
|
||||||
|
band0To10: this.config.enableBand0To10,
|
||||||
|
band10To30: this.config.enableBand10To30,
|
||||||
|
band30To100: this.config.enableBand30To100,
|
||||||
|
});
|
||||||
|
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
for (const bps of targets) {
|
||||||
|
const buyPrice = bid1 * (1 - bps / 10000);
|
||||||
|
const sellPrice = ask1 * (1 + bps / 10000);
|
||||||
|
|
||||||
|
const buyDepthQty = getDepthBetweenPrices(depth, "BUY", buyPrice);
|
||||||
|
const sellDepthQty = getDepthBetweenPrices(depth, "SELL", sellPrice);
|
||||||
|
const currentBuyOk = buyDepthQty >= minDepth;
|
||||||
|
const currentSellOk = sellDepthQty >= minDepth;
|
||||||
|
|
||||||
|
const lastStatus = this.lastDepthOkStatus[bps];
|
||||||
|
if (lastStatus) {
|
||||||
|
if (lastStatus.buy !== currentBuyOk || lastStatus.sell !== currentSellOk) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastDepthOkStatus[bps] = { buy: currentBuyOk, sell: currentSellOk };
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
private buildCloseOnlyOrders(
|
private buildCloseOnlyOrders(
|
||||||
position: PositionSnapshot,
|
position: PositionSnapshot,
|
||||||
bid1: number,
|
bid1: number,
|
||||||
@@ -1167,44 +1210,34 @@ export class MakerPointsEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lastThinDepthSkipBuy = false;
|
// 跟踪各档位的深度跳过状态 (按 bps 和 side 索引)
|
||||||
private lastThinDepthSkipSell = false;
|
private thinDepthSkipStatus: Record<string, boolean> = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录因深度不足而跳过挂单的日志
|
* 记录因深度不足而跳过挂单的日志
|
||||||
* 使用状态跟踪避免重复日志
|
* 使用状态跟踪避免重复日志
|
||||||
*/
|
*/
|
||||||
private logThinDepthSkip(side: "BUY" | "SELL", bps: number, depthQty: number, minDepth: number): void {
|
private logThinDepthSkip(side: "BUY" | "SELL", bps: number, depthQty: number, minDepth: number): void {
|
||||||
const isBuy = side === "BUY";
|
const key = `${side}_${bps}`;
|
||||||
const alreadySkipped = isBuy ? this.lastThinDepthSkipBuy : this.lastThinDepthSkipSell;
|
const alreadySkipped = this.thinDepthSkipStatus[key];
|
||||||
|
|
||||||
if (!alreadySkipped) {
|
if (!alreadySkipped) {
|
||||||
this.tradeLog.push(
|
this.tradeLog.push(
|
||||||
"info",
|
"info",
|
||||||
`跳过 ${side} ${bps}bps 挂单: 深度 ${depthQty.toFixed(4)} BTC < ${minDepth} BTC`
|
`跳过 ${side} ${bps}bps 挂单: 深度 ${depthQty.toFixed(4)} BTC < ${minDepth} BTC`
|
||||||
);
|
);
|
||||||
if (isBuy) {
|
this.thinDepthSkipStatus[key] = true;
|
||||||
this.lastThinDepthSkipBuy = true;
|
|
||||||
} else {
|
|
||||||
this.lastThinDepthSkipSell = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当深度恢复时重置跳过状态,允许下次再次记录
|
* 当深度恢复时重置跳过状态,允许下次再次记录
|
||||||
*/
|
*/
|
||||||
private resetThinDepthSkip(side: "BUY" | "SELL"): void {
|
private resetThinDepthSkip(side: "BUY" | "SELL", bps: number): void {
|
||||||
if (side === "BUY") {
|
const key = `${side}_${bps}`;
|
||||||
if (this.lastThinDepthSkipBuy) {
|
if (this.thinDepthSkipStatus[key]) {
|
||||||
this.tradeLog.push("info", "BUY 深度恢复,继续挂单");
|
this.tradeLog.push("info", `${side} ${bps}bps 深度恢复,继续挂单`);
|
||||||
this.lastThinDepthSkipBuy = false;
|
this.thinDepthSkipStatus[key] = false;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.lastThinDepthSkipSell) {
|
|
||||||
this.tradeLog.push("info", "SELL 深度恢复,继续挂单");
|
|
||||||
this.lastThinDepthSkipSell = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user