@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.
- package/CHANGELOG.md +216 -0
- package/dist/main/CrowdViewWidget/Main.js +1 -5
- package/dist/main/CrowdViewWidget/Main.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/Chart.js +16 -6
- package/dist/main/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/ChartWithData.js +15 -6
- package/dist/main/CrowdViewWidget/components/Chart/ChartWithData.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js +69 -29
- package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/types.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js +49 -26
- package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js +9 -10
- package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/index.js +0 -33
- package/dist/main/CrowdViewWidget/components/Chart/utils/index.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js +54 -12
- package/dist/main/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/processPriceCandles.js +49 -27
- package/dist/main/CrowdViewWidget/components/Chart/utils/processPriceCandles.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/processSentiments.js +32 -17
- package/dist/main/CrowdViewWidget/components/Chart/utils/processSentiments.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/validateData.js +8 -2
- package/dist/main/CrowdViewWidget/components/Chart/utils/validateData.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Legend/Legend.js +2 -3
- package/dist/main/CrowdViewWidget/components/Legend/Legend.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Legend/LegendBar.js +2 -2
- package/dist/main/CrowdViewWidget/components/Legend/LegendBar.js.map +1 -1
- package/dist/main/CrowdViewWidget/constants.js +2 -6
- package/dist/main/CrowdViewWidget/constants.js.map +1 -1
- package/dist/main/gql/getOrderPositionBooks.js +1 -1
- package/dist/main/gql/getOrderPositionBooks.js.map +1 -1
- package/dist/main/gql/getPriceCandles.js +1 -1
- package/dist/main/gql/getPriceCandles.js.map +1 -1
- package/dist/main/gql/types/gql.js +2 -2
- package/dist/main/gql/types/gql.js.map +1 -1
- package/dist/main/gql/types/graphql.js +111 -18
- package/dist/main/gql/types/graphql.js.map +1 -1
- package/dist/module/CrowdViewWidget/Main.js +2 -6
- package/dist/module/CrowdViewWidget/Main.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/Chart.js +17 -7
- package/dist/module/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/ChartWithData.js +15 -6
- package/dist/module/CrowdViewWidget/components/Chart/ChartWithData.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js +70 -30
- package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/types.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js +50 -27
- package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js +10 -11
- package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/index.js +0 -3
- package/dist/module/CrowdViewWidget/components/Chart/utils/index.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js +54 -12
- package/dist/module/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/processPriceCandles.js +49 -27
- package/dist/module/CrowdViewWidget/components/Chart/utils/processPriceCandles.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/processSentiments.js +32 -17
- package/dist/module/CrowdViewWidget/components/Chart/utils/processSentiments.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/validateData.js +8 -2
- package/dist/module/CrowdViewWidget/components/Chart/utils/validateData.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Legend/Legend.js +2 -3
- package/dist/module/CrowdViewWidget/components/Legend/Legend.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Legend/LegendBar.js +2 -2
- package/dist/module/CrowdViewWidget/components/Legend/LegendBar.js.map +1 -1
- package/dist/module/CrowdViewWidget/constants.js +1 -5
- package/dist/module/CrowdViewWidget/constants.js.map +1 -1
- package/dist/module/gql/getOrderPositionBooks.js +1 -1
- package/dist/module/gql/getOrderPositionBooks.js.map +1 -1
- package/dist/module/gql/getPriceCandles.js +1 -1
- package/dist/module/gql/getPriceCandles.js.map +1 -1
- package/dist/module/gql/types/gql.js +2 -2
- package/dist/module/gql/types/gql.js.map +1 -1
- package/dist/module/gql/types/graphql.js +111 -18
- package/dist/module/gql/types/graphql.js.map +1 -1
- package/dist/types/CrowdViewWidget/components/Chart/Chart.d.ts +1 -1
- package/dist/types/CrowdViewWidget/components/Chart/types.d.ts +28 -11
- package/dist/types/CrowdViewWidget/components/Chart/utils/chartUtils.d.ts +3 -4
- package/dist/types/CrowdViewWidget/components/Chart/utils/index.d.ts +0 -3
- package/dist/types/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.d.ts +10 -7
- package/dist/types/CrowdViewWidget/components/Chart/utils/processPriceCandles.d.ts +6 -21
- package/dist/types/CrowdViewWidget/components/Chart/utils/processSentiments.d.ts +5 -2
- package/dist/types/CrowdViewWidget/components/Chart/utils/validateData.d.ts +1 -1
- package/dist/types/CrowdViewWidget/components/Legend/Legend.d.ts +2 -2
- package/dist/types/CrowdViewWidget/components/Legend/LegendBar.d.ts +1 -1
- package/dist/types/CrowdViewWidget/constants.d.ts +1 -5
- package/dist/types/gql/types/gql.d.ts +6 -4
- package/dist/types/gql/types/graphql.d.ts +30 -11
- package/package.json +3 -3
- package/src/CrowdViewWidget/Main.tsx +2 -4
- package/src/CrowdViewWidget/components/Chart/Chart.tsx +15 -6
- package/src/CrowdViewWidget/components/Chart/ChartWithData.tsx +21 -4
- package/src/CrowdViewWidget/components/Chart/chartOptions.ts +78 -30
- package/src/CrowdViewWidget/components/Chart/types.ts +30 -19
- package/src/CrowdViewWidget/components/Chart/useCrowdViewData.ts +82 -65
- package/src/CrowdViewWidget/components/Chart/utils/chartUtils.ts +32 -20
- package/src/CrowdViewWidget/components/Chart/utils/index.ts +0 -3
- package/src/CrowdViewWidget/components/Chart/utils/processOrderPositionBooks.ts +84 -22
- package/src/CrowdViewWidget/components/Chart/utils/processPriceCandles.ts +52 -38
- package/src/CrowdViewWidget/components/Chart/utils/processSentiments.ts +45 -32
- package/src/CrowdViewWidget/components/Chart/utils/validateData.ts +10 -2
- package/src/CrowdViewWidget/components/Legend/Legend.tsx +4 -5
- package/src/CrowdViewWidget/components/Legend/LegendBar.tsx +3 -3
- package/src/CrowdViewWidget/constants.ts +1 -6
- package/src/gql/getOrderPositionBooks.ts +13 -5
- package/src/gql/getPriceCandles.ts +1 -0
- package/src/gql/types/gql.ts +6 -6
- package/src/gql/types/graphql.ts +98 -16
- package/test/components/Chart/utils/chartUtils.test.ts +32 -14
- package/test/components/Chart/utils/processSentiments.test.ts +137 -29
- package/test/utils/processOrderPositionBooks.test.ts +201 -84
- package/test/utils/processPriceCandles.test.ts +93 -67
- package/test/utils/validateData.test.ts +136 -38
- package/dist/main/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js +0 -37
- package/dist/main/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js.map +0 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js +0 -14
- package/dist/main/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js.map +0 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/processBuckets.js +0 -29
- package/dist/main/CrowdViewWidget/components/Chart/utils/processBuckets.js.map +0 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js +0 -29
- package/dist/module/CrowdViewWidget/components/Chart/utils/aggregateBuckets.js.map +0 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js +0 -7
- package/dist/module/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.js.map +0 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/processBuckets.js +0 -22
- package/dist/module/CrowdViewWidget/components/Chart/utils/processBuckets.js.map +0 -1
- package/dist/types/CrowdViewWidget/components/Chart/utils/aggregateBuckets.d.ts +0 -2
- package/dist/types/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.d.ts +0 -3
- package/dist/types/CrowdViewWidget/components/Chart/utils/processBuckets.d.ts +0 -3
- package/src/CrowdViewWidget/components/Chart/utils/aggregateBuckets.ts +0 -44
- package/src/CrowdViewWidget/components/Chart/utils/getTargetBucketWidth.ts +0 -13
- package/src/CrowdViewWidget/components/Chart/utils/processBuckets.ts +0 -43
- package/test/utils/aggregateBuckets.test.ts +0 -82
- package/test/utils/getTargetBucketWidth.test.ts +0 -37
- 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
|
|
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
|
|
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 = ({
|
|
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(
|
|
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 (!
|
|
117
|
+
if (!dates[startValue] || !dates[endValue]) {
|
|
109
118
|
return;
|
|
110
119
|
}
|
|
111
120
|
|
|
112
121
|
const isGreaterThanTwoWeeks = isDifferenceGreaterThanTwoWeeks(
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
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 {
|
|
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 && !!
|
|
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
|
|
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 {
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
35
|
+
displayPrecision,
|
|
24
36
|
bookType,
|
|
25
|
-
|
|
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 =
|
|
43
|
-
(
|
|
44
|
-
(
|
|
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
|
-
|
|
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(
|
|
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:
|
|
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) =>
|
|
157
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
37
|
+
displayPrecision: number;
|
|
33
38
|
bookType: BookType;
|
|
34
|
-
|
|
39
|
+
sentimentThresholdMin: number;
|
|
40
|
+
sentimentThresholdMax: number;
|
|
35
41
|
}
|
|
36
42
|
|
|
37
43
|
export interface UseCrowdViewDataReturn {
|
|
38
|
-
|
|
44
|
+
mainData?: CrowdViewMainData | null;
|
|
45
|
+
additionalData?: CrowdViewAdditionalData | null;
|
|
39
46
|
loading: boolean;
|
|
40
47
|
error: boolean;
|
|
41
48
|
}
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
) =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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(
|
|
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
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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
|
-
|
|
194
|
+
dates,
|
|
195
|
+
candlesOpen,
|
|
196
|
+
candlesClose,
|
|
197
|
+
candlesLow,
|
|
198
|
+
candlesHigh,
|
|
199
|
+
bookPrices,
|
|
200
|
+
bookIndexes,
|
|
201
|
+
sentimentShorts,
|
|
202
|
+
sentimentLongs,
|
|
203
|
+
bucketWidth,
|
|
186
204
|
buckets,
|
|
187
|
-
|
|
188
|
-
orderPositionBooks,
|
|
189
|
-
targetBucketWidth,
|
|
190
|
-
instrument,
|
|
205
|
+
pipsLocation,
|
|
191
206
|
bookType,
|
|
192
|
-
|
|
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
|
};
|