hyperprop-charting-library 0.1.40 → 0.1.42
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/hyperprop-charting-library.cjs +43 -12
- package/dist/hyperprop-charting-library.d.ts +1 -0
- package/dist/hyperprop-charting-library.js +43 -12
- package/dist/index.cjs +43 -12
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +43 -12
- package/package.json +1 -1
|
@@ -599,7 +599,8 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
599
599
|
if (!point || point.v === void 0 || point.v <= 0) {
|
|
600
600
|
continue;
|
|
601
601
|
}
|
|
602
|
-
const
|
|
602
|
+
const displayVolume = renderContext.getVolumeByIndex(index) ?? point.v;
|
|
603
|
+
const clampedVolume = Math.min(maxVolume, Math.max(0, displayVolume));
|
|
603
604
|
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
604
605
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
605
606
|
const xCenter = xFromIndex(index);
|
|
@@ -853,13 +854,19 @@ function createChart(element, options = {}) {
|
|
|
853
854
|
let doubleClickAction = mergedOptions.doubleClickAction;
|
|
854
855
|
let smoothedTickerPrice = null;
|
|
855
856
|
let tickerPriceTarget = null;
|
|
857
|
+
let smoothedTickerVolume = null;
|
|
858
|
+
let tickerVolumeTarget = null;
|
|
856
859
|
let smoothingRafId = null;
|
|
857
860
|
const tickerSmoothingLoop = () => {
|
|
858
861
|
smoothingRafId = null;
|
|
859
|
-
if (smoothedTickerPrice === null || tickerPriceTarget === null)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
+
if (smoothedTickerPrice === null || tickerPriceTarget === null || smoothedTickerVolume === null || tickerVolumeTarget === null) {
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
const priceDiff = tickerPriceTarget - smoothedTickerPrice;
|
|
866
|
+
const volumeDiff = tickerVolumeTarget - smoothedTickerVolume;
|
|
867
|
+
if (Math.abs(priceDiff) < 1e-9 && Math.abs(volumeDiff) < 1e-6) {
|
|
862
868
|
smoothedTickerPrice = tickerPriceTarget;
|
|
869
|
+
smoothedTickerVolume = tickerVolumeTarget;
|
|
863
870
|
draw({ updateAutoScale: false });
|
|
864
871
|
return;
|
|
865
872
|
}
|
|
@@ -867,20 +874,28 @@ function createChart(element, options = {}) {
|
|
|
867
874
|
const speed = clamp(tickerOpts.smoothingSpeed ?? 8, 1, 60);
|
|
868
875
|
const dt = 1 / 60;
|
|
869
876
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
870
|
-
smoothedTickerPrice +=
|
|
877
|
+
smoothedTickerPrice += priceDiff * lerp;
|
|
878
|
+
smoothedTickerVolume += volumeDiff * lerp;
|
|
871
879
|
draw({ updateAutoScale: false });
|
|
872
880
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
873
881
|
};
|
|
874
|
-
const
|
|
882
|
+
const pushSmoothedTicker = (targetPrice, targetVolume) => {
|
|
875
883
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
876
884
|
if (!tickerOpts.smoothing) {
|
|
877
885
|
smoothedTickerPrice = null;
|
|
878
886
|
tickerPriceTarget = null;
|
|
887
|
+
smoothedTickerVolume = null;
|
|
888
|
+
tickerVolumeTarget = null;
|
|
879
889
|
return;
|
|
880
890
|
}
|
|
881
|
-
|
|
891
|
+
const normalizedVolume = Math.max(0, targetVolume ?? 0);
|
|
892
|
+
tickerPriceTarget = targetPrice;
|
|
893
|
+
tickerVolumeTarget = normalizedVolume;
|
|
882
894
|
if (smoothedTickerPrice === null) {
|
|
883
|
-
smoothedTickerPrice =
|
|
895
|
+
smoothedTickerPrice = targetPrice;
|
|
896
|
+
}
|
|
897
|
+
if (smoothedTickerVolume === null) {
|
|
898
|
+
smoothedTickerVolume = normalizedVolume;
|
|
884
899
|
}
|
|
885
900
|
if (smoothingRafId === null) {
|
|
886
901
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
@@ -1853,6 +1868,12 @@ function createChart(element, options = {}) {
|
|
|
1853
1868
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1854
1869
|
const useSmoothedCandle = tickerOpts.smoothing && smoothedTickerPrice !== null;
|
|
1855
1870
|
const lastDataIndex = data.length - 1;
|
|
1871
|
+
const getVolumeByIndex = (index) => {
|
|
1872
|
+
if (useSmoothedCandle && index === lastDataIndex && smoothedTickerVolume !== null) {
|
|
1873
|
+
return smoothedTickerVolume;
|
|
1874
|
+
}
|
|
1875
|
+
return data[index]?.v;
|
|
1876
|
+
};
|
|
1856
1877
|
for (let index = startIndex; index <= endIndex; index += 1) {
|
|
1857
1878
|
const point = data[index];
|
|
1858
1879
|
if (!point) {
|
|
@@ -1909,6 +1930,7 @@ function createChart(element, options = {}) {
|
|
|
1909
1930
|
xFromIndex,
|
|
1910
1931
|
yFromPrice,
|
|
1911
1932
|
getCandleDirectionByIndex,
|
|
1933
|
+
getVolumeByIndex,
|
|
1912
1934
|
candleSpacing,
|
|
1913
1935
|
upColor: mergedOptions.upColor,
|
|
1914
1936
|
downColor: mergedOptions.downColor
|
|
@@ -1969,6 +1991,7 @@ function createChart(element, options = {}) {
|
|
|
1969
1991
|
xFromIndex,
|
|
1970
1992
|
yFromPrice: null,
|
|
1971
1993
|
getCandleDirectionByIndex,
|
|
1994
|
+
getVolumeByIndex,
|
|
1972
1995
|
candleSpacing,
|
|
1973
1996
|
upColor: mergedOptions.upColor,
|
|
1974
1997
|
downColor: mergedOptions.downColor
|
|
@@ -2638,6 +2661,7 @@ function createChart(element, options = {}) {
|
|
|
2638
2661
|
const crosshairButtonRegion = getCrosshairPriceActionRegion(point.x, point.y);
|
|
2639
2662
|
if (crosshairButtonRegion) {
|
|
2640
2663
|
canvas.style.cursor = "pointer";
|
|
2664
|
+
setCrosshairPoint(point);
|
|
2641
2665
|
return;
|
|
2642
2666
|
}
|
|
2643
2667
|
const orderRegion = getOrderActionRegion(point.x, point.y);
|
|
@@ -2826,12 +2850,15 @@ function createChart(element, options = {}) {
|
|
|
2826
2850
|
if (!isTickerSmoothingEnabled) {
|
|
2827
2851
|
smoothedTickerPrice = null;
|
|
2828
2852
|
tickerPriceTarget = null;
|
|
2853
|
+
smoothedTickerVolume = null;
|
|
2854
|
+
tickerVolumeTarget = null;
|
|
2829
2855
|
if (smoothingRafId !== null) {
|
|
2830
2856
|
cancelAnimationFrame(smoothingRafId);
|
|
2831
2857
|
smoothingRafId = null;
|
|
2832
2858
|
}
|
|
2833
2859
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2834
|
-
|
|
2860
|
+
const lastPoint = data[data.length - 1];
|
|
2861
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2835
2862
|
}
|
|
2836
2863
|
draw();
|
|
2837
2864
|
};
|
|
@@ -2855,6 +2882,10 @@ function createChart(element, options = {}) {
|
|
|
2855
2882
|
if (data.length === 0) {
|
|
2856
2883
|
xCenter = 0;
|
|
2857
2884
|
xSpan = 60;
|
|
2885
|
+
smoothedTickerPrice = null;
|
|
2886
|
+
tickerPriceTarget = null;
|
|
2887
|
+
smoothedTickerVolume = null;
|
|
2888
|
+
tickerVolumeTarget = null;
|
|
2858
2889
|
resetYViewport();
|
|
2859
2890
|
draw();
|
|
2860
2891
|
return;
|
|
@@ -2877,9 +2908,9 @@ function createChart(element, options = {}) {
|
|
|
2877
2908
|
fitXViewport();
|
|
2878
2909
|
}
|
|
2879
2910
|
}
|
|
2880
|
-
const
|
|
2881
|
-
if (
|
|
2882
|
-
|
|
2911
|
+
const lastPoint = data[data.length - 1];
|
|
2912
|
+
if (lastPoint) {
|
|
2913
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2883
2914
|
}
|
|
2884
2915
|
draw();
|
|
2885
2916
|
};
|
|
@@ -74,6 +74,7 @@ interface IndicatorRenderContext {
|
|
|
74
74
|
xFromIndex: (index: number) => number;
|
|
75
75
|
yFromPrice: ((price: number) => number) | null;
|
|
76
76
|
getCandleDirectionByIndex: (index: number) => "up" | "down";
|
|
77
|
+
getVolumeByIndex: (index: number) => number | undefined;
|
|
77
78
|
candleSpacing: number;
|
|
78
79
|
upColor: string;
|
|
79
80
|
downColor: string;
|
|
@@ -575,7 +575,8 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
575
575
|
if (!point || point.v === void 0 || point.v <= 0) {
|
|
576
576
|
continue;
|
|
577
577
|
}
|
|
578
|
-
const
|
|
578
|
+
const displayVolume = renderContext.getVolumeByIndex(index) ?? point.v;
|
|
579
|
+
const clampedVolume = Math.min(maxVolume, Math.max(0, displayVolume));
|
|
579
580
|
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
580
581
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
581
582
|
const xCenter = xFromIndex(index);
|
|
@@ -829,13 +830,19 @@ function createChart(element, options = {}) {
|
|
|
829
830
|
let doubleClickAction = mergedOptions.doubleClickAction;
|
|
830
831
|
let smoothedTickerPrice = null;
|
|
831
832
|
let tickerPriceTarget = null;
|
|
833
|
+
let smoothedTickerVolume = null;
|
|
834
|
+
let tickerVolumeTarget = null;
|
|
832
835
|
let smoothingRafId = null;
|
|
833
836
|
const tickerSmoothingLoop = () => {
|
|
834
837
|
smoothingRafId = null;
|
|
835
|
-
if (smoothedTickerPrice === null || tickerPriceTarget === null)
|
|
836
|
-
|
|
837
|
-
|
|
838
|
+
if (smoothedTickerPrice === null || tickerPriceTarget === null || smoothedTickerVolume === null || tickerVolumeTarget === null) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
const priceDiff = tickerPriceTarget - smoothedTickerPrice;
|
|
842
|
+
const volumeDiff = tickerVolumeTarget - smoothedTickerVolume;
|
|
843
|
+
if (Math.abs(priceDiff) < 1e-9 && Math.abs(volumeDiff) < 1e-6) {
|
|
838
844
|
smoothedTickerPrice = tickerPriceTarget;
|
|
845
|
+
smoothedTickerVolume = tickerVolumeTarget;
|
|
839
846
|
draw({ updateAutoScale: false });
|
|
840
847
|
return;
|
|
841
848
|
}
|
|
@@ -843,20 +850,28 @@ function createChart(element, options = {}) {
|
|
|
843
850
|
const speed = clamp(tickerOpts.smoothingSpeed ?? 8, 1, 60);
|
|
844
851
|
const dt = 1 / 60;
|
|
845
852
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
846
|
-
smoothedTickerPrice +=
|
|
853
|
+
smoothedTickerPrice += priceDiff * lerp;
|
|
854
|
+
smoothedTickerVolume += volumeDiff * lerp;
|
|
847
855
|
draw({ updateAutoScale: false });
|
|
848
856
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
849
857
|
};
|
|
850
|
-
const
|
|
858
|
+
const pushSmoothedTicker = (targetPrice, targetVolume) => {
|
|
851
859
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
852
860
|
if (!tickerOpts.smoothing) {
|
|
853
861
|
smoothedTickerPrice = null;
|
|
854
862
|
tickerPriceTarget = null;
|
|
863
|
+
smoothedTickerVolume = null;
|
|
864
|
+
tickerVolumeTarget = null;
|
|
855
865
|
return;
|
|
856
866
|
}
|
|
857
|
-
|
|
867
|
+
const normalizedVolume = Math.max(0, targetVolume ?? 0);
|
|
868
|
+
tickerPriceTarget = targetPrice;
|
|
869
|
+
tickerVolumeTarget = normalizedVolume;
|
|
858
870
|
if (smoothedTickerPrice === null) {
|
|
859
|
-
smoothedTickerPrice =
|
|
871
|
+
smoothedTickerPrice = targetPrice;
|
|
872
|
+
}
|
|
873
|
+
if (smoothedTickerVolume === null) {
|
|
874
|
+
smoothedTickerVolume = normalizedVolume;
|
|
860
875
|
}
|
|
861
876
|
if (smoothingRafId === null) {
|
|
862
877
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
@@ -1829,6 +1844,12 @@ function createChart(element, options = {}) {
|
|
|
1829
1844
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1830
1845
|
const useSmoothedCandle = tickerOpts.smoothing && smoothedTickerPrice !== null;
|
|
1831
1846
|
const lastDataIndex = data.length - 1;
|
|
1847
|
+
const getVolumeByIndex = (index) => {
|
|
1848
|
+
if (useSmoothedCandle && index === lastDataIndex && smoothedTickerVolume !== null) {
|
|
1849
|
+
return smoothedTickerVolume;
|
|
1850
|
+
}
|
|
1851
|
+
return data[index]?.v;
|
|
1852
|
+
};
|
|
1832
1853
|
for (let index = startIndex; index <= endIndex; index += 1) {
|
|
1833
1854
|
const point = data[index];
|
|
1834
1855
|
if (!point) {
|
|
@@ -1885,6 +1906,7 @@ function createChart(element, options = {}) {
|
|
|
1885
1906
|
xFromIndex,
|
|
1886
1907
|
yFromPrice,
|
|
1887
1908
|
getCandleDirectionByIndex,
|
|
1909
|
+
getVolumeByIndex,
|
|
1888
1910
|
candleSpacing,
|
|
1889
1911
|
upColor: mergedOptions.upColor,
|
|
1890
1912
|
downColor: mergedOptions.downColor
|
|
@@ -1945,6 +1967,7 @@ function createChart(element, options = {}) {
|
|
|
1945
1967
|
xFromIndex,
|
|
1946
1968
|
yFromPrice: null,
|
|
1947
1969
|
getCandleDirectionByIndex,
|
|
1970
|
+
getVolumeByIndex,
|
|
1948
1971
|
candleSpacing,
|
|
1949
1972
|
upColor: mergedOptions.upColor,
|
|
1950
1973
|
downColor: mergedOptions.downColor
|
|
@@ -2614,6 +2637,7 @@ function createChart(element, options = {}) {
|
|
|
2614
2637
|
const crosshairButtonRegion = getCrosshairPriceActionRegion(point.x, point.y);
|
|
2615
2638
|
if (crosshairButtonRegion) {
|
|
2616
2639
|
canvas.style.cursor = "pointer";
|
|
2640
|
+
setCrosshairPoint(point);
|
|
2617
2641
|
return;
|
|
2618
2642
|
}
|
|
2619
2643
|
const orderRegion = getOrderActionRegion(point.x, point.y);
|
|
@@ -2802,12 +2826,15 @@ function createChart(element, options = {}) {
|
|
|
2802
2826
|
if (!isTickerSmoothingEnabled) {
|
|
2803
2827
|
smoothedTickerPrice = null;
|
|
2804
2828
|
tickerPriceTarget = null;
|
|
2829
|
+
smoothedTickerVolume = null;
|
|
2830
|
+
tickerVolumeTarget = null;
|
|
2805
2831
|
if (smoothingRafId !== null) {
|
|
2806
2832
|
cancelAnimationFrame(smoothingRafId);
|
|
2807
2833
|
smoothingRafId = null;
|
|
2808
2834
|
}
|
|
2809
2835
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2810
|
-
|
|
2836
|
+
const lastPoint = data[data.length - 1];
|
|
2837
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2811
2838
|
}
|
|
2812
2839
|
draw();
|
|
2813
2840
|
};
|
|
@@ -2831,6 +2858,10 @@ function createChart(element, options = {}) {
|
|
|
2831
2858
|
if (data.length === 0) {
|
|
2832
2859
|
xCenter = 0;
|
|
2833
2860
|
xSpan = 60;
|
|
2861
|
+
smoothedTickerPrice = null;
|
|
2862
|
+
tickerPriceTarget = null;
|
|
2863
|
+
smoothedTickerVolume = null;
|
|
2864
|
+
tickerVolumeTarget = null;
|
|
2834
2865
|
resetYViewport();
|
|
2835
2866
|
draw();
|
|
2836
2867
|
return;
|
|
@@ -2853,9 +2884,9 @@ function createChart(element, options = {}) {
|
|
|
2853
2884
|
fitXViewport();
|
|
2854
2885
|
}
|
|
2855
2886
|
}
|
|
2856
|
-
const
|
|
2857
|
-
if (
|
|
2858
|
-
|
|
2887
|
+
const lastPoint = data[data.length - 1];
|
|
2888
|
+
if (lastPoint) {
|
|
2889
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2859
2890
|
}
|
|
2860
2891
|
draw();
|
|
2861
2892
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -599,7 +599,8 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
599
599
|
if (!point || point.v === void 0 || point.v <= 0) {
|
|
600
600
|
continue;
|
|
601
601
|
}
|
|
602
|
-
const
|
|
602
|
+
const displayVolume = renderContext.getVolumeByIndex(index) ?? point.v;
|
|
603
|
+
const clampedVolume = Math.min(maxVolume, Math.max(0, displayVolume));
|
|
603
604
|
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
604
605
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
605
606
|
const xCenter = xFromIndex(index);
|
|
@@ -853,13 +854,19 @@ function createChart(element, options = {}) {
|
|
|
853
854
|
let doubleClickAction = mergedOptions.doubleClickAction;
|
|
854
855
|
let smoothedTickerPrice = null;
|
|
855
856
|
let tickerPriceTarget = null;
|
|
857
|
+
let smoothedTickerVolume = null;
|
|
858
|
+
let tickerVolumeTarget = null;
|
|
856
859
|
let smoothingRafId = null;
|
|
857
860
|
const tickerSmoothingLoop = () => {
|
|
858
861
|
smoothingRafId = null;
|
|
859
|
-
if (smoothedTickerPrice === null || tickerPriceTarget === null)
|
|
860
|
-
|
|
861
|
-
|
|
862
|
+
if (smoothedTickerPrice === null || tickerPriceTarget === null || smoothedTickerVolume === null || tickerVolumeTarget === null) {
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
const priceDiff = tickerPriceTarget - smoothedTickerPrice;
|
|
866
|
+
const volumeDiff = tickerVolumeTarget - smoothedTickerVolume;
|
|
867
|
+
if (Math.abs(priceDiff) < 1e-9 && Math.abs(volumeDiff) < 1e-6) {
|
|
862
868
|
smoothedTickerPrice = tickerPriceTarget;
|
|
869
|
+
smoothedTickerVolume = tickerVolumeTarget;
|
|
863
870
|
draw({ updateAutoScale: false });
|
|
864
871
|
return;
|
|
865
872
|
}
|
|
@@ -867,20 +874,28 @@ function createChart(element, options = {}) {
|
|
|
867
874
|
const speed = clamp(tickerOpts.smoothingSpeed ?? 8, 1, 60);
|
|
868
875
|
const dt = 1 / 60;
|
|
869
876
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
870
|
-
smoothedTickerPrice +=
|
|
877
|
+
smoothedTickerPrice += priceDiff * lerp;
|
|
878
|
+
smoothedTickerVolume += volumeDiff * lerp;
|
|
871
879
|
draw({ updateAutoScale: false });
|
|
872
880
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
873
881
|
};
|
|
874
|
-
const
|
|
882
|
+
const pushSmoothedTicker = (targetPrice, targetVolume) => {
|
|
875
883
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
876
884
|
if (!tickerOpts.smoothing) {
|
|
877
885
|
smoothedTickerPrice = null;
|
|
878
886
|
tickerPriceTarget = null;
|
|
887
|
+
smoothedTickerVolume = null;
|
|
888
|
+
tickerVolumeTarget = null;
|
|
879
889
|
return;
|
|
880
890
|
}
|
|
881
|
-
|
|
891
|
+
const normalizedVolume = Math.max(0, targetVolume ?? 0);
|
|
892
|
+
tickerPriceTarget = targetPrice;
|
|
893
|
+
tickerVolumeTarget = normalizedVolume;
|
|
882
894
|
if (smoothedTickerPrice === null) {
|
|
883
|
-
smoothedTickerPrice =
|
|
895
|
+
smoothedTickerPrice = targetPrice;
|
|
896
|
+
}
|
|
897
|
+
if (smoothedTickerVolume === null) {
|
|
898
|
+
smoothedTickerVolume = normalizedVolume;
|
|
884
899
|
}
|
|
885
900
|
if (smoothingRafId === null) {
|
|
886
901
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
@@ -1853,6 +1868,12 @@ function createChart(element, options = {}) {
|
|
|
1853
1868
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1854
1869
|
const useSmoothedCandle = tickerOpts.smoothing && smoothedTickerPrice !== null;
|
|
1855
1870
|
const lastDataIndex = data.length - 1;
|
|
1871
|
+
const getVolumeByIndex = (index) => {
|
|
1872
|
+
if (useSmoothedCandle && index === lastDataIndex && smoothedTickerVolume !== null) {
|
|
1873
|
+
return smoothedTickerVolume;
|
|
1874
|
+
}
|
|
1875
|
+
return data[index]?.v;
|
|
1876
|
+
};
|
|
1856
1877
|
for (let index = startIndex; index <= endIndex; index += 1) {
|
|
1857
1878
|
const point = data[index];
|
|
1858
1879
|
if (!point) {
|
|
@@ -1909,6 +1930,7 @@ function createChart(element, options = {}) {
|
|
|
1909
1930
|
xFromIndex,
|
|
1910
1931
|
yFromPrice,
|
|
1911
1932
|
getCandleDirectionByIndex,
|
|
1933
|
+
getVolumeByIndex,
|
|
1912
1934
|
candleSpacing,
|
|
1913
1935
|
upColor: mergedOptions.upColor,
|
|
1914
1936
|
downColor: mergedOptions.downColor
|
|
@@ -1969,6 +1991,7 @@ function createChart(element, options = {}) {
|
|
|
1969
1991
|
xFromIndex,
|
|
1970
1992
|
yFromPrice: null,
|
|
1971
1993
|
getCandleDirectionByIndex,
|
|
1994
|
+
getVolumeByIndex,
|
|
1972
1995
|
candleSpacing,
|
|
1973
1996
|
upColor: mergedOptions.upColor,
|
|
1974
1997
|
downColor: mergedOptions.downColor
|
|
@@ -2638,6 +2661,7 @@ function createChart(element, options = {}) {
|
|
|
2638
2661
|
const crosshairButtonRegion = getCrosshairPriceActionRegion(point.x, point.y);
|
|
2639
2662
|
if (crosshairButtonRegion) {
|
|
2640
2663
|
canvas.style.cursor = "pointer";
|
|
2664
|
+
setCrosshairPoint(point);
|
|
2641
2665
|
return;
|
|
2642
2666
|
}
|
|
2643
2667
|
const orderRegion = getOrderActionRegion(point.x, point.y);
|
|
@@ -2826,12 +2850,15 @@ function createChart(element, options = {}) {
|
|
|
2826
2850
|
if (!isTickerSmoothingEnabled) {
|
|
2827
2851
|
smoothedTickerPrice = null;
|
|
2828
2852
|
tickerPriceTarget = null;
|
|
2853
|
+
smoothedTickerVolume = null;
|
|
2854
|
+
tickerVolumeTarget = null;
|
|
2829
2855
|
if (smoothingRafId !== null) {
|
|
2830
2856
|
cancelAnimationFrame(smoothingRafId);
|
|
2831
2857
|
smoothingRafId = null;
|
|
2832
2858
|
}
|
|
2833
2859
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2834
|
-
|
|
2860
|
+
const lastPoint = data[data.length - 1];
|
|
2861
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2835
2862
|
}
|
|
2836
2863
|
draw();
|
|
2837
2864
|
};
|
|
@@ -2855,6 +2882,10 @@ function createChart(element, options = {}) {
|
|
|
2855
2882
|
if (data.length === 0) {
|
|
2856
2883
|
xCenter = 0;
|
|
2857
2884
|
xSpan = 60;
|
|
2885
|
+
smoothedTickerPrice = null;
|
|
2886
|
+
tickerPriceTarget = null;
|
|
2887
|
+
smoothedTickerVolume = null;
|
|
2888
|
+
tickerVolumeTarget = null;
|
|
2858
2889
|
resetYViewport();
|
|
2859
2890
|
draw();
|
|
2860
2891
|
return;
|
|
@@ -2877,9 +2908,9 @@ function createChart(element, options = {}) {
|
|
|
2877
2908
|
fitXViewport();
|
|
2878
2909
|
}
|
|
2879
2910
|
}
|
|
2880
|
-
const
|
|
2881
|
-
if (
|
|
2882
|
-
|
|
2911
|
+
const lastPoint = data[data.length - 1];
|
|
2912
|
+
if (lastPoint) {
|
|
2913
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2883
2914
|
}
|
|
2884
2915
|
draw();
|
|
2885
2916
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -74,6 +74,7 @@ interface IndicatorRenderContext {
|
|
|
74
74
|
xFromIndex: (index: number) => number;
|
|
75
75
|
yFromPrice: ((price: number) => number) | null;
|
|
76
76
|
getCandleDirectionByIndex: (index: number) => "up" | "down";
|
|
77
|
+
getVolumeByIndex: (index: number) => number | undefined;
|
|
77
78
|
candleSpacing: number;
|
|
78
79
|
upColor: string;
|
|
79
80
|
downColor: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,7 @@ interface IndicatorRenderContext {
|
|
|
74
74
|
xFromIndex: (index: number) => number;
|
|
75
75
|
yFromPrice: ((price: number) => number) | null;
|
|
76
76
|
getCandleDirectionByIndex: (index: number) => "up" | "down";
|
|
77
|
+
getVolumeByIndex: (index: number) => number | undefined;
|
|
77
78
|
candleSpacing: number;
|
|
78
79
|
upColor: string;
|
|
79
80
|
downColor: string;
|
package/dist/index.js
CHANGED
|
@@ -575,7 +575,8 @@ var BUILTIN_VOLUME_INDICATOR = {
|
|
|
575
575
|
if (!point || point.v === void 0 || point.v <= 0) {
|
|
576
576
|
continue;
|
|
577
577
|
}
|
|
578
|
-
const
|
|
578
|
+
const displayVolume = renderContext.getVolumeByIndex(index) ?? point.v;
|
|
579
|
+
const clampedVolume = Math.min(maxVolume, Math.max(0, displayVolume));
|
|
579
580
|
const ratio = scaleType === "linear" ? Math.min(1, Math.max(0, clampedVolume / maxVolume)) : scaleType === "log" ? Math.min(1, Math.max(0, Math.log1p(clampedVolume) / Math.log1p(maxVolume))) : Math.min(1, Math.max(0, Math.sqrt(clampedVolume) / Math.sqrt(maxVolume)));
|
|
580
581
|
const volumeHeight = Math.max(1, Math.round(paneHeight * ratio));
|
|
581
582
|
const xCenter = xFromIndex(index);
|
|
@@ -829,13 +830,19 @@ function createChart(element, options = {}) {
|
|
|
829
830
|
let doubleClickAction = mergedOptions.doubleClickAction;
|
|
830
831
|
let smoothedTickerPrice = null;
|
|
831
832
|
let tickerPriceTarget = null;
|
|
833
|
+
let smoothedTickerVolume = null;
|
|
834
|
+
let tickerVolumeTarget = null;
|
|
832
835
|
let smoothingRafId = null;
|
|
833
836
|
const tickerSmoothingLoop = () => {
|
|
834
837
|
smoothingRafId = null;
|
|
835
|
-
if (smoothedTickerPrice === null || tickerPriceTarget === null)
|
|
836
|
-
|
|
837
|
-
|
|
838
|
+
if (smoothedTickerPrice === null || tickerPriceTarget === null || smoothedTickerVolume === null || tickerVolumeTarget === null) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
const priceDiff = tickerPriceTarget - smoothedTickerPrice;
|
|
842
|
+
const volumeDiff = tickerVolumeTarget - smoothedTickerVolume;
|
|
843
|
+
if (Math.abs(priceDiff) < 1e-9 && Math.abs(volumeDiff) < 1e-6) {
|
|
838
844
|
smoothedTickerPrice = tickerPriceTarget;
|
|
845
|
+
smoothedTickerVolume = tickerVolumeTarget;
|
|
839
846
|
draw({ updateAutoScale: false });
|
|
840
847
|
return;
|
|
841
848
|
}
|
|
@@ -843,20 +850,28 @@ function createChart(element, options = {}) {
|
|
|
843
850
|
const speed = clamp(tickerOpts.smoothingSpeed ?? 8, 1, 60);
|
|
844
851
|
const dt = 1 / 60;
|
|
845
852
|
const lerp = 1 - Math.exp(-speed * dt);
|
|
846
|
-
smoothedTickerPrice +=
|
|
853
|
+
smoothedTickerPrice += priceDiff * lerp;
|
|
854
|
+
smoothedTickerVolume += volumeDiff * lerp;
|
|
847
855
|
draw({ updateAutoScale: false });
|
|
848
856
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
849
857
|
};
|
|
850
|
-
const
|
|
858
|
+
const pushSmoothedTicker = (targetPrice, targetVolume) => {
|
|
851
859
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
852
860
|
if (!tickerOpts.smoothing) {
|
|
853
861
|
smoothedTickerPrice = null;
|
|
854
862
|
tickerPriceTarget = null;
|
|
863
|
+
smoothedTickerVolume = null;
|
|
864
|
+
tickerVolumeTarget = null;
|
|
855
865
|
return;
|
|
856
866
|
}
|
|
857
|
-
|
|
867
|
+
const normalizedVolume = Math.max(0, targetVolume ?? 0);
|
|
868
|
+
tickerPriceTarget = targetPrice;
|
|
869
|
+
tickerVolumeTarget = normalizedVolume;
|
|
858
870
|
if (smoothedTickerPrice === null) {
|
|
859
|
-
smoothedTickerPrice =
|
|
871
|
+
smoothedTickerPrice = targetPrice;
|
|
872
|
+
}
|
|
873
|
+
if (smoothedTickerVolume === null) {
|
|
874
|
+
smoothedTickerVolume = normalizedVolume;
|
|
860
875
|
}
|
|
861
876
|
if (smoothingRafId === null) {
|
|
862
877
|
smoothingRafId = requestAnimationFrame(tickerSmoothingLoop);
|
|
@@ -1829,6 +1844,12 @@ function createChart(element, options = {}) {
|
|
|
1829
1844
|
const tickerOpts = mergedOptions.tickerLine ?? DEFAULT_OPTIONS.tickerLine;
|
|
1830
1845
|
const useSmoothedCandle = tickerOpts.smoothing && smoothedTickerPrice !== null;
|
|
1831
1846
|
const lastDataIndex = data.length - 1;
|
|
1847
|
+
const getVolumeByIndex = (index) => {
|
|
1848
|
+
if (useSmoothedCandle && index === lastDataIndex && smoothedTickerVolume !== null) {
|
|
1849
|
+
return smoothedTickerVolume;
|
|
1850
|
+
}
|
|
1851
|
+
return data[index]?.v;
|
|
1852
|
+
};
|
|
1832
1853
|
for (let index = startIndex; index <= endIndex; index += 1) {
|
|
1833
1854
|
const point = data[index];
|
|
1834
1855
|
if (!point) {
|
|
@@ -1885,6 +1906,7 @@ function createChart(element, options = {}) {
|
|
|
1885
1906
|
xFromIndex,
|
|
1886
1907
|
yFromPrice,
|
|
1887
1908
|
getCandleDirectionByIndex,
|
|
1909
|
+
getVolumeByIndex,
|
|
1888
1910
|
candleSpacing,
|
|
1889
1911
|
upColor: mergedOptions.upColor,
|
|
1890
1912
|
downColor: mergedOptions.downColor
|
|
@@ -1945,6 +1967,7 @@ function createChart(element, options = {}) {
|
|
|
1945
1967
|
xFromIndex,
|
|
1946
1968
|
yFromPrice: null,
|
|
1947
1969
|
getCandleDirectionByIndex,
|
|
1970
|
+
getVolumeByIndex,
|
|
1948
1971
|
candleSpacing,
|
|
1949
1972
|
upColor: mergedOptions.upColor,
|
|
1950
1973
|
downColor: mergedOptions.downColor
|
|
@@ -2614,6 +2637,7 @@ function createChart(element, options = {}) {
|
|
|
2614
2637
|
const crosshairButtonRegion = getCrosshairPriceActionRegion(point.x, point.y);
|
|
2615
2638
|
if (crosshairButtonRegion) {
|
|
2616
2639
|
canvas.style.cursor = "pointer";
|
|
2640
|
+
setCrosshairPoint(point);
|
|
2617
2641
|
return;
|
|
2618
2642
|
}
|
|
2619
2643
|
const orderRegion = getOrderActionRegion(point.x, point.y);
|
|
@@ -2802,12 +2826,15 @@ function createChart(element, options = {}) {
|
|
|
2802
2826
|
if (!isTickerSmoothingEnabled) {
|
|
2803
2827
|
smoothedTickerPrice = null;
|
|
2804
2828
|
tickerPriceTarget = null;
|
|
2829
|
+
smoothedTickerVolume = null;
|
|
2830
|
+
tickerVolumeTarget = null;
|
|
2805
2831
|
if (smoothingRafId !== null) {
|
|
2806
2832
|
cancelAnimationFrame(smoothingRafId);
|
|
2807
2833
|
smoothingRafId = null;
|
|
2808
2834
|
}
|
|
2809
2835
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2810
|
-
|
|
2836
|
+
const lastPoint = data[data.length - 1];
|
|
2837
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2811
2838
|
}
|
|
2812
2839
|
draw();
|
|
2813
2840
|
};
|
|
@@ -2831,6 +2858,10 @@ function createChart(element, options = {}) {
|
|
|
2831
2858
|
if (data.length === 0) {
|
|
2832
2859
|
xCenter = 0;
|
|
2833
2860
|
xSpan = 60;
|
|
2861
|
+
smoothedTickerPrice = null;
|
|
2862
|
+
tickerPriceTarget = null;
|
|
2863
|
+
smoothedTickerVolume = null;
|
|
2864
|
+
tickerVolumeTarget = null;
|
|
2834
2865
|
resetYViewport();
|
|
2835
2866
|
draw();
|
|
2836
2867
|
return;
|
|
@@ -2853,9 +2884,9 @@ function createChart(element, options = {}) {
|
|
|
2853
2884
|
fitXViewport();
|
|
2854
2885
|
}
|
|
2855
2886
|
}
|
|
2856
|
-
const
|
|
2857
|
-
if (
|
|
2858
|
-
|
|
2887
|
+
const lastPoint = data[data.length - 1];
|
|
2888
|
+
if (lastPoint) {
|
|
2889
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2859
2890
|
}
|
|
2860
2891
|
draw();
|
|
2861
2892
|
};
|