Line data Source code
1 : import type { TopLevelSpec } from 'vega-lite';
2 :
3 : import type { ChartColors } from '../../ui/vegalite/vegalite_theme.js';
4 :
5 : /// The params of the bounds of the time window, in milliseconds since the epoch
6 1 : export const WINDOW_START_SIGNAL = 'windowStart';
7 1 : export const WINDOW_END_SIGNAL = 'windowEnd';
8 :
9 : /// The dataset of the rows of a chart
10 1 : export const ROWS_DATASET = 'rows';
11 :
12 1 : const WINDOW_PARAMS = [
13 1 : { name: WINDOW_START_SIGNAL, value: 0 },
14 1 : { name: WINDOW_END_SIGNAL, value: 1 },
15 1 : ];
16 :
17 : /// The x channel of the time of a row in the sliding window
18 1 : const TIME_X = {
19 1 : field: 't',
20 1 : type: 'temporal',
21 1 : title: null,
22 1 : scale: { domainMin: { expr: WINDOW_START_SIGNAL }, domainMax: { expr: WINDOW_END_SIGNAL } },
23 1 : axis: { format: '%H:%M:%S', tickCount: 4, labelPadding: 3, labelSeparation: 8 },
24 1 : } as const;
25 :
26 : /// The y axis of a small chart
27 1 : const Y_AXIS = { tickCount: 3, labelPadding: 3 };
28 :
29 : /// The price of a symbol per second, `{ t, open, high, low, close }`: the range of the second as a band and the close as a line.
30 : /// A rule with a tooltip marks the second nearest to the pointer.
31 1 : export function priceChartSpec(colors: ChartColors): TopLevelSpec {
32 1 : const y = { type: 'quantitative', title: null, scale: { zero: false }, axis: Y_AXIS };
33 1 : return {
34 1 : params: WINDOW_PARAMS,
35 1 : layer: [
36 1 : {
37 1 : data: { name: ROWS_DATASET },
38 1 : mark: { type: 'area', opacity: 0.15, clip: true, color: colors.primary },
39 1 : encoding: { x: TIME_X, y: { ...y, field: 'low' }, y2: { field: 'high' } },
40 1 : },
41 1 : {
42 1 : data: { name: ROWS_DATASET },
43 1 : mark: { type: 'line', clip: true, strokeWidth: 2, color: colors.primary },
44 1 : encoding: { x: TIME_X, y: { ...y, field: 'close' } },
45 1 : },
46 1 : {
47 1 : data: { name: ROWS_DATASET },
48 1 : params: [{
49 1 : name: 'hover',
50 1 : select: { type: 'point', encodings: ['x'], nearest: true, on: 'pointerover', clear: 'pointerout' },
51 1 : }],
52 1 : mark: { type: 'rule', color: colors.title },
53 1 : encoding: {
54 1 : x: TIME_X,
55 1 : opacity: { condition: { param: 'hover', empty: false, value: 1 }, value: 0 },
56 1 : tooltip: [
57 1 : { field: 't', type: 'temporal', format: '%H:%M:%S', title: 'Time' },
58 1 : { field: 'close', type: 'quantitative', format: ',.6~r', title: 'Close' },
59 1 : { field: 'high', type: 'quantitative', format: ',.6~r', title: 'High' },
60 1 : { field: 'low', type: 'quantitative', format: ',.6~r', title: 'Low' },
61 1 : { field: 'size', type: 'quantitative', format: ',.4~r', title: 'Size' },
62 1 : ],
63 1 : },
64 1 : },
65 1 : ],
66 1 : } as TopLevelSpec;
67 1 : }
68 :
69 : /// The trades per second, `{ t, trades }`, as bars that span their second
70 1 : export function throughputChartSpec(colors: ChartColors): TopLevelSpec {
71 1 : return {
72 1 : params: WINDOW_PARAMS,
73 1 : data: { name: ROWS_DATASET },
74 1 : transform: [{ calculate: 'datum.t + 1000', as: 't1' }],
75 : // A gap of 1px between the bars
76 1 : mark: { type: 'bar', clip: true, xOffset: 0.5, x2Offset: -0.5, color: colors.primary },
77 1 : encoding: {
78 1 : x: TIME_X,
79 1 : x2: { field: 't1' },
80 1 : y2: { datum: 0 },
81 1 : y: {
82 1 : field: 'trades',
83 1 : type: 'quantitative',
84 1 : title: null,
85 1 : axis: { ...Y_AXIS, labelExpr: "datum.value == 0 ? '' : format(datum.value, '~s')", tickMinStep: 1 },
86 1 : },
87 1 : tooltip: [
88 1 : { field: 't', type: 'temporal', format: '%H:%M:%S', title: 'Time' },
89 1 : { field: 'trades', type: 'quantitative', format: ',', title: 'Trades' },
90 1 : ],
91 1 : },
92 1 : } as TopLevelSpec;
93 1 : }
|