Fix compare chart date alignment
This commit is contained in:
@@ -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)!);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user