summaryrefslogtreecommitdiff
path: root/frontend/src/lib/coverage.ts
diff options
context:
space:
mode:
authorSomhairle H. Marisol <[email protected]>2026-09-17 14:32:37 +0800
committerSomhairle H. Marisol <[email protected]>2026-09-17 14:32:37 +0800
commit5c0ba37eda80d39e6ceca59bb1d5f4942f858995 (patch)
tree948723f9cedf7ccb0707fa6ee516bd30fe20fd10 /frontend/src/lib/coverage.ts
downloadstrategy-lab-5c0ba37eda80d39e6ceca59bb1d5f4942f858995.tar.gz
chore: establish Strategy Lab source baseline (development, not release)
Diffstat (limited to 'frontend/src/lib/coverage.ts')
-rw-r--r--frontend/src/lib/coverage.ts52
1 files changed, 52 insertions, 0 deletions
diff --git a/frontend/src/lib/coverage.ts b/frontend/src/lib/coverage.ts
new file mode 100644
index 0000000..c9a8447
--- /dev/null
+++ b/frontend/src/lib/coverage.ts
@@ -0,0 +1,52 @@
+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 };
+}