hyperprop-charting-library 0.1.41 → 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 +42 -12
- package/dist/hyperprop-charting-library.d.ts +1 -0
- package/dist/hyperprop-charting-library.js +42 -12
- package/dist/index.cjs +42 -12
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +42 -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
|
|
@@ -2827,12 +2850,15 @@ function createChart(element, options = {}) {
|
|
|
2827
2850
|
if (!isTickerSmoothingEnabled) {
|
|
2828
2851
|
smoothedTickerPrice = null;
|
|
2829
2852
|
tickerPriceTarget = null;
|
|
2853
|
+
smoothedTickerVolume = null;
|
|
2854
|
+
tickerVolumeTarget = null;
|
|
2830
2855
|
if (smoothingRafId !== null) {
|
|
2831
2856
|
cancelAnimationFrame(smoothingRafId);
|
|
2832
2857
|
smoothingRafId = null;
|
|
2833
2858
|
}
|
|
2834
2859
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2835
|
-
|
|
2860
|
+
const lastPoint = data[data.length - 1];
|
|
2861
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2836
2862
|
}
|
|
2837
2863
|
draw();
|
|
2838
2864
|
};
|
|
@@ -2856,6 +2882,10 @@ function createChart(element, options = {}) {
|
|
|
2856
2882
|
if (data.length === 0) {
|
|
2857
2883
|
xCenter = 0;
|
|
2858
2884
|
xSpan = 60;
|
|
2885
|
+
smoothedTickerPrice = null;
|
|
2886
|
+
tickerPriceTarget = null;
|
|
2887
|
+
smoothedTickerVolume = null;
|
|
2888
|
+
tickerVolumeTarget = null;
|
|
2859
2889
|
resetYViewport();
|
|
2860
2890
|
draw();
|
|
2861
2891
|
return;
|
|
@@ -2878,9 +2908,9 @@ function createChart(element, options = {}) {
|
|
|
2878
2908
|
fitXViewport();
|
|
2879
2909
|
}
|
|
2880
2910
|
}
|
|
2881
|
-
const
|
|
2882
|
-
if (
|
|
2883
|
-
|
|
2911
|
+
const lastPoint = data[data.length - 1];
|
|
2912
|
+
if (lastPoint) {
|
|
2913
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2884
2914
|
}
|
|
2885
2915
|
draw();
|
|
2886
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
|
|
@@ -2803,12 +2826,15 @@ function createChart(element, options = {}) {
|
|
|
2803
2826
|
if (!isTickerSmoothingEnabled) {
|
|
2804
2827
|
smoothedTickerPrice = null;
|
|
2805
2828
|
tickerPriceTarget = null;
|
|
2829
|
+
smoothedTickerVolume = null;
|
|
2830
|
+
tickerVolumeTarget = null;
|
|
2806
2831
|
if (smoothingRafId !== null) {
|
|
2807
2832
|
cancelAnimationFrame(smoothingRafId);
|
|
2808
2833
|
smoothingRafId = null;
|
|
2809
2834
|
}
|
|
2810
2835
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2811
|
-
|
|
2836
|
+
const lastPoint = data[data.length - 1];
|
|
2837
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2812
2838
|
}
|
|
2813
2839
|
draw();
|
|
2814
2840
|
};
|
|
@@ -2832,6 +2858,10 @@ function createChart(element, options = {}) {
|
|
|
2832
2858
|
if (data.length === 0) {
|
|
2833
2859
|
xCenter = 0;
|
|
2834
2860
|
xSpan = 60;
|
|
2861
|
+
smoothedTickerPrice = null;
|
|
2862
|
+
tickerPriceTarget = null;
|
|
2863
|
+
smoothedTickerVolume = null;
|
|
2864
|
+
tickerVolumeTarget = null;
|
|
2835
2865
|
resetYViewport();
|
|
2836
2866
|
draw();
|
|
2837
2867
|
return;
|
|
@@ -2854,9 +2884,9 @@ function createChart(element, options = {}) {
|
|
|
2854
2884
|
fitXViewport();
|
|
2855
2885
|
}
|
|
2856
2886
|
}
|
|
2857
|
-
const
|
|
2858
|
-
if (
|
|
2859
|
-
|
|
2887
|
+
const lastPoint = data[data.length - 1];
|
|
2888
|
+
if (lastPoint) {
|
|
2889
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2860
2890
|
}
|
|
2861
2891
|
draw();
|
|
2862
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
|
|
@@ -2827,12 +2850,15 @@ function createChart(element, options = {}) {
|
|
|
2827
2850
|
if (!isTickerSmoothingEnabled) {
|
|
2828
2851
|
smoothedTickerPrice = null;
|
|
2829
2852
|
tickerPriceTarget = null;
|
|
2853
|
+
smoothedTickerVolume = null;
|
|
2854
|
+
tickerVolumeTarget = null;
|
|
2830
2855
|
if (smoothingRafId !== null) {
|
|
2831
2856
|
cancelAnimationFrame(smoothingRafId);
|
|
2832
2857
|
smoothingRafId = null;
|
|
2833
2858
|
}
|
|
2834
2859
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2835
|
-
|
|
2860
|
+
const lastPoint = data[data.length - 1];
|
|
2861
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2836
2862
|
}
|
|
2837
2863
|
draw();
|
|
2838
2864
|
};
|
|
@@ -2856,6 +2882,10 @@ function createChart(element, options = {}) {
|
|
|
2856
2882
|
if (data.length === 0) {
|
|
2857
2883
|
xCenter = 0;
|
|
2858
2884
|
xSpan = 60;
|
|
2885
|
+
smoothedTickerPrice = null;
|
|
2886
|
+
tickerPriceTarget = null;
|
|
2887
|
+
smoothedTickerVolume = null;
|
|
2888
|
+
tickerVolumeTarget = null;
|
|
2859
2889
|
resetYViewport();
|
|
2860
2890
|
draw();
|
|
2861
2891
|
return;
|
|
@@ -2878,9 +2908,9 @@ function createChart(element, options = {}) {
|
|
|
2878
2908
|
fitXViewport();
|
|
2879
2909
|
}
|
|
2880
2910
|
}
|
|
2881
|
-
const
|
|
2882
|
-
if (
|
|
2883
|
-
|
|
2911
|
+
const lastPoint = data[data.length - 1];
|
|
2912
|
+
if (lastPoint) {
|
|
2913
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2884
2914
|
}
|
|
2885
2915
|
draw();
|
|
2886
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
|
|
@@ -2803,12 +2826,15 @@ function createChart(element, options = {}) {
|
|
|
2803
2826
|
if (!isTickerSmoothingEnabled) {
|
|
2804
2827
|
smoothedTickerPrice = null;
|
|
2805
2828
|
tickerPriceTarget = null;
|
|
2829
|
+
smoothedTickerVolume = null;
|
|
2830
|
+
tickerVolumeTarget = null;
|
|
2806
2831
|
if (smoothingRafId !== null) {
|
|
2807
2832
|
cancelAnimationFrame(smoothingRafId);
|
|
2808
2833
|
smoothingRafId = null;
|
|
2809
2834
|
}
|
|
2810
2835
|
} else if (!wasTickerSmoothingEnabled && data.length > 0) {
|
|
2811
|
-
|
|
2836
|
+
const lastPoint = data[data.length - 1];
|
|
2837
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2812
2838
|
}
|
|
2813
2839
|
draw();
|
|
2814
2840
|
};
|
|
@@ -2832,6 +2858,10 @@ function createChart(element, options = {}) {
|
|
|
2832
2858
|
if (data.length === 0) {
|
|
2833
2859
|
xCenter = 0;
|
|
2834
2860
|
xSpan = 60;
|
|
2861
|
+
smoothedTickerPrice = null;
|
|
2862
|
+
tickerPriceTarget = null;
|
|
2863
|
+
smoothedTickerVolume = null;
|
|
2864
|
+
tickerVolumeTarget = null;
|
|
2835
2865
|
resetYViewport();
|
|
2836
2866
|
draw();
|
|
2837
2867
|
return;
|
|
@@ -2854,9 +2884,9 @@ function createChart(element, options = {}) {
|
|
|
2854
2884
|
fitXViewport();
|
|
2855
2885
|
}
|
|
2856
2886
|
}
|
|
2857
|
-
const
|
|
2858
|
-
if (
|
|
2859
|
-
|
|
2887
|
+
const lastPoint = data[data.length - 1];
|
|
2888
|
+
if (lastPoint) {
|
|
2889
|
+
pushSmoothedTicker(lastPoint.c, lastPoint.v);
|
|
2860
2890
|
}
|
|
2861
2891
|
draw();
|
|
2862
2892
|
};
|