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
package/dist/index.cjs
CHANGED
|
@@ -133,6 +133,8 @@ var DEFAULT_OPTIONS = {
|
|
|
133
133
|
backgroundColor: "#101114",
|
|
134
134
|
axisColor: "#7f8289",
|
|
135
135
|
axis: DEFAULT_AXIS_OPTIONS,
|
|
136
|
+
xAxis: DEFAULT_AXIS_OPTIONS,
|
|
137
|
+
yAxis: DEFAULT_AXIS_OPTIONS,
|
|
136
138
|
priceDecimals: 2,
|
|
137
139
|
stabilizePriceLabels: true,
|
|
138
140
|
priceLabelMinIntegerDigits: 3,
|
|
@@ -151,6 +153,7 @@ var DEFAULT_OPTIONS = {
|
|
|
151
153
|
candleBodyWidthRatio: 0.7,
|
|
152
154
|
candleMinWidth: 0.5,
|
|
153
155
|
candleWickWidth: 1,
|
|
156
|
+
tickSize: 0,
|
|
154
157
|
candleColorMode: "openClose",
|
|
155
158
|
candleColorEpsilon: -1,
|
|
156
159
|
autoScaleSmoothing: 0.16,
|
|
@@ -388,6 +391,35 @@ var computeAtrSeries = (data, length) => {
|
|
|
388
391
|
}
|
|
389
392
|
return result;
|
|
390
393
|
};
|
|
394
|
+
var builtInSeriesCache = /* @__PURE__ */ new Map();
|
|
395
|
+
var getSeriesFingerprint = (data) => {
|
|
396
|
+
const length = data.length;
|
|
397
|
+
const last = length > 0 ? data[length - 1] : void 0;
|
|
398
|
+
const prev = length > 1 ? data[length - 2] : void 0;
|
|
399
|
+
if (!last) return "empty";
|
|
400
|
+
return [
|
|
401
|
+
length,
|
|
402
|
+
last.time.getTime(),
|
|
403
|
+
last.o,
|
|
404
|
+
last.h,
|
|
405
|
+
last.l,
|
|
406
|
+
last.c,
|
|
407
|
+
last.v ?? "",
|
|
408
|
+
prev?.time.getTime() ?? "",
|
|
409
|
+
prev?.c ?? "",
|
|
410
|
+
prev?.v ?? ""
|
|
411
|
+
].join("|");
|
|
412
|
+
};
|
|
413
|
+
var withCachedSeries = (key, data, compute) => {
|
|
414
|
+
const fingerprint = getSeriesFingerprint(data);
|
|
415
|
+
const existing = builtInSeriesCache.get(key);
|
|
416
|
+
if (existing && existing.fingerprint === fingerprint) {
|
|
417
|
+
return existing.values;
|
|
418
|
+
}
|
|
419
|
+
const values = compute();
|
|
420
|
+
builtInSeriesCache.set(key, { fingerprint, values });
|
|
421
|
+
return values;
|
|
422
|
+
};
|
|
391
423
|
var drawOverlaySeries = (ctx, renderContext, values, color, width) => {
|
|
392
424
|
if (!renderContext.yFromPrice) return;
|
|
393
425
|
const yFromPrice = renderContext.yFromPrice;
|
|
@@ -485,6 +517,8 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
485
517
|
defaultInputs: {
|
|
486
518
|
upOpacity: 0.7,
|
|
487
519
|
downOpacity: 0.7,
|
|
520
|
+
upColor: "",
|
|
521
|
+
downColor: "",
|
|
488
522
|
minBarWidth: 1,
|
|
489
523
|
overlayHeightRatio: 0.22
|
|
490
524
|
},
|
|
@@ -515,9 +549,11 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
515
549
|
const barY = Math.round(paneBottom - volumeHeight);
|
|
516
550
|
const direction = renderContext.getCandleDirectionByIndex(index);
|
|
517
551
|
const opacity = direction === "up" ? upOpacity : downOpacity;
|
|
552
|
+
const upBarColor = inputs.upColor && inputs.upColor.trim().length > 0 ? inputs.upColor : upColor;
|
|
553
|
+
const downBarColor = inputs.downColor && inputs.downColor.trim().length > 0 ? inputs.downColor : downColor;
|
|
518
554
|
ctx.save();
|
|
519
555
|
ctx.globalAlpha = opacity;
|
|
520
|
-
ctx.fillStyle = direction === "up" ?
|
|
556
|
+
ctx.fillStyle = direction === "up" ? upBarColor : downBarColor;
|
|
521
557
|
ctx.fillRect(barX, barY, Math.max(1, Math.round(barWidth)), volumeHeight);
|
|
522
558
|
ctx.restore();
|
|
523
559
|
}
|
|
@@ -530,7 +566,11 @@ var BUILTIN_SMA_INDICATOR = {
|
|
|
530
566
|
defaultInputs: { length: 20, source: "close", color: "#60a5fa", width: 2 },
|
|
531
567
|
draw: (ctx, renderContext, inputs) => {
|
|
532
568
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
533
|
-
const values =
|
|
569
|
+
const values = withCachedSeries(
|
|
570
|
+
`sma|${length}|${inputs.source ?? "close"}`,
|
|
571
|
+
renderContext.data,
|
|
572
|
+
() => computeSmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
573
|
+
);
|
|
534
574
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#60a5fa", Number(inputs.width) || 2);
|
|
535
575
|
}
|
|
536
576
|
};
|
|
@@ -541,7 +581,11 @@ var BUILTIN_EMA_INDICATOR = {
|
|
|
541
581
|
defaultInputs: { length: 20, source: "close", color: "#f59e0b", width: 2 },
|
|
542
582
|
draw: (ctx, renderContext, inputs) => {
|
|
543
583
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
544
|
-
const values =
|
|
584
|
+
const values = withCachedSeries(
|
|
585
|
+
`ema|${length}|${inputs.source ?? "close"}`,
|
|
586
|
+
renderContext.data,
|
|
587
|
+
() => computeEmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
588
|
+
);
|
|
545
589
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#f59e0b", Number(inputs.width) || 2);
|
|
546
590
|
}
|
|
547
591
|
};
|
|
@@ -552,7 +596,11 @@ var BUILTIN_WMA_INDICATOR = {
|
|
|
552
596
|
defaultInputs: { length: 20, source: "close", color: "#a78bfa", width: 2 },
|
|
553
597
|
draw: (ctx, renderContext, inputs) => {
|
|
554
598
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
555
|
-
const values =
|
|
599
|
+
const values = withCachedSeries(
|
|
600
|
+
`wma|${length}|${inputs.source ?? "close"}`,
|
|
601
|
+
renderContext.data,
|
|
602
|
+
() => computeWmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
603
|
+
);
|
|
556
604
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#a78bfa", Number(inputs.width) || 2);
|
|
557
605
|
}
|
|
558
606
|
};
|
|
@@ -563,7 +611,11 @@ var BUILTIN_VWMA_INDICATOR = {
|
|
|
563
611
|
defaultInputs: { length: 20, source: "close", color: "#ef4444", width: 2 },
|
|
564
612
|
draw: (ctx, renderContext, inputs) => {
|
|
565
613
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
566
|
-
const values =
|
|
614
|
+
const values = withCachedSeries(
|
|
615
|
+
`vwma|${length}|${inputs.source ?? "close"}`,
|
|
616
|
+
renderContext.data,
|
|
617
|
+
() => computeVwmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
618
|
+
);
|
|
567
619
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#ef4444", Number(inputs.width) || 2);
|
|
568
620
|
}
|
|
569
621
|
};
|
|
@@ -574,7 +626,11 @@ var BUILTIN_RMA_INDICATOR = {
|
|
|
574
626
|
defaultInputs: { length: 14, source: "close", color: "#22c55e", width: 2 },
|
|
575
627
|
draw: (ctx, renderContext, inputs) => {
|
|
576
628
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
577
|
-
const values =
|
|
629
|
+
const values = withCachedSeries(
|
|
630
|
+
`rma|${length}|${inputs.source ?? "close"}`,
|
|
631
|
+
renderContext.data,
|
|
632
|
+
() => computeRmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
633
|
+
);
|
|
578
634
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#22c55e", Number(inputs.width) || 2);
|
|
579
635
|
}
|
|
580
636
|
};
|
|
@@ -585,7 +641,11 @@ var BUILTIN_HMA_INDICATOR = {
|
|
|
585
641
|
defaultInputs: { length: 21, source: "close", color: "#14b8a6", width: 2 },
|
|
586
642
|
draw: (ctx, renderContext, inputs) => {
|
|
587
643
|
const length = clampIndicatorLength(inputs.length, 21);
|
|
588
|
-
const values =
|
|
644
|
+
const values = withCachedSeries(
|
|
645
|
+
`hma|${length}|${inputs.source ?? "close"}`,
|
|
646
|
+
renderContext.data,
|
|
647
|
+
() => computeHmaSeries(renderContext.data, length, inputs.source ?? "close")
|
|
648
|
+
);
|
|
589
649
|
drawOverlaySeries(ctx, renderContext, values, inputs.color ?? "#14b8a6", Number(inputs.width) || 2);
|
|
590
650
|
}
|
|
591
651
|
};
|
|
@@ -597,7 +657,11 @@ var BUILTIN_STDDEV_INDICATOR = {
|
|
|
597
657
|
defaultInputs: { length: 20, source: "close", color: "#f97316", width: 2 },
|
|
598
658
|
draw: (ctx, renderContext, inputs) => {
|
|
599
659
|
const length = clampIndicatorLength(inputs.length, 20);
|
|
600
|
-
const values =
|
|
660
|
+
const values = withCachedSeries(
|
|
661
|
+
`stddev|${length}|${inputs.source ?? "close"}`,
|
|
662
|
+
renderContext.data,
|
|
663
|
+
() => computeStdDevSeries(renderContext.data, length, inputs.source ?? "close")
|
|
664
|
+
);
|
|
601
665
|
drawSeparateSeries(ctx, renderContext, values, inputs.color ?? "#f97316", Number(inputs.width) || 2);
|
|
602
666
|
}
|
|
603
667
|
};
|
|
@@ -609,7 +673,7 @@ var BUILTIN_ATR_INDICATOR = {
|
|
|
609
673
|
defaultInputs: { length: 14, color: "#eab308", width: 2 },
|
|
610
674
|
draw: (ctx, renderContext, inputs) => {
|
|
611
675
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
612
|
-
const values = computeAtrSeries(renderContext.data, length);
|
|
676
|
+
const values = withCachedSeries(`atr|${length}`, renderContext.data, () => computeAtrSeries(renderContext.data, length));
|
|
613
677
|
drawSeparateSeries(ctx, renderContext, values, inputs.color ?? "#eab308", Number(inputs.width) || 2);
|
|
614
678
|
}
|
|
615
679
|
};
|
|
@@ -621,7 +685,7 @@ var BUILTIN_RSI_INDICATOR = {
|
|
|
621
685
|
defaultInputs: { length: 14, color: "#3b82f6", width: 2 },
|
|
622
686
|
draw: (ctx, renderContext, inputs) => {
|
|
623
687
|
const length = clampIndicatorLength(inputs.length, 14);
|
|
624
|
-
const values = computeRsiSeries(renderContext.data, length);
|
|
688
|
+
const values = withCachedSeries(`rsi|${length}`, renderContext.data, () => computeRsiSeries(renderContext.data, length));
|
|
625
689
|
drawSeparateSeries(
|
|
626
690
|
ctx,
|
|
627
691
|
renderContext,
|
|
@@ -655,6 +719,18 @@ function createChart(element, options = {}) {
|
|
|
655
719
|
...options.axis ?? {},
|
|
656
720
|
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {}
|
|
657
721
|
},
|
|
722
|
+
xAxis: {
|
|
723
|
+
...DEFAULT_AXIS_OPTIONS,
|
|
724
|
+
...options.axis ?? {},
|
|
725
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
726
|
+
...options.xAxis ?? {}
|
|
727
|
+
},
|
|
728
|
+
yAxis: {
|
|
729
|
+
...DEFAULT_AXIS_OPTIONS,
|
|
730
|
+
...options.axis ?? {},
|
|
731
|
+
...options.axisColor ? { lineColor: options.axisColor, textColor: options.axisColor } : {},
|
|
732
|
+
...options.yAxis ?? {}
|
|
733
|
+
},
|
|
658
734
|
crosshair: {
|
|
659
735
|
...DEFAULT_CROSSHAIR_OPTIONS,
|
|
660
736
|
...options.crosshair ?? {}
|
|
@@ -710,6 +786,9 @@ function createChart(element, options = {}) {
|
|
|
710
786
|
visible: indicator.visible ?? true,
|
|
711
787
|
pane: indicator.pane ?? plugin?.pane ?? "overlay",
|
|
712
788
|
...indicator.paneHeightRatio === void 0 ? {} : { paneHeightRatio: indicator.paneHeightRatio },
|
|
789
|
+
zIndex: Math.round(Number(indicator.zIndex) || 0),
|
|
790
|
+
excludeFromAutoscale: indicator.excludeFromAutoscale ?? true,
|
|
791
|
+
overlayScaleWeight: Math.min(1, Math.max(0, Number(indicator.overlayScaleWeight) || 0.25)),
|
|
713
792
|
inputs: {
|
|
714
793
|
...defaults,
|
|
715
794
|
...indicator.inputs ?? {}
|
|
@@ -865,20 +944,56 @@ function createChart(element, options = {}) {
|
|
|
865
944
|
}
|
|
866
945
|
return { min: nextMin, max: nextMax };
|
|
867
946
|
};
|
|
947
|
+
const getConfiguredPriceDecimals = () => clamp(Math.round(mergedOptions.priceDecimals), 0, 8);
|
|
948
|
+
const getConfiguredTickSize = () => {
|
|
949
|
+
const step = Number(mergedOptions.tickSize);
|
|
950
|
+
return Number.isFinite(step) && step > 0 ? step : 0;
|
|
951
|
+
};
|
|
952
|
+
const getTickSizeDecimals = () => {
|
|
953
|
+
const tickSize = getConfiguredTickSize();
|
|
954
|
+
if (tickSize <= 0) {
|
|
955
|
+
return 0;
|
|
956
|
+
}
|
|
957
|
+
let scaled = tickSize;
|
|
958
|
+
let decimals = 0;
|
|
959
|
+
while (decimals < 8 && Math.abs(Math.round(scaled) - scaled) > 1e-10) {
|
|
960
|
+
scaled *= 10;
|
|
961
|
+
decimals += 1;
|
|
962
|
+
}
|
|
963
|
+
return decimals;
|
|
964
|
+
};
|
|
965
|
+
const getDisplayPriceDecimals = () => {
|
|
966
|
+
const configured = getConfiguredPriceDecimals();
|
|
967
|
+
const tickDecimals = getTickSizeDecimals();
|
|
968
|
+
return Math.max(configured, tickDecimals);
|
|
969
|
+
};
|
|
970
|
+
const quantizeToTickSize = (price) => {
|
|
971
|
+
const tickSize = getConfiguredTickSize();
|
|
972
|
+
if (tickSize <= 0 || !Number.isFinite(price)) {
|
|
973
|
+
return price;
|
|
974
|
+
}
|
|
975
|
+
return Math.round(price / tickSize) * tickSize;
|
|
976
|
+
};
|
|
868
977
|
const formatPrice = (price) => {
|
|
869
|
-
const
|
|
870
|
-
|
|
978
|
+
const rounded = quantizeToTickSize(price);
|
|
979
|
+
const decimals = getDisplayPriceDecimals();
|
|
980
|
+
return rounded.toFixed(decimals);
|
|
871
981
|
};
|
|
872
982
|
const roundToPricePrecision = (price) => {
|
|
873
|
-
const
|
|
874
|
-
|
|
983
|
+
const rounded = quantizeToTickSize(price);
|
|
984
|
+
const decimals = getDisplayPriceDecimals();
|
|
985
|
+
return Number(rounded.toFixed(decimals));
|
|
875
986
|
};
|
|
876
987
|
const getResolvedCandleColorEpsilon = () => {
|
|
877
988
|
const configured = mergedOptions.candleColorEpsilon;
|
|
878
989
|
if (configured >= 0) {
|
|
879
990
|
return configured;
|
|
880
991
|
}
|
|
881
|
-
const
|
|
992
|
+
const tickSize = getConfiguredTickSize();
|
|
993
|
+
if (tickSize > 0) {
|
|
994
|
+
return tickSize / 2;
|
|
995
|
+
}
|
|
996
|
+
const decimals = getDisplayPriceDecimals();
|
|
882
997
|
return decimals > 0 ? 0.5 / 10 ** decimals : 0;
|
|
883
998
|
};
|
|
884
999
|
const getDirectionFromDelta = (delta) => {
|
|
@@ -1410,6 +1525,10 @@ function createChart(element, options = {}) {
|
|
|
1410
1525
|
canvas.height = Math.floor(height * pixelRatio);
|
|
1411
1526
|
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
|
1412
1527
|
const axis = { ...DEFAULT_AXIS_OPTIONS, ...mergedOptions.axis ?? {} };
|
|
1528
|
+
const xAxis = { ...DEFAULT_AXIS_OPTIONS, ...mergedOptions.xAxis ?? {} };
|
|
1529
|
+
const yAxis = { ...DEFAULT_AXIS_OPTIONS, ...mergedOptions.yAxis ?? {} };
|
|
1530
|
+
const xAxisFontSize = Math.max(8, xAxis.fontSize);
|
|
1531
|
+
const yAxisFontSize = Math.max(8, yAxis.fontSize);
|
|
1413
1532
|
ctx.font = `${Math.max(8, axis.fontSize)}px ${mergedOptions.fontFamily}`;
|
|
1414
1533
|
ctx.fillStyle = mergedOptions.backgroundColor;
|
|
1415
1534
|
ctx.fillRect(0, 0, width, height);
|
|
@@ -1424,6 +1543,9 @@ function createChart(element, options = {}) {
|
|
|
1424
1543
|
const separatePaneSpacing = 6;
|
|
1425
1544
|
const activeSeparateIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1426
1545
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "separate"
|
|
1546
|
+
).sort((a, b) => a.indicator.zIndex - b.indicator.zIndex);
|
|
1547
|
+
const overlayIndicatorsForScale = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1548
|
+
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
1427
1549
|
);
|
|
1428
1550
|
const separatePaneHeightDefaults = activeSeparateIndicators.map(({ indicator, plugin }) => {
|
|
1429
1551
|
const ratio = Math.min(0.45, Math.max(0.08, indicator.paneHeightRatio ?? plugin.paneHeightRatio ?? 0.22));
|
|
@@ -1475,8 +1597,47 @@ function createChart(element, options = {}) {
|
|
|
1475
1597
|
}
|
|
1476
1598
|
}
|
|
1477
1599
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1600
|
+
let minPrice = Math.min(...priceSource.map((point) => point.l));
|
|
1601
|
+
let maxPrice = Math.max(...priceSource.map((point) => point.h));
|
|
1602
|
+
if (overlayIndicatorsForScale.length > 0) {
|
|
1603
|
+
for (const { indicator } of overlayIndicatorsForScale) {
|
|
1604
|
+
if (indicator.excludeFromAutoscale) {
|
|
1605
|
+
continue;
|
|
1606
|
+
}
|
|
1607
|
+
const type = indicator.type;
|
|
1608
|
+
const inputs = indicator.inputs;
|
|
1609
|
+
const source = inputs.source ?? "close";
|
|
1610
|
+
const length = clampIndicatorLength(inputs.length ?? 14, 14);
|
|
1611
|
+
let series = null;
|
|
1612
|
+
if (type === "sma") series = withCachedSeries(`sma|${length}|${source}`, data, () => computeSmaSeries(data, length, source));
|
|
1613
|
+
if (type === "ema") series = withCachedSeries(`ema|${length}|${source}`, data, () => computeEmaSeries(data, length, source));
|
|
1614
|
+
if (type === "wma") series = withCachedSeries(`wma|${length}|${source}`, data, () => computeWmaSeries(data, length, source));
|
|
1615
|
+
if (type === "vwma") series = withCachedSeries(`vwma|${length}|${source}`, data, () => computeVwmaSeries(data, length, source));
|
|
1616
|
+
if (type === "rma") series = withCachedSeries(`rma|${length}|${source}`, data, () => computeRmaSeries(data, length, source));
|
|
1617
|
+
if (type === "hma") series = withCachedSeries(`hma|${length}|${source}`, data, () => computeHmaSeries(data, length, source));
|
|
1618
|
+
if (!series) {
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
const visibleValues = [];
|
|
1622
|
+
for (let idx = startIndex; idx <= endIndex; idx += 1) {
|
|
1623
|
+
const value = series[idx];
|
|
1624
|
+
if (Number.isFinite(value ?? Number.NaN)) {
|
|
1625
|
+
visibleValues.push(value);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
if (visibleValues.length === 0) {
|
|
1629
|
+
continue;
|
|
1630
|
+
}
|
|
1631
|
+
const seriesMin = Math.min(...visibleValues);
|
|
1632
|
+
const seriesMax = Math.max(...visibleValues);
|
|
1633
|
+
const weight = Math.min(1, Math.max(0, indicator.overlayScaleWeight));
|
|
1634
|
+
const currentMid = (minPrice + maxPrice) / 2;
|
|
1635
|
+
const weightedMin = currentMid + (seriesMin - currentMid) * weight;
|
|
1636
|
+
const weightedMax = currentMid + (seriesMax - currentMid) * weight;
|
|
1637
|
+
minPrice = Math.min(minPrice, weightedMin);
|
|
1638
|
+
maxPrice = Math.max(maxPrice, weightedMax);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1480
1641
|
const priceRange = maxPrice - minPrice || 1;
|
|
1481
1642
|
const autoMin = minPrice - priceRange * 0.08;
|
|
1482
1643
|
const autoMax = maxPrice + priceRange * 0.08;
|
|
@@ -1636,7 +1797,7 @@ function createChart(element, options = {}) {
|
|
|
1636
1797
|
}
|
|
1637
1798
|
const activeOverlayIndicators = indicators.filter((indicator) => indicator.visible).map((indicator) => ({ indicator, plugin: indicatorRegistry.get(indicator.type) })).filter(
|
|
1638
1799
|
(value) => value.plugin !== void 0 && (value.indicator.pane ?? value.plugin.pane ?? "overlay") === "overlay"
|
|
1639
|
-
);
|
|
1800
|
+
).sort((a, b) => a.indicator.zIndex - b.indicator.zIndex);
|
|
1640
1801
|
if (activeOverlayIndicators.length > 0) {
|
|
1641
1802
|
const xFromIndex = (index) => chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth;
|
|
1642
1803
|
activeOverlayIndicators.forEach(({ indicator, plugin }) => {
|
|
@@ -1746,7 +1907,10 @@ function createChart(element, options = {}) {
|
|
|
1746
1907
|
const ratio = tick / yTicks;
|
|
1747
1908
|
const price = yMin + yRange * ratio;
|
|
1748
1909
|
const y = yFromPrice(price);
|
|
1749
|
-
|
|
1910
|
+
const prevFont = ctx.font;
|
|
1911
|
+
ctx.font = `${yAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
1912
|
+
drawText(formatPrice(price), chartRight + 6, y, "left", "middle", yAxis.textColor);
|
|
1913
|
+
ctx.font = prevFont;
|
|
1750
1914
|
}
|
|
1751
1915
|
const ticker = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1752
1916
|
const lastPoint = data[data.length - 1];
|
|
@@ -1803,7 +1967,10 @@ function createChart(element, options = {}) {
|
|
|
1803
1967
|
month: "short",
|
|
1804
1968
|
day: "numeric"
|
|
1805
1969
|
});
|
|
1806
|
-
|
|
1970
|
+
const prevFont = ctx.font;
|
|
1971
|
+
ctx.font = `${xAxisFontSize}px ${mergedOptions.fontFamily}`;
|
|
1972
|
+
drawText(timeLabel, x, fullChartBottom + 8, "center", "top", xAxis.textColor);
|
|
1973
|
+
ctx.font = prevFont;
|
|
1807
1974
|
}
|
|
1808
1975
|
if (crosshair.visible && crosshairPoint) {
|
|
1809
1976
|
const cx = clamp(crosshairPoint.x, chartLeft, chartRight);
|
|
@@ -2574,6 +2741,27 @@ function createChart(element, options = {}) {
|
|
|
2574
2741
|
indicators = indicators.filter((indicator) => indicator.type !== type);
|
|
2575
2742
|
draw();
|
|
2576
2743
|
};
|
|
2744
|
+
const listBuiltInIndicators = () => {
|
|
2745
|
+
return BUILTIN_INDICATORS.map((indicator) => ({
|
|
2746
|
+
id: indicator.id,
|
|
2747
|
+
name: indicator.name,
|
|
2748
|
+
pane: indicator.pane ?? "overlay",
|
|
2749
|
+
...indicator.paneHeightRatio === void 0 ? {} : { paneHeightRatio: indicator.paneHeightRatio }
|
|
2750
|
+
}));
|
|
2751
|
+
};
|
|
2752
|
+
const getIndicators = () => {
|
|
2753
|
+
return indicators.map((indicator) => ({
|
|
2754
|
+
id: indicator.id,
|
|
2755
|
+
type: indicator.type,
|
|
2756
|
+
visible: indicator.visible,
|
|
2757
|
+
pane: indicator.pane,
|
|
2758
|
+
...indicator.paneHeightRatio === void 0 ? {} : { paneHeightRatio: indicator.paneHeightRatio },
|
|
2759
|
+
zIndex: indicator.zIndex,
|
|
2760
|
+
excludeFromAutoscale: indicator.excludeFromAutoscale,
|
|
2761
|
+
overlayScaleWeight: indicator.overlayScaleWeight,
|
|
2762
|
+
inputs: { ...indicator.inputs }
|
|
2763
|
+
}));
|
|
2764
|
+
};
|
|
2577
2765
|
const setIndicators = (nextIndicators) => {
|
|
2578
2766
|
indicators = nextIndicators.map((indicator) => normalizeIndicatorState(indicator));
|
|
2579
2767
|
draw();
|
|
@@ -2603,6 +2791,9 @@ function createChart(element, options = {}) {
|
|
|
2603
2791
|
visible: patch.visible ?? indicator.visible,
|
|
2604
2792
|
pane: patch.pane ?? indicator.pane ?? plugin?.pane ?? "overlay",
|
|
2605
2793
|
...patch.paneHeightRatio !== void 0 || indicator.paneHeightRatio !== void 0 ? { paneHeightRatio: patch.paneHeightRatio ?? indicator.paneHeightRatio } : {},
|
|
2794
|
+
zIndex: patch.zIndex === void 0 ? indicator.zIndex : Math.round(Number(patch.zIndex) || 0),
|
|
2795
|
+
excludeFromAutoscale: patch.excludeFromAutoscale ?? indicator.excludeFromAutoscale,
|
|
2796
|
+
overlayScaleWeight: patch.overlayScaleWeight === void 0 ? indicator.overlayScaleWeight : Math.min(1, Math.max(0, Number(patch.overlayScaleWeight) || 0)),
|
|
2606
2797
|
type: patch.type ?? indicator.type,
|
|
2607
2798
|
inputs: {
|
|
2608
2799
|
...indicator.inputs,
|
|
@@ -2652,6 +2843,8 @@ function createChart(element, options = {}) {
|
|
|
2652
2843
|
setDoubleClickAction,
|
|
2653
2844
|
registerIndicator,
|
|
2654
2845
|
unregisterIndicator,
|
|
2846
|
+
listBuiltInIndicators,
|
|
2847
|
+
getIndicators,
|
|
2655
2848
|
addIndicator,
|
|
2656
2849
|
updateIndicator,
|
|
2657
2850
|
removeIndicator,
|
package/dist/index.d.cts
CHANGED
|
@@ -4,6 +4,8 @@ interface ChartOptions {
|
|
|
4
4
|
backgroundColor?: string;
|
|
5
5
|
axisColor?: string;
|
|
6
6
|
axis?: AxisOptions;
|
|
7
|
+
xAxis?: AxisOptions;
|
|
8
|
+
yAxis?: AxisOptions;
|
|
7
9
|
priceDecimals?: number;
|
|
8
10
|
stabilizePriceLabels?: boolean;
|
|
9
11
|
priceLabelMinIntegerDigits?: number;
|
|
@@ -22,6 +24,7 @@ interface ChartOptions {
|
|
|
22
24
|
candleBodyWidthRatio?: number;
|
|
23
25
|
candleMinWidth?: number;
|
|
24
26
|
candleWickWidth?: number;
|
|
27
|
+
tickSize?: number;
|
|
25
28
|
candleColorMode?: "openClose" | "prevClose";
|
|
26
29
|
candleColorEpsilon?: number;
|
|
27
30
|
autoScaleSmoothing?: number;
|
|
@@ -44,6 +47,9 @@ interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Rec
|
|
|
44
47
|
visible?: boolean;
|
|
45
48
|
pane?: IndicatorPane;
|
|
46
49
|
paneHeightRatio?: number;
|
|
50
|
+
zIndex?: number;
|
|
51
|
+
excludeFromAutoscale?: boolean;
|
|
52
|
+
overlayScaleWeight?: number;
|
|
47
53
|
inputs?: Partial<TInputs>;
|
|
48
54
|
}
|
|
49
55
|
interface IndicatorRenderContext {
|
|
@@ -80,6 +86,12 @@ interface IndicatorPlugin<TInputs extends Record<string, unknown> = Record<strin
|
|
|
80
86
|
defaultInputs?: TInputs;
|
|
81
87
|
draw: (ctx: CanvasRenderingContext2D, renderContext: IndicatorRenderContext, inputs: TInputs) => void;
|
|
82
88
|
}
|
|
89
|
+
interface BuiltInIndicatorInfo {
|
|
90
|
+
id: string;
|
|
91
|
+
name: string;
|
|
92
|
+
pane: IndicatorPane;
|
|
93
|
+
paneHeightRatio?: number;
|
|
94
|
+
}
|
|
83
95
|
interface DashPatternOptions {
|
|
84
96
|
dotted: [number, number];
|
|
85
97
|
dashed: [number, number];
|
|
@@ -271,6 +283,8 @@ interface ChartInstance {
|
|
|
271
283
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
272
284
|
registerIndicator: (plugin: IndicatorPlugin<any>) => void;
|
|
273
285
|
unregisterIndicator: (type: string) => void;
|
|
286
|
+
listBuiltInIndicators: () => BuiltInIndicatorInfo[];
|
|
287
|
+
getIndicators: () => IndicatorInstanceOptions[];
|
|
274
288
|
addIndicator: (type: string, inputs?: Record<string, unknown>, options?: Partial<IndicatorInstanceOptions>) => string;
|
|
275
289
|
updateIndicator: (id: string, patch: Partial<IndicatorInstanceOptions>) => void;
|
|
276
290
|
removeIndicator: (id: string) => void;
|
|
@@ -288,4 +302,4 @@ interface OhlcDataPoint {
|
|
|
288
302
|
}
|
|
289
303
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
290
304
|
|
|
291
|
-
export { type AxisOptions, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPlugin, type IndicatorRenderContext, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
|
305
|
+
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPlugin, type IndicatorRenderContext, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ interface ChartOptions {
|
|
|
4
4
|
backgroundColor?: string;
|
|
5
5
|
axisColor?: string;
|
|
6
6
|
axis?: AxisOptions;
|
|
7
|
+
xAxis?: AxisOptions;
|
|
8
|
+
yAxis?: AxisOptions;
|
|
7
9
|
priceDecimals?: number;
|
|
8
10
|
stabilizePriceLabels?: boolean;
|
|
9
11
|
priceLabelMinIntegerDigits?: number;
|
|
@@ -22,6 +24,7 @@ interface ChartOptions {
|
|
|
22
24
|
candleBodyWidthRatio?: number;
|
|
23
25
|
candleMinWidth?: number;
|
|
24
26
|
candleWickWidth?: number;
|
|
27
|
+
tickSize?: number;
|
|
25
28
|
candleColorMode?: "openClose" | "prevClose";
|
|
26
29
|
candleColorEpsilon?: number;
|
|
27
30
|
autoScaleSmoothing?: number;
|
|
@@ -44,6 +47,9 @@ interface IndicatorInstanceOptions<TInputs extends Record<string, unknown> = Rec
|
|
|
44
47
|
visible?: boolean;
|
|
45
48
|
pane?: IndicatorPane;
|
|
46
49
|
paneHeightRatio?: number;
|
|
50
|
+
zIndex?: number;
|
|
51
|
+
excludeFromAutoscale?: boolean;
|
|
52
|
+
overlayScaleWeight?: number;
|
|
47
53
|
inputs?: Partial<TInputs>;
|
|
48
54
|
}
|
|
49
55
|
interface IndicatorRenderContext {
|
|
@@ -80,6 +86,12 @@ interface IndicatorPlugin<TInputs extends Record<string, unknown> = Record<strin
|
|
|
80
86
|
defaultInputs?: TInputs;
|
|
81
87
|
draw: (ctx: CanvasRenderingContext2D, renderContext: IndicatorRenderContext, inputs: TInputs) => void;
|
|
82
88
|
}
|
|
89
|
+
interface BuiltInIndicatorInfo {
|
|
90
|
+
id: string;
|
|
91
|
+
name: string;
|
|
92
|
+
pane: IndicatorPane;
|
|
93
|
+
paneHeightRatio?: number;
|
|
94
|
+
}
|
|
83
95
|
interface DashPatternOptions {
|
|
84
96
|
dotted: [number, number];
|
|
85
97
|
dashed: [number, number];
|
|
@@ -271,6 +283,8 @@ interface ChartInstance {
|
|
|
271
283
|
setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
|
|
272
284
|
registerIndicator: (plugin: IndicatorPlugin<any>) => void;
|
|
273
285
|
unregisterIndicator: (type: string) => void;
|
|
286
|
+
listBuiltInIndicators: () => BuiltInIndicatorInfo[];
|
|
287
|
+
getIndicators: () => IndicatorInstanceOptions[];
|
|
274
288
|
addIndicator: (type: string, inputs?: Record<string, unknown>, options?: Partial<IndicatorInstanceOptions>) => string;
|
|
275
289
|
updateIndicator: (id: string, patch: Partial<IndicatorInstanceOptions>) => void;
|
|
276
290
|
removeIndicator: (id: string) => void;
|
|
@@ -288,4 +302,4 @@ interface OhlcDataPoint {
|
|
|
288
302
|
}
|
|
289
303
|
declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
|
|
290
304
|
|
|
291
|
-
export { type AxisOptions, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPlugin, type IndicatorRenderContext, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|
|
305
|
+
export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPlugin, type IndicatorRenderContext, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type WatermarkOptions, createChart };
|