|
@@ -31,25 +31,39 @@ async function render() {
|
|
|
getCXPC(tickerSelect.value, 'NC1'), getCXPC(tickerSelect.value, 'CI1'),
|
|
getCXPC(tickerSelect.value, 'NC1'), getCXPC(tickerSelect.value, 'CI1'),
|
|
|
getCXPC(tickerSelect.value, 'IC1'), getCXPC(tickerSelect.value, 'AI1'),
|
|
getCXPC(tickerSelect.value, 'IC1'), getCXPC(tickerSelect.value, 'AI1'),
|
|
|
]);
|
|
]);
|
|
|
- const maxPrice = Math.max(...cxpc.flatMap((cxPrices) => cxPrices.map((p) => p.High)));
|
|
|
|
|
- const maxTraded = Math.max(...cxpc.flatMap((cxPrices) => cxPrices.map((t) => t.Traded)));
|
|
|
|
|
|
|
+
|
|
|
|
|
+ let minDate = null, maxDate = null;
|
|
|
|
|
+ let maxPrice = 0, maxTraded = 0;
|
|
|
|
|
+ for (const cxPrices of cxpc)
|
|
|
|
|
+ for (const p of cxPrices) {
|
|
|
|
|
+ if (minDate === null || p.DateEpochMs < minDate) minDate = p.DateEpochMs;
|
|
|
|
|
+ if (maxDate === null || p.DateEpochMs > maxDate) maxDate = p.DateEpochMs;
|
|
|
|
|
+ if (p.High > maxPrice) maxPrice = p.High;
|
|
|
|
|
+ if (p.Traded > maxTraded) maxTraded = p.Traded;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (minDate === null || maxDate === null)
|
|
|
|
|
+ throw new Error('no data');
|
|
|
|
|
+
|
|
|
|
|
+ const dateRange: [Date, Date] = [new Date(minDate), new Date(maxDate)];
|
|
|
charts.append(
|
|
charts.append(
|
|
|
- renderPriceChart('NC1', maxPrice, maxTraded, cxpc[0]), renderPriceChart('CI1', maxPrice, maxTraded, cxpc[1]),
|
|
|
|
|
- renderPriceChart('IC1', maxPrice, maxTraded, cxpc[2]), renderPriceChart('AI1', maxPrice, maxTraded, cxpc[3]),
|
|
|
|
|
|
|
+ renderPriceChart('NC1', dateRange, maxPrice, maxTraded, cxpc[0]), renderPriceChart('CI1', dateRange, maxPrice, maxTraded, cxpc[1]),
|
|
|
|
|
+ renderPriceChart('IC1', dateRange, maxPrice, maxTraded, cxpc[2]), renderPriceChart('AI1', dateRange, maxPrice, maxTraded, cxpc[3]),
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async function getCXPC(ticker: string, cx: string): Promise<PriceChartPoint[]> {
|
|
async function getCXPC(ticker: string, cx: string): Promise<PriceChartPoint[]> {
|
|
|
const cxpc: PriceChartPoint[] = await cachedFetchJSON(`https://rest.fnar.net/exchange/cxpc/${ticker}.${cx}`);
|
|
const cxpc: PriceChartPoint[] = await cachedFetchJSON(`https://rest.fnar.net/exchange/cxpc/${ticker}.${cx}`);
|
|
|
- return cxpc.filter((p) => p.Interval === 'HOUR_TWELVE');
|
|
|
|
|
|
|
+ const threshold = Date.now() - 100 * 24 * 60 * 60 * 1000; // work around FIO bug that shows old data
|
|
|
|
|
+ return cxpc.filter((p) => p.Interval === 'HOUR_TWELVE' && p.DateEpochMs > threshold);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-function renderPriceChart(cx: string, maxPrice: number, maxTraded: number, cxpc: PriceChartPoint[]):
|
|
|
|
|
|
|
+function renderPriceChart(cx: string, dateRange: [Date, Date], maxPrice: number, maxTraded: number, cxpc: PriceChartPoint[]):
|
|
|
SVGSVGElement | HTMLElement {
|
|
SVGSVGElement | HTMLElement {
|
|
|
return Plot.plot({
|
|
return Plot.plot({
|
|
|
grid: true,
|
|
grid: true,
|
|
|
width: charts.getBoundingClientRect().width / 2 - 10,
|
|
width: charts.getBoundingClientRect().width / 2 - 10,
|
|
|
height: 400,
|
|
height: 400,
|
|
|
|
|
+ x: {domain: dateRange},
|
|
|
y: {axis: 'left', label: cx, domain: [0, maxPrice * 1.1]},
|
|
y: {axis: 'left', label: cx, domain: [0, maxPrice * 1.1]},
|
|
|
marks: [
|
|
marks: [
|
|
|
Plot.axisY(d3.ticks(0, maxTraded * 1.5, 10), {
|
|
Plot.axisY(d3.ticks(0, maxTraded * 1.5, 10), {
|