@oanda/labs-crowd-view-widget 1.0.44 → 1.0.45

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 (44) hide show
  1. package/CHANGELOG.md +184 -0
  2. package/dist/main/CrowdViewWidget/Main.js +17 -6
  3. package/dist/main/CrowdViewWidget/Main.js.map +1 -1
  4. package/dist/main/CrowdViewWidget/components/Chart/Chart.js +6 -10
  5. package/dist/main/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
  6. package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js +33 -18
  7. package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
  8. package/dist/main/CrowdViewWidget/components/Chart/types.js.map +1 -1
  9. package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js +23 -9
  10. package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
  11. package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js +39 -2
  12. package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
  13. package/dist/main/CrowdViewWidget/constants.js +5 -4
  14. package/dist/main/CrowdViewWidget/constants.js.map +1 -1
  15. package/dist/main/translations/sources/en.json +24 -0
  16. package/dist/module/CrowdViewWidget/Main.js +18 -7
  17. package/dist/module/CrowdViewWidget/Main.js.map +1 -1
  18. package/dist/module/CrowdViewWidget/components/Chart/Chart.js +7 -11
  19. package/dist/module/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
  20. package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js +34 -19
  21. package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
  22. package/dist/module/CrowdViewWidget/components/Chart/types.js.map +1 -1
  23. package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js +23 -9
  24. package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
  25. package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js +36 -1
  26. package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
  27. package/dist/module/CrowdViewWidget/constants.js +5 -4
  28. package/dist/module/CrowdViewWidget/constants.js.map +1 -1
  29. package/dist/module/translations/sources/en.json +24 -0
  30. package/dist/types/CrowdViewWidget/components/Chart/types.d.ts +6 -2
  31. package/dist/types/CrowdViewWidget/components/Chart/utils/chartUtils.d.ts +5 -0
  32. package/dist/types/CrowdViewWidget/constants.d.ts +4 -3
  33. package/lokalise.config.json +1 -1
  34. package/package.json +3 -3
  35. package/src/CrowdViewWidget/Main.tsx +23 -7
  36. package/src/CrowdViewWidget/components/Chart/Chart.tsx +6 -12
  37. package/src/CrowdViewWidget/components/Chart/chartOptions.ts +41 -17
  38. package/src/CrowdViewWidget/components/Chart/types.ts +6 -2
  39. package/src/CrowdViewWidget/components/Chart/useCrowdViewData.ts +34 -9
  40. package/src/CrowdViewWidget/components/Chart/utils/chartUtils.ts +69 -1
  41. package/src/CrowdViewWidget/constants.ts +4 -3
  42. package/src/translations/sources/en.json +24 -0
  43. package/test/Main.test.tsx +72 -26
  44. package/test/components/Chart/utils/chartUtils.test.ts +172 -0
@@ -48,8 +48,22 @@ const processOrderPositionBooks = (orderPositionData, candleMap) => {
48
48
  return orderPositionData.orderPositionBooks.filter(book => {
49
49
  var _book$buckets;
50
50
  return book !== null && ((_book$buckets = book.buckets) === null || _book$buckets === void 0 ? void 0 : _book$buckets.length) > 0;
51
- }).map(book => {
51
+ }).map((book, index) => {
52
52
  var _candle$high;
53
+ const candle = candleMap.get(book.time);
54
+ const price = (_candle$high = candle === null || candle === void 0 ? void 0 : candle.high) !== null && _candle$high !== void 0 ? _candle$high : null;
55
+ return [book.time, price, index];
56
+ });
57
+ };
58
+ const processBuckets = orderPositionData => {
59
+ var _orderPositionData$or2;
60
+ if (!(orderPositionData !== null && orderPositionData !== void 0 && (_orderPositionData$or2 = orderPositionData.orderPositionBooks) !== null && _orderPositionData$or2 !== void 0 && _orderPositionData$or2.length)) {
61
+ return [];
62
+ }
63
+ return orderPositionData.orderPositionBooks.filter(book => {
64
+ var _book$buckets2;
65
+ return book !== null && ((_book$buckets2 = book.buckets) === null || _book$buckets2 === void 0 ? void 0 : _book$buckets2.length) > 0;
66
+ }).map(book => {
53
67
  const filteredBuckets = book.buckets.filter(bucket => {
54
68
  if (!bucket || bucket.sentiment === undefined || bucket.sentiment === null || bucket.price === undefined) {
55
69
  return false;
@@ -59,15 +73,13 @@ const processOrderPositionBooks = (orderPositionData, candleMap) => {
59
73
  price: bucket.price,
60
74
  sentiment: bucket.sentiment
61
75
  }));
62
- const candle = candleMap.get(book.time);
63
- const price = (_candle$high = candle === null || candle === void 0 ? void 0 : candle.high) !== null && _candle$high !== void 0 ? _candle$high : null;
64
- return [book.time, price, JSON.stringify(filteredBuckets)];
76
+ return filteredBuckets;
65
77
  });
66
78
  };
67
79
  const validateData = (priceCandlesData, orderPositionData, hasValidCandles) => {
68
- var _priceCandlesData$pri2, _priceCandlesData$pri3, _orderPositionData$or2, _orderPositionData$or3;
80
+ var _priceCandlesData$pri2, _priceCandlesData$pri3, _orderPositionData$or3, _orderPositionData$or4;
69
81
  const hasValidPriceData = ((_priceCandlesData$pri2 = priceCandlesData === null || priceCandlesData === void 0 || (_priceCandlesData$pri3 = priceCandlesData.priceCandles) === null || _priceCandlesData$pri3 === void 0 || (_priceCandlesData$pri3 = _priceCandlesData$pri3.candle) === null || _priceCandlesData$pri3 === void 0 ? void 0 : _priceCandlesData$pri3.length) !== null && _priceCandlesData$pri2 !== void 0 ? _priceCandlesData$pri2 : 0) >= 1;
70
- const hasValidOrderData = ((_orderPositionData$or2 = orderPositionData === null || orderPositionData === void 0 || (_orderPositionData$or3 = orderPositionData.orderPositionBooks) === null || _orderPositionData$or3 === void 0 ? void 0 : _orderPositionData$or3.length) !== null && _orderPositionData$or2 !== void 0 ? _orderPositionData$or2 : 0) >= 1;
82
+ const hasValidOrderData = ((_orderPositionData$or3 = orderPositionData === null || orderPositionData === void 0 || (_orderPositionData$or4 = orderPositionData.orderPositionBooks) === null || _orderPositionData$or4 === void 0 ? void 0 : _orderPositionData$or4.length) !== null && _orderPositionData$or3 !== void 0 ? _orderPositionData$or3 : 0) >= 1;
71
83
  if (!hasValidPriceData) {
72
84
  return new Error('Insufficient price candle data');
73
85
  }
@@ -128,6 +140,7 @@ export const useCrowdViewData = _ref => {
128
140
  });
129
141
  const loading = priceCandlesLoading || orderPositionLoading;
130
142
  const orderPositionBooks = useMemo(() => processOrderPositionBooks(orderPositionData, candleMap), [orderPositionData, candleMap]);
143
+ const buckets = useMemo(() => processBuckets(orderPositionData), [orderPositionData]);
131
144
  const error = useMemo(() => {
132
145
  if (priceCandlesError) {
133
146
  return new Error("Price candles error: ".concat(priceCandlesError.message));
@@ -141,19 +154,20 @@ export const useCrowdViewData = _ref => {
141
154
  return validateData(priceCandlesData, orderPositionData, hasValidCandles);
142
155
  }, [priceCandlesError, orderPositionError, loading, priceCandlesData, orderPositionData, hasValidCandles]);
143
156
  const data = useMemo(() => {
144
- var _orderPositionData$or4;
157
+ var _orderPositionData$or5;
145
158
  if (!priceCandlesData || !orderPositionData || error) {
146
159
  return null;
147
160
  }
148
161
  const xAxisData = candles.map(candle => (candle === null || candle === void 0 ? void 0 : candle.point) || '');
149
162
  const candlesSeriesData = candles.map(candle => [(candle === null || candle === void 0 ? void 0 : candle.open) || 0, (candle === null || candle === void 0 ? void 0 : candle.close) || 0, (candle === null || candle === void 0 ? void 0 : candle.low) || 0, (candle === null || candle === void 0 ? void 0 : candle.high) || 0]);
150
163
  return {
164
+ buckets,
151
165
  xAxisData,
152
166
  candlesSeriesData,
153
167
  orderPositionBooks,
154
- bucketWidth: ((_orderPositionData$or4 = orderPositionData.orderPositionBooks) === null || _orderPositionData$or4 === void 0 || (_orderPositionData$or4 = _orderPositionData$or4[0]) === null || _orderPositionData$or4 === void 0 ? void 0 : _orderPositionData$or4.bucketWidth) || 0
168
+ bucketWidth: ((_orderPositionData$or5 = orderPositionData.orderPositionBooks) === null || _orderPositionData$or5 === void 0 || (_orderPositionData$or5 = _orderPositionData$or5[0]) === null || _orderPositionData$or5 === void 0 ? void 0 : _orderPositionData$or5.bucketWidth) || 0
155
169
  };
156
- }, [priceCandlesData, orderPositionData, error, candles, orderPositionBooks]);
170
+ }, [priceCandlesData, orderPositionData, error, candles, orderPositionBooks, buckets]);
157
171
  return {
158
172
  data,
159
173
  loading,
@@ -1 +1 @@
1
- {"version":3,"file":"useCrowdViewData.js","names":["useQuery","useMemo","getOrderPositionBooks","getPriceCandles","BookType","DataSource","Division","BOOKS_THRESHOLDS","BUCKET_CONFIG","getTimeSpanForGranularity","processPriceCandles","priceCandlesData","_priceCandlesData$pri","priceCandles","candle","length","minPrice","maxPrice","hasValidCandles","candleMap","Map","candles","calculatedMinPrice","Number","MAX_VALUE","calculatedMaxPrice","MIN_VALUE","forEach","high","low","point","set","processOrderPositionBooks","orderPositionData","_orderPositionData$or","orderPositionBooks","filter","book","_book$buckets","buckets","map","_candle$high","filteredBuckets","bucket","sentiment","undefined","price","Math","abs","MIN","get","time","JSON","stringify","validateData","_priceCandlesData$pri2","_priceCandlesData$pri3","_orderPositionData$or2","_orderPositionData$or3","hasValidPriceData","hasValidOrderData","Error","useCrowdViewData","_ref","instrument","bookType","division","granularity","loading","priceCandlesLoading","data","error","priceCandlesError","variables","dataSource","Oc","V20","Mt5","timeSpan","fetchPolicy","priceCandlesProcessed","maxBookPrice","DEFAULT_WIDTH","PRICE_PADDING_MULTIPLIER","minBookPrice","orderPositionLoading","orderPositionError","Order","skip","concat","message","_orderPositionData$or4","xAxisData","candlesSeriesData","open","close","bucketWidth"],"sources":["../../../../../src/CrowdViewWidget/components/Chart/useCrowdViewData.ts"],"sourcesContent":["import { useQuery } from '@apollo/client';\nimport { useMemo } from 'react';\n\nimport { getOrderPositionBooks } from '../../../gql/getOrderPositionBooks';\nimport { getPriceCandles } from '../../../gql/getPriceCandles';\nimport type {\n GetOrderPositionBooksQuery,\n GetOrderPositionBooksQueryVariables,\n GetPriceCandlesQuery,\n GetPriceCandlesQueryVariables,\n} from '../../../gql/types/graphql';\nimport { BookType, DataSource, Division } from '../../../gql/types/graphql';\nimport { BOOKS_THRESHOLDS, BUCKET_CONFIG } from '../../constants';\nimport type { UseCrowdViewDataProps, UseCrowdViewDataReturn } from './types';\nimport { getTimeSpanForGranularity } from './utils/chartUtils';\n\nconst processPriceCandles = (\n priceCandlesData: GetPriceCandlesQuery | undefined\n) => {\n if (!priceCandlesData?.priceCandles?.candle?.length) {\n return {\n minPrice: 0,\n maxPrice: 0,\n hasValidCandles: false,\n candleMap: new Map(),\n candles: [],\n };\n }\n\n const candles = priceCandlesData.priceCandles.candle;\n let calculatedMinPrice = Number.MAX_VALUE;\n let calculatedMaxPrice = Number.MIN_VALUE;\n\n const candleMap = new Map<\n string,\n {\n point?: string;\n high?: number;\n low?: number;\n open?: number;\n close?: number;\n }\n >();\n\n candles.forEach((candle) => {\n if (!candle) return;\n\n if (candle.high > calculatedMaxPrice) {\n calculatedMaxPrice = candle.high;\n }\n if (candle.low < calculatedMinPrice) {\n calculatedMinPrice = candle.low;\n }\n\n if (candle.point) {\n candleMap.set(candle.point, candle);\n }\n });\n\n return {\n minPrice: calculatedMinPrice,\n maxPrice: calculatedMaxPrice,\n hasValidCandles: true,\n candleMap,\n candles,\n };\n};\n\nconst processOrderPositionBooks = (\n orderPositionData: GetOrderPositionBooksQuery | undefined,\n candleMap: Map<\n string,\n {\n point?: string;\n high?: number;\n low?: number;\n open?: number;\n close?: number;\n }\n >\n) => {\n if (!orderPositionData?.orderPositionBooks?.length) {\n return [];\n }\n\n return orderPositionData.orderPositionBooks\n .filter((book): book is NonNullable<typeof book> => {\n return book !== null && book.buckets?.length > 0;\n })\n .map((book) => {\n const filteredBuckets = book.buckets\n .filter((bucket) => {\n if (\n !bucket ||\n bucket.sentiment === undefined ||\n bucket.sentiment === null ||\n bucket.price === undefined\n ) {\n return false;\n }\n return Math.abs(bucket.sentiment) >= BOOKS_THRESHOLDS.MIN;\n })\n .map((bucket) => ({\n price: bucket!.price!,\n sentiment: bucket!.sentiment!,\n }));\n\n const candle = candleMap.get(book.time);\n const price = candle?.high ?? null;\n\n return [book.time, price, JSON.stringify(filteredBuckets)] as [\n string,\n number,\n string,\n ];\n });\n};\n\nconst validateData = (\n priceCandlesData: GetPriceCandlesQuery | undefined,\n orderPositionData: GetOrderPositionBooksQuery | undefined,\n hasValidCandles: boolean\n): Error | null => {\n const hasValidPriceData =\n (priceCandlesData?.priceCandles?.candle?.length ?? 0) >= 1;\n const hasValidOrderData =\n (orderPositionData?.orderPositionBooks?.length ?? 0) >= 1;\n\n if (!hasValidPriceData) {\n return new Error('Insufficient price candle data');\n }\n if (!hasValidOrderData) {\n return new Error('Insufficient order position data');\n }\n if (!hasValidCandles) {\n return new Error('Invalid candle data');\n }\n\n return null;\n};\n\nexport const useCrowdViewData = ({\n instrument,\n bookType,\n division,\n granularity,\n}: UseCrowdViewDataProps): UseCrowdViewDataReturn => {\n const {\n loading: priceCandlesLoading,\n data: priceCandlesData,\n error: priceCandlesError,\n } = useQuery<GetPriceCandlesQuery, GetPriceCandlesQueryVariables>(\n getPriceCandles,\n {\n variables: {\n dataSource: division === Division.Oc ? DataSource.V20 : DataSource.Mt5,\n division,\n instrument,\n granularity,\n timeSpan: getTimeSpanForGranularity(granularity),\n },\n fetchPolicy: 'no-cache',\n }\n );\n\n const priceCandlesProcessed = useMemo(\n () => processPriceCandles(priceCandlesData),\n [priceCandlesData]\n );\n\n const { minPrice, maxPrice, hasValidCandles, candleMap, candles } =\n priceCandlesProcessed;\n\n const maxBookPrice = useMemo(\n () =>\n maxPrice +\n BUCKET_CONFIG.DEFAULT_WIDTH * BUCKET_CONFIG.PRICE_PADDING_MULTIPLIER,\n [maxPrice]\n );\n\n const minBookPrice = useMemo(\n () =>\n minPrice -\n BUCKET_CONFIG.DEFAULT_WIDTH * BUCKET_CONFIG.PRICE_PADDING_MULTIPLIER,\n [minPrice]\n );\n\n const {\n loading: orderPositionLoading,\n data: orderPositionData,\n error: orderPositionError,\n } = useQuery<GetOrderPositionBooksQuery, GetOrderPositionBooksQueryVariables>(\n getOrderPositionBooks,\n {\n variables: {\n instrument,\n bookType: bookType || BookType.Order,\n timeSpan: getTimeSpanForGranularity(granularity),\n granularity,\n maxBookPrice,\n minBookPrice,\n },\n fetchPolicy: 'no-cache',\n skip: priceCandlesLoading || !!priceCandlesError,\n }\n );\n\n const loading = priceCandlesLoading || orderPositionLoading;\n\n const orderPositionBooks = useMemo(\n () => processOrderPositionBooks(orderPositionData, candleMap),\n [orderPositionData, candleMap]\n );\n\n const error = useMemo((): Error | null => {\n if (priceCandlesError) {\n return new Error(`Price candles error: ${priceCandlesError.message}`);\n }\n if (orderPositionError) {\n return new Error(`Order position error: ${orderPositionError.message}`);\n }\n if (loading) {\n return null;\n }\n return validateData(priceCandlesData, orderPositionData, hasValidCandles);\n }, [\n priceCandlesError,\n orderPositionError,\n loading,\n priceCandlesData,\n orderPositionData,\n hasValidCandles,\n ]);\n\n const data = useMemo(() => {\n if (!priceCandlesData || !orderPositionData || error) {\n return null;\n }\n\n const xAxisData = candles.map((candle) => candle?.point || '');\n const candlesSeriesData: [number, number, number, number][] = candles.map(\n (candle) => [\n candle?.open || 0,\n candle?.close || 0,\n candle?.low || 0,\n candle?.high || 0,\n ]\n );\n\n return {\n xAxisData,\n candlesSeriesData,\n orderPositionBooks,\n bucketWidth: orderPositionData.orderPositionBooks?.[0]?.bucketWidth || 0,\n };\n }, [priceCandlesData, orderPositionData, error, candles, orderPositionBooks]);\n\n return {\n data,\n loading,\n error: !!error,\n };\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"useCrowdViewData.js","names":["useQuery","useMemo","getOrderPositionBooks","getPriceCandles","BookType","DataSource","Division","BOOKS_THRESHOLDS","BUCKET_CONFIG","getTimeSpanForGranularity","processPriceCandles","priceCandlesData","_priceCandlesData$pri","priceCandles","candle","length","minPrice","maxPrice","hasValidCandles","candleMap","Map","candles","calculatedMinPrice","Number","MAX_VALUE","calculatedMaxPrice","MIN_VALUE","forEach","high","low","point","set","processOrderPositionBooks","orderPositionData","_orderPositionData$or","orderPositionBooks","filter","book","_book$buckets","buckets","map","index","_candle$high","get","time","price","processBuckets","_orderPositionData$or2","_book$buckets2","filteredBuckets","bucket","sentiment","undefined","Math","abs","MIN","validateData","_priceCandlesData$pri2","_priceCandlesData$pri3","_orderPositionData$or3","_orderPositionData$or4","hasValidPriceData","hasValidOrderData","Error","useCrowdViewData","_ref","instrument","bookType","division","granularity","loading","priceCandlesLoading","data","error","priceCandlesError","variables","dataSource","Oc","V20","Mt5","timeSpan","fetchPolicy","priceCandlesProcessed","maxBookPrice","DEFAULT_WIDTH","PRICE_PADDING_MULTIPLIER","minBookPrice","orderPositionLoading","orderPositionError","Order","skip","concat","message","_orderPositionData$or5","xAxisData","candlesSeriesData","open","close","bucketWidth"],"sources":["../../../../../src/CrowdViewWidget/components/Chart/useCrowdViewData.ts"],"sourcesContent":["import { useQuery } from '@apollo/client';\nimport { useMemo } from 'react';\n\nimport { getOrderPositionBooks } from '../../../gql/getOrderPositionBooks';\nimport { getPriceCandles } from '../../../gql/getPriceCandles';\nimport type {\n GetOrderPositionBooksQuery,\n GetOrderPositionBooksQueryVariables,\n GetPriceCandlesQuery,\n GetPriceCandlesQueryVariables,\n} from '../../../gql/types/graphql';\nimport { BookType, DataSource, Division } from '../../../gql/types/graphql';\nimport { BOOKS_THRESHOLDS, BUCKET_CONFIG } from '../../constants';\nimport type { UseCrowdViewDataProps, UseCrowdViewDataReturn } from './types';\nimport { getTimeSpanForGranularity } from './utils/chartUtils';\n\nconst processPriceCandles = (\n priceCandlesData: GetPriceCandlesQuery | undefined\n) => {\n if (!priceCandlesData?.priceCandles?.candle?.length) {\n return {\n minPrice: 0,\n maxPrice: 0,\n hasValidCandles: false,\n candleMap: new Map(),\n candles: [],\n };\n }\n\n const candles = priceCandlesData.priceCandles.candle;\n let calculatedMinPrice = Number.MAX_VALUE;\n let calculatedMaxPrice = Number.MIN_VALUE;\n\n const candleMap = new Map<\n string,\n {\n point?: string;\n high?: number;\n low?: number;\n open?: number;\n close?: number;\n }\n >();\n\n candles.forEach((candle) => {\n if (!candle) return;\n\n if (candle.high > calculatedMaxPrice) {\n calculatedMaxPrice = candle.high;\n }\n if (candle.low < calculatedMinPrice) {\n calculatedMinPrice = candle.low;\n }\n\n if (candle.point) {\n candleMap.set(candle.point, candle);\n }\n });\n\n return {\n minPrice: calculatedMinPrice,\n maxPrice: calculatedMaxPrice,\n hasValidCandles: true,\n candleMap,\n candles,\n };\n};\n\nconst processOrderPositionBooks = (\n orderPositionData: GetOrderPositionBooksQuery | undefined,\n candleMap: Map<\n string,\n {\n point?: string;\n high?: number;\n low?: number;\n open?: number;\n close?: number;\n }\n >\n) => {\n if (!orderPositionData?.orderPositionBooks?.length) {\n return [];\n }\n\n return orderPositionData.orderPositionBooks\n .filter((book): book is NonNullable<typeof book> => {\n return book !== null && book.buckets?.length > 0;\n })\n .map((book, index) => {\n const candle = candleMap.get(book.time);\n const price = candle?.high ?? null;\n\n return [book.time, price, index] as [string, number, number];\n });\n};\n\nconst processBuckets = (\n orderPositionData: GetOrderPositionBooksQuery | undefined\n) => {\n if (!orderPositionData?.orderPositionBooks?.length) {\n return [];\n }\n\n return orderPositionData.orderPositionBooks\n .filter((book): book is NonNullable<typeof book> => {\n return book !== null && book.buckets?.length > 0;\n })\n .map((book) => {\n const filteredBuckets = book.buckets\n .filter((bucket) => {\n if (\n !bucket ||\n bucket.sentiment === undefined ||\n bucket.sentiment === null ||\n bucket.price === undefined\n ) {\n return false;\n }\n return Math.abs(bucket.sentiment) >= BOOKS_THRESHOLDS.MIN;\n })\n .map((bucket) => ({\n price: bucket!.price!,\n sentiment: bucket!.sentiment!,\n }));\n\n return filteredBuckets;\n });\n};\n\nconst validateData = (\n priceCandlesData: GetPriceCandlesQuery | undefined,\n orderPositionData: GetOrderPositionBooksQuery | undefined,\n hasValidCandles: boolean\n): Error | null => {\n const hasValidPriceData =\n (priceCandlesData?.priceCandles?.candle?.length ?? 0) >= 1;\n const hasValidOrderData =\n (orderPositionData?.orderPositionBooks?.length ?? 0) >= 1;\n\n if (!hasValidPriceData) {\n return new Error('Insufficient price candle data');\n }\n if (!hasValidOrderData) {\n return new Error('Insufficient order position data');\n }\n if (!hasValidCandles) {\n return new Error('Invalid candle data');\n }\n\n return null;\n};\n\nexport const useCrowdViewData = ({\n instrument,\n bookType,\n division,\n granularity,\n}: UseCrowdViewDataProps): UseCrowdViewDataReturn => {\n const {\n loading: priceCandlesLoading,\n data: priceCandlesData,\n error: priceCandlesError,\n } = useQuery<GetPriceCandlesQuery, GetPriceCandlesQueryVariables>(\n getPriceCandles,\n {\n variables: {\n dataSource: division === Division.Oc ? DataSource.V20 : DataSource.Mt5,\n division,\n instrument,\n granularity,\n timeSpan: getTimeSpanForGranularity(granularity),\n },\n fetchPolicy: 'no-cache',\n }\n );\n\n const priceCandlesProcessed = useMemo(\n () => processPriceCandles(priceCandlesData),\n [priceCandlesData]\n );\n\n const { minPrice, maxPrice, hasValidCandles, candleMap, candles } =\n priceCandlesProcessed;\n\n const maxBookPrice = useMemo(\n () =>\n maxPrice +\n BUCKET_CONFIG.DEFAULT_WIDTH * BUCKET_CONFIG.PRICE_PADDING_MULTIPLIER,\n [maxPrice]\n );\n\n const minBookPrice = useMemo(\n () =>\n minPrice -\n BUCKET_CONFIG.DEFAULT_WIDTH * BUCKET_CONFIG.PRICE_PADDING_MULTIPLIER,\n [minPrice]\n );\n\n const {\n loading: orderPositionLoading,\n data: orderPositionData,\n error: orderPositionError,\n } = useQuery<GetOrderPositionBooksQuery, GetOrderPositionBooksQueryVariables>(\n getOrderPositionBooks,\n {\n variables: {\n instrument,\n bookType: bookType || BookType.Order,\n timeSpan: getTimeSpanForGranularity(granularity),\n granularity,\n maxBookPrice,\n minBookPrice,\n },\n fetchPolicy: 'no-cache',\n skip: priceCandlesLoading || !!priceCandlesError,\n }\n );\n\n const loading = priceCandlesLoading || orderPositionLoading;\n\n const orderPositionBooks = useMemo(\n () => processOrderPositionBooks(orderPositionData, candleMap),\n [orderPositionData, candleMap]\n );\n\n const buckets = useMemo(\n () => processBuckets(orderPositionData),\n [orderPositionData]\n );\n\n const error = useMemo((): Error | null => {\n if (priceCandlesError) {\n return new Error(`Price candles error: ${priceCandlesError.message}`);\n }\n if (orderPositionError) {\n return new Error(`Order position error: ${orderPositionError.message}`);\n }\n if (loading) {\n return null;\n }\n return validateData(priceCandlesData, orderPositionData, hasValidCandles);\n }, [\n priceCandlesError,\n orderPositionError,\n loading,\n priceCandlesData,\n orderPositionData,\n hasValidCandles,\n ]);\n\n const data = useMemo(() => {\n if (!priceCandlesData || !orderPositionData || error) {\n return null;\n }\n\n const xAxisData = candles.map((candle) => candle?.point || '');\n const candlesSeriesData: [number, number, number, number][] = candles.map(\n (candle) => [\n candle?.open || 0,\n candle?.close || 0,\n candle?.low || 0,\n candle?.high || 0,\n ]\n );\n\n return {\n buckets,\n xAxisData,\n candlesSeriesData,\n orderPositionBooks,\n bucketWidth: orderPositionData.orderPositionBooks?.[0]?.bucketWidth || 0,\n };\n }, [\n priceCandlesData,\n orderPositionData,\n error,\n candles,\n orderPositionBooks,\n buckets,\n ]);\n\n return {\n data,\n loading,\n error: !!error,\n };\n};\n"],"mappings":"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","ignoreList":[]}
@@ -16,7 +16,7 @@ export const getLabelData = _ref => {
16
16
  return isGreaterThanTwoWeeks ? currentDate.getDate() !== previousDate.getDate() : currentDate.getMonth() !== previousDate.getMonth();
17
17
  }).map(item => ({
18
18
  name: new Date(item).toLocaleDateString(undefined, {
19
- month: 'short',
19
+ month: isGreaterThanTwoWeeks ? 'short' : 'long',
20
20
  day: isGreaterThanTwoWeeks ? 'numeric' : undefined
21
21
  }),
22
22
  xAxis: item,
@@ -56,4 +56,39 @@ const getGradientColor = (value, startColor, targetColor) => {
56
56
  return colorScale(value).hex();
57
57
  };
58
58
  export const getRectColor = sentiment => sentiment < 0 ? getGradientColor(sentiment * -1, COLOR_MAP.short[0], COLOR_MAP.short[1]) : getGradientColor(sentiment, COLOR_MAP.long[0], COLOR_MAP.long[1]);
59
+ export const getTooltipFormatter = (params, buckets, bucketWidth, selectedPrice, labelCallback) => {
60
+ var _booksParam$value;
61
+ const arr = params;
62
+ const candleParam = arr[0];
63
+ const booksParam = arr[1];
64
+ const time = new Date(candleParam.axisValue);
65
+ const candleData = candleParam.value;
66
+ const booksData = (_booksParam$value = booksParam === null || booksParam === void 0 ? void 0 : booksParam.value) !== null && _booksParam$value !== void 0 ? _booksParam$value : [];
67
+ const bucketsIndex = booksData[2];
68
+ const selectedBuckets = buckets[bucketsIndex];
69
+ const matchedBucket = selectedBuckets === null || selectedBuckets === void 0 ? void 0 : selectedBuckets.find(_ref2 => {
70
+ let {
71
+ price
72
+ } = _ref2;
73
+ return selectedPrice >= price && selectedPrice < price + bucketWidth;
74
+ });
75
+ const showCandles = !!candleData[1] && !!candleData[2] && !!candleData[3] && !!candleData[4];
76
+ return "<p>".concat(time.toLocaleString(undefined, {
77
+ hour: '2-digit',
78
+ minute: '2-digit',
79
+ year: 'numeric',
80
+ day: 'numeric',
81
+ month: 'numeric',
82
+ timeZoneName: 'short'
83
+ }), "</p><br />\n").concat(showCandles ? "<p><b>".concat(labelCallback('candle'), ":</b></p>\n<p>").concat(labelCallback('open_price'), ": ").concat(candleData[1], " </p>\n<p>").concat(labelCallback('close_price'), ": ").concat(candleData[2], " </p>\n<p>").concat(labelCallback('low'), ": ").concat(candleData[3], " </p>\n<p>").concat(labelCallback('high'), ": ").concat(candleData[4], " </p>\n") : '', "\n").concat(matchedBucket ? "<br /><p><b>".concat(labelCallback('orders'), ":</b></p>\n<p>").concat(labelCallback('price_range'), ": ").concat(matchedBucket.price, " - ").concat(Number(matchedBucket.price + bucketWidth).toFixed(4), " </p>\n<p>").concat(matchedBucket.sentiment < 0 ? labelCallback('sell_advantage') : labelCallback('buy_advantage'), ": ").concat(Math.abs(matchedBucket.sentiment), "% </p>") : '');
84
+ };
85
+ export const formatXAxisLabel = (value, isGreaterThanTwoWeeks) => {
86
+ const date = new Date(value);
87
+ return isGreaterThanTwoWeeks ? "".concat(date.toLocaleTimeString(undefined, {
88
+ hour: '2-digit',
89
+ minute: '2-digit'
90
+ })) : "".concat(CHART_CONFIG.X_AXIS_DATE_PADDING).concat(date.toLocaleDateString(undefined, {
91
+ day: 'numeric'
92
+ })).concat(CHART_CONFIG.X_AXIS_DATE_PADDING);
93
+ };
59
94
  //# sourceMappingURL=chartUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chartUtils.js","names":["chroma","Granularity","TimeSpan","BOOKS_THRESHOLDS","CHART_CONFIG","COLOR_MAP","TIME_THRESHOLDS","getLabelData","_ref","xAxisData","isGreaterThanTwoWeeks","filter","record","index","arr","previousTimestamp","currentDate","Date","previousDate","getDate","getMonth","map","item","name","toLocaleDateString","undefined","month","day","xAxis","y","HEIGHT","silent","emphasis","disabled","label","fontFamily","fontSize","position","align","formatter","isDifferenceGreaterThanTwoWeeks","startDate","endDate","date1","date2","differenceInMs","Math","abs","getTime","TWO_WEEKS_MS","getTimeSpanForGranularity","granularity","granularityTimeSpanMap","M5","TwoDays","M15","FiveDays","H1","TwentyDays","H4","NinetyDays","getGradientColor","value","startColor","targetColor","startThreshold","MIN","endThreshold","MAX","colorScale","scale","domain","mode","hex","getRectColor","sentiment","short","long"],"sources":["../../../../../../src/CrowdViewWidget/components/Chart/utils/chartUtils.ts"],"sourcesContent":["import chroma from 'chroma-js';\n\nimport { Granularity, TimeSpan } from '../../../../gql/types/graphql';\nimport {\n BOOKS_THRESHOLDS,\n CHART_CONFIG,\n COLOR_MAP,\n TIME_THRESHOLDS,\n} from '../../../constants';\nimport type { GetLabelsDataProps } from '../types';\n\nexport const getLabelData = ({\n xAxisData,\n isGreaterThanTwoWeeks,\n}: GetLabelsDataProps) =>\n xAxisData\n .filter((record, index, arr) => {\n if (index === 0) {\n return false;\n }\n const previousTimestamp = arr[index - 1];\n const currentDate = new Date(record);\n const previousDate = new Date(previousTimestamp);\n\n return isGreaterThanTwoWeeks\n ? currentDate.getDate() !== previousDate.getDate()\n : currentDate.getMonth() !== previousDate.getMonth();\n })\n .map((item) => ({\n name: new Date(item).toLocaleDateString(undefined, {\n month: 'short',\n day: isGreaterThanTwoWeeks ? 'numeric' : undefined,\n }),\n xAxis: item,\n y: CHART_CONFIG.HEIGHT - 22,\n silent: true,\n emphasis: {\n disabled: true,\n },\n label: {\n fontFamily: 'Sofia W03',\n fontSize: 10,\n position: 'bottom',\n align: 'center',\n formatter: '{b}',\n },\n }));\n\nexport const isDifferenceGreaterThanTwoWeeks = (\n startDate: string,\n endDate: string\n) => {\n const date1 = new Date(startDate);\n const date2 = new Date(endDate);\n\n const differenceInMs = Math.abs(date2.getTime() - date1.getTime());\n\n return differenceInMs < TIME_THRESHOLDS.TWO_WEEKS_MS;\n};\n\nexport const getTimeSpanForGranularity = (\n granularity: Granularity\n): TimeSpan => {\n const granularityTimeSpanMap: Record<Granularity, TimeSpan> = {\n [Granularity.M5]: TimeSpan.TwoDays,\n [Granularity.M15]: TimeSpan.FiveDays,\n [Granularity.H1]: TimeSpan.TwentyDays,\n [Granularity.H4]: TimeSpan.NinetyDays,\n };\n\n return granularityTimeSpanMap[granularity] || TimeSpan.TwoDays;\n};\n\nconst getGradientColor = (\n value: number,\n startColor: string,\n targetColor: string\n): string => {\n const startThreshold = BOOKS_THRESHOLDS.MIN;\n const endThreshold = BOOKS_THRESHOLDS.MAX;\n\n const colorScale = chroma\n .scale([startColor, targetColor])\n .domain([startThreshold, endThreshold])\n .mode('rgb');\n\n return colorScale(value).hex();\n};\n\nexport const getRectColor = (sentiment: number) =>\n sentiment < 0\n ? getGradientColor(sentiment * -1, COLOR_MAP.short[0], COLOR_MAP.short[1])\n : getGradientColor(sentiment, COLOR_MAP.long[0], COLOR_MAP.long[1]);\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"chartUtils.js","names":["chroma","Granularity","TimeSpan","BOOKS_THRESHOLDS","CHART_CONFIG","COLOR_MAP","TIME_THRESHOLDS","getLabelData","_ref","xAxisData","isGreaterThanTwoWeeks","filter","record","index","arr","previousTimestamp","currentDate","Date","previousDate","getDate","getMonth","map","item","name","toLocaleDateString","undefined","month","day","xAxis","y","HEIGHT","silent","emphasis","disabled","label","fontFamily","fontSize","position","align","formatter","isDifferenceGreaterThanTwoWeeks","startDate","endDate","date1","date2","differenceInMs","Math","abs","getTime","TWO_WEEKS_MS","getTimeSpanForGranularity","granularity","granularityTimeSpanMap","M5","TwoDays","M15","FiveDays","H1","TwentyDays","H4","NinetyDays","getGradientColor","value","startColor","targetColor","startThreshold","MIN","endThreshold","MAX","colorScale","scale","domain","mode","hex","getRectColor","sentiment","short","long","getTooltipFormatter","params","buckets","bucketWidth","selectedPrice","labelCallback","_booksParam$value","candleParam","booksParam","time","axisValue","candleData","booksData","bucketsIndex","selectedBuckets","matchedBucket","find","_ref2","price","showCandles","concat","toLocaleString","hour","minute","year","timeZoneName","Number","toFixed","formatXAxisLabel","date","toLocaleTimeString","X_AXIS_DATE_PADDING"],"sources":["../../../../../../src/CrowdViewWidget/components/Chart/utils/chartUtils.ts"],"sourcesContent":["import chroma from 'chroma-js';\n\nimport { Granularity, TimeSpan } from '../../../../gql/types/graphql';\nimport {\n BOOKS_THRESHOLDS,\n CHART_CONFIG,\n COLOR_MAP,\n TIME_THRESHOLDS,\n} from '../../../constants';\nimport type { GetLabelsDataProps } from '../types';\n\nexport const getLabelData = ({\n xAxisData,\n isGreaterThanTwoWeeks,\n}: GetLabelsDataProps) =>\n xAxisData\n .filter((record, index, arr) => {\n if (index === 0) {\n return false;\n }\n const previousTimestamp = arr[index - 1];\n const currentDate = new Date(record);\n const previousDate = new Date(previousTimestamp);\n\n return isGreaterThanTwoWeeks\n ? currentDate.getDate() !== previousDate.getDate()\n : currentDate.getMonth() !== previousDate.getMonth();\n })\n .map((item) => ({\n name: new Date(item).toLocaleDateString(undefined, {\n month: isGreaterThanTwoWeeks ? 'short' : 'long',\n day: isGreaterThanTwoWeeks ? 'numeric' : undefined,\n }),\n xAxis: item,\n y: CHART_CONFIG.HEIGHT - 22,\n silent: true,\n emphasis: {\n disabled: true,\n },\n label: {\n fontFamily: 'Sofia W03',\n fontSize: 10,\n position: 'bottom',\n align: 'center',\n formatter: '{b}',\n },\n }));\n\nexport const isDifferenceGreaterThanTwoWeeks = (\n startDate: string,\n endDate: string\n) => {\n const date1 = new Date(startDate);\n const date2 = new Date(endDate);\n\n const differenceInMs = Math.abs(date2.getTime() - date1.getTime());\n\n return differenceInMs < TIME_THRESHOLDS.TWO_WEEKS_MS;\n};\n\nexport const getTimeSpanForGranularity = (\n granularity: Granularity\n): TimeSpan => {\n const granularityTimeSpanMap: Record<Granularity, TimeSpan> = {\n [Granularity.M5]: TimeSpan.TwoDays,\n [Granularity.M15]: TimeSpan.FiveDays,\n [Granularity.H1]: TimeSpan.TwentyDays,\n [Granularity.H4]: TimeSpan.NinetyDays,\n };\n\n return granularityTimeSpanMap[granularity] || TimeSpan.TwoDays;\n};\n\nconst getGradientColor = (\n value: number,\n startColor: string,\n targetColor: string\n): string => {\n const startThreshold = BOOKS_THRESHOLDS.MIN;\n const endThreshold = BOOKS_THRESHOLDS.MAX;\n\n const colorScale = chroma\n .scale([startColor, targetColor])\n .domain([startThreshold, endThreshold])\n .mode('rgb');\n\n return colorScale(value).hex();\n};\n\nexport const getRectColor = (sentiment: number) =>\n sentiment < 0\n ? getGradientColor(sentiment * -1, COLOR_MAP.short[0], COLOR_MAP.short[1])\n : getGradientColor(sentiment, COLOR_MAP.long[0], COLOR_MAP.long[1]);\n\nexport const getTooltipFormatter = (\n params: unknown,\n buckets: Array<Array<{ price: number; sentiment: number }>>,\n bucketWidth: number,\n selectedPrice: number,\n labelCallback: (key: string) => string\n) => {\n const arr = params as unknown as Array<Record<string, unknown>>;\n const candleParam = arr[0] as {\n axisValue: string;\n value: [number, number, number, number, number];\n };\n const booksParam = arr[1] as { value: [string, number, number] };\n const time = new Date(candleParam.axisValue as string);\n\n const candleData = candleParam.value;\n const booksData = booksParam?.value ?? [];\n const bucketsIndex = booksData[2];\n const selectedBuckets = buckets[bucketsIndex];\n\n const matchedBucket = selectedBuckets?.find(\n ({ price }) => selectedPrice >= price && selectedPrice < price + bucketWidth\n );\n const showCandles =\n !!candleData[1] && !!candleData[2] && !!candleData[3] && !!candleData[4];\n\n return `<p>${time.toLocaleString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n year: 'numeric',\n day: 'numeric',\n month: 'numeric',\n timeZoneName: 'short',\n })}</p><br />\n${\n showCandles\n ? `<p><b>${labelCallback('candle')}:</b></p>\n<p>${labelCallback('open_price')}: ${candleData[1]} </p>\n<p>${labelCallback('close_price')}: ${candleData[2]} </p>\n<p>${labelCallback('low')}: ${candleData[3]} </p>\n<p>${labelCallback('high')}: ${candleData[4]} </p>\n`\n : ''\n}\n${\n matchedBucket\n ? `<br /><p><b>${labelCallback('orders')}:</b></p>\n<p>${labelCallback('price_range')}: ${matchedBucket.price} - ${Number(matchedBucket.price + bucketWidth).toFixed(4)} </p>\n<p>${matchedBucket.sentiment < 0 ? labelCallback('sell_advantage') : labelCallback('buy_advantage')}: ${Math.abs(matchedBucket.sentiment)}% </p>`\n : ''\n}`;\n};\n\nexport const formatXAxisLabel = (\n value: unknown,\n isGreaterThanTwoWeeks: boolean\n) => {\n const date = new Date(value as string);\n return isGreaterThanTwoWeeks\n ? `${date.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n })}`\n : `${CHART_CONFIG.X_AXIS_DATE_PADDING}${date.toLocaleDateString(undefined, {\n day: 'numeric',\n })}${CHART_CONFIG.X_AXIS_DATE_PADDING}`;\n};\n"],"mappings":"AAAA,OAAOA,MAAM,MAAM,WAAW;AAE9B,SAASC,WAAW,EAAEC,QAAQ,QAAQ,+BAA+B;AACrE,SACEC,gBAAgB,EAChBC,YAAY,EACZC,SAAS,EACTC,eAAe,QACV,oBAAoB;AAG3B,OAAO,MAAMC,YAAY,GAAGC,IAAA;EAAA,IAAC;IAC3BC,SAAS;IACTC;EACkB,CAAC,GAAAF,IAAA;EAAA,OACnBC,SAAS,CACNE,MAAM,CAAC,CAACC,MAAM,EAAEC,KAAK,EAAEC,GAAG,KAAK;IAC9B,IAAID,KAAK,KAAK,CAAC,EAAE;MACf,OAAO,KAAK;IACd;IACA,MAAME,iBAAiB,GAAGD,GAAG,CAACD,KAAK,GAAG,CAAC,CAAC;IACxC,MAAMG,WAAW,GAAG,IAAIC,IAAI,CAACL,MAAM,CAAC;IACpC,MAAMM,YAAY,GAAG,IAAID,IAAI,CAACF,iBAAiB,CAAC;IAEhD,OAAOL,qBAAqB,GACxBM,WAAW,CAACG,OAAO,CAAC,CAAC,KAAKD,YAAY,CAACC,OAAO,CAAC,CAAC,GAChDH,WAAW,CAACI,QAAQ,CAAC,CAAC,KAAKF,YAAY,CAACE,QAAQ,CAAC,CAAC;EACxD,CAAC,CAAC,CACDC,GAAG,CAAEC,IAAI,KAAM;IACdC,IAAI,EAAE,IAAIN,IAAI,CAACK,IAAI,CAAC,CAACE,kBAAkB,CAACC,SAAS,EAAE;MACjDC,KAAK,EAAEhB,qBAAqB,GAAG,OAAO,GAAG,MAAM;MAC/CiB,GAAG,EAAEjB,qBAAqB,GAAG,SAAS,GAAGe;IAC3C,CAAC,CAAC;IACFG,KAAK,EAAEN,IAAI;IACXO,CAAC,EAAEzB,YAAY,CAAC0B,MAAM,GAAG,EAAE;IAC3BC,MAAM,EAAE,IAAI;IACZC,QAAQ,EAAE;MACRC,QAAQ,EAAE;IACZ,CAAC;IACDC,KAAK,EAAE;MACLC,UAAU,EAAE,WAAW;MACvBC,QAAQ,EAAE,EAAE;MACZC,QAAQ,EAAE,QAAQ;MAClBC,KAAK,EAAE,QAAQ;MACfC,SAAS,EAAE;IACb;EACF,CAAC,CAAC,CAAC;AAAA;AAEP,OAAO,MAAMC,+BAA+B,GAAGA,CAC7CC,SAAiB,EACjBC,OAAe,KACZ;EACH,MAAMC,KAAK,GAAG,IAAI1B,IAAI,CAACwB,SAAS,CAAC;EACjC,MAAMG,KAAK,GAAG,IAAI3B,IAAI,CAACyB,OAAO,CAAC;EAE/B,MAAMG,cAAc,GAAGC,IAAI,CAACC,GAAG,CAACH,KAAK,CAACI,OAAO,CAAC,CAAC,GAAGL,KAAK,CAACK,OAAO,CAAC,CAAC,CAAC;EAElE,OAAOH,cAAc,GAAGvC,eAAe,CAAC2C,YAAY;AACtD,CAAC;AAED,OAAO,MAAMC,yBAAyB,GACpCC,WAAwB,IACX;EACb,MAAMC,sBAAqD,GAAG;IAC5D,CAACnD,WAAW,CAACoD,EAAE,GAAGnD,QAAQ,CAACoD,OAAO;IAClC,CAACrD,WAAW,CAACsD,GAAG,GAAGrD,QAAQ,CAACsD,QAAQ;IACpC,CAACvD,WAAW,CAACwD,EAAE,GAAGvD,QAAQ,CAACwD,UAAU;IACrC,CAACzD,WAAW,CAAC0D,EAAE,GAAGzD,QAAQ,CAAC0D;EAC7B,CAAC;EAED,OAAOR,sBAAsB,CAACD,WAAW,CAAC,IAAIjD,QAAQ,CAACoD,OAAO;AAChE,CAAC;AAED,MAAMO,gBAAgB,GAAGA,CACvBC,KAAa,EACbC,UAAkB,EAClBC,WAAmB,KACR;EACX,MAAMC,cAAc,GAAG9D,gBAAgB,CAAC+D,GAAG;EAC3C,MAAMC,YAAY,GAAGhE,gBAAgB,CAACiE,GAAG;EAEzC,MAAMC,UAAU,GAAGrE,MAAM,CACtBsE,KAAK,CAAC,CAACP,UAAU,EAAEC,WAAW,CAAC,CAAC,CAChCO,MAAM,CAAC,CAACN,cAAc,EAAEE,YAAY,CAAC,CAAC,CACtCK,IAAI,CAAC,KAAK,CAAC;EAEd,OAAOH,UAAU,CAACP,KAAK,CAAC,CAACW,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,OAAO,MAAMC,YAAY,GAAIC,SAAiB,IAC5CA,SAAS,GAAG,CAAC,GACTd,gBAAgB,CAACc,SAAS,GAAG,CAAC,CAAC,EAAEtE,SAAS,CAACuE,KAAK,CAAC,CAAC,CAAC,EAAEvE,SAAS,CAACuE,KAAK,CAAC,CAAC,CAAC,CAAC,GACxEf,gBAAgB,CAACc,SAAS,EAAEtE,SAAS,CAACwE,IAAI,CAAC,CAAC,CAAC,EAAExE,SAAS,CAACwE,IAAI,CAAC,CAAC,CAAC,CAAC;AAEvE,OAAO,MAAMC,mBAAmB,GAAGA,CACjCC,MAAe,EACfC,OAA2D,EAC3DC,WAAmB,EACnBC,aAAqB,EACrBC,aAAsC,KACnC;EAAA,IAAAC,iBAAA;EACH,MAAMtE,GAAG,GAAGiE,MAAmD;EAC/D,MAAMM,WAAW,GAAGvE,GAAG,CAAC,CAAC,CAGxB;EACD,MAAMwE,UAAU,GAAGxE,GAAG,CAAC,CAAC,CAAwC;EAChE,MAAMyE,IAAI,GAAG,IAAItE,IAAI,CAACoE,WAAW,CAACG,SAAmB,CAAC;EAEtD,MAAMC,UAAU,GAAGJ,WAAW,CAACvB,KAAK;EACpC,MAAM4B,SAAS,IAAAN,iBAAA,GAAGE,UAAU,aAAVA,UAAU,uBAAVA,UAAU,CAAExB,KAAK,cAAAsB,iBAAA,cAAAA,iBAAA,GAAI,EAAE;EACzC,MAAMO,YAAY,GAAGD,SAAS,CAAC,CAAC,CAAC;EACjC,MAAME,eAAe,GAAGZ,OAAO,CAACW,YAAY,CAAC;EAE7C,MAAME,aAAa,GAAGD,eAAe,aAAfA,eAAe,uBAAfA,eAAe,CAAEE,IAAI,CACzCC,KAAA;IAAA,IAAC;MAAEC;IAAM,CAAC,GAAAD,KAAA;IAAA,OAAKb,aAAa,IAAIc,KAAK,IAAId,aAAa,GAAGc,KAAK,GAAGf,WAAW;EAAA,CAC9E,CAAC;EACD,MAAMgB,WAAW,GACf,CAAC,CAACR,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAACA,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAACA,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAACA,UAAU,CAAC,CAAC,CAAC;EAE1E,aAAAS,MAAA,CAAaX,IAAI,CAACY,cAAc,CAAC1E,SAAS,EAAE;IAC1C2E,IAAI,EAAE,SAAS;IACfC,MAAM,EAAE,SAAS;IACjBC,IAAI,EAAE,SAAS;IACf3E,GAAG,EAAE,SAAS;IACdD,KAAK,EAAE,SAAS;IAChB6E,YAAY,EAAE;EAChB,CAAC,CAAC,kBAAAL,MAAA,CAEFD,WAAW,YAAAC,MAAA,CACEf,aAAa,CAAC,QAAQ,CAAC,oBAAAe,MAAA,CACjCf,aAAa,CAAC,YAAY,CAAC,QAAAe,MAAA,CAAKT,UAAU,CAAC,CAAC,CAAC,gBAAAS,MAAA,CAC7Cf,aAAa,CAAC,aAAa,CAAC,QAAAe,MAAA,CAAKT,UAAU,CAAC,CAAC,CAAC,gBAAAS,MAAA,CAC9Cf,aAAa,CAAC,KAAK,CAAC,QAAAe,MAAA,CAAKT,UAAU,CAAC,CAAC,CAAC,gBAAAS,MAAA,CACtCf,aAAa,CAAC,MAAM,CAAC,QAAAe,MAAA,CAAKT,UAAU,CAAC,CAAC,CAAC,eAEtC,EAAE,QAAAS,MAAA,CAGNL,aAAa,kBAAAK,MAAA,CACMf,aAAa,CAAC,QAAQ,CAAC,oBAAAe,MAAA,CACvCf,aAAa,CAAC,aAAa,CAAC,QAAAe,MAAA,CAAKL,aAAa,CAACG,KAAK,SAAAE,MAAA,CAAMM,MAAM,CAACX,aAAa,CAACG,KAAK,GAAGf,WAAW,CAAC,CAACwB,OAAO,CAAC,CAAC,CAAC,gBAAAP,MAAA,CAC9GL,aAAa,CAAClB,SAAS,GAAG,CAAC,GAAGQ,aAAa,CAAC,gBAAgB,CAAC,GAAGA,aAAa,CAAC,eAAe,CAAC,QAAAe,MAAA,CAAKpD,IAAI,CAACC,GAAG,CAAC8C,aAAa,CAAClB,SAAS,CAAC,cACnI,EAAE;AAER,CAAC;AAED,OAAO,MAAM+B,gBAAgB,GAAGA,CAC9B5C,KAAc,EACdpD,qBAA8B,KAC3B;EACH,MAAMiG,IAAI,GAAG,IAAI1F,IAAI,CAAC6C,KAAe,CAAC;EACtC,OAAOpD,qBAAqB,MAAAwF,MAAA,CACrBS,IAAI,CAACC,kBAAkB,CAACnF,SAAS,EAAE;IACpC2E,IAAI,EAAE,SAAS;IACfC,MAAM,EAAE;EACV,CAAC,CAAC,OAAAH,MAAA,CACC9F,YAAY,CAACyG,mBAAmB,EAAAX,MAAA,CAAGS,IAAI,CAACnF,kBAAkB,CAACC,SAAS,EAAE;IACvEE,GAAG,EAAE;EACP,CAAC,CAAC,EAAAuE,MAAA,CAAG9F,YAAY,CAACyG,mBAAmB,CAAE;AAC7C,CAAC","ignoreList":[]}
@@ -14,11 +14,12 @@ export const CHART_CONFIG = {
14
14
  WIDTH: 9999,
15
15
  X_LABEL_SIZE: 40,
16
16
  Y_LABEL_SIZE_DESKTOP: 60,
17
- INITIAL_START_ZOOM: 80,
18
- INITIAL_END_ZOOM: 100
17
+ INITIAL_START_ZOOM: 0,
18
+ INITIAL_END_ZOOM: 100,
19
+ X_AXIS_DATE_PADDING: ' '
19
20
  };
20
21
  export const COLOR_MAP = {
21
- long: ['#ffffff', '#fdb833'],
22
- short: ['#ffffff', '#0096c7']
22
+ long: ['#fcedca', '#FAB313'],
23
+ short: ['#c8ebfa', '#309DCC']
23
24
  };
24
25
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":["BOOKS_THRESHOLDS","MIN","MAX","BUCKET_CONFIG","DEFAULT_WIDTH","PRICE_PADDING_MULTIPLIER","TIME_THRESHOLDS","TWO_WEEKS_MS","CHART_CONFIG","HEIGHT","WIDTH","X_LABEL_SIZE","Y_LABEL_SIZE_DESKTOP","INITIAL_START_ZOOM","INITIAL_END_ZOOM","COLOR_MAP","long","short"],"sources":["../../../src/CrowdViewWidget/constants.ts"],"sourcesContent":["export const BOOKS_THRESHOLDS = {\n MIN: 0.15,\n MAX: 0.55,\n} as const;\n\nexport const BUCKET_CONFIG = {\n DEFAULT_WIDTH: 0.0005,\n PRICE_PADDING_MULTIPLIER: 2,\n} as const;\n\nexport const TIME_THRESHOLDS = {\n TWO_WEEKS_MS: 14 * 24 * 60 * 60 * 1000,\n} as const;\n\nexport const CHART_CONFIG = {\n HEIGHT: 425,\n WIDTH: 9999,\n X_LABEL_SIZE: 40,\n Y_LABEL_SIZE_DESKTOP: 60,\n INITIAL_START_ZOOM: 80,\n INITIAL_END_ZOOM: 100,\n} as const;\n\nexport const COLOR_MAP = {\n long: ['#ffffff', '#fdb833'],\n short: ['#ffffff', '#0096c7'],\n} as const;\n"],"mappings":"AAAA,OAAO,MAAMA,gBAAgB,GAAG;EAC9BC,GAAG,EAAE,IAAI;EACTC,GAAG,EAAE;AACP,CAAU;AAEV,OAAO,MAAMC,aAAa,GAAG;EAC3BC,aAAa,EAAE,MAAM;EACrBC,wBAAwB,EAAE;AAC5B,CAAU;AAEV,OAAO,MAAMC,eAAe,GAAG;EAC7BC,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;AACpC,CAAU;AAEV,OAAO,MAAMC,YAAY,GAAG;EAC1BC,MAAM,EAAE,GAAG;EACXC,KAAK,EAAE,IAAI;EACXC,YAAY,EAAE,EAAE;EAChBC,oBAAoB,EAAE,EAAE;EACxBC,kBAAkB,EAAE,EAAE;EACtBC,gBAAgB,EAAE;AACpB,CAAU;AAEV,OAAO,MAAMC,SAAS,GAAG;EACvBC,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;EAC5BC,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS;AAC9B,CAAU","ignoreList":[]}
1
+ {"version":3,"file":"constants.js","names":["BOOKS_THRESHOLDS","MIN","MAX","BUCKET_CONFIG","DEFAULT_WIDTH","PRICE_PADDING_MULTIPLIER","TIME_THRESHOLDS","TWO_WEEKS_MS","CHART_CONFIG","HEIGHT","WIDTH","X_LABEL_SIZE","Y_LABEL_SIZE_DESKTOP","INITIAL_START_ZOOM","INITIAL_END_ZOOM","X_AXIS_DATE_PADDING","COLOR_MAP","long","short"],"sources":["../../../src/CrowdViewWidget/constants.ts"],"sourcesContent":["export const BOOKS_THRESHOLDS = {\n MIN: 0.15,\n MAX: 0.55,\n} as const;\n\nexport const BUCKET_CONFIG = {\n DEFAULT_WIDTH: 0.0005,\n PRICE_PADDING_MULTIPLIER: 2,\n} as const;\n\nexport const TIME_THRESHOLDS = {\n TWO_WEEKS_MS: 14 * 24 * 60 * 60 * 1000,\n} as const;\n\nexport const CHART_CONFIG = {\n HEIGHT: 425,\n WIDTH: 9999,\n X_LABEL_SIZE: 40,\n Y_LABEL_SIZE_DESKTOP: 60,\n INITIAL_START_ZOOM: 0,\n INITIAL_END_ZOOM: 100,\n X_AXIS_DATE_PADDING: ' ',\n} as const;\n\nexport const COLOR_MAP = {\n long: ['#fcedca', '#FAB313'],\n short: ['#c8ebfa', '#309DCC'],\n} as const;\n"],"mappings":"AAAA,OAAO,MAAMA,gBAAgB,GAAG;EAC9BC,GAAG,EAAE,IAAI;EACTC,GAAG,EAAE;AACP,CAAU;AAEV,OAAO,MAAMC,aAAa,GAAG;EAC3BC,aAAa,EAAE,MAAM;EACrBC,wBAAwB,EAAE;AAC5B,CAAU;AAEV,OAAO,MAAMC,eAAe,GAAG;EAC7BC,YAAY,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;AACpC,CAAU;AAEV,OAAO,MAAMC,YAAY,GAAG;EAC1BC,MAAM,EAAE,GAAG;EACXC,KAAK,EAAE,IAAI;EACXC,YAAY,EAAE,EAAE;EAChBC,oBAAoB,EAAE,EAAE;EACxBC,kBAAkB,EAAE,CAAC;EACrBC,gBAAgB,EAAE,GAAG;EACrBC,mBAAmB,EAAE;AACvB,CAAU;AAEV,OAAO,MAAMC,SAAS,GAAG;EACvBC,IAAI,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;EAC5BC,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS;AAC9B,CAAU","ignoreList":[]}
@@ -1,2 +1,26 @@
1
1
  {
2
+ "data_unavailable": "Data unavailable",
3
+ "no_matching_results": "No matching results",
4
+ "pagination_entries_range": "{{firstItemOnPage}}-{{lastItemOnPage}} of {{itemCount}} entries",
5
+ "order_book": "Order book",
6
+ "position_book": "Position book",
7
+ "long": "Long",
8
+ "short": "Short",
9
+ "instrument": "Instrument",
10
+ "granularity": "Granularity",
11
+ "search": "Search",
12
+ "5_minutes": "5 minutes",
13
+ "15_minutes": "15 minutes",
14
+ "1_hour": "1 hour",
15
+ "4_hours": "4 hours",
16
+ "candle": "Candle",
17
+ "open_price": "Open price",
18
+ "close_price": "Close price",
19
+ "low": "Low",
20
+ "high": "High",
21
+ "orders": "Orders",
22
+ "price_range": "Price range",
23
+ "sentiment": "Sentiment",
24
+ "buy_advantage": "Buy advantage",
25
+ "sell_advantage": "Sell advantage"
2
26
  }
@@ -9,15 +9,19 @@ export interface UseCrowdViewDataProps {
9
9
  interface CrowdViewData {
10
10
  xAxisData: string[];
11
11
  candlesSeriesData: [number, number, number, number][];
12
- orderPositionBooks: ([string, number, string] | null)[];
12
+ orderPositionBooks: ([string, number, number] | null)[];
13
13
  bucketWidth: number;
14
+ buckets: {
15
+ price: number;
16
+ sentiment: number;
17
+ }[][];
14
18
  }
15
19
  export interface UseCrowdViewDataReturn {
16
20
  data: CrowdViewData | null;
17
21
  loading: boolean;
18
22
  error: boolean;
19
23
  }
20
- export type GetOptionType = (props: CrowdViewData, isDark: boolean) => EChartsOption;
24
+ export type GetOptionType = (props: CrowdViewData, isDark: boolean, labelCallback: (key: string, params?: Record<string, unknown>) => string) => EChartsOption;
21
25
  export interface ChartProps {
22
26
  data: CrowdViewData;
23
27
  }
@@ -19,3 +19,8 @@ export declare const getLabelData: ({ xAxisData, isGreaterThanTwoWeeks, }: GetLa
19
19
  export declare const isDifferenceGreaterThanTwoWeeks: (startDate: string, endDate: string) => boolean;
20
20
  export declare const getTimeSpanForGranularity: (granularity: Granularity) => TimeSpan;
21
21
  export declare const getRectColor: (sentiment: number) => string;
22
+ export declare const getTooltipFormatter: (params: unknown, buckets: Array<Array<{
23
+ price: number;
24
+ sentiment: number;
25
+ }>>, bucketWidth: number, selectedPrice: number, labelCallback: (key: string) => string) => string;
26
+ export declare const formatXAxisLabel: (value: unknown, isGreaterThanTwoWeeks: boolean) => string;
@@ -14,10 +14,11 @@ export declare const CHART_CONFIG: {
14
14
  readonly WIDTH: 9999;
15
15
  readonly X_LABEL_SIZE: 40;
16
16
  readonly Y_LABEL_SIZE_DESKTOP: 60;
17
- readonly INITIAL_START_ZOOM: 80;
17
+ readonly INITIAL_START_ZOOM: 0;
18
18
  readonly INITIAL_END_ZOOM: 100;
19
+ readonly X_AXIS_DATE_PADDING: " ";
19
20
  };
20
21
  export declare const COLOR_MAP: {
21
- readonly long: readonly ["#ffffff", "#fdb833"];
22
- readonly short: readonly ["#ffffff", "#0096c7"];
22
+ readonly long: readonly ["#fcedca", "#FAB313"];
23
+ readonly short: readonly ["#c8ebfa", "#309DCC"];
23
24
  };
@@ -13,6 +13,6 @@
13
13
  "plural_format": "i18next",
14
14
  "export_empty_as": "skip",
15
15
  "include_tags": ["common_widgets"],
16
- "filter_langs": ["en", "zh_TW", "es", "th"]
16
+ "filter_langs": ["en"]
17
17
  }
18
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oanda/labs-crowd-view-widget",
3
- "version": "1.0.44",
3
+ "version": "1.0.45",
4
4
  "description": "Labs Crowd View Widget",
5
5
  "main": "dist/main/index.js",
6
6
  "module": "dist/module/index.js",
@@ -13,7 +13,7 @@
13
13
  "author": "OANDA",
14
14
  "license": "UNLICENSED",
15
15
  "dependencies": {
16
- "@oanda/labs-widget-common": "^1.0.226",
16
+ "@oanda/labs-widget-common": "^1.0.227",
17
17
  "@oanda/mono-i18n": "10.0.1",
18
18
  "chroma-js": "^3.1.2",
19
19
  "graphql": "16.8.1"
@@ -23,5 +23,5 @@
23
23
  "@graphql-codegen/client-preset": "4.1.0",
24
24
  "@types/chroma-js": "^3.1.2"
25
25
  },
26
- "gitHead": "4709e181ae37de87e1c5d5569391c5f6cfeeca33"
26
+ "gitHead": "f9361b30919526b3d6248b5a4eef570c0759bc19"
27
27
  }
@@ -6,7 +6,7 @@ import {
6
6
  useLayoutProvider,
7
7
  } from '@oanda/labs-widget-common';
8
8
  import { useLocale } from '@oanda/mono-i18n';
9
- import React, { useState } from 'react';
9
+ 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';
@@ -17,18 +17,34 @@ import type { InstrumentId } from './types/instruments';
17
17
  import { getInstrumentConfigForDivision } from './utils/instrumentUtils';
18
18
 
19
19
  const Main = ({ division }: MainProps) => {
20
- const instrumentSelectConfigWithDivision =
21
- getInstrumentConfigForDivision(division);
22
-
20
+ const { lang } = useLocale();
23
21
  const { size } = useLayoutProvider();
24
22
  const isDesktop = size === Size.DESKTOP;
23
+
25
24
  const [bookType, setBookType] = useState(BookType.Order);
25
+
26
+ const granularitySelectConfigWithLang = useMemo(
27
+ () =>
28
+ granularitySelectConfig.map((opt) => ({
29
+ ...opt,
30
+ label: lang(opt.label),
31
+ })),
32
+ [lang]
33
+ );
34
+
35
+ const instrumentSelectConfigWithDivision =
36
+ getInstrumentConfigForDivision(division);
26
37
  const [instrument, setInstrument] = useState(
27
38
  instrumentSelectConfigWithDivision[0]
28
39
  );
29
40
 
30
- const [granularity, setGranularity] = useState(granularitySelectConfig[0]);
31
- const { lang } = useLocale();
41
+ const [granularity, setGranularity] = useState(
42
+ granularitySelectConfigWithLang[0]
43
+ );
44
+
45
+ useEffect(() => {
46
+ setGranularity(granularitySelectConfigWithLang[0]);
47
+ }, [granularitySelectConfigWithLang]);
32
48
 
33
49
  return (
34
50
  <>
@@ -68,7 +84,7 @@ const Main = ({ division }: MainProps) => {
68
84
  })}
69
85
  >
70
86
  <Select
71
- options={granularitySelectConfig}
87
+ options={granularitySelectConfigWithLang}
72
88
  searchPlaceholder={lang('search')}
73
89
  selectLabel={lang('granularity')}
74
90
  selectedOption={granularity}
@@ -4,6 +4,7 @@ import {
4
4
  Theme,
5
5
  useLayoutProvider,
6
6
  } from '@oanda/labs-widget-common';
7
+ import { useLocale } from '@oanda/mono-i18n';
7
8
  import type { EChartsType } from 'echarts';
8
9
  import {
9
10
  BarChart,
@@ -26,6 +27,7 @@ import { CHART_CONFIG } from '../../constants';
26
27
  import { getOption } from './chartOptions';
27
28
  import type { ChartProps } from './types';
28
29
  import {
30
+ formatXAxisLabel,
29
31
  getLabelData,
30
32
  isDifferenceGreaterThanTwoWeeks,
31
33
  } from './utils/chartUtils';
@@ -48,6 +50,7 @@ echarts.registerTheme('light_theme', getChartTheme(Theme.Light));
48
50
 
49
51
  const Chart = ({ data }: ChartProps) => {
50
52
  const { isDark } = useLayoutProvider();
53
+ const { lang } = useLocale();
51
54
 
52
55
  return (
53
56
  <BaseChart
@@ -55,7 +58,7 @@ const Chart = ({ data }: ChartProps) => {
55
58
  echarts={echarts}
56
59
  isDark={isDark}
57
60
  lazyUpdate={true}
58
- option={getOption(data, isDark)}
61
+ option={getOption(data, isDark, lang)}
59
62
  opts={{ renderer: 'canvas' }}
60
63
  onEvents={{
61
64
  datazoom: (_params: unknown, instance: EChartsType) => {
@@ -78,17 +81,8 @@ const Chart = ({ data }: ChartProps) => {
78
81
  instance.setOption({
79
82
  xAxis: {
80
83
  axisLabel: {
81
- formatter: (value: string) => {
82
- const date = new Date(value);
83
- return isGreaterThanTwoWeeks
84
- ? `${date.toLocaleTimeString(undefined, {
85
- hour: '2-digit',
86
- minute: '2-digit',
87
- })}`
88
- : `${date.toLocaleDateString(undefined, {
89
- day: 'numeric',
90
- })}`;
91
- },
84
+ formatter: (value: string) =>
85
+ formatXAxisLabel(value, isGreaterThanTwoWeeks),
92
86
  },
93
87
  },
94
88
  series: [
@@ -7,16 +7,20 @@ import {
7
7
  import { CHART_CONFIG } from '../../constants';
8
8
  import type { GetOptionType } from './types';
9
9
  import {
10
+ formatXAxisLabel,
10
11
  getLabelData,
11
12
  getRectColor,
13
+ getTooltipFormatter,
12
14
  isDifferenceGreaterThanTwoWeeks,
13
15
  } from './utils/chartUtils';
14
16
 
15
17
  // @ts-expect-error
16
18
  export const getOption: GetOptionType = (
17
- { xAxisData, candlesSeriesData, orderPositionBooks, bucketWidth },
18
- isDark
19
+ { xAxisData, candlesSeriesData, orderPositionBooks, bucketWidth, buckets },
20
+ isDark,
21
+ labelCallback
19
22
  ) => {
23
+ let selectedPrice: number;
20
24
  const visibleXAxisData = xAxisData.slice(
21
25
  (xAxisData.length * CHART_CONFIG.INITIAL_START_ZOOM) / 100,
22
26
  (xAxisData.length * CHART_CONFIG.INITIAL_END_ZOOM) / 100
@@ -55,29 +59,49 @@ export const getOption: GetOptionType = (
55
59
  trigger: 'axis',
56
60
  axisPointer: {
57
61
  type: 'cross',
62
+ axis: 'x',
63
+ label: {
64
+ formatter: (params) => {
65
+ if (params.axisDimension === 'y') {
66
+ selectedPrice = Number(params.value);
67
+ return Number(params.value).toFixed(5);
68
+ }
69
+
70
+ if (params.axisDimension === 'x') {
71
+ const date = new Date(params.value as string);
72
+ return date.toLocaleString(undefined, {
73
+ hour: '2-digit',
74
+ minute: '2-digit',
75
+ day: 'numeric',
76
+ month: 'short',
77
+ });
78
+ }
79
+
80
+ return null;
81
+ },
82
+ },
58
83
  },
84
+ confine: true,
85
+ formatter: (params) =>
86
+ getTooltipFormatter(
87
+ params,
88
+ buckets,
89
+ bucketWidth,
90
+ selectedPrice,
91
+ labelCallback
92
+ ),
59
93
  },
60
94
  xAxis: {
61
95
  type: 'category',
62
96
  data: xAxisData,
97
+ splitNumber: 1,
63
98
  axisTick: {
64
99
  show: false,
65
100
  },
66
101
  axisLabel: {
67
102
  padding: [8, 16, 8, 16],
68
103
  margin: 0,
69
- showMinLabel: false,
70
- formatter: (value) => {
71
- const date = new Date(value as string);
72
- return isGreaterThanTwoWeeks
73
- ? `${date.toLocaleTimeString(undefined, {
74
- hour: '2-digit',
75
- minute: '2-digit',
76
- })}`
77
- : `${date.toLocaleDateString(undefined, {
78
- day: 'numeric',
79
- })}`;
80
- },
104
+ formatter: (value) => formatXAxisLabel(value, isGreaterThanTwoWeeks),
81
105
  },
82
106
  },
83
107
  yAxis: {
@@ -115,7 +139,8 @@ export const getOption: GetOptionType = (
115
139
  clip: true,
116
140
  renderItem: (_params, api) => {
117
141
  const xVal = api.value(0);
118
- const metaValues = JSON.parse(api.value(2) as string);
142
+ const bucketIndex = api.value(2) as number;
143
+ const metaValues = buckets[bucketIndex];
119
144
 
120
145
  const [rectWidth, rectHeight] = api.size!([
121
146
  0,
@@ -130,13 +155,12 @@ export const getOption: GetOptionType = (
130
155
  type: 'rect',
131
156
  shape: {
132
157
  x: start[0] - rectWidth / 2,
133
- y: start[1],
158
+ y: start[1] - rectHeight,
134
159
  width: rectWidth,
135
160
  height: rectHeight,
136
161
  },
137
162
  style: {
138
163
  fill: getRectColor(sentiment),
139
- opacity: 0.7,
140
164
  },
141
165
  silent: true,
142
166
  emphasisDisabled: true,
@@ -15,9 +15,12 @@ export interface UseCrowdViewDataProps {
15
15
 
16
16
  interface CrowdViewData {
17
17
  xAxisData: string[];
18
+ // [open, close, low, high]
18
19
  candlesSeriesData: [number, number, number, number][];
19
- orderPositionBooks: ([string, number, string] | null)[];
20
+ // [time, price, index]
21
+ orderPositionBooks: ([string, number, number] | null)[];
20
22
  bucketWidth: number;
23
+ buckets: { price: number; sentiment: number }[][];
21
24
  }
22
25
 
23
26
  export interface UseCrowdViewDataReturn {
@@ -28,7 +31,8 @@ export interface UseCrowdViewDataReturn {
28
31
 
29
32
  export type GetOptionType = (
30
33
  props: CrowdViewData,
31
- isDark: boolean
34
+ isDark: boolean,
35
+ labelCallback: (key: string, params?: Record<string, unknown>) => string
32
36
  ) => EChartsOption;
33
37
 
34
38
  export interface ChartProps {