Browse Source

mat: scale charts together

raylu 1 ngày trước cách đây
mục cha
commit
8e9027dc55
1 tập tin đã thay đổi với 29 bổ sung24 xóa
  1. 29 24
      ts/mat.ts

+ 29 - 24
ts/mat.ts

@@ -27,58 +27,63 @@ tickerSelect.addEventListener('change', async () => {
 	
 async function render() {
 	charts.innerHTML = '';
-	renderPriceChart(tickerSelect.value, 'NC1');
-	renderPriceChart(tickerSelect.value, 'CI1');
-	renderPriceChart(tickerSelect.value, 'IC1');
-	renderPriceChart(tickerSelect.value, 'AI1');
+	const cxpc = await Promise.all([
+		getCXPC(tickerSelect.value, 'NC1'), getCXPC(tickerSelect.value, 'CI1'),
+		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)));
+	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]),
+	);
 }
 
-async function renderPriceChart(ticker: string, cx: string) {
+async function getCXPC(ticker: string, cx: string): Promise<PriceChartPoint[]> {
 	const cxpc: PriceChartPoint[] = await cachedFetchJSON(`https://rest.fnar.net/exchange/cxpc/${ticker}.${cx}`);
-	const filtered = cxpc.filter((p) => p.Interval === 'HOUR_TWELVE').map((p) => ({
-		...p,
-		Date: new Date(p.DateEpochMs)
-	}));
-	const maxPrice = Math.max(...filtered.map((p) => p.High));
-	const maxTraded = Math.max(...filtered.map((t) => t.Traded));
-	charts.appendChild(Plot.plot({
+	return cxpc.filter((p) => p.Interval === 'HOUR_TWELVE');
+}
+
+function renderPriceChart(cx: string, maxPrice: number, maxTraded: number, cxpc: PriceChartPoint[]):
+		SVGSVGElement | HTMLElement {
+	return Plot.plot({
 		grid: true,
 		width: charts.getBoundingClientRect().width / 2 - 10,
 		height: 400,
 		y: {axis: 'left', label: cx, domain: [0, maxPrice * 1.1]},
 		marks: [
-			Plot.axisY(d3.ticks(0, maxTraded * 2, 10), {
+			Plot.axisY(d3.ticks(0, maxTraded * 1.5, 10), {
 				label: 'traded',
 				anchor: 'right',
 				y: (d) => (d / maxTraded) * maxPrice / 3,
 			}),
-			Plot.rectY(filtered, {
-				x: 'Date',
-				y: (t) => (t.Traded / maxTraded) * maxPrice / 3, // scale traded to price
+			Plot.rectY(cxpc, {
+				x: (p) => new Date(p.DateEpochMs),
+				y: (p) => (p.Traded / maxTraded) * maxPrice / 3, // scale traded to price
 				interval: 'day',
 				fill: '#272',
-				fillOpacity: 0.1,
+				fillOpacity: 0.2,
 			}),
-			Plot.ruleX(filtered, {
-				x: 'Date',
+			Plot.ruleX(cxpc, {
+				x: (p) => new Date(p.DateEpochMs),
 				y1: 'Low',
 				y2: 'High',
 				strokeWidth: 5,
 				stroke: '#42a',
 			}),
-			Plot.dot(filtered, {
-				x: 'Date',
+			Plot.dot(cxpc, {
+				x: (p) => new Date(p.DateEpochMs),
 				y: (p) => p.Volume / p.Traded,
 				fill: '#a37',
 				r: 2,
 			}),
-			Plot.crosshairX(filtered, {
-				x: 'Date',
+			Plot.crosshairX(cxpc, {
+				x: (p) => new Date(p.DateEpochMs),
 				y: (p) => p.Volume / p.Traded,
 				textStrokeWidth: 0,
 			})
 		]
-	}));
+	});
 }
 
 interface Material {