export interface CoverageEntry { instrument: string; market?: string; asset_type?: string; requested_start?: string | null; requested_end?: string | null; actual_start?: string | null; actual_end?: string | null; row_count?: number; warnings?: string[]; } export interface CoverageSummary { common: { start: string | null; end: string | null }; warnings: string[]; } export function summarizeCoverage(entries: CoverageEntry[]): CoverageSummary { const warnings: string[] = []; const withData = entries.filter((e) => (e.row_count ?? 0) > 0 && e.actual_start && e.actual_end); for (const e of entries) { if ((e.row_count ?? 0) === 0) { warnings.push(`${e.instrument} 没有返回任何数据行`); } else if (!e.actual_start || !e.actual_end) { warnings.push(`${e.instrument} 数据区间不完整`); } } let common: { start: string | null; end: string | null } = { start: null, end: null }; if (withData.length > 0) { const starts = withData.map((e) => e.actual_start as string).sort(); const startsAsc = [...starts]; const earliest = startsAsc[0]; const lateStart = starts[starts.length - 1]; if (lateStart > earliest) { const owner = withData.find((e) => e.actual_start === lateStart); if (owner) { warnings.push(`${owner.instrument} 起始数据较其他标的更晚(${lateStart})`); } } const ends = withData.map((e) => e.actual_end as string); const commonEnd = ends.sort()[0]; const earlyOwners = withData.filter((e) => e.actual_end === commonEnd); const otherEnds = withData.filter((e) => (e.actual_end as string) > commonEnd); if (otherEnds.length > 0) { for (const e of earlyOwners) { warnings.push(`${e.instrument} 较早结束(${commonEnd}),造成共有区间缺失`); } } common = { start: lateStart, end: commonEnd }; } return { common, warnings }; }