@oanda/labs-crowd-view-widget 1.0.52 → 1.0.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CHANGELOG.md +216 -0
  2. package/dist/main/CrowdViewWidget/Main.js +1 -5
  3. package/dist/main/CrowdViewWidget/Main.js.map +1 -1
  4. package/dist/main/CrowdViewWidget/components/Chart/Chart.js +16 -6
  5. package/dist/main/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
  6. package/dist/main/CrowdViewWidget/components/Chart/ChartWithData.js +15 -6
  7. package/dist/main/CrowdViewWidget/components/Chart/ChartWithData.js.map +1 -1
  8. package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js +69 -29
  9. package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
  10. package/dist/main/CrowdViewWidget/components/Chart/types.js.map +1 -1
  11. package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js +49 -26
  12. package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
  13. package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js +9 -10
  14. package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
  15. package/dist/main/CrowdViewWidget/components/Chart/utils/index.js +0 -33
  16. package/dist/main/CrowdViewWidget/components/Chart/utils/index.js.map +1 -1
  17. package/dist/main/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js +54 -12
  18. package/dist/main/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js.map +1 -1
  19. package/dist/main/CrowdViewWidget/components/Chart/utils/processPriceCandles.js +49 -27
  20. package/dist/main/CrowdViewWidget/components/Chart/utils/processPriceCandles.js.map +1 -1
  21. package/dist/main/CrowdViewWidget/components/Chart/utils/processSentiments.js +32 -17
  22. package/dist/main/CrowdViewWidget/components/Chart/utils/processSentiments.js.map +1 -1
  23. package/dist/main/CrowdViewWidget/components/Chart/utils/validateData.js +8 -2
  24. package/dist/main/CrowdViewWidget/components/Chart/utils/validateData.js.map +1 -1
  25. package/dist/main/CrowdViewWidget/components/Legend/Legend.js +2 -3
  26. package/dist/main/CrowdViewWidget/components/Legend/Legend.js.map +1 -1
  27. package/dist/main/CrowdViewWidget/components/Legend/LegendBar.js +2 -2
  28. package/dist/main/CrowdViewWidget/components/Legend/LegendBar.js.map +1 -1
  29. package/dist/main/CrowdViewWidget/constants.js +2 -6
  30. package/dist/main/CrowdViewWidget/constants.js.map +1 -1
  31. package/dist/main/gql/getOrderPositionBooks.js +1 -1
  32. package/dist/main/gql/getOrderPositionBooks.js.map +1 -1
  33. package/dist/main/gql/getPriceCandles.js +1 -1
  34. package/dist/main/gql/getPriceCandles.js.map +1 -1
  35. package/dist/main/gql/types/gql.js +2 -2
  36. package/dist/main/gql/types/gql.js.map +1 -1
  37. package/dist/main/gql/types/graphql.js +111 -18
  38. package/dist/main/gql/types/graphql.js.map +1 -1
  39. package/dist/module/CrowdViewWidget/Main.js +2 -6
  40. package/dist/module/CrowdViewWidget/Main.js.map +1 -1
  41. package/dist/module/CrowdViewWidget/components/Chart/Chart.js +17 -7
  42. package/dist/module/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
  43. package/dist/module/CrowdViewWidget/components/Chart/ChartWithData.js +15 -6
  44. package/dist/module/CrowdViewWidget/components/Chart/ChartWithData.js.map +1 -1
  45. package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js +70 -30
  46. package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
  47. package/dist/module/CrowdViewWidget/components/Chart/types.js.map +1 -1
  48. package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js +50 -27
  49. package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
  50. package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js +10 -11
  51. package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
  52. package/dist/module/CrowdViewWidget/components/Chart/utils/index.js +0 -3
  53. package/dist/module/CrowdViewWidget/components/Chart/utils/index.js.map +1 -1
  54. package/dist/module/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js +54 -12
  55. package/dist/module/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js.map +1 -1
  56. package/dist/module/CrowdViewWidget/components/Chart/utils/processPriceCandles.js +49 -27
  57. package/dist/module/CrowdViewWidget/components/Chart/utils/processPriceCandles.js.map +1 -1
  58. package/dist/module/CrowdViewWidget/components/Chart/utils/processSentiments.js +32 -17
  59. package/dist/module/CrowdViewWidget/components/Chart/utils/processSentiments.js.map +1 -1
  60. package/dist/module/CrowdViewWidget/components/Chart/utils/validateData.js +8 -2
  61. package/dist/module/CrowdViewWidget/components/Chart/utils/validateData.js.map +1 -1
  62. package/dist/module/CrowdViewWidget/components/Legend/Legend.js +2 -3
  63. package/dist/module/CrowdViewWidget/components/Legend/Legend.js.map +1 -1
  64. package/dist/module/CrowdViewWidget/components/Legend/LegendBar.js +2 -2
  65. package/dist/module/CrowdViewWidget/components/Legend/LegendBar.js.map +1 -1
  66. package/dist/module/CrowdViewWidget/constants.js +1 -5
  67. package/dist/module/CrowdViewWidget/constants.js.map +1 -1
  68. package/dist/module/gql/getOrderPositionBooks.js +1 -1
  69. package/dist/module/gql/getOrderPositionBooks.js.map +1 -1
  70. package/dist/module/gql/getPriceCandles.js +1 -1
  71. package/dist/module/gql/getPriceCandles.js.map +1 -1
  72. package/dist/module/gql/types/gql.js +2 -2
  73. package/dist/module/gql/types/gql.js.map +1 -1
  74. package/dist/module/gql/types/graphql.js +111 -18
  75. package/dist/module/gql/types/graphql.js.map +1 -1
  76. package/dist/types/CrowdViewWidget/components/Chart/Chart.d.ts +1 -1
  77. package/dist/types/CrowdViewWidget/components/Chart/types.d.ts +28 -11
  78. package/dist/types/CrowdViewWidget/components/Chart/utils/chartUtils.d.ts +3 -4
  79. package/dist/types/CrowdViewWidget/components/Chart/utils/index.d.ts +0 -3
  80. package/dist/types/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.d.ts +10 -7
  81. package/dist/types/CrowdViewWidget/components/Chart/utils/processPriceCandles.d.ts +6 -21
  82. package/dist/types/CrowdViewWidget/components/Chart/utils/processSentiments.d.ts +5 -2
  83. package/dist/types/CrowdViewWidget/components/Chart/utils/validateData.d.ts +1 -1
  84. package/dist/types/CrowdViewWidget/components/Legend/Legend.d.ts +2 -2
  85. package/dist/types/CrowdViewWidget/components/Legend/LegendBar.d.ts +1 -1
  86. package/dist/types/CrowdViewWidget/constants.d.ts +1 -5
  87. package/dist/types/gql/types/gql.d.ts +6 -4
  88. package/dist/types/gql/types/graphql.d.ts +30 -11
  89. package/package.json +3 -3
  90. package/src/CrowdViewWidget/Main.tsx +2 -4
  91. package/src/CrowdViewWidget/components/Chart/Chart.tsx +15 -6
  92. package/src/CrowdViewWidget/components/Chart/ChartWithData.tsx +21 -4
  93. package/src/CrowdViewWidget/components/Chart/chartOptions.ts +78 -30
  94. package/src/CrowdViewWidget/components/Chart/types.ts +30 -19
  95. package/src/CrowdViewWidget/components/Chart/useCrowdViewData.ts +82 -65
  96. package/src/CrowdViewWidget/components/Chart/utils/chartUtils.ts +32 -20
  97. package/src/CrowdViewWidget/components/Chart/utils/index.ts +0 -3
  98. package/src/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.ts +84 -22
  99. package/src/CrowdViewWidget/components/Chart/utils/processPriceCandles.ts +52 -38
  100. package/src/CrowdViewWidget/components/Chart/utils/processSentiments.ts +45 -32
  101. package/src/CrowdViewWidget/components/Chart/utils/validateData.ts +10 -2
  102. package/src/CrowdViewWidget/components/Legend/Legend.tsx +4 -5
  103. package/src/CrowdViewWidget/components/Legend/LegendBar.tsx +3 -3
  104. package/src/CrowdViewWidget/constants.ts +1 -6
  105. package/src/gql/getOrderPositionBooks.ts +13 -5
  106. package/src/gql/getPriceCandles.ts +1 -0
  107. package/src/gql/types/gql.ts +6 -6
  108. package/src/gql/types/graphql.ts +98 -16
  109. package/test/components/Chart/utils/chartUtils.test.ts +32 -14
  110. package/test/components/Chart/utils/processSentiments.test.ts +137 -29
  111. package/test/utils/processOrderPositionBooks.test.ts +201 -84
  112. package/test/utils/processPriceCandles.test.ts +93 -67
  113. package/test/utils/validateData.test.ts +136 -38
  114. package/dist/main/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js +0 -37
  115. package/dist/main/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js.map +0 -1
  116. package/dist/main/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js +0 -14
  117. package/dist/main/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js.map +0 -1
  118. package/dist/main/CrowdViewWidget/components/Chart/utils/processBuckets.js +0 -29
  119. package/dist/main/CrowdViewWidget/components/Chart/utils/processBuckets.js.map +0 -1
  120. package/dist/module/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js +0 -29
  121. package/dist/module/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js.map +0 -1
  122. package/dist/module/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js +0 -7
  123. package/dist/module/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js.map +0 -1
  124. package/dist/module/CrowdViewWidget/components/Chart/utils/processBuckets.js +0 -22
  125. package/dist/module/CrowdViewWidget/components/Chart/utils/processBuckets.js.map +0 -1
  126. package/dist/types/CrowdViewWidget/components/Chart/utils/aggregateBuckets.d.ts +0 -2
  127. package/dist/types/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.d.ts +0 -3
  128. package/dist/types/CrowdViewWidget/components/Chart/utils/processBuckets.d.ts +0 -3
  129. package/src/CrowdViewWidget/components/Chart/utils/aggregateBuckets.ts +0 -44
  130. package/src/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.ts +0 -13
  131. package/src/CrowdViewWidget/components/Chart/utils/processBuckets.ts +0 -43
  132. package/test/utils/aggregateBuckets.test.ts +0 -82
  133. package/test/utils/getTargetBucketWidth.test.ts +0 -37
  134. package/test/utils/processBuckets.test.ts +0 -153
@@ -10,14 +10,14 @@ import React, { useEffect, useMemo, useState } from 'react';
10
10
 
11
11
  import type { Granularity } from '../gql/types/graphql';
12
12
  import { BookType } from '../gql/types/graphql';
13
- import { ChartWithData, Legend } from './components';
13
+ import { ChartWithData } from './components';
14
14
  import { granularitySelectConfig, navigationConfig } from './selectConfig';
15
15
  import type { InstrumentId, MainProps } from './types';
16
16
  import { getInstrumentConfigForDivision } from './utils/instrumentUtils';
17
17
 
18
18
  const Main = ({ division }: MainProps) => {
19
19
  const { lang } = useLocale();
20
- const { size, isDark } = useLayoutProvider();
20
+ const { size } = useLayoutProvider();
21
21
  const isDesktop = size === Size.DESKTOP;
22
22
 
23
23
  const [bookType, setBookType] = useState(BookType.Order);
@@ -107,8 +107,6 @@ const Main = ({ division }: MainProps) => {
107
107
  granularity={granularity.id}
108
108
  instrument={instrument.id}
109
109
  />
110
-
111
- <Legend bookType={bookType} isDark={isDark} />
112
110
  </div>
113
111
  )}
114
112
  </>
@@ -8,6 +8,7 @@ import { useLocale } from '@oanda/mono-i18n';
8
8
  import type { EChartsType } from 'echarts';
9
9
  import { CandlestickChart, CustomChart, LineChart } from 'echarts/charts';
10
10
  import {
11
+ DatasetComponent,
11
12
  DataZoomInsideComponent,
12
13
  GraphicComponent,
13
14
  GridSimpleComponent,
@@ -46,12 +47,13 @@ echarts.use([
46
47
  MarkAreaComponent,
47
48
  LineChart,
48
49
  VisualMapComponent,
50
+ DatasetComponent,
49
51
  ]);
50
52
 
51
53
  echarts.registerTheme('dark_theme', getChartTheme(Theme.Dark));
52
54
  echarts.registerTheme('light_theme', getChartTheme(Theme.Light));
53
55
 
54
- const Chart = ({ data, isDesktop }: ChartProps) => {
56
+ const Chart = ({ mainData, additionalData, isDesktop }: ChartProps) => {
55
57
  const { isDark } = useLayoutProvider();
56
58
  const { lang } = useLocale();
57
59
 
@@ -61,7 +63,13 @@ const Chart = ({ data, isDesktop }: ChartProps) => {
61
63
  echarts={echarts}
62
64
  isDark={isDark}
63
65
  lazyUpdate={true}
64
- option={getOption(data, isDark, isDesktop, lang)}
66
+ option={getOption({
67
+ mainData,
68
+ additionalData,
69
+ isDark,
70
+ isDesktop,
71
+ labelCallback: lang,
72
+ })}
65
73
  opts={{ renderer: 'canvas' }}
66
74
  onEvents={{
67
75
  datazoom: (params: DataZoomEvent, instance: EChartsType) => {
@@ -69,6 +77,7 @@ const Chart = ({ data, isDesktop }: ChartProps) => {
69
77
  return;
70
78
  }
71
79
 
80
+ const { dates } = mainData;
72
81
  const batchItem = params.batch[0];
73
82
  const { start, end } = batchItem;
74
83
 
@@ -105,13 +114,13 @@ const Chart = ({ data, isDesktop }: ChartProps) => {
105
114
  });
106
115
  }
107
116
 
108
- if (!data.xAxisData[startValue] || !data.xAxisData[endValue]) {
117
+ if (!dates[startValue] || !dates[endValue]) {
109
118
  return;
110
119
  }
111
120
 
112
121
  const isGreaterThanTwoWeeks = isDifferenceGreaterThanTwoWeeks(
113
- data.xAxisData[startValue],
114
- data.xAxisData[endValue]
122
+ dates[startValue],
123
+ dates[endValue]
115
124
  );
116
125
 
117
126
  const wasGreaterThanTwoWeeks =
@@ -121,7 +130,7 @@ const Chart = ({ data, isDesktop }: ChartProps) => {
121
130
 
122
131
  if (isGreaterThanTwoWeeks !== wasGreaterThanTwoWeeks) {
123
132
  const labelsData = getLabelData({
124
- xAxisData: data.xAxisData,
133
+ dates,
125
134
  isGreaterThanTwoWeeks,
126
135
  });
127
136
 
@@ -7,6 +7,7 @@ import {
7
7
  } from '@oanda/labs-widget-common';
8
8
  import React from 'react';
9
9
 
10
+ import { Legend } from '../Legend';
10
11
  import { Chart } from './Chart';
11
12
  import type { ChartWithDataProps } from './types';
12
13
  import { useCrowdViewData } from './useCrowdViewData';
@@ -17,10 +18,10 @@ const ChartWithData = ({
17
18
  division,
18
19
  granularity,
19
20
  }: ChartWithDataProps) => {
20
- const { size } = useLayoutProvider();
21
+ const { size, isDark } = useLayoutProvider();
21
22
  const isDesktop = size === Size.DESKTOP;
22
23
 
23
- const { data, loading, error } = useCrowdViewData({
24
+ const { mainData, additionalData, loading, error } = useCrowdViewData({
24
25
  instrument,
25
26
  bookType,
26
27
  division,
@@ -40,12 +41,28 @@ const ChartWithData = ({
40
41
  <Spinner size={SpinnerSize.lg} />
41
42
  </div>
42
43
  )}
43
- {!loading && !error && !!data && (
44
+ {!loading && !error && !!mainData && !!additionalData && (
44
45
  <div className="lw-absolute lw-left-0 lw-top-0 lw-flex lw-h-full lw-w-full">
45
- <Chart data={data} isDesktop={isDesktop} />
46
+ <Chart
47
+ additionalData={additionalData}
48
+ isDesktop={isDesktop}
49
+ mainData={mainData}
50
+ />
46
51
  </div>
47
52
  )}
48
53
  </div>
54
+ <Legend
55
+ bookType={bookType}
56
+ isDark={isDark}
57
+ longValues={[
58
+ additionalData?.sentimentThresholdMin,
59
+ additionalData?.sentimentThresholdMax,
60
+ ]}
61
+ shortValues={[
62
+ additionalData?.sentimentThresholdMin,
63
+ additionalData?.sentimentThresholdMax,
64
+ ]}
65
+ />
49
66
  </>
50
67
  );
51
68
  };
@@ -1,6 +1,10 @@
1
1
  import chroma from 'chroma-js';
2
2
 
3
- import { CHART_CONFIG, CHART_CONFIG_CALCULATED } from '../../constants';
3
+ import {
4
+ BUCKET_CONFIG,
5
+ CHART_CONFIG,
6
+ CHART_CONFIG_CALCULATED,
7
+ } from '../../constants';
4
8
  import type { Bucket, GetOptionType, TooltipParam } from './types';
5
9
  import {
6
10
  formatXAxisLabel,
@@ -13,21 +17,30 @@ import { getChartStyles } from './utils/getChartStyles';
13
17
  import { getGridLines } from './utils/getGridLines';
14
18
 
15
19
  // @ts-expect-error
16
- export const getOption: GetOptionType = (
17
- {
18
- xAxisData,
19
- candlesSeriesData,
20
- orderPositionBooks,
20
+ export const getOption: GetOptionType = ({
21
+ mainData: {
22
+ dates,
23
+ candlesOpen,
24
+ candlesClose,
25
+ candlesLow,
26
+ candlesHigh,
27
+ bookPrices,
28
+ bookIndexes,
29
+ sentimentShorts,
30
+ sentimentLongs,
31
+ },
32
+ additionalData: {
21
33
  bucketWidth,
22
34
  buckets,
23
- precision,
35
+ displayPrecision,
24
36
  bookType,
25
- sentiments,
37
+ sentimentThresholdMin,
38
+ sentimentThresholdMax,
26
39
  },
27
40
  isDark,
28
41
  isDesktop,
29
- labelCallback
30
- ) => {
42
+ labelCallback,
43
+ }) => {
31
44
  let selectedPrice: number;
32
45
  const {
33
46
  sentimentLongColor,
@@ -39,9 +52,9 @@ export const getOption: GetOptionType = (
39
52
  sentimentLabelColor,
40
53
  } = getChartStyles(isDark);
41
54
 
42
- const visibleXAxisData = xAxisData.slice(
43
- (xAxisData.length * CHART_CONFIG.INITIAL_START_ZOOM) / 100,
44
- (xAxisData.length * CHART_CONFIG.INITIAL_END_ZOOM) / 100
55
+ const visibleXAxisData = dates.slice(
56
+ (dates.length * CHART_CONFIG.INITIAL_START_ZOOM) / 100,
57
+ (dates.length * CHART_CONFIG.INITIAL_END_ZOOM) / 100
45
58
  );
46
59
 
47
60
  const isGreaterThanTwoWeeks = isDifferenceGreaterThanTwoWeeks(
@@ -50,7 +63,7 @@ export const getOption: GetOptionType = (
50
63
  );
51
64
 
52
65
  const labelsData = getLabelData({
53
- xAxisData,
66
+ dates,
54
67
  isGreaterThanTwoWeeks,
55
68
  });
56
69
 
@@ -96,7 +109,7 @@ export const getOption: GetOptionType = (
96
109
  formatter: (params) => {
97
110
  if (params.axisDimension === 'y' && params.axisIndex === 0) {
98
111
  selectedPrice = Number(params.value);
99
- return ` ${Number(params.value).toFixed(precision)} `;
112
+ return ` ${Number(params.value).toFixed(displayPrecision)} `;
100
113
  }
101
114
 
102
115
  return null;
@@ -111,7 +124,6 @@ export const getOption: GetOptionType = (
111
124
  bucketWidth,
112
125
  selectedPrice,
113
126
  labelCallback,
114
- precision,
115
127
  bookType,
116
128
  }),
117
129
  },
@@ -123,7 +135,6 @@ export const getOption: GetOptionType = (
123
135
  fontSize: 0,
124
136
  },
125
137
  id: 'main-xAxis',
126
- data: xAxisData,
127
138
  splitNumber: 1,
128
139
  axisTick: {
129
140
  show: false,
@@ -138,7 +149,7 @@ export const getOption: GetOptionType = (
138
149
  type: 'category',
139
150
  gridIndex: 1,
140
151
  show: false,
141
- data: xAxisData,
152
+ data: dates,
142
153
  splitNumber: 1,
143
154
  axisTick: {
144
155
  show: false,
@@ -153,15 +164,16 @@ export const getOption: GetOptionType = (
153
164
  type: 'value',
154
165
  gridIndex: 0,
155
166
  position: 'right',
156
- min: (val) => val.min - bucketWidth * 2,
157
- max: (val) => val.max + bucketWidth * 2,
167
+ min: (val) =>
168
+ val.min - bucketWidth * BUCKET_CONFIG.PRICE_MARGIN_MULTIPLIER,
169
+ max: (val) =>
170
+ val.max + bucketWidth * BUCKET_CONFIG.PRICE_MARGIN_MULTIPLIER,
158
171
  axisLine: { show: false },
159
172
  axisTick: { show: false },
160
173
  axisLabel: {
161
174
  showMaxLabel: false,
162
175
  showMinLabel: false,
163
- margin: isDesktop ? 4 : 2,
164
- formatter: (value: number) => value.toFixed(precision - 1),
176
+ formatter: (value: number) => value.toFixed(displayPrecision - 1),
165
177
  },
166
178
  },
167
179
  {
@@ -239,6 +251,19 @@ export const getOption: GetOptionType = (
239
251
  },
240
252
  ],
241
253
  },
254
+ dataset: {
255
+ source: {
256
+ dates,
257
+ candlesOpen,
258
+ candlesClose,
259
+ candlesLow,
260
+ candlesHigh,
261
+ bookPrices,
262
+ bookIndexes,
263
+ sentimentShorts,
264
+ sentimentLongs,
265
+ },
266
+ },
242
267
  series: [
243
268
  {
244
269
  type: 'candlestick',
@@ -246,7 +271,10 @@ export const getOption: GetOptionType = (
246
271
  gridIndex: 0,
247
272
  xAxisIndex: 0,
248
273
  yAxisIndex: 0,
249
- data: candlesSeriesData,
274
+ encode: {
275
+ x: 'dates',
276
+ y: ['open', 'close', 'low', 'high'],
277
+ },
250
278
  itemStyle: {
251
279
  color: chroma(candleShortColor).desaturate().css(),
252
280
  color0: chroma(candleLongColor).desaturate().css(),
@@ -274,9 +302,19 @@ export const getOption: GetOptionType = (
274
302
  yAxisIndex: 0,
275
303
  silent: true,
276
304
  clip: true,
305
+ encode: {
306
+ x: 'dates',
307
+ y: 'bookPrices',
308
+ },
309
+ dimensions: ['dates', 'bookPrices', 'bookIndexes'],
277
310
  renderItem: (_params, api) => {
278
311
  const xVal = api.value(0);
279
312
  const bucketIndex = api.value(2) as number;
313
+
314
+ if (!bucketIndex) {
315
+ return null;
316
+ }
317
+
280
318
  const metaValues = buckets[bucketIndex];
281
319
 
282
320
  const [rectWidth, rectHeight] = api.size!([
@@ -296,7 +334,12 @@ export const getOption: GetOptionType = (
296
334
  height: rectHeight,
297
335
  },
298
336
  style: {
299
- fill: getRectColor(sentiment, isDark),
337
+ fill: getRectColor(
338
+ sentiment,
339
+ isDark,
340
+ sentimentThresholdMin,
341
+ sentimentThresholdMax
342
+ ),
300
343
  },
301
344
  silent: true,
302
345
  emphasisDisabled: true,
@@ -310,7 +353,6 @@ export const getOption: GetOptionType = (
310
353
  emphasisDisabled: true,
311
354
  };
312
355
  },
313
- data: orderPositionBooks,
314
356
  },
315
357
  {
316
358
  type: 'line',
@@ -318,7 +360,6 @@ export const getOption: GetOptionType = (
318
360
  id: 'sentiment',
319
361
  xAxisIndex: 1,
320
362
  yAxisIndex: 1,
321
- data: sentiments,
322
363
  showSymbol: false,
323
364
  symbol: 'none',
324
365
  lineStyle: {
@@ -330,11 +371,14 @@ export const getOption: GetOptionType = (
330
371
  opacity: sentimentAreaOpacity,
331
372
  },
332
373
  emphasis: {
333
- areaStyle: {
334
- opacity: 0,
335
- },
374
+ disabled: true,
336
375
  },
337
376
  stack: 'sentiment',
377
+ dimensions: ['dates', 'sentimentShorts', 'sentimentLongs'],
378
+ encode: {
379
+ x: 'dates',
380
+ y: 'sentimentShorts',
381
+ },
338
382
  },
339
383
  {
340
384
  type: 'line',
@@ -342,7 +386,6 @@ export const getOption: GetOptionType = (
342
386
  id: 'sentiment-long',
343
387
  xAxisIndex: 1,
344
388
  yAxisIndex: 1,
345
- data: sentiments.map((sentiment) => [sentiment[0], sentiment[2]]),
346
389
  symbol: 'none',
347
390
  lineStyle: {
348
391
  color: 'transparent',
@@ -359,6 +402,11 @@ export const getOption: GetOptionType = (
359
402
  tooltip: {
360
403
  show: false,
361
404
  },
405
+ dimensions: ['dates', 'sentimentLongs'],
406
+ encode: {
407
+ x: 'dates',
408
+ y: 'sentimentLongs',
409
+ },
362
410
  },
363
411
  ],
364
412
  grid: [
@@ -19,36 +19,47 @@ export interface UseCrowdViewDataProps {
19
19
  granularity: Granularity;
20
20
  }
21
21
 
22
- export type ProcessedSentiment = [string, number, number];
23
-
24
- interface CrowdViewData {
25
- xAxisData: string[];
26
- // [open, close, low, high]
27
- candlesSeriesData: [number, number, number, number][];
28
- // [time, price, index]
29
- orderPositionBooks: [string, number | null, number][];
22
+ interface CrowdViewMainData {
23
+ dates: string[];
24
+ candlesOpen: number[];
25
+ candlesClose: number[];
26
+ candlesLow: number[];
27
+ candlesHigh: number[];
28
+ bookPrices?: (number | null)[];
29
+ bookIndexes?: (number | null)[];
30
+ sentimentShorts: (number | null)[];
31
+ sentimentLongs: (number | null)[];
32
+ }
33
+
34
+ interface CrowdViewAdditionalData {
30
35
  bucketWidth: number;
31
36
  buckets: Bucket[][];
32
- precision: number;
37
+ displayPrecision: number;
33
38
  bookType: BookType;
34
- sentiments: ProcessedSentiment[];
39
+ sentimentThresholdMin: number;
40
+ sentimentThresholdMax: number;
35
41
  }
36
42
 
37
43
  export interface UseCrowdViewDataReturn {
38
- data: CrowdViewData | null;
44
+ mainData?: CrowdViewMainData | null;
45
+ additionalData?: CrowdViewAdditionalData | null;
39
46
  loading: boolean;
40
47
  error: boolean;
41
48
  }
42
49
 
43
- export type GetOptionType = (
44
- props: CrowdViewData,
45
- isDark: boolean,
46
- isDesktop: boolean,
47
- labelCallback: (key: string, params?: Record<string, unknown>) => string
48
- ) => EChartsOption;
50
+ interface GetOptionProps {
51
+ mainData: CrowdViewMainData;
52
+ additionalData: CrowdViewAdditionalData;
53
+ isDark: boolean;
54
+ isDesktop: boolean;
55
+ labelCallback: (key: string, params?: Record<string, unknown>) => string;
56
+ }
57
+
58
+ export type GetOptionType = (props: GetOptionProps) => EChartsOption;
49
59
 
50
60
  export interface ChartProps {
51
- data: CrowdViewData;
61
+ mainData: CrowdViewMainData;
62
+ additionalData: CrowdViewAdditionalData;
52
63
  isDesktop: boolean;
53
64
  }
54
65
 
@@ -60,7 +71,7 @@ export interface ChartWithDataProps {
60
71
  }
61
72
 
62
73
  export interface GetLabelsDataProps {
63
- xAxisData: string[];
74
+ dates: string[];
64
75
  isGreaterThanTwoWeeks: boolean;
65
76
  }
66
77
 
@@ -16,9 +16,7 @@ import { BookType, DataSource, Division } from '../../../gql/types/graphql';
16
16
  import { BUCKET_CONFIG, INSTRUMENTS_CONFIG } from '../../constants';
17
17
  import type { UseCrowdViewDataProps, UseCrowdViewDataReturn } from './types';
18
18
  import {
19
- getTargetBucketWidth,
20
19
  getTimeSpanForGranularity,
21
- processBuckets,
22
20
  processOrderPositionBooks,
23
21
  processPriceCandles,
24
22
  processSentiments,
@@ -35,6 +33,8 @@ export const useCrowdViewData = ({
35
33
  division === Division.Ogm || division === Division.Oj
36
34
  ? DataSource.Mt5
37
35
  : DataSource.V20;
36
+
37
+ // Get price candles data
38
38
  const {
39
39
  loading: priceCandlesLoading,
40
40
  data: priceCandlesData,
@@ -56,26 +56,19 @@ export const useCrowdViewData = ({
56
56
  }
57
57
  );
58
58
 
59
- const priceCandlesProcessed = useMemo(
60
- () => processPriceCandles(priceCandlesData),
61
- [priceCandlesData]
62
- );
63
-
64
- const { minPrice, maxPrice, hasValidCandles, candleMap, candles } =
65
- priceCandlesProcessed;
66
-
67
- const targetBucketWidth = getTargetBucketWidth(granularity, instrument);
68
-
69
- const maxBookPrice = useMemo(
70
- () => maxPrice + targetBucketWidth * BUCKET_CONFIG.PRICE_PADDING_MULTIPLIER,
71
- [maxPrice, targetBucketWidth]
72
- );
73
-
74
- const minBookPrice = useMemo(
75
- () => minPrice - targetBucketWidth * BUCKET_CONFIG.PRICE_PADDING_MULTIPLIER,
76
- [minPrice, targetBucketWidth]
77
- );
78
-
59
+ const {
60
+ minPrice,
61
+ maxPrice,
62
+ hasValidCandles,
63
+ dates,
64
+ candlesOpen,
65
+ candlesClose,
66
+ candlesLow,
67
+ candlesHigh,
68
+ pipsLocation,
69
+ } = useMemo(() => processPriceCandles(priceCandlesData), [priceCandlesData]);
70
+
71
+ // Get order position books data
79
72
  const {
80
73
  loading: orderPositionLoading,
81
74
  data: orderPositionData,
@@ -88,14 +81,30 @@ export const useCrowdViewData = ({
88
81
  bookType: bookType || BookType.Order,
89
82
  timeSpan: getTimeSpanForGranularity(granularity),
90
83
  granularity,
91
- maxBookPrice,
92
- minBookPrice,
84
+ maxBookPrice: maxPrice,
85
+ minBookPrice: minPrice,
86
+ bucketMultiplier: 3,
87
+ bucketMargin: BUCKET_CONFIG.PRICE_MARGIN_MULTIPLIER,
93
88
  },
94
89
  fetchPolicy: 'no-cache',
95
90
  skip: priceCandlesLoading || !!priceCandlesError,
96
91
  }
97
92
  );
98
93
 
94
+ const {
95
+ bookPrices,
96
+ bookIndexes,
97
+ buckets,
98
+ bucketWidth,
99
+ sentimentThresholdMin,
100
+ sentimentThresholdMax,
101
+ hasValidBooks,
102
+ } = useMemo(
103
+ () => processOrderPositionBooks(orderPositionData, dates),
104
+ [orderPositionData, dates]
105
+ );
106
+
107
+ // Get sentiments data
99
108
  const {
100
109
  loading: sentimentsLoading,
101
110
  data: sentimentsData,
@@ -110,24 +119,14 @@ export const useCrowdViewData = ({
110
119
  skip: priceCandlesLoading || !!priceCandlesError,
111
120
  });
112
121
 
113
- const loading =
114
- priceCandlesLoading || orderPositionLoading || sentimentsLoading;
115
- const xAxisData = candles.map((candle) => candle?.point || '');
116
-
117
- const orderPositionBooks = useMemo(
118
- () => processOrderPositionBooks(orderPositionData, candleMap),
119
- [orderPositionData, candleMap]
122
+ const { sentimentLongs, sentimentShorts, hasValidSentiments } = useMemo(
123
+ () => processSentiments(sentimentsData, dates),
124
+ [sentimentsData, dates]
120
125
  );
121
126
 
122
- const buckets = useMemo(
123
- () => processBuckets(orderPositionData, targetBucketWidth),
124
- [orderPositionData, targetBucketWidth]
125
- );
126
-
127
- const sentiments = useMemo(
128
- () => processSentiments(sentimentsData, xAxisData),
129
- [sentimentsData, xAxisData]
130
- );
127
+ // Gather all results
128
+ const loading =
129
+ priceCandlesLoading || orderPositionLoading || sentimentsLoading;
131
130
 
132
131
  const error = useMemo((): Error | null => {
133
132
  if (priceCandlesError) {
@@ -142,7 +141,13 @@ export const useCrowdViewData = ({
142
141
  if (loading) {
143
142
  return null;
144
143
  }
145
- return validateData(priceCandlesData, orderPositionData, hasValidCandles);
144
+ return validateData(
145
+ priceCandlesData,
146
+ orderPositionData,
147
+ hasValidCandles,
148
+ hasValidBooks,
149
+ hasValidSentiments
150
+ );
146
151
  }, [
147
152
  priceCandlesError,
148
153
  orderPositionError,
@@ -151,6 +156,8 @@ export const useCrowdViewData = ({
151
156
  priceCandlesData,
152
157
  orderPositionData,
153
158
  hasValidCandles,
159
+ hasValidBooks,
160
+ hasValidSentiments,
154
161
  ]);
155
162
 
156
163
  const data = useMemo(() => {
@@ -158,42 +165,52 @@ export const useCrowdViewData = ({
158
165
  return null;
159
166
  }
160
167
 
161
- const candlesSeriesData: [number, number, number, number][] = candles.map(
162
- (candle) => [
163
- candle?.open || 0,
164
- candle?.close || 0,
165
- candle?.low || 0,
166
- candle?.high || 0,
167
- ]
168
- );
169
-
170
168
  return {
171
- buckets,
172
- xAxisData,
173
- candlesSeriesData,
174
- orderPositionBooks,
175
- bucketWidth: targetBucketWidth,
176
- precision: INSTRUMENTS_CONFIG[instrument].precision,
177
- bookType,
178
- sentiments,
169
+ mainData: {
170
+ dates,
171
+ candlesOpen,
172
+ candlesClose,
173
+ candlesLow,
174
+ candlesHigh,
175
+ bookPrices,
176
+ bookIndexes,
177
+ sentimentShorts,
178
+ sentimentLongs,
179
+ },
180
+ additionalData: {
181
+ bucketWidth,
182
+ buckets,
183
+ displayPrecision: pipsLocation,
184
+ bookType,
185
+ sentimentThresholdMin,
186
+ sentimentThresholdMax,
187
+ },
179
188
  };
180
189
  }, [
181
190
  priceCandlesData,
182
191
  orderPositionData,
183
192
  sentimentsData,
184
193
  error,
185
- candles,
194
+ dates,
195
+ candlesOpen,
196
+ candlesClose,
197
+ candlesLow,
198
+ candlesHigh,
199
+ bookPrices,
200
+ bookIndexes,
201
+ sentimentShorts,
202
+ sentimentLongs,
203
+ bucketWidth,
186
204
  buckets,
187
- xAxisData,
188
- orderPositionBooks,
189
- targetBucketWidth,
190
- instrument,
205
+ pipsLocation,
191
206
  bookType,
192
- sentiments,
207
+ sentimentThresholdMin,
208
+ sentimentThresholdMax,
193
209
  ]);
194
210
 
195
211
  return {
196
- data,
212
+ mainData: data?.mainData,
213
+ additionalData: data?.additionalData,
197
214
  loading,
198
215
  error: !!error,
199
216
  };