52 lines
1.4 KiB
TypeScript
52 lines
1.4 KiB
TypeScript
|
|
import type {
|
||
|
|
RadarHistoryPoint,
|
||
|
|
RadarMetricKind,
|
||
|
|
} from "../api/sector-radar.types"
|
||
|
|
|
||
|
|
/** Produce a chronological ranking series; missing observations break the line and rank 1 stays on top. */
|
||
|
|
export function buildRadarRankChartOption(
|
||
|
|
points: RadarHistoryPoint[],
|
||
|
|
metric: RadarMetricKind,
|
||
|
|
) {
|
||
|
|
const ordered = [...points].sort((a, b) =>
|
||
|
|
a.trade_date.localeCompare(b.trade_date),
|
||
|
|
)
|
||
|
|
return {
|
||
|
|
animation: false,
|
||
|
|
grid: { left: 48, right: 20, top: 24, bottom: 36 },
|
||
|
|
tooltip: {
|
||
|
|
trigger: "axis" as const,
|
||
|
|
renderMode: "richText" as const,
|
||
|
|
valueFormatter: (value: unknown) =>
|
||
|
|
value == null ? "缺失" : `第 ${String(value)} 名`,
|
||
|
|
},
|
||
|
|
xAxis: {
|
||
|
|
type: "category" as const,
|
||
|
|
data: ordered.map((point) => point.trade_date),
|
||
|
|
boundaryGap: false,
|
||
|
|
},
|
||
|
|
yAxis: {
|
||
|
|
type: "value" as const,
|
||
|
|
inverse: true,
|
||
|
|
min: 1,
|
||
|
|
max: Math.max(2, ...ordered.map((point) => point[metric].pool_size)),
|
||
|
|
minInterval: 1,
|
||
|
|
name: "排名",
|
||
|
|
},
|
||
|
|
series: [
|
||
|
|
{
|
||
|
|
name: "排名",
|
||
|
|
type: "line" as const,
|
||
|
|
connectNulls: false,
|
||
|
|
showSymbol: true,
|
||
|
|
showAllSymbol: true,
|
||
|
|
data: ordered.map((point) =>
|
||
|
|
point[metric].missing ? null : point[metric].rank_position,
|
||
|
|
),
|
||
|
|
lineStyle: { color: "#2563eb" },
|
||
|
|
itemStyle: { color: "#2563eb" },
|
||
|
|
},
|
||
|
|
],
|
||
|
|
}
|
||
|
|
}
|