Fix compare chart date alignment

This commit is contained in:
2026-03-13 00:25:20 -04:00
parent a3d4c97f4e
commit 54172f9e8b
2 changed files with 130 additions and 14 deletions

View File

@@ -1,6 +1,15 @@
import { subWeeks, subMonths, subYears } from 'date-fns';
import type { TimeRange, ChartDataPoint } from '@/lib/types';
function toTradingDayKey(value: string): string {
const parsed = Date.parse(value);
if (!Number.isFinite(parsed)) {
return value;
}
return new Date(parsed).toISOString().slice(0, 10);
}
/**
* Filter chart data by time range
*/
@@ -128,30 +137,55 @@ export function calculateVolumeMax<T extends ChartDataPoint>(data: T[]): number
*/
export function mergeDataSeries<T extends ChartDataPoint>(
seriesArray: Array<{ id: string; data: T[] }>
): Array<T & Record<string, number>> {
): Array<{ date: string } & Record<string, string | number>> {
if (!seriesArray || seriesArray.length === 0) return [];
// Create map indexed by date
const dateMap = new Map<string, T & Record<string, number>>();
// Create map indexed by normalized trading day.
const dateMap = new Map<string, { date: string } & Record<string, string | number>>();
const seriesPointMaps = seriesArray.map((series) => {
const pointMap = new Map<string, number>();
seriesArray.forEach(series => {
series.data.forEach(point => {
const date = point.date;
const existing = dateMap.get(date) || { date } as T & Record<string, number>;
const date = toTradingDayKey(point.date);
// Add value for this series
if (isOHLCVData(point)) {
existing[series.id] = point.close;
pointMap.set(date, point.close);
} else if (isPriceData(point)) {
existing[series.id] = point.price;
pointMap.set(date, point.price);
}
});
pointMap.forEach((_value, date) => {
const existing = dateMap.get(date) || { date } as { date: string } & Record<string, string | number>;
dateMap.set(date, existing);
});
return {
id: series.id,
pointMap
};
});
const mergedDates = Array.from(dateMap.keys()).sort((a, b) =>
new Date(a).getTime() - new Date(b).getTime()
);
// Fill forward each series to keep benchmark/comparison lines aligned on trading days.
seriesPointMaps.forEach(({ id, pointMap }) => {
let lastKnownValue: number | null = null;
mergedDates.forEach((date) => {
const currentValue = pointMap.get(date);
if (typeof currentValue === 'number') {
lastKnownValue = currentValue;
}
dateMap.set(date, existing);
const existing = dateMap.get(date);
if (existing && lastKnownValue !== null) {
existing[id] = lastKnownValue;
}
});
});
// Convert to array and sort by date
return Array.from(dateMap.values()).sort((a, b) =>
new Date(a.date).getTime() - new Date(b.date).getTime()
);
return mergedDates.map((date) => dateMap.get(date)!);
}