From c4b8d4421545cc224b8a3fbbeff32fdcd6271a44 Mon Sep 17 00:00:00 2001 From: 0112020179 Date: Sun, 6 Sep 2026 23:15:21 +0800 Subject: [PATCH] fix(intraday): hide unavailable average line --- docs/plugin-development.md | 5 ++++- frontend/src/components/EChartsIntraday.tsx | 4 ++-- frontend/src/components/EChartsMultiDayIntraday.tsx | 9 +++++---- frontend/src/lib/intraday-chart.ts | 6 +++--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/plugin-development.md b/docs/plugin-development.md index 9fe8e9d..1edad0c 100644 --- a/docs/plugin-development.md +++ b/docs/plugin-development.md @@ -151,7 +151,7 @@ class MyProvider: def get_minute(self, symbols, start_time, end_time, asset_type="stock", on_chunk_done=None, freq="1m") -> pl.DataFrame: - """分钟K: [symbol, datetime(北京墙钟), open, high, low, close, volume, amount]""" + """分钟K: [symbol, datetime(北京墙钟), open, high, low, close, volume, amount(元, 可空)]""" def get_intraday_batch(self, symbols, count=300, asset_type="stock") -> pl.DataFrame: """(声明 full_minute 数据集时实现) 全量分钟修复轮: 给定标的当日 1 分钟K, @@ -208,6 +208,9 @@ provider 不应自行切换或回退到其他数据源。 (09:30–11:30 / 13:00–15:00)映射每根K线,UTC 口径的帧会导致全部点位落在时轴外、 分时图空白。 +`amount` 单位为元;数据源无法提供可靠的分钟成交额时应返回 `null`,不得伪造。 +成交额缺失后无法继续计算累计成交均价,前端会停止绘制后续均价线并显示 `—`。 + 入口守卫(`kline_sync._enforce_minute_beijing_wallclock`)对所有分钟源强制归一: 带时区 → 自动换算成北京墙钟;naive 但整体呈 UTC 特征(如 01:30)→ 自动 +8 纠偏并 记日志;完全无法识别的口径 → 拒收并回退 TickFlow。契约仍要求源头写对,守卫只是兜底。 diff --git a/frontend/src/components/EChartsIntraday.tsx b/frontend/src/components/EChartsIntraday.tsx index 8b777da..e3f76e9 100644 --- a/frontend/src/components/EChartsIntraday.tsx +++ b/frontend/src/components/EChartsIntraday.tsx @@ -63,7 +63,7 @@ function getLimitPrices(prevClose: number, priceLimit?: PriceLimitInfo): { return { limitUp, limitDown, upPct, downPct } } -function buildOption(data: MinuteKlineRow[], prevClose: number | undefined, avgPrices: number[], lineColor: string, areaColor: string, yMode: YMode, ct: ChartTheme, priceLimit?: PriceLimitInfo, showLimitLines = true, showAvgLine = true, priceLines: Props['priceLines'] = []): EChartsOption { +function buildOption(data: MinuteKlineRow[], prevClose: number | undefined, avgPrices: (number | null)[], lineColor: string, areaColor: string, yMode: YMode, ct: ChartTheme, priceLimit?: PriceLimitInfo, showLimitLines = true, showAvgLine = true, priceLines: Props['priceLines'] = []): EChartsOption { // 将数据映射到全天时间轴上的正确位置 const timeIndexMap = new Map(FULL_DAY_TIMES.map((t, i) => [t, i])) const closes = new Array(FULL_DAY_TIMES.length).fill(null) as (number | null)[] @@ -601,7 +601,7 @@ export function EChartsIntraday({ {showAvgLine && - {avg?.toFixed(2)} + {avg != null ? avg.toFixed(2) : '—'} } {d.volume.toFixed(0)} diff --git a/frontend/src/components/EChartsMultiDayIntraday.tsx b/frontend/src/components/EChartsMultiDayIntraday.tsx index 8012726..ab33da5 100644 --- a/frontend/src/components/EChartsMultiDayIntraday.tsx +++ b/frontend/src/components/EChartsMultiDayIntraday.tsx @@ -25,7 +25,7 @@ interface Props { interface InfoPoint { date: string row: MinuteKlineRow - average: number + average: number | null prevClose: number | null } @@ -65,7 +65,7 @@ function buildModel(sessions: MinuteKlineSession[]) { } const averagePrices = computeIntradayAverage(session.rows) - const rowsByTime = new Map() + const rowsByTime = new Map() session.rows.forEach((row, index) => { rowsByTime.set(formatMinuteTime(row.datetime), { row, @@ -105,7 +105,8 @@ function buildModel(sessions: MinuteKlineSession[]) { }, }) prevRef = row.close - priceValues.push(row.low, row.high, average) + priceValues.push(row.low, row.high) + if (average != null) priceValues.push(average) pointByIndex.set(index, { date: session.date, row, @@ -422,7 +423,7 @@ export function EChartsMultiDayIntraday({ {changePct != null && ( {changePct >= 0 ? '+' : ''}{changePct.toFixed(2)}% )} - 均价{info.average.toFixed(2)} + 均价{info.average != null ? info.average.toFixed(2) : '—'} {info.row.volume.toFixed(0)} {formatAmount(info.row.amount)} diff --git a/frontend/src/lib/intraday-chart.ts b/frontend/src/lib/intraday-chart.ts index 2d96c8f..4bdbdab 100644 --- a/frontend/src/lib/intraday-chart.ts +++ b/frontend/src/lib/intraday-chart.ts @@ -7,8 +7,8 @@ export function formatMinuteTime(datetime: string): string { return `${match[1]}:${match[2]}` } -export function computeIntradayAverage(data: MinuteKlineRow[]): number[] { - const result: number[] = [] +export function computeIntradayAverage(data: MinuteKlineRow[]): (number | null)[] { + const result: (number | null)[] = [] let amount = 0 let volume = 0 let hasAmount = true @@ -19,7 +19,7 @@ export function computeIntradayAverage(data: MinuteKlineRow[]): number[] { hasAmount = false } volume += row.volume * 100 - result.push(hasAmount && volume > 0 ? amount / volume : row.close) + result.push(hasAmount && volume > 0 ? amount / volume : null) } return result }