hyperprop-charting-library 0.1.24 → 0.1.25
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/README.md +31 -0
- package/dist/hyperprop-charting-library.cjs +213 -20
- package/dist/hyperprop-charting-library.d.ts +15 -1
- package/dist/hyperprop-charting-library.js +213 -20
- package/dist/index.cjs +213 -20
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +213 -20
- package/docs/API.md +16 -1
- package/docs/RECIPES.md +39 -0
- package/package.json +1 -1
|
@@ -109,6 +109,8 @@ var DEFAULT_OPTIONS = {
|
|
|
109
109
|
backgroundColor: "#101114",
|
|
110
110
|
axisColor: "#7f8289",
|
|
111
111
|
axis: DEFAULT_AXIS_OPTIONS,
|
|
112
|
+
xAxis: DEFAULT_AXIS_OPTIONS,
|
|
113
|
+
yAxis: DEFAULT_AXIS_OPTIONS,
|
|
112
114
|
priceDecimals: 2,
|
|
113
115
|
stabilizePriceLabels: true,
|
|
114
116
|
priceLabelMinIntegerDigits: 3,
|
|
@@ -127,6 +129,7 @@ var DEFAULT_OPTIONS = {
|
|
|
127
129
|
candleBodyWidthRatio: 0.7,
|
|
128
130
|
candleMinWidth: 0.5,
|
|
129
131
|
candleWickWidth: 1,
|
|
132
|
+
tickSize: 0,
|
|
130
133
|
candleColorMode: "openClose",
|
|
131
134
|
candleColorEpsilon: -1,
|
|
132
135
|
autoScaleSmoothing: 0.16,
|
|
@@ -364,6 +367,35 @@ var computeAtrSeries = (data, length) => {
|
|
|
364
367
|
}
|
|
365
368
|
return result;
|
|
366
369
|
};
|
|
370
|
+
var builtInSeriesCache = /* @__PURE__ */ new Map();
|
|
371
|
+
var getSeriesFingerprint = (data) => {
|
|
372
|
+
const length = data.length;
|
|
373
|
+
const last = length > 0 ? data[length - 1] : void 0;
|
|
374
|
+
const prev = length > 1 ? data[length - 2] : void 0;
|
|
375
|
+
if (!last) return "empty";
|
|
376
|
+
return [
|
|
377
|
+
length,
|
|
378
|
+
last.time.getTime(),
|
|
379
|
+
last.o,
|
|
380
|
+
last.h,
|
|
381
|
+
last.l,
|
|
382
|
+
last.c,
|
|
383
|
+
last.v ?? "",
|
|
384
|
+
prev?.time.getTime() ?? "",
|
|
385
|
+
prev?.c ?? "",
|
|
386
|
+
prev?.v ?? ""
|
|
387
|
+
].join("|");
|
|
388
|
+
};
|
|
389
|
+
var withCachedSeries = (key, data, compute) => {
|
|
390
|
+
const fingerprint = getSeriesFingerprint(data);
|
|
391
|
+
const existing = builtInSeriesCache.get(key);
|
|
392
|
+
if (existing && existing.fingerprint === fingerprint) {
|
|
393
|
+
return existing.values;
|
|
394
|
+
}
|
|
395
|
+
const values = compute();
|
|
396
|
+
builtInSeriesCache.set(key, { fingerprint, values });
|
|
397
|
+
return values;
|
|
398
|
+
};
|
|
367
399
|
var drawOverlaySeries = (ctx, renderContext, values, color, width) => {
|
|
368
400
|
if (!renderContext.yFromPrice) return;
|
|
369
401
|
const yFromPrice = renderContext.yFromPrice;
|
|
@@ -461,6 +493,8 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
461
493
|
defaultInputs: {
|
|
462
494
|
upOpacity: 0.7,
|
|
463
495
|
downOpacity: 0.7,
|
|
496
|
+
upColor: "",
|
|
497
|
+
downColor: "",
|
|
464
498
|
minBarWidth: 1,
|
|
465
499
|
overlayHeightRatio: 0.22
|
|
466
500
|
},
|
|
@@ -491,9 +525,11 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
491
525
|
const barY = Math.round(paneBottom - volumeHeight);
|
|
492
526
|
const direction = renderContext.getCandleDirectionByIndex(index);
|
|
493
527
|
const opacity = direction === "up" ? upOpacity : downOpacity;
|
|
528
|
+
const upBarColor = inputs.upColor && inputs.upColor.trim().length > 0 ? inputs.upColor : upColor;
|
|
529
|
+
const downBarColor = inputs.downColor && inputs.downColor.trim().length > 0 ? inputs.downColor : downColor;
|
|
494
530
|
ctx.save();
|
|
495
531
|
ctx.globalAlpha = opacity;
|
|
496
|
-
ctx.fillStyle = direction === "up" ?
|
|
532
|
+
ctx.fillStyle = direction === "up" ? upBarColor : downBarColor;
|
|
497
533
|
ctx.fillRect(barX, barY, Math.max(1, Math.round(barWidth)), volumeHeight);
|
|
498
534
|
ctx.restore();
|
|
499
535
|
}
|
|
@@ -506,7 +542,11 @@ var BUILTIN_SMA_INDICATOR = {
|
|
|
506
542
|
defaultInputs: { length: 20, source: "close", color: "#60a5fa", width: 2 },
|
|
507
543
|
draw: (ctx, renderContext, inputs) => {
|
|
508
544
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
509
|
-
const values =
|
|
545
|
+
const values = withCachedSeries(
|
|
546
|
+
`sma|${length}|${inputs.source ?? "close"}`,
|
|
547
|
+
renderContext.data,
|
|
548
|
+
() => computeSmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
549
|
+
);
|
|
510
550
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#60a5fa", Number(inputs.width) || 2);
|
|
511
551
|
}
|
|
512
552
|
};
|
|
@@ -517,7 +557,11 @@ var BUILTIN_EMA_INDICATOR = {
|
|
|
517
557
|
defaultInputs: { length: 20, source: "close", color: "#f59e0b", width: 2 },
|
|
518
558
|
draw: (ctx, renderContext, inputs) => {
|
|
519
559
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
520
|
-
const values =
|
|
560
|
+
const values = withCachedSeries(
|
|
561
|
+
`ema|${length}|${inputs.source ?? "close"}`,
|
|
562
|
+
renderContext.data,
|
|
563
|
+
() => computeEmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
564
|
+
);
|
|
521
565
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#f59e0b", Number(inputs.width) || 2);
|
|
522
566
|
}
|
|
523
567
|
};
|
|
@@ -528,7 +572,11 @@ var BUILTIN_WMA_INDICATOR = {
|
|
|
528
572
|
defaultInputs: { length: 20, source: "close", color: "#a78bfa", width: 2 },
|
|
529
573
|
draw: (ctx, renderContext, inputs) => {
|
|
530
574
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
531
|
-
const values =
|
|
575
|
+
const values = withCachedSeries(
|
|
576
|
+
`wma|${length}|${inputs.source ?? "close"}`,
|
|
577
|
+
renderContext.data,
|
|
578
|
+
() => computeWmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
579
|
+
);
|
|
532
580
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#a78bfa", Number(inputs.width) || 2);
|
|
533
581
|
}
|
|
534
582
|
};
|
|
@@ -539,7 +587,11 @@ var BUILTIN_VWMA_INDICATOR = {
|
|
|
539
587
|
defaultInputs: { length: 20, source: "close", color: "#ef4444", width: 2 },
|
|
540
588
|
draw: (ctx, renderContext, inputs) => {
|
|
541
589
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
542
|
-
const values =
|
|
590
|
+
const values = withCachedSeries(
|
|
591
|
+
`vwma|${length}|${inputs.source ?? "close"}`,
|
|
592
|
+
renderContext.data,
|
|
593
|
+
() => computeVwmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
594
|
+
);
|
|
543
595
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#ef4444", Number(inputs.width) || 2);
|
|
544
596
|
}
|
|
545
597
|
};
|
|
@@ -550,7 +602,11 @@ var BUILTIN_RMA_INDICATOR = {
|
|
|
550
602
|
defaultInputs: { length: 14, source: "close", color: "#22c55e", width: 2 },
|
|
551
603
|
draw: (ctx, renderContext, inputs) => {
|
|
552
604
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
553
|
-
const values =
|
|
605
|
+
const values = withCachedSeries(
|
|
606
|
+
`rma|${length}|${inputs.source ?? "close"}`,
|
|
607
|
+
renderContext.data,
|
|
608
|
+
() => computeRmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
609
|
+
);
|
|
554
610
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#22c55e", Number(inputs.width) || 2);
|
|
555
611
|
}
|
|
556
612
|
};
|
|
@@ -561,7 +617,11 @@ var BUILTIN_HMA_INDICATOR = {
|
|
|
561
617
|
defaultInputs: { length: 21, source: "close", color: "#14b8a6", width: 2 },
|
|
562
618
|
draw: (ctx, renderContext, inputs) => {
|
|
563
619
|
const length = clampIndicatorLength(inputs.length, 21);
|
|
564
|
-
const values =
|
|
620
|
+
const values = withCachedSeries(
|
|
621
|
+
`hma|${length}|${inputs.source ?? "close"}`,
|
|
622
|
+
renderContext.data,
|
|
623
|
+
() => computeHmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
624
|
+
);
|
|
565
625
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#14b8a6", Number(inputs.width) || 2);
|
|
566
626
|
}
|
|
567
627
|
};
|
|
@@ -573,7 +633,11 @@ var BUILTIN_STDDEV_INDICATOR = {
|
|
|
573
633
|
defaultInputs: { length: 20, source: "close", color: "#f97316", width: 2 },
|
|
574
634
|
draw: (ctx, renderContext, inputs) => {
|
|
575
635
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
576
|
-
const values =
|
|
636
|
+
const values = withCachedSeries(
|
|
637
|
+
`stddev|${length}|${inputs.source ?? "close"}`,
|
|
638
|
+
renderContext.data,
|
|
639
|
+
() => computeStdDevSeries(renderContext.data, length, inputs.source ?? "close")
|
|
640
|
+
);
|
|
577
641
|
drawSeparateSeries(ctx, renderContext, values, inputs.color ?? "#f97316", Number(inputs.width) || 2);
|
|
578
642
|
}
|
|
579
643
|
};
|
|
@@ -585,7 +649,7 @@ var BUILTIN_ATR_INDICATOR = {
|
|
|
585
649
|
defaultInputs: { length: 14, color: "#eab308", width: 2 },
|
|
586
650
|
draw: (ctx, renderContext, inputs) => {
|
|
587
651
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
588
|
-
const values = computeAtrSeries(renderContext.data, length);
|
|
652
|
+
const values = withCachedSeries(`atr|${length}`, renderContext.data, () => computeAtrSeries(renderContext.data, length));
|
|
589
653
|
drawSeparateSeries(ctx, renderContext, values, inputs.color ?? "#eab308", Number(inputs.width) || 2);
|
|
590
654
|
}
|
|
591
655
|
};
|
|
@@ -597,7 +661,7 @@ var BUILTIN_RSI_INDICATOR = {
|
|
|
597
661
|
defaultInputs: { length: 14, color: "#3b82f6", width: 2 },
|
|
598
662
|
draw: (ctx, renderContext, inputs) => {
|
|
599
663
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
600
|
-
const values = computeRsiSeries(renderContext.data, length);
|
|
664
|
+
const values = withCachedSeries(`rsi|${length}`, renderContext.data, () => computeRsiSeries(renderContext.data, length));
|
|
601
665
|
drawSeparateSeries(
|
|
602
666
|
ctx,
|
|
603
667
|
renderContext,
|
|
@@ -631,6 +695,18 @@ function createChart(element, options = {}) {
|
|
|
631
695
|
...options.axis ?? {},
|
|
632
696
|
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
633
697
|
},
|
|
698
|
+
xAxis: {
|
|
699
|
+
...DEFAULT_AXIS_OPTIONS,
|
|
700
|
+
...options.axis ?? {},
|
|
701
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
702
|
+
...options.xAxis ?? {}
|
|
703
|
+
},
|
|
704
|
+
yAxis: {
|
|
705
|
+
...DEFAULT_AXIS_OPTIONS,
|
|
706
|
+
...options.axis ?? {},
|
|
707
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
708
|
+
...options.yAxis ?? {}
|
|
709
|
+
},
|
|
634
710
|
crosshair: {
|
|
635
711
|
...DEFAULT_CROSSHAIR_OPTIONS,
|
|
636
712
|
...options.crosshair ?? {}
|
|
@@ -686,6 +762,9 @@ function createChart(element, options = {}) {
|
|
|
686
762
|
visible: indicator.visible ?? true,
|
|
687
763
|
pane: indicator.pane ?? plugin?.pane ?? "overlay",
|
|
688
764
|
...indicator.paneHeightRatio === void 0 ? {} : { paneHeightRatio: indicator.paneHeightRatio },
|
|
765
|
+
zIndex: Math.round(Number(indicator.zIndex) || 0),
|
|
766
|
+
excludeFromAutoscale: indicator.excludeFromAutoscale ?? true,
|
|
767
|
+
overlayScaleWeight: Math.min(1, Math.max(0, Number(indicator.overlayScaleWeight) || 0.25)),
|
|
689
768
|
inputs: {
|
|
690
769
|
...defaults,
|
|
691
770
|
...indicator.inputs ?? {}
|
|
@@ -841,20 +920,56 @@ function createChart(element, options = {}) {
|
|
|
841
920
|
}
|
|
842
921
|
return { min: nextMin, max: nextMax };
|
|
843
922
|
};
|
|
923
|
+
const getConfiguredPriceDecimals = () => clamp(Math.round(mergedOptions.priceDecimals), 0, 8);
|
|
924
|
+
const getConfiguredTickSize = () => {
|
|
925
|
+
const step = Number(mergedOptions.tickSize);
|
|
926
|
+
return Number.isFinite(step) && step > 0 ? step : 0;
|
|
927
|
+
};
|
|
928
|
+
const getTickSizeDecimals = () => {
|
|
929
|
+
const tickSize = getConfiguredTickSize();
|
|
930
|
+
if (tickSize <= 0) {
|
|
931
|
+
return 0;
|
|
932
|
+
}
|
|
933
|
+
let scaled = tickSize;
|
|
934
|
+
let decimals = 0;
|
|
935
|
+
while (decimals < 8 && Math.abs(Math.round(scaled) - scaled) > 1e-10) {
|
|
936
|
+
scaled *= 10;
|
|
937
|
+
decimals += 1;
|
|
938
|
+
}
|
|
939
|
+
return decimals;
|
|
940
|
+
};
|
|
941
|
+
const getDisplayPriceDecimals = () => {
|
|
942
|
+
const configured = getConfiguredPriceDecimals();
|
|
943
|
+
const tickDecimals = getTickSizeDecimals();
|
|
944
|
+
return Math.max(configured, tickDecimals);
|
|
945
|
+
};
|
|
946
|
+
const quantizeToTickSize = (price) => {
|
|
947
|
+
const tickSize = getConfiguredTickSize();
|
|
948
|
+
if (tickSize <= 0 || !Number.isFinite(price)) {
|
|
949
|
+
return price;
|
|
950
|
+
}
|
|
951
|
+
return Math.round(price / tickSize) * tickSize;
|
|
952
|
+
};
|
|
844
953
|
const formatPrice = (price) => {
|
|
845
|
-
const
|
|
846
|
-
|
|
954
|
+
const rounded = quantizeToTickSize(price);
|
|
955
|
+
const decimals = getDisplayPriceDecimals();
|
|
956
|
+
return rounded.toFixed(decimals);
|
|
847
957
|
};
|
|
848
958
|
const roundToPricePrecision = (price) => {
|
|
849
|
-
const
|
|
850
|
-
|
|
959
|
+
const rounded = quantizeToTickSize(price);
|
|
960
|
+
const decimals = getDisplayPriceDecimals();
|
|
961
|
+
return Number(rounded.toFixed(decimals));
|
|
851
962
|
};
|
|
852
963
|
const getResolvedCandleColorEpsilon = () => {
|
|
853
964
|
const configured = mergedOptions.candleColorEpsilon;
|
|
854
965
|
if (configured >= 0) {
|
|
855
966
|
return configured;
|
|
856
967
|
}
|
|
857
|
-
const
|
|
968
|
+
const tickSize = getConfiguredTickSize();
|
|
969
|
+
if (tickSize > 0) {
|
|
970
|
+
return tickSize / 2;
|
|
971
|
+
}
|
|
972
|
+
const decimals = getDisplayPriceDecimals();
|
|
858
973
|
return decimals > 0 ? 0.5 / 10 ** decimals : 0;
|
|
859
974
|
};
|
|
860
975
|
const getDirectionFromDelta = (delta) => {
|
|
@@ -1386,6 +1501,10 @@ function createChart(element, options = {}) {
|
|
|
1386
1501
|
canvas.height = Math.floor(height * pixelRatio);
|
|
1387
1502
|
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
1388
1503
|
const axis = { ...DEFAULT_AXIS_OPTIONS, ...mergedOptions.axis ?? {} };
|
|
1504
|
+
const xAxis = { ...DEFAULT_AXIS_OPTIONS, ...mergedOptions.xAxis ?? {} };
|
|
1505
|
+
const yAxis = { ...DEFAULT_AXIS_OPTIONS, ...mergedOptions.yAxis ?? {} };
|
|
1506
|
+
const xAxisFontSize = Math.max(8, xAxis.fontSize);
|
|
1507
|
+
const yAxisFontSize = Math.max(8, yAxis.fontSize);
|
|
1389
1508
|
ctx.font = `${Math.max(8, axis.fontSize)}px ${mergedOptions.fontFamily}`;
|
|
1390
1509
|
ctx.fillStyle = mergedOptions.backgroundColor;
|
|
1391
1510
|
ctx.fillRect(0, 0, width, height);
|
|
@@ -1400,6 +1519,9 @@ function createChart(element, options = {}) {
|
|
|
1400
1519
|
const separatePaneSpacing = 6;
|
|
1401
1520
|
const activeSeparateIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1402
1521
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "separate"
|
|
1522
|
+
).sort((a, b) => a.indicator.zIndex - b.indicator.zIndex);
|
|
1523
|
+
const overlayIndicatorsForScale = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1524
|
+
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
1403
1525
|
);
|
|
1404
1526
|
const separatePaneHeightDefaults = activeSeparateIndicators.map(({ indicator, plugin }) => {
|
|
1405
1527
|
const ratio = Math.min(0.45, Math.max(0.08, indicator.paneHeightRatio ?? plugin.paneHeightRatio ?? 0.22));
|
|
@@ -1451,8 +1573,47 @@ function createChart(element, options = {}) {
|
|
|
1451
1573
|
}
|
|
1452
1574
|
}
|
|
1453
1575
|
}
|
|
1454
|
-
|
|
1455
|
-
|
|
1576
|
+
let minPrice = Math.min(...priceSource.map((point) => point.l));
|
|
1577
|
+
let maxPrice = Math.max(...priceSource.map((point) => point.h));
|
|
1578
|
+
if (overlayIndicatorsForScale.length > 0) {
|
|
1579
|
+
for (const { indicator } of overlayIndicatorsForScale) {
|
|
1580
|
+
if (indicator.excludeFromAutoscale) {
|
|
1581
|
+
continue;
|
|
1582
|
+
}
|
|
1583
|
+
const type = indicator.type;
|
|
1584
|
+
const inputs = indicator.inputs;
|
|
1585
|
+
const source = inputs.source ?? "close";
|
|
1586
|
+
const length = clampIndicatorLength(inputs.length ?? 14, 14);
|
|
1587
|
+
let series = null;
|
|
1588
|
+
if (type === "sma") series = withCachedSeries(`sma|${length}|${source}`, data, () => computeSmaSeries(data, length, source));
|
|
1589
|
+
if (type === "ema") series = withCachedSeries(`ema|${length}|${source}`, data, () => computeEmaSeries(data, length, source));
|
|
1590
|
+
if (type === "wma") series = withCachedSeries(`wma|${length}|${source}`, data, () => computeWmaSeries(data, length, source));
|
|
1591
|
+
if (type === "vwma") series = withCachedSeries(`vwma|${length}|${source}`, data, () => computeVwmaSeries(data, length, source));
|
|
1592
|
+
if (type === "rma") series = withCachedSeries(`rma|${length}|${source}`, data, () => computeRmaSeries(data, length, source));
|
|
1593
|
+
if (type === "hma") series = withCachedSeries(`hma|${length}|${source}`, data, () => computeHmaSeries(data, length, source));
|
|
1594
|
+
if (!series) {
|
|
1595
|
+
continue;
|
|
1596
|
+
}
|
|
1597
|
+
const visibleValues = [];
|
|
1598
|
+
for (let idx = startIndex; idx <= endIndex; idx += 1) {
|
|
1599
|
+
const value = series[idx];
|
|
1600
|
+
if (Number.isFinite(value ?? Number.NaN)) {
|
|
1601
|
+
visibleValues.push(value);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
if (visibleValues.length === 0) {
|
|
1605
|
+
continue;
|
|
1606
|
+
}
|
|
1607
|
+
const seriesMin = Math.min(...visibleValues);
|
|
1608
|
+
const seriesMax = Math.max(...visibleValues);
|
|
1609
|
+
const weight = Math.min(1, Math.max(0, indicator.overlayScaleWeight));
|
|
1610
|
+
const currentMid = (minPrice + maxPrice) / 2;
|
|
1611
|
+
const weightedMin = currentMid + (seriesMin - currentMid) * weight;
|
|
1612
|
+
const weightedMax = currentMid + (seriesMax - currentMid) * weight;
|
|
1613
|
+
minPrice = Math.min(minPrice, weightedMin);
|
|
1614
|
+
maxPrice = Math.max(maxPrice, weightedMax);
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1456
1617
|
const priceRange = maxPrice - minPrice || 1;
|
|
1457
1618
|
const autoMin = minPrice - priceRange * 0.08;
|
|
1458
1619
|
const autoMax = maxPrice + priceRange * 0.08;
|
|
@@ -1612,7 +1773,7 @@ function createChart(element, options = {}) {
|
|
|
1612
1773
|
}
|
|
1613
1774
|
const activeOverlayIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1614
1775
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
1615
|
-
);
|
|
1776
|
+
).sort((a, b) => a.indicator.zIndex - b.indicator.zIndex);
|
|
1616
1777
|
if (activeOverlayIndicators.length > 0) {
|
|
1617
1778
|
const xFromIndex = (index) => chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
1618
1779
|
activeOverlayIndicators.forEach(({ indicator, plugin }) => {
|
|
@@ -1722,7 +1883,10 @@ function createChart(element, options = {}) {
|
|
|
1722
1883
|
const ratio = tick / yTicks;
|
|
1723
1884
|
const price = yMin + yRange * ratio;
|
|
1724
1885
|
const y = yFromPrice(price);
|
|
1725
|
-
|
|
1886
|
+
const prevFont = ctx.font;
|
|
1887
|
+
ctx.font = `${yAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
1888
|
+
drawText(formatPrice(price), chartRight + 6, y, "left", "middle", yAxis.textColor);
|
|
1889
|
+
ctx.font = prevFont;
|
|
1726
1890
|
}
|
|
1727
1891
|
const ticker = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1728
1892
|
const lastPoint = data[data.length - 1];
|
|
@@ -1779,7 +1943,10 @@ function createChart(element, options = {}) {
|
|
|
1779
1943
|
month: "short",
|
|
1780
1944
|
day: "numeric"
|
|
1781
1945
|
});
|
|
1782
|
-
|
|
1946
|
+
const prevFont = ctx.font;
|
|
1947
|
+
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
1948
|
+
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|
|
1949
|
+
ctx.font = prevFont;
|
|
1783
1950
|
}
|
|
1784
1951
|
if (crosshair.visible && crosshairPoint) {
|
|
1785
1952
|
const cx = clamp(crosshairPoint.x, chartLeft, chartRight);
|
|
@@ -2550,6 +2717,27 @@ function createChart(element, options = {}) {
|
|
|
2550
2717
|
indicators = indicators.filter((indicator) => indicator.type !== type);
|
|
2551
2718
|
draw();
|
|
2552
2719
|
};
|
|
2720
|
+
const listBuiltInIndicators = () => {
|
|
2721
|
+
return BUILTIN_INDICATORS.map((indicator) => ({
|
|
2722
|
+
id: indicator.id,
|
|
2723
|
+
name: indicator.name,
|
|
2724
|
+
pane: indicator.pane ?? "overlay",
|
|
2725
|
+
...indicator.paneHeightRatio === void 0 ? {} : { paneHeightRatio: indicator.paneHeightRatio }
|
|
2726
|
+
}));
|
|
2727
|
+
};
|
|
2728
|
+
const getIndicators = () => {
|
|
2729
|
+
return indicators.map((indicator) => ({
|
|
2730
|
+
id: indicator.id,
|
|
2731
|
+
type: indicator.type,
|
|
2732
|
+
visible: indicator.visible,
|
|
2733
|
+
pane: indicator.pane,
|
|
2734
|
+
...indicator.paneHeightRatio === void 0 ? {} : { paneHeightRatio: indicator.paneHeightRatio },
|
|
2735
|
+
zIndex: indicator.zIndex,
|
|
2736
|
+
excludeFromAutoscale: indicator.excludeFromAutoscale,
|
|
2737
|
+
overlayScaleWeight: indicator.overlayScaleWeight,
|
|
2738
|
+
inputs: { ...indicator.inputs }
|
|
2739
|
+
}));
|
|
2740
|
+
};
|
|
2553
2741
|
const setIndicators = (nextIndicators) => {
|
|
2554
2742
|
indicators = nextIndicators.map((indicator) => normalizeIndicatorState(indicator));
|
|
2555
2743
|
draw();
|
|
@@ -2579,6 +2767,9 @@ function createChart(element, options = {}) {
|
|
|
2579
2767
|
visible: patch.visible ?? indicator.visible,
|
|
2580
2768
|
pane: patch.pane ?? indicator.pane ?? plugin?.pane ?? "overlay",
|
|
2581
2769
|
...patch.paneHeightRatio !== void 0 || indicator.paneHeightRatio !== void 0 ? { paneHeightRatio: patch.paneHeightRatio ?? indicator.paneHeightRatio } : {},
|
|
2770
|
+
zIndex: patch.zIndex === void 0 ? indicator.zIndex : Math.round(Number(patch.zIndex) || 0),
|
|
2771
|
+
excludeFromAutoscale: patch.excludeFromAutoscale ?? indicator.excludeFromAutoscale,
|
|
2772
|
+
overlayScaleWeight: patch.overlayScaleWeight === void 0 ? indicator.overlayScaleWeight : Math.min(1, Math.max(0, Number(patch.overlayScaleWeight) || 0)),
|
|
2582
2773
|
type: patch.type ?? indicator.type,
|
|
2583
2774
|
inputs: {
|
|
2584
2775
|
...indicator.inputs,
|
|
@@ -2628,6 +2819,8 @@ function createChart(element, options = {}) {
|
|
|
2628
2819
|
setDoubleClickAction,
|
|
2629
2820
|
registerIndicator,
|
|
2630
2821
|
unregisterIndicator,
|
|
2822
|
+
listBuiltInIndicators,
|
|
2823
|
+
getIndicators,
|
|
2631
2824
|
addIndicator,
|
|
2632
2825
|
updateIndicator,
|
|
2633
2826
|
removeIndicator,
|