diff --git a/src/config.ts b/src/config.ts index fe4071a..1c3d679 100644 --- a/src/config.ts +++ b/src/config.ts @@ -199,7 +199,7 @@ export interface MakerPointsConfig { minRepriceBps: number; /** 是否根据 Binance 盘口深度失衡自动取消单边挂单,默认 true */ enableBinanceDepthCancel: boolean; - /** 各档位最小深度阈值 (BTC),盘口到目标价之间的挂单量低于此值则跳过该档位,默认 1 */ + /** 各档位最小深度阈值 (BTC),盘口到目标价之间的挂单量低于此值则跳过该档位,默认 50 */ filterMinDepth: number; } @@ -226,7 +226,7 @@ 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), - filterMinDepth: parseNumber(process.env.MAKER_POINTS_FILTER_MIN_DEPTH, 1), + filterMinDepth: parseNumber(process.env.MAKER_POINTS_FILTER_MIN_DEPTH, 50), }; export interface BasisArbConfig { diff --git a/src/i18n/index.ts b/src/i18n/index.ts index c4dddad..2855234 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -202,6 +202,10 @@ const translations: Record = { zh: "Binance 深度: 买10 {buy} | 卖10 {sell} | 状态: {status}", en: "Binance depth: bid10 {buy} | ask10 {sell} | Status: {status}", }, + "makerPoints.bandDepthLine": { + zh: "StandX 档位 {band}bps 深度: 买 {buy} | 卖 {sell}", + en: "StandX band {band}bps depth: buy {buy} | sell {sell}", + }, "makerPoints.mode.closeOnly": { zh: "平仓", en: "Close only" }, "makerPoints.mode.normal": { zh: "正常", en: "Normal" }, "makerPoints.feed.binance": { zh: "Binance", en: "Binance" }, diff --git a/src/strategy/common/binance-depth.ts b/src/strategy/common/binance-depth.ts index b436b85..587d877 100644 --- a/src/strategy/common/binance-depth.ts +++ b/src/strategy/common/binance-depth.ts @@ -65,6 +65,7 @@ export class BinanceDepthTracker { baseUrl?: string; levels?: number; ratio?: number; + speedMs?: number; logger?: (context: string, error: unknown) => void; } ) {} @@ -229,7 +230,9 @@ export class BinanceDepthTracker { private buildUrl(): string { const base = this.options?.baseUrl ?? DEFAULT_BASE_URL; - const stream = `${this.symbol.toLowerCase()}@depth10@100ms`; + const levels = this.options?.levels ?? 10; + const speed = this.options?.speedMs ?? 100; + const stream = `${this.symbol.toLowerCase()}@depth${levels}@${speed}ms`; return `${base}/${stream}`; } diff --git a/src/strategy/maker-points-engine.ts b/src/strategy/maker-points-engine.ts index ac449c4..8309722 100644 --- a/src/strategy/maker-points-engine.ts +++ b/src/strategy/maker-points-engine.ts @@ -71,6 +71,13 @@ export interface MakerPointsSnapshot { binance: boolean; }; binanceDepth: BinanceDepthSnapshot | null; + bandDepths: Array<{ + band: "0-10" | "10-30" | "30-100"; + bps: number; + buyDepth: number | null; + sellDepth: number | null; + enabled: boolean; + }>; quoteStatus: { closeOnly: boolean; skipBuy: boolean; @@ -184,8 +191,9 @@ export class MakerPointsEngine { this.qtyStep = Math.max(1e-9, this.config.qtyStep); this.binanceDepth = new BinanceDepthTracker(resolveBinanceSymbol(this.config.symbol), { baseUrl: process.env.BINANCE_WS_URL, - levels: 10, - ratio: 3, + levels: 20, + ratio: 5, + speedMs: 500, logger: (context, error) => { this.tradeLog.push("warn", `Binance ${context} 异常: ${extractMessage(error)}`); }, @@ -1190,6 +1198,7 @@ export class MakerPointsEngine { const { topBid, topAsk } = getTopPrices(this.depthSnapshot); const spread = topBid != null && topAsk != null ? topAsk - topBid : null; const pnl = computePositionPnl(position, topBid, topAsk); + const bandDepths = this.computeBandDepths(topBid, topAsk); return { ready: this.isReady(), @@ -1208,6 +1217,7 @@ export class MakerPointsEngine { lastUpdated: Date.now(), feedStatus: { ...this.feedStatus }, binanceDepth: this.binanceDepth.getSnapshot(), + bandDepths, quoteStatus: { closeOnly: this.lastCloseOnly, skipBuy: this.lastSkipBuy, @@ -1216,6 +1226,26 @@ export class MakerPointsEngine { }; } + private computeBandDepths(topBid: number | null, topAsk: number | null): MakerPointsSnapshot["bandDepths"] { + const bands: MakerPointsSnapshot["bandDepths"] = [ + { band: "0-10", bps: 9, buyDepth: null, sellDepth: null, enabled: this.config.enableBand0To10 }, + { band: "10-30", bps: 29, buyDepth: null, sellDepth: null, enabled: this.config.enableBand10To30 }, + { band: "30-100", bps: 99, buyDepth: null, sellDepth: null, enabled: this.config.enableBand30To100 }, + ]; + + if (!this.depthSnapshot || topBid == null || topAsk == null) { + return bands; + } + + return bands.map((band) => { + const buyPrice = topBid * (1 - band.bps / 10000); + const sellPrice = topAsk * (1 + band.bps / 10000); + const buyDepth = getDepthBetweenPrices(this.depthSnapshot, "BUY", buyPrice); + const sellDepth = getDepthBetweenPrices(this.depthSnapshot, "SELL", sellPrice); + return { ...band, buyDepth, sellDepth }; + }); + } + private getReferencePrice(): number | null { return getMidOrLast(this.depthSnapshot, this.tickerSnapshot); } diff --git a/src/ui/MakerPointsApp.tsx b/src/ui/MakerPointsApp.tsx index c90dc06..c144446 100644 --- a/src/ui/MakerPointsApp.tsx +++ b/src/ui/MakerPointsApp.tsx @@ -135,6 +135,7 @@ export function MakerPointsApp({ onExit }: MakerPointsAppProps) { ? t("offset.imbalance.sell") : t("offset.imbalance.balanced"); const quoteMode = snapshot.quoteStatus.closeOnly ? t("makerPoints.mode.closeOnly") : t("makerPoints.mode.normal"); + const formatDepth = (value: number | null) => (value == null ? "-" : formatNumber(value, 4)); return ( @@ -164,6 +165,15 @@ export function MakerPointsApp({ onExit }: MakerPointsAppProps) { status: imbalanceLabel, })} + {snapshot.bandDepths.map((band) => ( + + {t("makerPoints.bandDepthLine", { + band: band.band, + buy: formatDepth(band.buyDepth), + sell: formatDepth(band.sellDepth), + })} + + ))} {t("maker.dataStatus")} {feedEntries.map((entry, index) => (