From 33b540724560278c529368f1c4f2185c35dbbc0d Mon Sep 17 00:00:00 2001 From: discountry Date: Tue, 6 Jan 2026 16:18:54 +0800 Subject: [PATCH] Refactor Maker Points logic by removing dislocation calculations and related UI elements. Update MakerPointsEngine to utilize new price fetching methods and streamline order synchronization. Adjust translations and tests accordingly to reflect these changes. --- src/i18n/index.ts | 4 -- src/strategy/maker-points-engine.ts | 96 +++---------------------- src/strategy/maker-points-logic.test.ts | 10 +-- src/strategy/maker-points-logic.ts | 21 ------ src/ui/MakerPointsApp.tsx | 12 ---- 5 files changed, 11 insertions(+), 132 deletions(-) diff --git a/src/i18n/index.ts b/src/i18n/index.ts index bbb46c0..d665369 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -185,10 +185,6 @@ const translations: Record = { zh: "交易所: {exchange} | 交易对: {symbol} | 买一价: {bid} | 卖一价: {ask} | 点差: {spread}", en: "Exchange: {exchange} | Symbol: {symbol} | Best Bid: {bid} | Best Ask: {ask} | Spread: {spread}", }, - "makerPoints.markLine": { - zh: "标记价: {mark} | 偏离: {bps} bps | 阻断: {block} bps", - en: "Mark: {mark} | Dislocation: {bps} bps | Block: {block} bps", - }, "makerPoints.quoteLine": { zh: "挂单模式: {mode} | BUY {buy} | SELL {sell}", en: "Quote mode: {mode} | BUY {buy} | SELL {sell}", diff --git a/src/strategy/maker-points-engine.ts b/src/strategy/maker-points-engine.ts index 2d3b7be..70d8ab1 100644 --- a/src/strategy/maker-points-engine.ts +++ b/src/strategy/maker-points-engine.ts @@ -13,7 +13,7 @@ import { isOrderActiveStatus } from "../utils/order-status"; import { getPosition, parseSymbolParts } from "../utils/strategy"; import type { PositionSnapshot } from "../utils/strategy"; import { computePositionPnl } from "../utils/pnl"; -import { getTopPrices } from "../utils/price"; +import { getMidOrLast, getTopPrices } from "../utils/price"; import { marketClose, placeOrder, @@ -27,7 +27,7 @@ import { StrategyEventEmitter } from "./common/event-emitter"; import { safeSubscribe, type LogHandler } from "./common/subscriptions"; import { SessionVolumeTracker } from "./common/session-volume"; import { BinanceDepthTracker, type BinanceDepthSnapshot } from "./common/binance-depth"; -import { buildBpsTargets, computeDislocationBps } from "./maker-points-logic"; +import { buildBpsTargets } from "./maker-points-logic"; import { t } from "../i18n"; interface DesiredOrder { @@ -43,9 +43,6 @@ export interface MakerPointsSnapshot { topBid: number | null; topAsk: number | null; spread: number | null; - markPrice: number | null; - dislocationBps: number | null; - blockedBps: number; priceDecimals: number; position: PositionSnapshot; pnl: number; @@ -75,7 +72,6 @@ type MakerPointsListener = (snapshot: MakerPointsSnapshot) => void; const EPS = 1e-5; const INSUFFICIENT_BALANCE_COOLDOWN_MS = 15_000; -const DISLOCATION_THRESHOLD_BPS = 1; const STOP_LOSS_COOLDOWN_MS = 10_000; export class MakerPointsEngine { @@ -108,9 +104,7 @@ export class MakerPointsEngine { private accountUnrealized = 0; private initialOrderSnapshotReady = false; private initialOrderResetDone = false; - private entryPricePendingLogged = false; private lastDesiredSummary: string | null = null; - private lastDislocationBlock = 0; private lastCloseOnly = false; private lastSkipBuy = false; private lastSkipSell = false; @@ -340,35 +334,6 @@ export class MakerPointsEngine { this.lastCloseOnly = closeOnly; } - const markPrice = this.getMarkPrice(); - const hasMarkPrice = Number.isFinite(markPrice) && (markPrice ?? 0) > 0; - if (!hasMarkPrice && !closeOnly) { - if (!this.entryPricePendingLogged) { - this.tradeLog.push("info", "等待标记价格推送…"); - this.entryPricePendingLogged = true; - } - this.emitUpdate(); - return; - } - if (hasMarkPrice) { - this.entryPricePendingLogged = false; - } - - const resolvedMarkPrice = hasMarkPrice ? Number(markPrice) : 0; - const dislocationBps = hasMarkPrice ? computeDislocationBps(resolvedMarkPrice, topBid, topAsk) : null; - const blockBps = - dislocationBps != null && dislocationBps > DISLOCATION_THRESHOLD_BPS - ? Math.floor(dislocationBps + 1e-9) - : 0; - const prevBlockBps = this.lastDislocationBlock; - if (blockBps !== prevBlockBps) { - if (blockBps > 0) { - this.tradeLog.push("warn", `标记价偏离盘口 ${blockBps} bps,撤销该范围挂单`); - } else if (prevBlockBps > 0) { - this.tradeLog.push("info", "标记价偏离已恢复,恢复挂单"); - } - this.lastDislocationBlock = blockBps; - } const binanceSnapshot = this.binanceDepth.getSnapshot(); const rawSkipBuy = Boolean(binanceSnapshot?.skipBuySide); @@ -388,14 +353,12 @@ export class MakerPointsEngine { this.lastSkipSell = skipSell; } - const blockChanged = blockBps !== prevBlockBps; const closeOnlyChanged = closeOnly !== prevCloseOnly; const skipChanged = skipBuy !== prevSkipBuy || skipSell !== prevSkipSell; const repriceNeeded = closeOnly ? true : this.shouldReprice(topBid, topAsk); const shouldRecompute = closeOnly || repriceNeeded || - blockChanged || closeOnlyChanged || skipChanged || this.desiredOrders.length === 0; @@ -406,8 +369,6 @@ export class MakerPointsEngine { : this.buildDesiredOrders({ bid1: topBid, ask1: topAsk, - markPrice: resolvedMarkPrice, - blockBps, skipBuy, skipSell, }) @@ -426,7 +387,7 @@ export class MakerPointsEngine { this.desiredOrders = desired; this.logDesiredOrders(desired); this.sessionVolume.update(position, this.getReferencePrice()); - await this.syncOrders(desired, resolvedMarkPrice, closeOnly); + await this.syncOrders(desired, closeOnly); this.emitUpdate(); } catch (error) { if (isRateLimitError(error)) { @@ -446,12 +407,10 @@ export class MakerPointsEngine { private buildDesiredOrders(params: { bid1: number; ask1: number; - markPrice: number; - blockBps: number; skipBuy: boolean; skipSell: boolean; }): DesiredOrder[] { - const { bid1, ask1, markPrice, blockBps, skipBuy, skipSell } = params; + const { bid1, ask1, skipBuy, skipSell } = params; const amount = Number(this.config.perOrderAmount); if (!Number.isFinite(amount) || amount <= 0) return []; @@ -469,12 +428,7 @@ export class MakerPointsEngine { for (const bps of targets) { if (!skipBuy) { const price = bid1 * (1 - bps / 10000); - const distanceBps = (markPrice - price) / markPrice * 10000; - if ( - Number.isFinite(price) && - price > 0 && - (!Number.isFinite(distanceBps) || distanceBps > blockBps) - ) { + if (Number.isFinite(price) && price > 0) { desired.push({ side: "BUY", price: formatPriceToString(price, priceDecimals), @@ -485,12 +439,7 @@ export class MakerPointsEngine { } if (!skipSell) { const price = ask1 * (1 + bps / 10000); - const distanceBps = (price - markPrice) / markPrice * 10000; - if ( - Number.isFinite(price) && - price > 0 && - (!Number.isFinite(distanceBps) || distanceBps > blockBps) - ) { + if (Number.isFinite(price) && price > 0) { desired.push({ side: "SELL", price: formatPriceToString(price, priceDecimals), @@ -574,7 +523,7 @@ export class MakerPointsEngine { } } - private async syncOrders(targets: DesiredOrder[], markPrice: number, closeOnly: boolean): Promise { + private async syncOrders(targets: DesiredOrder[], closeOnly: boolean): Promise { const availableOrders = this.openOrders.filter((o) => !this.pendingCancelOrders.has(String(o.orderId))); const openOrders = availableOrders.filter((order) => isOrderActiveStatus(order.status)); const { toCancel, toPlace } = makeOrderPlan(openOrders, targets); @@ -626,15 +575,11 @@ export class MakerPointsEngine { target.amount, (type, detail) => this.tradeLog.push(type, detail), target.reduceOnly, - closeOnly - ? undefined - : { - markPrice, - maxPct: this.config.maxCloseSlippagePct, - }, + undefined, { priceTick: this.priceTick, qtyStep: this.qtyStep, + skipDedupe: true, } ); } catch (error) { @@ -783,12 +728,6 @@ export class MakerPointsEngine { const position = getPosition(this.accountSnapshot, this.config.symbol); const { topBid, topAsk } = getTopPrices(this.depthSnapshot); const spread = topBid != null && topAsk != null ? topAsk - topBid : null; - const markPrice = this.getMarkPrice(); - const dislocationBps = computeDislocationBps(markPrice, topBid, topAsk); - const blockBps = - dislocationBps != null && dislocationBps > DISLOCATION_THRESHOLD_BPS - ? Math.floor(dislocationBps + 1e-9) - : 0; const pnl = computePositionPnl(position, topBid, topAsk); return { @@ -797,9 +736,6 @@ export class MakerPointsEngine { topBid, topAsk, spread, - markPrice, - dislocationBps, - blockedBps: blockBps, priceDecimals: this.getPriceDecimals(), position, pnl, @@ -820,19 +756,7 @@ export class MakerPointsEngine { } private getReferencePrice(): number | null { - const mark = Number(this.tickerSnapshot?.markPrice); - if (Number.isFinite(mark) && mark > 0) return mark; - const last = Number(this.tickerSnapshot?.lastPrice); - return Number.isFinite(last) && last > 0 ? last : null; - } - - private getMarkPrice(): number | null { - const mark = Number(this.tickerSnapshot?.markPrice); - if (Number.isFinite(mark) && mark > 0) return mark; - const positionMark = Number(getPosition(this.accountSnapshot, this.config.symbol).markPrice); - if (Number.isFinite(positionMark) && positionMark > 0) return positionMark; - const last = Number(this.tickerSnapshot?.lastPrice); - return Number.isFinite(last) && last > 0 ? last : null; + return getMidOrLast(this.depthSnapshot, this.tickerSnapshot); } private logReadinessBlockers(): void { diff --git a/src/strategy/maker-points-logic.test.ts b/src/strategy/maker-points-logic.test.ts index d9bf757..9dc776e 100644 --- a/src/strategy/maker-points-logic.test.ts +++ b/src/strategy/maker-points-logic.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { buildBpsTargets, computeDislocationBps } from "./maker-points-logic"; +import { buildBpsTargets } from "./maker-points-logic"; describe("maker points target builder", () => { it("builds fixed bps targets per enabled band", () => { @@ -20,11 +20,3 @@ describe("maker points target builder", () => { expect(targets).toEqual([9, 99]); }); }); - -describe("maker points dislocation", () => { - it("computes max bps dislocation from mark vs bid/ask", () => { - const bps = computeDislocationBps(100, 99.97, 100.02); - expect(bps).not.toBeNull(); - expect(Number(bps?.toFixed(2))).toBe(3.0); - }); -}); diff --git a/src/strategy/maker-points-logic.ts b/src/strategy/maker-points-logic.ts index e7dcb03..5136eca 100644 --- a/src/strategy/maker-points-logic.ts +++ b/src/strategy/maker-points-logic.ts @@ -11,24 +11,3 @@ export function buildBpsTargets(config: MakerPointsBandConfig): number[] { if (config.band30To100) targets.push(99); return targets.sort((a, b) => a - b); } - -export function computeDislocationBps( - markPrice: number | null | undefined, - bestBid: number | null | undefined, - bestAsk: number | null | undefined -): number | null { - const mark = Number(markPrice); - if (!Number.isFinite(mark) || mark <= 0) return null; - const distances: number[] = []; - const bid = Number(bestBid); - const ask = Number(bestAsk); - if (Number.isFinite(bid)) { - distances.push(Math.abs(mark - bid) / mark * 10000); - } - if (Number.isFinite(ask)) { - distances.push(Math.abs(ask - mark) / mark * 10000); - } - if (!distances.length) return null; - const max = Math.max(...distances); - return Number.isFinite(max) ? max : null; -} diff --git a/src/ui/MakerPointsApp.tsx b/src/ui/MakerPointsApp.tsx index 01ac2f3..c90dc06 100644 --- a/src/ui/MakerPointsApp.tsx +++ b/src/ui/MakerPointsApp.tsx @@ -79,10 +79,6 @@ export function MakerPointsApp({ onExit }: MakerPointsAppProps) { const spreadDisplay = snapshot.spread != null ? `${formatNumber(snapshot.spread, spreadDigits)} USDT` : "-"; const hasPosition = Math.abs(snapshot.position.positionAmt) > 1e-5; - const markDisplay = Number.isFinite(snapshot.markPrice) ? formatNumber(snapshot.markPrice, priceDigits) : "-"; - const dislocationDisplay = - snapshot.dislocationBps != null ? formatNumber(snapshot.dislocationBps, 2) : "-"; - const blockDisplay = snapshot.blockedBps > 0 ? String(snapshot.blockedBps) : "-"; const sortedOrders = [...snapshot.openOrders].sort((a, b) => (Number(b.updateTime ?? 0) - Number(a.updateTime ?? 0)) || Number(b.orderId) - Number(a.orderId) @@ -153,13 +149,6 @@ export function MakerPointsApp({ onExit }: MakerPointsAppProps) { spread: spreadDisplay, })} - - {t("makerPoints.markLine", { - mark: markDisplay, - bps: dislocationDisplay, - block: blockDisplay, - })} - {t("trend.statusLine", { status: readyStatus })} {t("makerPoints.quoteLine", { @@ -247,4 +236,3 @@ export function MakerPointsApp({ onExit }: MakerPointsAppProps) { ); } -