Add Binance depth monitoring configuration to MakerPoints

- Introduced new environment variables `MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS` and `MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO` to configure Binance depth monitoring.
- Updated `MakerPointsConfig` interface and implementation to include these new parameters.
- Enhanced translations to reflect dynamic depth window information in the UI.
- Added tests to validate the new configuration options and their integration into the MakerPoints engine.
This commit is contained in:
discountry
2026-02-07 23:58:01 +08:00
parent 858b2f304b
commit 61e6e4cdde
8 changed files with 138 additions and 5 deletions
+4
View File
@@ -59,6 +59,10 @@ MAKER_REFRESH_INTERVAL_MS=500 # Maker refresh cadence (ms)
MAKER_MAX_CLOSE_SLIPPAGE_PCT=0.05 # Maker close slippage guard (fallbacks to MAX_CLOSE_SLIPPAGE_PCT)
MAKER_PRICE_TICK=0.1 # Maker price tick size (defaults to PRICE_TICK)
# Maker-points Binance depth imbalance monitor
MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS=5 # Binance depth monitor window around best bid/ask (bps)
MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO=8 # Imbalance threshold ratio (e.g. 8 => one side >= 8x)
# Grid strategy defaults
GRID_LOWER_PRICE=25000 # Grid lower bound price (quote currency)
GRID_UPPER_PRICE=35000 # Grid upper bound price
+6
View File
@@ -132,6 +132,8 @@ MAKER_POINTS_ORDER_AMOUNT=0.01
MAKER_POINTS_CLOSE_THRESHOLD=0.1
MAKER_POINTS_STOP_LOSS_USD=0
MAKER_POINTS_MIN_REPRICE_BPS=3
MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS=5
MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO=8
# ===== 挂单档位开关 =====
MAKER_POINTS_BAND_0_10=true
@@ -173,6 +175,8 @@ MAKER_POINTS_ORDER_AMOUNT=0.01
MAKER_POINTS_CLOSE_THRESHOLD=0.1
MAKER_POINTS_STOP_LOSS_USD=0
MAKER_POINTS_MIN_REPRICE_BPS=3
MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS=5
MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO=8
MAKER_POINTS_BAND_0_10=true
MAKER_POINTS_BAND_10_30=true
MAKER_POINTS_BAND_30_100=true
@@ -214,6 +218,8 @@ bun run pm2:start:maker-points
| `MAKER_POINTS_ORDER_AMOUNT` | 每笔挂单数量 | 建议 `0.01` 起步 |
| `MAKER_POINTS_CLOSE_THRESHOLD` | 持仓达到多少开始平仓 | 设为 `0` 表示不自动平仓 |
| `MAKER_POINTS_STOP_LOSS_USD` | 亏损多少美元强制平仓 | 设为 `0` 表示关闭止损 |
| `MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS` | Binance 失衡检测窗口(bps | 默认 `5` |
| `MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO` | Binance 失衡比例阈值 | 默认 `8` |
| `MAKER_POINTS_BAND_*` | 三个挂单档位的开关 | 全部 `true` 即可 |
| `STANDX_TOKEN_CREATE_DATE` | Token 创建日期 | 推荐配置,格式 YYYY-MM-DD |
| `STANDX_TOKEN_VALIDITY_DAYS` | Token 有效期天数 | 推荐配置,与创建日期配合使用 |
+6
View File
@@ -227,6 +227,10 @@ export interface MakerPointsConfig {
minRepriceBps: number;
/** 是否根据 Binance 盘口深度失衡自动取消单边挂单,默认 true */
enableBinanceDepthCancel: boolean;
/** Binance 深度监控窗口(bps),默认 5 */
binanceDepthWindowBps?: number;
/** Binance 深度失衡比例阈值,默认 8 */
binanceDepthImbalanceRatio?: number;
/** 各档位最小深度阈值 (BTC),盘口到目标价之间的挂单量低于此值则跳过该档位,默认 10 */
filterMinDepth: number;
}
@@ -254,6 +258,8 @@ export const makerPointsConfig: MakerPointsConfig = {
band30To100Amount: parseNumber(process.env.MAKER_POINTS_BAND_30_100_AMOUNT, defaultMakerPointsAmount),
minRepriceBps: parseNumber(process.env.MAKER_POINTS_MIN_REPRICE_BPS, 3),
enableBinanceDepthCancel: parseBoolean(process.env.MAKER_POINTS_BINANCE_DEPTH_CANCEL, true),
binanceDepthWindowBps: parseNumber(process.env.MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS, 5),
binanceDepthImbalanceRatio: parseNumber(process.env.MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO, 8),
filterMinDepth: parseNumber(process.env.MAKER_POINTS_FILTER_MIN_DEPTH, 10),
};
+2 -2
View File
@@ -248,8 +248,8 @@ const translations: Record<string, TranslationEntry> = {
en: "Quote mode: {mode} | BUY {buy} | SELL {sell}",
},
"makerPoints.binanceLine": {
zh: "Binance 深度(±9bps): 买 {buy} 卖 {sell} 状态: {status}",
en: "Binance depth (±9bps): bid {buy} | ask {sell} | Status: {status}",
zh: "Binance 深度(±{windowBps}bps): 买 {buy} 卖 {sell} 状态: {status}",
en: "Binance depth (±{windowBps}bps): bid {buy} | ask {sell} | Status: {status}",
},
"makerPoints.bandDepthLine": {
zh: "StandX 档位 {band}bps 深度: 买 {buy} 卖 {sell}",
+6 -2
View File
@@ -206,8 +206,12 @@ export class MakerPointsEngine {
baseUrl: process.env.BINANCE_SPOT_WS_URL ?? process.env.BINANCE_WS_URL,
restBaseUrl: process.env.BINANCE_REST_URL,
levels: 20,
ratio: 2,
depthWindowBps: 9,
ratio: Number.isFinite(this.config.binanceDepthImbalanceRatio)
? Math.max(1.01, Number(this.config.binanceDepthImbalanceRatio))
: 8,
depthWindowBps: Number.isFinite(this.config.binanceDepthWindowBps)
? Math.max(1, Number(this.config.binanceDepthWindowBps))
: 5,
speedMs: 100,
logger: (context, error) => {
this.tradeLog.push("warn", `Binance ${context} 异常: ${extractMessage(error)}`);
+1
View File
@@ -162,6 +162,7 @@ export function MakerPointsApp({ onExit }: MakerPointsAppProps) {
{t("makerPoints.binanceLine", {
buy: formatNumber(snapshot.binanceDepth?.buySum ?? 0, 4),
sell: formatNumber(snapshot.binanceDepth?.sellSum ?? 0, 4),
windowBps: snapshot.binanceDepth?.windowBps ?? 5,
status: imbalanceLabel,
})}
</Text>
+4 -1
View File
@@ -28,10 +28,14 @@ describe("config env parsing", () => {
process.env.EXCHANGE = "standx";
process.env.MAKER_POINTS_STOP_LOSS_USD = "1 # comment";
process.env.MAKER_POINTS_CLOSE_THRESHOLD = "2 ; comment";
process.env.MAKER_POINTS_BINANCE_DEPTH_WINDOW_BPS = "6 # comment";
process.env.MAKER_POINTS_BINANCE_DEPTH_IMBALANCE_RATIO = "9 ; comment";
const { makerPointsConfig } = await loadConfig();
expect(makerPointsConfig.stopLossUsd).toBe(1);
expect(makerPointsConfig.closeThreshold).toBe(2);
expect(makerPointsConfig.binanceDepthWindowBps).toBe(6);
expect(makerPointsConfig.binanceDepthImbalanceRatio).toBe(9);
});
it("parses boolean maker-points env values with inline comments", async () => {
@@ -42,4 +46,3 @@ describe("config env parsing", () => {
expect(makerPointsConfig.enableBand10To30).toBe(false);
});
});
@@ -0,0 +1,109 @@
import { describe, expect, it } from "vitest";
import type { ExchangeAdapter } from "../src/exchanges/adapter";
import type { AsterAccountSnapshot, AsterDepth, AsterKline, AsterOrder, AsterTicker } from "../src/exchanges/types";
import { t } from "../src/i18n";
import { MakerPointsEngine } from "../src/strategy/maker-points-engine";
class StubAdapter implements ExchangeAdapter {
id = "standx";
supportsTrailingStops(): boolean {
return false;
}
watchAccount(_cb: (snapshot: AsterAccountSnapshot) => void): void {}
watchOrders(_cb: (orders: AsterOrder[]) => void): void {}
watchDepth(_symbol: string, _cb: (depth: AsterDepth) => void): void {}
watchTicker(_symbol: string, _cb: (ticker: AsterTicker) => void): void {}
watchKlines(_symbol: string, _interval: string, _cb: (klines: AsterKline[]) => void): void {}
async createOrder(): Promise<AsterOrder> {
throw new Error("not implemented");
}
async cancelOrder(): Promise<void> {}
async cancelOrders(): Promise<void> {}
async cancelAllOrders(): Promise<void> {}
}
describe("MakerPointsEngine Binance depth monitor config", () => {
it("uses default 5bps window and ratio 8", () => {
const engine = new MakerPointsEngine(
{
symbol: "BTC-USD",
perOrderAmount: 0.01,
closeThreshold: 0,
stopLossUsd: 1,
refreshIntervalMs: 500,
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: true,
filterMinDepth: 0,
},
new StubAdapter()
);
const trackerOptions = ((engine as any).binanceDepth as { options?: { depthWindowBps?: number; ratio?: number } })
.options;
expect(trackerOptions?.depthWindowBps).toBe(5);
expect(trackerOptions?.ratio).toBe(8);
engine.stop();
});
it("uses configured window and ratio", () => {
const engine = new MakerPointsEngine(
{
symbol: "BTC-USD",
perOrderAmount: 0.01,
closeThreshold: 0,
stopLossUsd: 1,
refreshIntervalMs: 500,
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: true,
binanceDepthWindowBps: 7,
binanceDepthImbalanceRatio: 11,
filterMinDepth: 0,
},
new StubAdapter()
);
const trackerOptions = ((engine as any).binanceDepth as { options?: { depthWindowBps?: number; ratio?: number } })
.options;
expect(trackerOptions?.depthWindowBps).toBe(7);
expect(trackerOptions?.ratio).toBe(11);
engine.stop();
});
it("renders binance depth line with dynamic window bps", () => {
const line = t(
"makerPoints.binanceLine",
{ windowBps: 5, buy: "1.23", sell: "1.11", status: "Balanced" },
"en"
);
expect(line).toContain("±5bps");
});
});