@devexperts/dxcharts-lite 2.5.7 → 2.6.0
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/dist/chart/__tests__/chart.test.js +5 -5
- package/dist/chart/__tests__/env.js +1 -1
- package/dist/chart/bootstrap.js +2 -2
- package/dist/chart/canvas/canvas-bounds-container.js +24 -3
- package/dist/chart/chart.config.d.ts +2 -0
- package/dist/chart/chart.config.js +2 -1
- package/dist/chart/components/chart/basic-scale.d.ts +5 -1
- package/dist/chart/components/chart/basic-scale.js +10 -6
- package/dist/chart/components/chart/candle-transformer.functions.js +1 -1
- package/dist/chart/components/chart/candle.functions.d.ts +1 -1
- package/dist/chart/components/chart/candle.functions.js +3 -2
- package/dist/chart/components/chart/chart.component.d.ts +29 -8
- package/dist/chart/components/chart/chart.component.js +33 -4
- package/dist/chart/components/chart/chart.model.d.ts +42 -5
- package/dist/chart/components/chart/chart.model.js +99 -19
- package/dist/chart/components/chart/fake-candles.js +2 -0
- package/dist/chart/components/chart/fake-visual-candle.d.ts +4 -4
- package/dist/chart/components/chart/fake-visual-candle.js +4 -4
- package/dist/chart/components/pane/pane.component.js +3 -3
- package/dist/chart/components/volumes/separate-volumes.component.d.ts +1 -3
- package/dist/chart/components/volumes/separate-volumes.component.js +1 -3
- package/dist/chart/components/volumes/volumes.component.js +1 -1
- package/dist/chart/components/volumes/volumes.drawer.js +3 -3
- package/dist/chart/components/watermark/water-mark.component.d.ts +3 -12
- package/dist/chart/components/watermark/water-mark.component.js +1 -1
- package/dist/chart/components/x_axis/time/parser/time-formats-parser.functions.js +1 -1
- package/dist/chart/components/x_axis/x-axis-labels.generator.d.ts +2 -2
- package/dist/chart/components/x_axis/x-axis-labels.generator.js +6 -6
- package/dist/chart/components/x_axis/x-axis-scale.handler.js +2 -2
- package/dist/chart/components/x_axis/x-axis.component.js +1 -1
- package/dist/chart/components/y_axis/y-axis-scale.handler.js +3 -3
- package/dist/chart/drawers/drawing-manager.d.ts +1 -1
- package/dist/chart/drawers/drawing-manager.js +0 -1
- package/dist/chart/inputhandlers/hover-producer.component.js +8 -2
- package/dist/chart/inputhandlers/main-canvas-touch.handler.js +1 -1
- package/dist/chart/model/candle.model.d.ts +3 -0
- package/dist/chart/model/candle.model.js +7 -1
- package/dist/chart/model/data-series.model.d.ts +3 -3
- package/dist/chart/model/data-series.model.js +1 -1
- package/dist/chart/model/scale.model.js +1 -1
- package/dist/chart/model/scaling/viewport.model.d.ts +2 -1
- package/dist/chart/model/scaling/viewport.model.js +6 -1
- package/dist/chart/model/time-zone.model.js +1 -3
- package/dist/chart/utils/candles-generator-ts.utils.d.ts +1 -0
- package/dist/chart/utils/candles-generator.utils.d.ts +1 -0
- package/dist/chart/utils/candles-generator.utils.js +2 -0
- package/dist/chart/utils/string.utils.d.ts +6 -0
- package/dist/chart/utils/string.utils.js +19 -0
- package/dist/chart/utils/types.utils.d.ts +9 -0
- package/dist/chart/utils/types.utils.js +6 -0
- package/dist/dxchart.min.js +4 -4
- package/package.json +1 -1
|
@@ -59,12 +59,19 @@ export class ChartModel extends ChartBaseElement {
|
|
|
59
59
|
this.toY = (value) => {
|
|
60
60
|
return this.mainCandleSeries.view.toY(value);
|
|
61
61
|
};
|
|
62
|
+
this.prepareCandles = (candles) => {
|
|
63
|
+
const prepared = candles.map(prepareCandle).filter(isCandle);
|
|
64
|
+
const { sortCandles } = this.config.components.chart;
|
|
65
|
+
return sortCandles ? sortCandles(prepared) : prepared;
|
|
66
|
+
};
|
|
62
67
|
this.chartTypeChanged.next(this.config.components.chart.type);
|
|
63
68
|
this.secondaryChartColors = new SecondaryChartColorsPool(this.config);
|
|
64
69
|
const candleSeries = new MainCandleSeriesModel(this.chartBaseModel, this.paneManager.panes[CHART_UUID].mainExtent, uuid(), this.paneManager.hitTestController.getNewDataSeriesHitTestId(), this.bus, this.scale, new ChartInstrument(), this.candlesTransformersByChartType, this.candleWidthByChartType, Object.assign({}, this.config.colors));
|
|
65
70
|
candleSeries.config.type = this.config.components.chart.type;
|
|
66
71
|
this.candleSeries.push(candleSeries);
|
|
67
|
-
|
|
72
|
+
if (this.config.components.chart.minCandlesOffset > 0) {
|
|
73
|
+
scale.addXConstraint((_, state) => candleEdgesConstrait(state, this.mainCandleSeries.visualPoints, this.config.components.chart.minCandlesOffset, scale.getBounds()));
|
|
74
|
+
}
|
|
68
75
|
this.basicScaleViewportTransformer = createBasicScaleViewportTransformer(scale);
|
|
69
76
|
this.timeFrameViewportTransformer = createTimeFrameViewportTransformer(scale, this);
|
|
70
77
|
this.pane = this.paneManager.panes[CHART_UUID];
|
|
@@ -162,7 +169,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
162
169
|
* @returns {CandleSeriesModel | undefined} - The newly created secondary candle series model or undefined if it could not be created.
|
|
163
170
|
*/
|
|
164
171
|
setSecondaryCandleSeries(candles, instrument = this.mainCandleSeries.instrument, recalculateAndUpdate = true) {
|
|
165
|
-
const preparedCandles = prepareCandles(candles);
|
|
172
|
+
const preparedCandles = this.prepareCandles(candles);
|
|
166
173
|
// set correct indexes based on main candles timestamp
|
|
167
174
|
const reindexCandles = this.reindexCandlesBasedOnSeries(this.mainCandleSeries.dataPoints, preparedCandles);
|
|
168
175
|
// ensure there are no gaps in new candles
|
|
@@ -198,7 +205,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
198
205
|
this.mainInstrumentChangedSubject.next(mainSeries.instrument);
|
|
199
206
|
}
|
|
200
207
|
this.rememberCurrentTimeframe();
|
|
201
|
-
const preparedCandles = prepareCandles(mainSeries.candles);
|
|
208
|
+
const preparedCandles = this.prepareCandles(mainSeries.candles);
|
|
202
209
|
this.mainCandleSeries.clearData();
|
|
203
210
|
reindexCandles(preparedCandles);
|
|
204
211
|
this.mainCandleSeries.dataPoints = preparedCandles;
|
|
@@ -217,7 +224,9 @@ export class ChartModel extends ChartBaseElement {
|
|
|
217
224
|
});
|
|
218
225
|
this.chartBaseModel.recalculatePeriod();
|
|
219
226
|
this.autoScaleOnCandles();
|
|
220
|
-
this.scale.
|
|
227
|
+
if (this.config.scale.auto) {
|
|
228
|
+
this.scale.doAutoScale();
|
|
229
|
+
}
|
|
221
230
|
this.candlesSetSubject.next();
|
|
222
231
|
this.canvasModel.fireDraw();
|
|
223
232
|
}
|
|
@@ -282,7 +291,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
282
291
|
console.error('All series update failed. Instruments for series are different.');
|
|
283
292
|
return;
|
|
284
293
|
}
|
|
285
|
-
const preparedCandles = prepareCandles(mainSeries.candles);
|
|
294
|
+
const preparedCandles = this.prepareCandles(mainSeries.candles);
|
|
286
295
|
const updateResult = updateCandles(this.mainCandleSeries.dataPoints, preparedCandles);
|
|
287
296
|
const updatedCandles = updateResult.candles;
|
|
288
297
|
reindexCandles(updatedCandles);
|
|
@@ -290,7 +299,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
290
299
|
// re-create series
|
|
291
300
|
secondarySeries.map(series => {
|
|
292
301
|
var _a, _b, _c, _d;
|
|
293
|
-
const preparedCandles = prepareCandles(series.candles);
|
|
302
|
+
const preparedCandles = this.prepareCandles(series.candles);
|
|
294
303
|
const updatedCandles = updateCandles((_d = (_c = this.findSecondarySeriesBySymbol((_b = (_a = series.instrument) === null || _a === void 0 ? void 0 : _a.symbol) !== null && _b !== void 0 ? _b : '')) === null || _c === void 0 ? void 0 : _c.dataPoints) !== null && _d !== void 0 ? _d : [], preparedCandles).candles;
|
|
295
304
|
return this.setSecondaryCandleSeries(updatedCandles, series.instrument, false);
|
|
296
305
|
});
|
|
@@ -325,9 +334,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
325
334
|
series.dataPoints = series.dataPoints.slice(0, index);
|
|
326
335
|
});
|
|
327
336
|
});
|
|
328
|
-
this.
|
|
329
|
-
this.candlesUpdatedSubject.next();
|
|
330
|
-
this.canvasModel.fireDraw();
|
|
337
|
+
this.candlesChangedRedraw();
|
|
331
338
|
}
|
|
332
339
|
/**
|
|
333
340
|
* Creates a secondary candle series model for a given instrument.
|
|
@@ -373,8 +380,8 @@ export class ChartModel extends ChartBaseElement {
|
|
|
373
380
|
secondarySeriesAdjustments(mainSeries, secondarySeries) {
|
|
374
381
|
const result = [];
|
|
375
382
|
mainSeries.forEach(mainCandle => {
|
|
376
|
-
|
|
377
|
-
const idx =
|
|
383
|
+
const candleIdx = this.candleIdxFromId(mainCandle.id);
|
|
384
|
+
const idx = candleIdx > 0 ? candleIdx : 0;
|
|
378
385
|
const compareCandle = secondarySeries[idx];
|
|
379
386
|
if (!compareCandle) {
|
|
380
387
|
// take first candle to left or right
|
|
@@ -521,6 +528,23 @@ export class ChartModel extends ChartBaseElement {
|
|
|
521
528
|
const dataPointsSource = selectedCandleSeries.dataPoints;
|
|
522
529
|
return this.chartBaseModel.dataFromTimestamp(timestamp, extrapolate, dataPointsSource);
|
|
523
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* For given id finds the target candle
|
|
533
|
+
* @param id
|
|
534
|
+
* @param selectedCandleSeries
|
|
535
|
+
*/
|
|
536
|
+
candleFromId(id, selectedCandleSeries = this.mainCandleSeries) {
|
|
537
|
+
return selectedCandleSeries.visualPoints.find(vc => vc.candle.id === id);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* For given id finds the target candle index
|
|
541
|
+
* @param id
|
|
542
|
+
* @param selectedCandleSeries
|
|
543
|
+
* @returns candle index, -1 if not found
|
|
544
|
+
*/
|
|
545
|
+
candleIdxFromId(id, selectedCandleSeries = this.mainCandleSeries) {
|
|
546
|
+
return selectedCandleSeries.visualPoints.findIndex(vc => vc.candle.id === id);
|
|
547
|
+
}
|
|
524
548
|
/**
|
|
525
549
|
* For given index returns the closest visual candle, or fake candle with correct X coordinate.
|
|
526
550
|
* @param idx - index of candle
|
|
@@ -722,7 +746,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
722
746
|
* Updates candles in series. Default is main series.
|
|
723
747
|
* Any number of candles may be provided - they would be matched by their index and updated.
|
|
724
748
|
* @param candles - any list of new (updated) candles
|
|
725
|
-
* @param
|
|
749
|
+
* @param instrumentSymbol - name of instrument to update
|
|
726
750
|
*/
|
|
727
751
|
// I'd like to keep this method, for me one generic method is more convenient than 3 (updateLastCandle, addLastCandle, prepend...)
|
|
728
752
|
updateCandles(candles, instrumentSymbol = this.mainCandleSeries.instrument.symbol) {
|
|
@@ -779,7 +803,9 @@ export class ChartModel extends ChartBaseElement {
|
|
|
779
803
|
series.recalculateVisualPoints();
|
|
780
804
|
}
|
|
781
805
|
});
|
|
782
|
-
this.scale.
|
|
806
|
+
if (this.config.scale.auto) {
|
|
807
|
+
this.scale.doAutoScale();
|
|
808
|
+
}
|
|
783
809
|
this.candlesUpdatedSubject.next();
|
|
784
810
|
}
|
|
785
811
|
/**
|
|
@@ -852,7 +878,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
852
878
|
if (idx < 0) {
|
|
853
879
|
prepend.push(c);
|
|
854
880
|
}
|
|
855
|
-
else if (target[idx].
|
|
881
|
+
else if (target[idx].id === c.id) {
|
|
856
882
|
targetCopy[idx] = c;
|
|
857
883
|
}
|
|
858
884
|
else {
|
|
@@ -867,7 +893,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
867
893
|
/**
|
|
868
894
|
* Adds new candle to the chart
|
|
869
895
|
* @param candle - new candle
|
|
870
|
-
* @param
|
|
896
|
+
* @param instrumentSymbol - name of the instrument to update
|
|
871
897
|
*/
|
|
872
898
|
addLastCandle(candle, instrumentSymbol = this.mainCandleSeries.instrument.symbol) {
|
|
873
899
|
this.updateCandles([candle], instrumentSymbol);
|
|
@@ -875,7 +901,7 @@ export class ChartModel extends ChartBaseElement {
|
|
|
875
901
|
/**
|
|
876
902
|
* Updates last candle value
|
|
877
903
|
* @param candle - updated candle
|
|
878
|
-
* @param
|
|
904
|
+
* @param instrumentSymbol - name of the instrument to update
|
|
879
905
|
*/
|
|
880
906
|
updateLastCandle(candle, instrumentSymbol = this.mainCandleSeries.instrument.symbol) {
|
|
881
907
|
this.updateCandles([candle], instrumentSymbol);
|
|
@@ -883,9 +909,12 @@ export class ChartModel extends ChartBaseElement {
|
|
|
883
909
|
/**
|
|
884
910
|
* Remove candle by idx and recaculate indexes
|
|
885
911
|
* @param candle - new candle
|
|
886
|
-
* @param
|
|
912
|
+
* @param instrumentSymbol - name of the instrument to update
|
|
887
913
|
*/
|
|
888
914
|
removeCandleByIdx(idx, instrumentSymbol = this.mainCandleSeries.instrument.symbol) {
|
|
915
|
+
if (idx < 0) {
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
889
918
|
const seriesList = this.findSeriesBySymbol(instrumentSymbol);
|
|
890
919
|
if (seriesList.length === 0) {
|
|
891
920
|
console.warn("removeCandle by id failed. Can't find series", instrumentSymbol);
|
|
@@ -896,13 +925,64 @@ export class ChartModel extends ChartBaseElement {
|
|
|
896
925
|
reindexCandles(series.dataPoints);
|
|
897
926
|
series.recalculateVisualPoints();
|
|
898
927
|
});
|
|
928
|
+
this.candlesChangedRedraw();
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Remove candles by ids and recalculate indexes, candles should be as a sequence, follow one by one
|
|
932
|
+
* Works faster than removeCandlesByIds
|
|
933
|
+
*
|
|
934
|
+
* @param ids - candles ids to remove
|
|
935
|
+
* @param selectedCandleSeries - candle series to remove candles from
|
|
936
|
+
*/
|
|
937
|
+
removeCandlesByIdsSequence(ids, selectedCandleSeries) {
|
|
938
|
+
const firstIdx = this.candleIdxFromId(ids[0], selectedCandleSeries);
|
|
939
|
+
const lastIdx = this.candleIdxFromId(ids[ids.length - 1], selectedCandleSeries);
|
|
940
|
+
if (firstIdx < 0 || lastIdx < 0) {
|
|
941
|
+
console.warn('Candle is not found');
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
// if array is a sequence the removal process should be faster because reindex and recalculate visual points would call only once
|
|
945
|
+
selectedCandleSeries.dataPoints = selectedCandleSeries.dataPoints
|
|
946
|
+
.slice(0, firstIdx)
|
|
947
|
+
.concat(selectedCandleSeries.dataPoints.slice(lastIdx + 1));
|
|
948
|
+
reindexCandles(selectedCandleSeries.dataPoints, lastIdx);
|
|
949
|
+
selectedCandleSeries.recalculateVisualPoints();
|
|
950
|
+
this.candlesChangedRedraw();
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* Remove candles by ids and recalculate indexes
|
|
954
|
+
* @param ids - candles ids to remove
|
|
955
|
+
* @param selectedCandleSeries - candle series to remove candles from
|
|
956
|
+
*/
|
|
957
|
+
removeCandlesByIds(ids, selectedCandleSeries) {
|
|
958
|
+
ids.forEach(id => this.removeCandleByIdx(this.candleIdxFromId(id, selectedCandleSeries)));
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Add candles by id and recalculate indexes
|
|
962
|
+
*
|
|
963
|
+
* @param candles - candles to add
|
|
964
|
+
* @param startId - target candle to start adding candles from
|
|
965
|
+
* @param selectedCandleSeries - candle series to add candles to
|
|
966
|
+
*/
|
|
967
|
+
addCandlesById(candles, startId, selectedCandleSeries) {
|
|
968
|
+
const targetCandleIdx = this.candleIdxFromId(startId);
|
|
969
|
+
if (targetCandleIdx < 0) {
|
|
970
|
+
console.warn('Selected start candle is not found');
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
const candlesBefore = selectedCandleSeries.dataPoints.slice(0, targetCandleIdx);
|
|
974
|
+
const candlesAfter = selectedCandleSeries.dataPoints.slice(targetCandleIdx);
|
|
975
|
+
selectedCandleSeries.dataPoints = candlesBefore.concat(candles).concat(candlesAfter);
|
|
976
|
+
reindexCandles(selectedCandleSeries.dataPoints);
|
|
977
|
+
selectedCandleSeries.recalculateVisualPoints();
|
|
978
|
+
this.candlesChangedRedraw();
|
|
979
|
+
}
|
|
980
|
+
candlesChangedRedraw() {
|
|
899
981
|
this.candlesRemovedSubject.next();
|
|
900
982
|
this.candlesUpdatedSubject.next();
|
|
901
983
|
this.canvasModel.fireDraw();
|
|
902
984
|
}
|
|
903
985
|
}
|
|
904
|
-
const sortCandles = (candles) => candles.slice().sort((a, b) => (a.timestamp === b.timestamp ? 0 : a.timestamp > b.timestamp ? 1 : -1));
|
|
905
|
-
const prepareCandles = (candles) => sortCandles(candles.map(prepareCandle).filter(isCandle));
|
|
906
986
|
const findFirstNotEmptyCandle = (candles, startIdx, iterateStep) => {
|
|
907
987
|
if (startIdx >= candles.length) {
|
|
908
988
|
return candles[candles.length - 1];
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
+
import { generateCandleId } from '../../model/candle.model';
|
|
6
7
|
import { firstOf, lastOf } from '../../utils/array.utils';
|
|
7
8
|
import { round } from '../../utils/math.utils';
|
|
8
9
|
export const DEFAULT_PERIOD = 60; // 1 minute
|
|
9
10
|
export const fakeCandle = (candles, index, period = DEFAULT_PERIOD) => {
|
|
10
11
|
const t = getTimestampOfIndex(candles, index, period);
|
|
11
12
|
return {
|
|
13
|
+
id: generateCandleId(t, t),
|
|
12
14
|
hi: NaN,
|
|
13
15
|
lo: NaN,
|
|
14
16
|
open: NaN,
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import { Candle } from
|
|
7
|
-
import { DataSeriesPoint, VisualSeriesPoint } from
|
|
8
|
-
import { Index } from
|
|
9
|
-
import VisualCandle from
|
|
6
|
+
import { Candle } from '../../model/candle.model';
|
|
7
|
+
import { DataSeriesPoint, VisualSeriesPoint } from '../../model/data-series.model';
|
|
8
|
+
import { Index } from '../../model/scaling/viewport.model';
|
|
9
|
+
import VisualCandle from '../../model/visual-candle';
|
|
10
10
|
/**
|
|
11
11
|
* Generates fake candle for left and right "out of data range" zones.
|
|
12
12
|
* Requires period to calculate the fake timestamp.
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
|
-
import { nameDirection } from
|
|
7
|
-
import { VisualSeriesPoint } from
|
|
8
|
-
import VisualCandle from
|
|
9
|
-
import { DEFAULT_PERIOD, fakeCandle, fakeDataPoint } from
|
|
6
|
+
import { nameDirection } from '../../model/candle.model';
|
|
7
|
+
import { VisualSeriesPoint } from '../../model/data-series.model';
|
|
8
|
+
import VisualCandle from '../../model/visual-candle';
|
|
9
|
+
import { DEFAULT_PERIOD, fakeCandle, fakeDataPoint } from './fake-candles';
|
|
10
10
|
/**
|
|
11
11
|
* Generates fake candle for left and right "out of data range" zones.
|
|
12
12
|
* Requires period to calculate the fake timestamp.
|
|
@@ -88,9 +88,9 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
88
88
|
* @param {NumericYAxisLabelsGenerator} yAxisLabelsGenerator - The generator used to create the labels for the y-axis.
|
|
89
89
|
* @returns {GridComponent} - The newly created GridComponent instance.
|
|
90
90
|
*/
|
|
91
|
-
createGridComponent(uuid, scale,
|
|
91
|
+
createGridComponent(uuid, scale, yAxisState, yAxisLabelsGetter, yAxisBaselineGetter) {
|
|
92
92
|
const chartPaneId = CanvasElement.PANE_UUID(uuid);
|
|
93
|
-
const gridComponent = new GridComponent(this.mainCanvasModel, scale, this.config, yAxisState, `PANE_${uuid}_grid_drawer`, this.drawingManager, () => this.canvasBoundsContainer.getBounds(chartPaneId), () => this.canvasBoundsContainer.getBounds(chartPaneId), () => [], () =>
|
|
93
|
+
const gridComponent = new GridComponent(this.mainCanvasModel, scale, this.config, yAxisState, `PANE_${uuid}_grid_drawer`, this.drawingManager, () => this.canvasBoundsContainer.getBounds(chartPaneId), () => this.canvasBoundsContainer.getBounds(chartPaneId), () => [], yAxisLabelsGetter, yAxisBaselineGetter, () => this.config.components.grid.visible);
|
|
94
94
|
return gridComponent;
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
@@ -135,7 +135,7 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
135
135
|
if (useDefaultHighLow) {
|
|
136
136
|
scaleModel.autoScaleModel.setHighLowProvider('default', createCandlesOffsetProvider(() => ({ top: 10, bottom: 10, left: 0, right: 0, visible: true }), createDefaultYExtentHighLowProvider(yExtentComponent)));
|
|
137
137
|
}
|
|
138
|
-
const gridComponent = this.createGridComponent(this.uuid, scaleModel, yExtentComponent.yAxis.model.
|
|
138
|
+
const gridComponent = this.createGridComponent(this.uuid, scaleModel, yExtentComponent.yAxis.state, () => yExtentComponent.yAxis.model.baseLabelsModel.labels, () => yExtentComponent.toY(yExtentComponent.getBaseline()));
|
|
139
139
|
yExtentComponent.addChildEntity(gridComponent);
|
|
140
140
|
yExtentComponent.activate();
|
|
141
141
|
this.yExtentComponents.push(yExtentComponent);
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
import { FullChartConfig } from '../../chart.config';
|
|
7
|
-
import { DrawingManager } from '../../drawers/drawing-manager';
|
|
8
7
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
9
8
|
import { Pixel, Unit } from '../../model/scaling/viewport.model';
|
|
10
9
|
import { ChartComponent } from '../chart/chart.component';
|
|
@@ -13,13 +12,12 @@ import { PaneComponent } from '../pane/pane.component';
|
|
|
13
12
|
import { VolumesModel } from './volumes.model';
|
|
14
13
|
export declare class SeparateVolumesComponent extends ChartBaseElement {
|
|
15
14
|
private chartComponent;
|
|
16
|
-
private drawingManager;
|
|
17
15
|
config: FullChartConfig;
|
|
18
16
|
private volumesModel;
|
|
19
17
|
private paneManager;
|
|
20
18
|
static UUID: string;
|
|
21
19
|
pane: PaneComponent | undefined;
|
|
22
|
-
constructor(chartComponent: ChartComponent,
|
|
20
|
+
constructor(chartComponent: ChartComponent, config: FullChartConfig, volumesModel: VolumesModel, paneManager: PaneManager);
|
|
23
21
|
protected doActivate(): void;
|
|
24
22
|
/**
|
|
25
23
|
* Activates the separate volumes feature.
|
|
@@ -7,10 +7,9 @@ import { ChartBaseElement } from '../../model/chart-base-element';
|
|
|
7
7
|
import { createCandlesOffsetProvider } from '../chart/data-series.high-low-provider';
|
|
8
8
|
import { volumeFormatter } from './volumes.formatter';
|
|
9
9
|
class SeparateVolumesComponent extends ChartBaseElement {
|
|
10
|
-
constructor(chartComponent,
|
|
10
|
+
constructor(chartComponent, config, volumesModel, paneManager) {
|
|
11
11
|
super();
|
|
12
12
|
this.chartComponent = chartComponent;
|
|
13
|
-
this.drawingManager = drawingManager;
|
|
14
13
|
this.config = config;
|
|
15
14
|
this.volumesModel = volumesModel;
|
|
16
15
|
this.paneManager = paneManager;
|
|
@@ -53,7 +52,6 @@ class SeparateVolumesComponent extends ChartBaseElement {
|
|
|
53
52
|
deactiveSeparateVolumes() {
|
|
54
53
|
this.paneManager.removePane(SeparateVolumesComponent.UUID);
|
|
55
54
|
delete this.pane;
|
|
56
|
-
this.drawingManager.removeDrawerByName('UNDERLAY_VOLUMES_AREA');
|
|
57
55
|
}
|
|
58
56
|
/**
|
|
59
57
|
* Converts a pixel value from the Y-axis of the scale model to the corresponding data value.
|
|
@@ -23,7 +23,7 @@ export class VolumesComponent extends ChartBaseElement {
|
|
|
23
23
|
const volumesModel = new VolumesModel(chartComponent, scale);
|
|
24
24
|
this.volumesModel = volumesModel;
|
|
25
25
|
this.addChildEntity(volumesModel);
|
|
26
|
-
this.separateVolumes = new SeparateVolumesComponent(chartComponent,
|
|
26
|
+
this.separateVolumes = new SeparateVolumesComponent(chartComponent, config, volumesModel, paneManager);
|
|
27
27
|
this.volumesDrawer = new VolumesDrawer(config, this.volumesModel, chartComponent.chartModel, () => { var _a, _b; return (this.config.components.volumes.showSeparately ? (_b = (_a = this.separateVolumes.pane) === null || _a === void 0 ? void 0 : _a.scale) !== null && _b !== void 0 ? _b : scale : scale); }, this.volumesColorByChartTypeMap, () => true);
|
|
28
28
|
config.components.volumes.visible && this.syncVolumesDynamicObject();
|
|
29
29
|
this.addChildEntity(this.separateVolumes);
|
|
@@ -101,12 +101,12 @@ export class VolumesDrawer {
|
|
|
101
101
|
const width = nextX !== undefined ? nextX - x : floorToDPR(unitToPixels(vCandle.width, viewportModel.zoomX));
|
|
102
102
|
if (this.config.components.volumes.showSeparately) {
|
|
103
103
|
const y = floorToDPR(viewportModel.toY(vCandle.candle.volume));
|
|
104
|
-
const height =
|
|
104
|
+
const height = ceilToDPR(viewportModel.toY(0)) - y;
|
|
105
105
|
this.drawVolume(canvasModel, vCandle, x, y, width, height);
|
|
106
106
|
}
|
|
107
107
|
else {
|
|
108
108
|
const zoomY = volumeMax / (fullVHeight / OVERLAY_VOLUME_TOTAL_HEIGHT_DIVISOR);
|
|
109
|
-
const height = Math.max(unitToPixels(vCandle.candle.volume, zoomY), 2);
|
|
109
|
+
const height = Math.max(ceilToDPR(unitToPixels(vCandle.candle.volume, zoomY)), 2);
|
|
110
110
|
const y = floorToDPR(bounds.y + fullVHeight - height);
|
|
111
111
|
this.drawVolume(canvasModel, vCandle, x, y, width, height);
|
|
112
112
|
}
|
|
@@ -139,7 +139,7 @@ export class VolumesDrawer {
|
|
|
139
139
|
ctx.stroke();
|
|
140
140
|
}
|
|
141
141
|
else {
|
|
142
|
-
ctx.fillRect(x, y, width,
|
|
142
|
+
ctx.fillRect(x, y, width, height);
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
}
|
|
@@ -5,21 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { CanvasBoundsContainer } from '../../canvas/canvas-bounds-container';
|
|
7
7
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
8
|
-
import { FullChartConfig } from '../../chart.config';
|
|
8
|
+
import { ChartConfigComponentsWaterMark, FullChartConfig } from '../../chart.config';
|
|
9
9
|
import { CanvasModel } from '../../model/canvas.model';
|
|
10
10
|
import { DrawingManager } from '../../drawers/drawing-manager';
|
|
11
11
|
import EventBus from '../../events/event-bus';
|
|
12
12
|
import { ChartModel } from '../chart/chart.model';
|
|
13
13
|
import { PaneManager } from '../pane/pane-manager.component';
|
|
14
|
-
export interface WaterMarkConfig {
|
|
15
|
-
isVisible?: boolean;
|
|
16
|
-
fontFamily?: string;
|
|
17
|
-
firstRowFontSize?: number;
|
|
18
|
-
firstRowBottomPadding?: number;
|
|
19
|
-
secondRowFontSize?: number;
|
|
20
|
-
secondRowBottomPadding?: number;
|
|
21
|
-
thirdRowFontSize?: number;
|
|
22
|
-
}
|
|
23
14
|
export interface WaterMarkData {
|
|
24
15
|
firstRow?: string;
|
|
25
16
|
secondRow?: string;
|
|
@@ -55,11 +46,11 @@ export declare class WaterMarkComponent extends ChartBaseElement {
|
|
|
55
46
|
private getWaterMarkData;
|
|
56
47
|
/**
|
|
57
48
|
* Sets the watermark configuration for the chart.
|
|
58
|
-
* @param {
|
|
49
|
+
* @param {ChartConfigComponentsWaterMark} watermarkConfig - The configuration object for the watermark.
|
|
59
50
|
* @returns {void}
|
|
60
51
|
|
|
61
52
|
*/
|
|
62
|
-
setWaterMarkConfig(watermarkConfig:
|
|
53
|
+
setWaterMarkConfig(watermarkConfig: ChartConfigComponentsWaterMark): void;
|
|
63
54
|
/**
|
|
64
55
|
* Sets the logo image to be used as a watermark.
|
|
65
56
|
* @param {CanvasImageSource} img - The image to be used as a watermark.
|
|
@@ -56,7 +56,7 @@ export class WaterMarkComponent extends ChartBaseElement {
|
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* Sets the watermark configuration for the chart.
|
|
59
|
-
* @param {
|
|
59
|
+
* @param {ChartConfigComponentsWaterMark} watermarkConfig - The configuration object for the watermark.
|
|
60
60
|
* @returns {void}
|
|
61
61
|
|
|
62
62
|
*/
|
|
@@ -75,7 +75,7 @@ export const parseTimeFormatsFromKey = (format) => {
|
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
78
|
-
console.warn(`${format} is not fit, check the documentation to see available formats
|
|
78
|
+
console.warn(`${format} is not fit, check the documentation to see available formats in dxchart-lite documentation.`);
|
|
79
79
|
return null;
|
|
80
80
|
}
|
|
81
81
|
};
|
|
@@ -18,7 +18,7 @@ export interface XAxisLabelsGenerator {
|
|
|
18
18
|
/**
|
|
19
19
|
* Generates x-axis labels from scratch. Heavy operation.
|
|
20
20
|
*/
|
|
21
|
-
generateLabels(): void;
|
|
21
|
+
generateLabels(prependedCandles?: VisualCandle[]): void;
|
|
22
22
|
/**
|
|
23
23
|
* Updates current labels state (x-position). Lightweight operation.
|
|
24
24
|
*/
|
|
@@ -107,7 +107,7 @@ export declare class XAxisTimeLabelsGenerator implements XAxisLabelsGenerator {
|
|
|
107
107
|
* Calls the method generateWeightedLabels to generate labels.
|
|
108
108
|
* @returns {void}
|
|
109
109
|
*/
|
|
110
|
-
generateLabels(): void;
|
|
110
|
+
generateLabels(prependedCandles?: VisualCandle[]): void;
|
|
111
111
|
/**
|
|
112
112
|
* Recalculates the labels by calling the method recalculateCachedLabels.
|
|
113
113
|
* @returns {void}
|
|
@@ -86,14 +86,14 @@ export class XAxisTimeLabelsGenerator {
|
|
|
86
86
|
/**
|
|
87
87
|
* Make a prediction(750) about how many candles we need to fake to fill all X axis by labels
|
|
88
88
|
*/
|
|
89
|
-
getAllCandlesWithFake() {
|
|
89
|
+
getAllCandlesWithFake(prependedCandles = []) {
|
|
90
90
|
const visualCandles = this.chartModel.mainCandleSeries.visualPoints;
|
|
91
91
|
if (visualCandles.length === 0) {
|
|
92
92
|
return [];
|
|
93
93
|
}
|
|
94
94
|
const fakeCandlesForSides = Array.from({ length: 750 });
|
|
95
95
|
const appendFakeCandle = fakeCandlesForSides.map((_, idx) => fakeVisualCandle(this.chartModel.mainCandleSeries.dataPoints, this.chartModel.mainCandleSeries.visualPoints, this.chartModel.mainCandleSeries.meanCandleWidth, visualCandles.length + idx, this.chartModel.getPeriod()));
|
|
96
|
-
return [...visualCandles, ...appendFakeCandle];
|
|
96
|
+
return [...prependedCandles, ...visualCandles, ...appendFakeCandle];
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
99
|
* Maps an array of weighted points to an array of XAxisLabelWeighted objects.
|
|
@@ -139,8 +139,8 @@ export class XAxisTimeLabelsGenerator {
|
|
|
139
139
|
* @function
|
|
140
140
|
* @returns {void}
|
|
141
141
|
*/
|
|
142
|
-
generateWeightedLabels() {
|
|
143
|
-
const allCandlesWithFake = this.getAllCandlesWithFake();
|
|
142
|
+
generateWeightedLabels(prependedCandles = []) {
|
|
143
|
+
const allCandlesWithFake = this.getAllCandlesWithFake(prependedCandles);
|
|
144
144
|
const weightedPoints = mapCandlesToWeightedPoints(allCandlesWithFake, this.weightToTimeFormatMatcherArray, this.timeZoneModel.tzOffset(this.config.timezone));
|
|
145
145
|
const weightedLabels = this.mapWeightedPointsToLabels(weightedPoints, allCandlesWithFake);
|
|
146
146
|
this.labelsGroupedByWeight = groupLabelsByWeight(weightedLabels);
|
|
@@ -253,8 +253,8 @@ export class XAxisTimeLabelsGenerator {
|
|
|
253
253
|
* Calls the method generateWeightedLabels to generate labels.
|
|
254
254
|
* @returns {void}
|
|
255
255
|
*/
|
|
256
|
-
generateLabels() {
|
|
257
|
-
this.generateWeightedLabels();
|
|
256
|
+
generateLabels(prependedCandles) {
|
|
257
|
+
this.generateWeightedLabels(prependedCandles);
|
|
258
258
|
}
|
|
259
259
|
/**
|
|
260
260
|
* Recalculates the labels by calling the method recalculateCachedLabels.
|
|
@@ -47,8 +47,8 @@ export class XAxisScaleHandler extends ChartBaseElement {
|
|
|
47
47
|
// Continue redrawing hit test
|
|
48
48
|
this.hitTestCanvasModel.hitTestDrawersPredicateSubject.next(true);
|
|
49
49
|
};
|
|
50
|
-
this.setDblTapCallback = (cb) => this.dblTapCallback = cb;
|
|
51
|
-
this.setDblClickCallback = (cb) => this.dblClickCallback = cb;
|
|
50
|
+
this.setDblTapCallback = (cb) => (this.dblTapCallback = cb);
|
|
51
|
+
this.setDblClickCallback = (cb) => (this.dblClickCallback = cb);
|
|
52
52
|
this.dblClickCallback = () => chartModel.doBasicScale();
|
|
53
53
|
this.dblTapCallback = () => chartModel.doBasicScale();
|
|
54
54
|
const dragNDropXComponent = new DragNDropXComponent(hitTest, {
|
|
@@ -82,7 +82,7 @@ export class XAxisComponent extends ChartBaseElement {
|
|
|
82
82
|
this.xAxisLabelsGenerator.recalculateLabels();
|
|
83
83
|
}));
|
|
84
84
|
this.addRxSubscription(this.chartComponent.chartModel.candlesUpdatedSubject
|
|
85
|
-
.pipe(map(() => lastOf(this.chartComponent.chartModel.mainCandleSeries.visualPoints)), distinctUntilChanged((a, b) => { var _a, _b; return ((_a = a === null || a === void 0 ? void 0 : a.candle) === null || _a === void 0 ? void 0 : _a.
|
|
85
|
+
.pipe(map(() => lastOf(this.chartComponent.chartModel.mainCandleSeries.visualPoints)), distinctUntilChanged((a, b) => { var _a, _b; return ((_a = a === null || a === void 0 ? void 0 : a.candle) === null || _a === void 0 ? void 0 : _a.id) === ((_b = b === null || b === void 0 ? void 0 : b.candle) === null || _b === void 0 ? void 0 : _b.id); }), filter(notEmpty))
|
|
86
86
|
.subscribe(x => { var _a, _b; return (_b = (_a = this.xAxisLabelsGenerator) === null || _a === void 0 ? void 0 : _a.updateLastLabel) === null || _b === void 0 ? void 0 : _b.call(_a, x); }));
|
|
87
87
|
}
|
|
88
88
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
import { Subject } from 'rxjs';
|
|
7
|
-
import { CanvasElement, DEFAULT_MIN_PANE_HEIGHT } from '../../canvas/canvas-bounds-container';
|
|
7
|
+
import { CanvasElement, DEFAULT_MIN_PANE_HEIGHT, } from '../../canvas/canvas-bounds-container';
|
|
8
8
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
9
9
|
import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.component';
|
|
10
10
|
// if you drag full Y height from top to bottom - you will have x3 zoom, and vice-versa
|
|
@@ -73,8 +73,8 @@ export class YAxisScaleHandler extends ChartBaseElement {
|
|
|
73
73
|
// Continue redrawing hit test
|
|
74
74
|
this.hitTestCanvasModel.hitTestDrawersPredicateSubject.next(true);
|
|
75
75
|
};
|
|
76
|
-
this.setDblTapCallback = (cb) => this.dblTapCallback = cb;
|
|
77
|
-
this.setDblClickCallback = (cb) => this.dblClickCallback = cb;
|
|
76
|
+
this.setDblTapCallback = (cb) => (this.dblTapCallback = cb);
|
|
77
|
+
this.setDblClickCallback = (cb) => (this.dblClickCallback = cb);
|
|
78
78
|
this.dblClickCallback = () => scale.autoScale(true);
|
|
79
79
|
this.dblTapCallback = () => scale.autoScale(true);
|
|
80
80
|
// drag to Y-scale and double click to auto scale
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import EventBus from '../events/event-bus';
|
|
7
7
|
import { ChartResizeHandler } from '../inputhandlers/chart-resize.handler';
|
|
8
8
|
export declare const HIT_TEST_PREFIX = "HIT_TEST_";
|
|
9
|
-
declare const drawerTypes: readonly ["MAIN_BACKGROUND", "MAIN_CLEAR", "HIT_TEST_CLEAR", "YAXIS_CLEAR", "SERIES_CLEAR", "OVER_SERIES_CLEAR", "HIT_TEST_DRAWINGS", "GRID", "
|
|
9
|
+
declare const drawerTypes: readonly ["MAIN_BACKGROUND", "MAIN_CLEAR", "HIT_TEST_CLEAR", "YAXIS_CLEAR", "SERIES_CLEAR", "OVER_SERIES_CLEAR", "HIT_TEST_DRAWINGS", "GRID", "X_AXIS", "Y_AXIS", "HIGH_LOW", "DYNAMIC_OBJECTS", "N_MAP_CHART", "PL_CHART", "WATERMARK", "EMPTY_CHART", "OFFLINE_CHART", "LABELS", "EVENTS", "HIT_TEST_EVENTS", "ZERO_LINE", "PL_ZERO_LINE_BACKGROUND", "CROSS_TOOL"];
|
|
10
10
|
export type DrawerType = typeof drawerTypes[number];
|
|
11
11
|
/**
|
|
12
12
|
* Manages the drawing process.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
import { BehaviorSubject, merge } from 'rxjs';
|
|
7
|
+
import { filter, switchMap } from 'rxjs/operators';
|
|
7
8
|
import { CHART_UUID, CanvasElement } from '../canvas/canvas-bounds-container';
|
|
8
9
|
import { CandleHoverProducerPart } from '../model/candle-hover';
|
|
9
10
|
import { ChartBaseElement } from '../model/chart-base-element';
|
|
@@ -50,8 +51,13 @@ export class HoverProducerComponent extends ChartBaseElement {
|
|
|
50
51
|
*/
|
|
51
52
|
doActivate() {
|
|
52
53
|
super.doActivate();
|
|
53
|
-
this.addRxSubscription(
|
|
54
|
-
|
|
54
|
+
this.addRxSubscription(
|
|
55
|
+
// required for initial legend initialization, do not show cross tool
|
|
56
|
+
this.chartModel.candlesSetSubject
|
|
57
|
+
.pipe(
|
|
58
|
+
// check the scale is valid before doing candle-based hover event
|
|
59
|
+
switchMap(() => this.scale.initialViewportValidSubject.pipe(filter(Boolean))))
|
|
60
|
+
.subscribe(() => {
|
|
55
61
|
const lastCandle = this.chartModel.getLastVisualCandle();
|
|
56
62
|
lastCandle && this.createAndFireHoverFromCandle(lastCandle);
|
|
57
63
|
}));
|
|
@@ -89,7 +89,7 @@ export class MainCanvasTouchHandler extends ChartBaseElement {
|
|
|
89
89
|
const last = first +
|
|
90
90
|
((candleIndexes[0] - candleIndexes[1]) / (touchPositions[0] - touchPositions[1])) *
|
|
91
91
|
this.scale.getBounds().width;
|
|
92
|
-
if (first >= last) {
|
|
92
|
+
if (first >= last || touchPositions[0] === touchPositions[1]) {
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
this.scale.setXScale(first, last);
|
|
@@ -11,6 +11,7 @@ export declare const BASIC_CANDLE_WIDTH: Unit;
|
|
|
11
11
|
* @doc-tags-name Candle
|
|
12
12
|
*/
|
|
13
13
|
export interface Candle {
|
|
14
|
+
readonly id: string;
|
|
14
15
|
readonly hi: number;
|
|
15
16
|
readonly lo: number;
|
|
16
17
|
readonly open: number;
|
|
@@ -22,6 +23,8 @@ export interface Candle {
|
|
|
22
23
|
readonly impVolatility?: number;
|
|
23
24
|
readonly vwap?: number;
|
|
24
25
|
}
|
|
26
|
+
export declare const defaultSortCandles: (candles: Candle[]) => Candle[];
|
|
27
|
+
export declare const generateCandleId: (timestamp: number, hashValue: number | string) => string;
|
|
25
28
|
/**
|
|
26
29
|
* Provides the name of candle difference
|
|
27
30
|
* @param {Number} open
|