lightweight-charts-indicators 0.9.0 → 0.9.1
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 +3 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/render/renderer.d.ts +23 -0
- package/dist/render/renderer.d.ts.map +1 -1
- package/dist/render.mjs +131 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,6 +69,9 @@ before, and the indicator pane keeps its height across a redraw.
|
|
|
69
69
|
- **Render options**: `inputs` (plots whose visibility follows an input), `plots` (per-plot `visible`, `color`,
|
|
70
70
|
`lineWidth`, `style`, `palette`), `lastValueVisible`, `titleVisible`, `priceLineVisible`, `precision`, and
|
|
71
71
|
`autoscale: false` to leave the indicator out of the price-pane autoscale.
|
|
72
|
+
- **Live updates**: `reuseSeries: true` keeps the series of the previous render (same indicator, bars changed at
|
|
73
|
+
the end). Series of the same type, pane and creation order are kept; when only their newest points changed
|
|
74
|
+
(or a bar was added) those points are updated instead of the whole data being set again.
|
|
72
75
|
|
|
73
76
|
The demo page (`example/`) uses the same renderer.
|
|
74
77
|
|
package/dist/index.cjs
CHANGED
|
@@ -169207,4 +169207,4 @@ var registryPart5 = [
|
|
|
169207
169207
|
}
|
|
169208
169208
|
];
|
|
169209
169209
|
var indicatorRegistry = [...registryPart1, ...registryPart2, ...registryPart3, ...registryPart4, ...registryPart5];
|
|
169210
|
-
var version = "0.9.
|
|
169210
|
+
var version = "0.9.1";
|
package/dist/index.d.ts
CHANGED
|
@@ -2493,5 +2493,5 @@ export interface IndicatorRegistryEntry {
|
|
|
2493
2493
|
calculate: (bars: Bar[], inputs?: any) => any;
|
|
2494
2494
|
}
|
|
2495
2495
|
export declare const indicatorRegistry: IndicatorRegistryEntry[];
|
|
2496
|
-
export declare const version = "0.9.
|
|
2496
|
+
export declare const version = "0.9.1";
|
|
2497
2497
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.mjs
CHANGED
|
@@ -167004,7 +167004,7 @@ var registryPart5 = [
|
|
|
167004
167004
|
}
|
|
167005
167005
|
];
|
|
167006
167006
|
var indicatorRegistry = [...registryPart1, ...registryPart2, ...registryPart3, ...registryPart4, ...registryPart5];
|
|
167007
|
-
var version = "0.9.
|
|
167007
|
+
var version = "0.9.1";
|
|
167008
167008
|
export {
|
|
167009
167009
|
ADR,
|
|
167010
167010
|
ADX,
|
|
@@ -55,6 +55,12 @@ export interface RenderOptions {
|
|
|
55
55
|
precision?: number | null;
|
|
56
56
|
/** Series in the price pane take part in its autoscale (default true; false = scale on the price only) */
|
|
57
57
|
autoscale?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Keep the series of the previous render (same indicator, bars changed at the end: a live update). A series of the
|
|
60
|
+
* same type in the same pane and creation order is kept with the new options; when only its newest points changed
|
|
61
|
+
* they are updated, else its data is replaced. Default false: every series is created again.
|
|
62
|
+
*/
|
|
63
|
+
reuseSeries?: boolean;
|
|
58
64
|
}
|
|
59
65
|
export declare class IndicatorRenderer {
|
|
60
66
|
private readonly chart;
|
|
@@ -70,6 +76,15 @@ export declare class IndicatorRenderer {
|
|
|
70
76
|
private tableObserver;
|
|
71
77
|
private tableFrame;
|
|
72
78
|
private renderOpts;
|
|
79
|
+
/** Series of this render in creation order, with their type (series definition or custom pane view class) */
|
|
80
|
+
private created;
|
|
81
|
+
/** Series of the previous render a reuseSeries render can take again (by creation order); null = taken */
|
|
82
|
+
private pool;
|
|
83
|
+
private kinds;
|
|
84
|
+
/** Series taken from the pool in this render */
|
|
85
|
+
private reused;
|
|
86
|
+
/** Data last set on each series */
|
|
87
|
+
private lastData;
|
|
73
88
|
constructor(chart: IChartApi, options?: IndicatorRendererOptions);
|
|
74
89
|
/** Pane of a non-overlay indicator for the next render() */
|
|
75
90
|
setPaneIndex(paneIndex: number): void;
|
|
@@ -80,14 +95,22 @@ export declare class IndicatorRenderer {
|
|
|
80
95
|
* redraw (its height is not lost).
|
|
81
96
|
*/
|
|
82
97
|
render(entry: RenderableIndicator, result: IndicatorResult, bars: Bar[], options?: RenderOptions): void;
|
|
98
|
+
private draw;
|
|
83
99
|
/** Remove everything this instance drew (and its pane when it becomes empty, unless preserveEmptyPane) */
|
|
84
100
|
clear(): void;
|
|
101
|
+
/** Remove what the last render drew; `keepSeries`: its series go to the pool instead (reuseSeries) */
|
|
85
102
|
private clearOwned;
|
|
86
103
|
/** Options of a series in `pane`: left out of the autoscale in the price pane when autoscale is off */
|
|
87
104
|
private scaleOptions;
|
|
88
105
|
/** Plot series options from the render options (labels on the price scale, precision) */
|
|
89
106
|
private plotOptions;
|
|
90
107
|
private own;
|
|
108
|
+
/** The pool series of this creation slot when it has the same type and pane (options re-applied), else null */
|
|
109
|
+
private take;
|
|
110
|
+
private addSeries;
|
|
111
|
+
private addCustomSeries;
|
|
112
|
+
/** Series data; a reused series whose newest points alone changed (or that has new bars) gets them as updates */
|
|
113
|
+
private setData;
|
|
91
114
|
private attach;
|
|
92
115
|
/** Invisible line series that holds primitives (and, with autoscale, the price range of what they draw) */
|
|
93
116
|
private anchor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EASL,KAAK,SAAS,EACd,KAAK,UAAU,EAIf,KAAK,UAAU,EAQf,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/render/renderer.ts"],"names":[],"mappings":"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"}
|
package/dist/render.mjs
CHANGED
|
@@ -1606,6 +1606,15 @@ var IndicatorRenderer = class {
|
|
|
1606
1606
|
tableObserver = null;
|
|
1607
1607
|
tableFrame = 0;
|
|
1608
1608
|
renderOpts = {};
|
|
1609
|
+
/** Series of this render in creation order, with their type (series definition or custom pane view class) */
|
|
1610
|
+
created = [];
|
|
1611
|
+
/** Series of the previous render a reuseSeries render can take again (by creation order); null = taken */
|
|
1612
|
+
pool = [];
|
|
1613
|
+
kinds = /* @__PURE__ */ new WeakMap();
|
|
1614
|
+
/** Series taken from the pool in this render */
|
|
1615
|
+
reused = /* @__PURE__ */ new Set();
|
|
1616
|
+
/** Data last set on each series */
|
|
1617
|
+
lastData = /* @__PURE__ */ new WeakMap();
|
|
1609
1618
|
/** Pane of a non-overlay indicator for the next render() */
|
|
1610
1619
|
setPaneIndex(paneIndex) {
|
|
1611
1620
|
this.opts.paneIndex = paneIndex;
|
|
@@ -1623,14 +1632,21 @@ var IndicatorRenderer = class {
|
|
|
1623
1632
|
const paneApi = pane > 0 ? this.chart.panes()[pane] : void 0;
|
|
1624
1633
|
const preserved = paneApi?.preserveEmptyPane();
|
|
1625
1634
|
paneApi?.setPreserveEmptyPane(true);
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1635
|
+
try {
|
|
1636
|
+
this.clearOwned(options.reuseSeries === true);
|
|
1637
|
+
this.renderOpts = options;
|
|
1638
|
+
this.grid.setBars(bars);
|
|
1639
|
+
if (bars.length)
|
|
1640
|
+
this.draw(entry, result, bars, pane);
|
|
1641
|
+
} finally {
|
|
1642
|
+
for (const p of this.pool.splice(0))
|
|
1643
|
+
if (p)
|
|
1644
|
+
this.chart.removeSeries(p.series);
|
|
1645
|
+
if (paneApi && !this.opts.preserveEmptyPane)
|
|
1646
|
+
paneApi.setPreserveEmptyPane(preserved ?? false);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
draw(entry, r, bars, pane) {
|
|
1634
1650
|
this.drawPlots(entry, r, pane);
|
|
1635
1651
|
this.drawHLines(entry, r, pane, bars);
|
|
1636
1652
|
if (r.fills?.length) {
|
|
@@ -1682,15 +1698,21 @@ var IndicatorRenderer = class {
|
|
|
1682
1698
|
this.chart.removePane(i);
|
|
1683
1699
|
}
|
|
1684
1700
|
}
|
|
1685
|
-
|
|
1701
|
+
/** Remove what the last render drew; `keepSeries`: its series go to the pool instead (reuseSeries) */
|
|
1702
|
+
clearOwned(keepSeries = false) {
|
|
1686
1703
|
for (const { series, primitive } of this.attached)
|
|
1687
1704
|
series.detachPrimitive(primitive);
|
|
1688
1705
|
this.attached = [];
|
|
1689
1706
|
for (const p of this.markerPlugins)
|
|
1690
1707
|
p.detach();
|
|
1691
1708
|
this.markerPlugins = [];
|
|
1692
|
-
|
|
1693
|
-
this.
|
|
1709
|
+
if (keepSeries)
|
|
1710
|
+
this.pool = this.created;
|
|
1711
|
+
else
|
|
1712
|
+
for (const s of this.series())
|
|
1713
|
+
this.chart.removeSeries(s);
|
|
1714
|
+
this.created = [];
|
|
1715
|
+
this.reused.clear();
|
|
1694
1716
|
this.plotSeries = [];
|
|
1695
1717
|
this.otherSeries = [];
|
|
1696
1718
|
for (const { el } of this.tables)
|
|
@@ -1719,16 +1741,58 @@ var IndicatorRenderer = class {
|
|
|
1719
1741
|
};
|
|
1720
1742
|
}
|
|
1721
1743
|
own(series, plot = false) {
|
|
1722
|
-
|
|
1744
|
+
const s = series;
|
|
1745
|
+
(plot ? this.plotSeries : this.otherSeries).push(s);
|
|
1746
|
+
this.created.push({ series: s, kind: this.kinds.get(s) });
|
|
1747
|
+
return series;
|
|
1748
|
+
}
|
|
1749
|
+
/** The pool series of this creation slot when it has the same type and pane (options re-applied), else null */
|
|
1750
|
+
take(kind, pane, options) {
|
|
1751
|
+
const slot = this.created.length;
|
|
1752
|
+
const p = this.pool[slot];
|
|
1753
|
+
if (!p || p.kind !== kind || p.series.getPane().paneIndex() !== pane)
|
|
1754
|
+
return null;
|
|
1755
|
+
this.pool[slot] = null;
|
|
1756
|
+
p.series.applyOptions(options);
|
|
1757
|
+
this.reused.add(p.series);
|
|
1758
|
+
return p.series;
|
|
1759
|
+
}
|
|
1760
|
+
addSeries(definition, options, pane) {
|
|
1761
|
+
const reused = this.take(definition, pane, options);
|
|
1762
|
+
if (reused)
|
|
1763
|
+
return reused;
|
|
1764
|
+
const series = this.chart.addSeries(definition, options, pane);
|
|
1765
|
+
this.kinds.set(series, definition);
|
|
1766
|
+
return series;
|
|
1767
|
+
}
|
|
1768
|
+
addCustomSeries(view, options, pane) {
|
|
1769
|
+
const reused = this.take(view.constructor, pane, options);
|
|
1770
|
+
if (reused)
|
|
1771
|
+
return reused;
|
|
1772
|
+
const series = this.chart.addCustomSeries(view, options, pane);
|
|
1773
|
+
this.kinds.set(series, view.constructor);
|
|
1723
1774
|
return series;
|
|
1724
1775
|
}
|
|
1776
|
+
/** Series data; a reused series whose newest points alone changed (or that has new bars) gets them as updates */
|
|
1777
|
+
setData(series, data) {
|
|
1778
|
+
const s = series;
|
|
1779
|
+
const old = this.reused.has(s) ? this.lastData.get(s) : void 0;
|
|
1780
|
+
this.lastData.set(s, data);
|
|
1781
|
+
const from = old ? changedTail(old, data) : -1;
|
|
1782
|
+
if (from < 0) {
|
|
1783
|
+
s.setData(data);
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
for (let i = from; i < data.length; i++)
|
|
1787
|
+
s.update(data[i], i < old.length - 1);
|
|
1788
|
+
}
|
|
1725
1789
|
attach(series, primitive) {
|
|
1726
1790
|
series.attachPrimitive(primitive);
|
|
1727
1791
|
this.attached.push({ series, primitive });
|
|
1728
1792
|
}
|
|
1729
1793
|
/** Invisible line series that holds primitives (and, with autoscale, the price range of what they draw) */
|
|
1730
1794
|
anchor(pane, autoscale = true) {
|
|
1731
|
-
return this.own(this.
|
|
1795
|
+
return this.own(this.addSeries(LineSeries, {
|
|
1732
1796
|
color: "transparent",
|
|
1733
1797
|
lineVisible: false,
|
|
1734
1798
|
lastValueVisible: false,
|
|
@@ -1801,7 +1865,7 @@ var IndicatorRenderer = class {
|
|
|
1801
1865
|
}
|
|
1802
1866
|
addLine(data, o, pane, title) {
|
|
1803
1867
|
const lineWidth = o.lineWidth && o.lineWidth >= 1 ? o.lineWidth : 2;
|
|
1804
|
-
const series = this.own(this.
|
|
1868
|
+
const series = this.own(this.addSeries(LineSeries, {
|
|
1805
1869
|
color: o.color,
|
|
1806
1870
|
lineWidth,
|
|
1807
1871
|
lineStyle: o.lineStyle,
|
|
@@ -1815,7 +1879,7 @@ var IndicatorRenderer = class {
|
|
|
1815
1879
|
}, pane), true);
|
|
1816
1880
|
const valid = data.filter((d) => d.value != null && !Number.isNaN(d.value));
|
|
1817
1881
|
const simpleLine = (o.lineType ?? LineType.Simple) === LineType.Simple && o.lineVisible !== false && !o.pointMarkersVisible;
|
|
1818
|
-
|
|
1882
|
+
this.setData(series, simpleLine ? segmentColors(valid, o.color) : valid);
|
|
1819
1883
|
return series;
|
|
1820
1884
|
}
|
|
1821
1885
|
/**
|
|
@@ -1835,14 +1899,15 @@ var IndicatorRenderer = class {
|
|
|
1835
1899
|
}
|
|
1836
1900
|
/** plot.style_histogram: bars of the plot line width from histbase (thin histogram series) */
|
|
1837
1901
|
addThinHistogram(data, color, lineWidth, base, pane, title) {
|
|
1838
|
-
const series = this.own(this.
|
|
1902
|
+
const series = this.own(this.addCustomSeries(new ThinHistogramPaneView(), {
|
|
1839
1903
|
histColor: color,
|
|
1840
1904
|
histWidth: Math.max(1, lineWidth ?? 1),
|
|
1841
1905
|
histBase: base,
|
|
1842
1906
|
...this.plotOptions(title),
|
|
1843
1907
|
...this.scaleOptions(pane)
|
|
1844
1908
|
}, pane), true);
|
|
1845
|
-
|
|
1909
|
+
this.setData(
|
|
1910
|
+
series,
|
|
1846
1911
|
data.map((d) => {
|
|
1847
1912
|
const time = d.time;
|
|
1848
1913
|
if (d.value == null || Number.isNaN(d.value))
|
|
@@ -1853,17 +1918,17 @@ var IndicatorRenderer = class {
|
|
|
1853
1918
|
}
|
|
1854
1919
|
/** plot.style_columns: bars of the bar slot width from histbase */
|
|
1855
1920
|
addColumns(data, color, base, pane, title) {
|
|
1856
|
-
const series = this.own(this.
|
|
1921
|
+
const series = this.own(this.addSeries(HistogramSeries, {
|
|
1857
1922
|
color,
|
|
1858
1923
|
base,
|
|
1859
1924
|
...this.plotOptions(title),
|
|
1860
1925
|
...this.scaleOptions(pane)
|
|
1861
1926
|
}, pane), true);
|
|
1862
|
-
|
|
1927
|
+
this.setData(series, data.filter((d) => d.value != null && !Number.isNaN(d.value)));
|
|
1863
1928
|
}
|
|
1864
1929
|
addCross(data, color, lineWidth, pane) {
|
|
1865
1930
|
const anchor = this.anchor(pane);
|
|
1866
|
-
|
|
1931
|
+
this.setData(anchor, data.filter((d) => d.value != null && !Number.isNaN(d.value)));
|
|
1867
1932
|
const primitive = new CrossPlotPrimitive();
|
|
1868
1933
|
this.attach(anchor, primitive);
|
|
1869
1934
|
primitive.setData(data, color, (lineWidth ?? 2) * 3);
|
|
@@ -1871,7 +1936,7 @@ var IndicatorRenderer = class {
|
|
|
1871
1936
|
/** linebr / steplinebr: a line that breaks at na values */
|
|
1872
1937
|
addLineBr(data, color, lineWidth, lineStyle, steps, pane) {
|
|
1873
1938
|
const anchor = this.anchor(pane);
|
|
1874
|
-
|
|
1939
|
+
this.setData(anchor, data.filter((d) => d.value != null && !Number.isNaN(d.value)));
|
|
1875
1940
|
const primitive = new LineBrPrimitive();
|
|
1876
1941
|
this.attach(anchor, primitive);
|
|
1877
1942
|
primitive.setData(data, color, lineWidth ?? 2, lineStyle, steps);
|
|
@@ -1892,7 +1957,7 @@ var IndicatorRenderer = class {
|
|
|
1892
1957
|
for (const h of hlines) {
|
|
1893
1958
|
if (h.display === "none")
|
|
1894
1959
|
continue;
|
|
1895
|
-
const series = this.own(this.
|
|
1960
|
+
const series = this.own(this.addSeries(LineSeries, {
|
|
1896
1961
|
color: h.color ?? "#787B86",
|
|
1897
1962
|
lineWidth: h.linewidth ?? 1,
|
|
1898
1963
|
lineStyle: LINE_STYLES[h.linestyle ?? "solid"] ?? LineStyle.Solid,
|
|
@@ -1901,7 +1966,7 @@ var IndicatorRenderer = class {
|
|
|
1901
1966
|
priceLineVisible: false,
|
|
1902
1967
|
...this.scaleOptions(pane)
|
|
1903
1968
|
}, pane));
|
|
1904
|
-
|
|
1969
|
+
this.setData(series, [{ time: first, value: h.price }, { time: last, value: h.price }]);
|
|
1905
1970
|
}
|
|
1906
1971
|
if (!entry.hlineConfig?.length)
|
|
1907
1972
|
return;
|
|
@@ -1936,7 +2001,7 @@ var IndicatorRenderer = class {
|
|
|
1936
2001
|
const gradient = fill.gradient;
|
|
1937
2002
|
const colors = fill.colors;
|
|
1938
2003
|
const anchor = this.anchor(pane);
|
|
1939
|
-
|
|
2004
|
+
this.setData(anchor, bars.map((b) => ({ time: b.time, value: Math.max(p1, p2) })));
|
|
1940
2005
|
const primitive = new PlotFillPrimitive();
|
|
1941
2006
|
primitive.setData(bars.map((b, i) => ({
|
|
1942
2007
|
time: b.time,
|
|
@@ -1949,7 +2014,7 @@ var IndicatorRenderer = class {
|
|
|
1949
2014
|
continue;
|
|
1950
2015
|
}
|
|
1951
2016
|
const color = fill.color ?? "rgba(41,98,255,0.1)";
|
|
1952
|
-
const series = this.own(this.
|
|
2017
|
+
const series = this.own(this.addSeries(BaselineSeries, {
|
|
1953
2018
|
baseValue: { type: "price", price: Math.min(p1, p2) },
|
|
1954
2019
|
topFillColor1: color,
|
|
1955
2020
|
topFillColor2: color,
|
|
@@ -1963,7 +2028,7 @@ var IndicatorRenderer = class {
|
|
|
1963
2028
|
crosshairMarkerVisible: false,
|
|
1964
2029
|
...this.scaleOptions(pane)
|
|
1965
2030
|
}, pane));
|
|
1966
|
-
|
|
2031
|
+
this.setData(series, [
|
|
1967
2032
|
{ time: first, value: Math.max(p1, p2) },
|
|
1968
2033
|
{ time: last, value: Math.max(p1, p2) }
|
|
1969
2034
|
]);
|
|
@@ -2012,7 +2077,7 @@ var IndicatorRenderer = class {
|
|
|
2012
2077
|
continue;
|
|
2013
2078
|
const bothOverlay = overlayPlots.has(String(fill.plot1)) && overlayPlots.has(String(fill.plot2));
|
|
2014
2079
|
const anchor = this.anchor(bothOverlay ? 0 : pane);
|
|
2015
|
-
|
|
2080
|
+
this.setData(anchor, valid.map((p) => ({ time: p.time, value: Math.max(p.v1, p.v2) })));
|
|
2016
2081
|
const primitive = new PlotFillPrimitive();
|
|
2017
2082
|
primitive.setData(points);
|
|
2018
2083
|
this.attach(anchor, primitive);
|
|
@@ -2058,7 +2123,7 @@ var IndicatorRenderer = class {
|
|
|
2058
2123
|
if (onPrice.native.length || onPrice.extended.length) {
|
|
2059
2124
|
const target = main ?? this.anchor(0, false);
|
|
2060
2125
|
if (!main)
|
|
2061
|
-
|
|
2126
|
+
this.setData(target, anchorData(this.grid.bars.map((b) => ({ time: b.time, value: b.close })), this.grid));
|
|
2062
2127
|
if (onPrice.native.length)
|
|
2063
2128
|
this.markerPlugins.push(createSeriesMarkers(target, onPrice.native));
|
|
2064
2129
|
if (onPrice.extended.length) {
|
|
@@ -2071,7 +2136,7 @@ var IndicatorRenderer = class {
|
|
|
2071
2136
|
if (paneMarkers.length) {
|
|
2072
2137
|
const parts = split(paneMarkers, true);
|
|
2073
2138
|
const anchor = this.anchor(pane);
|
|
2074
|
-
|
|
2139
|
+
this.setData(anchor, anchorData(paneMarkers.map((m) => ({ time: m.time, value: m.price })), this.grid));
|
|
2075
2140
|
if (parts.native.length)
|
|
2076
2141
|
this.markerPlugins.push(createSeriesMarkers(anchor, parts.native));
|
|
2077
2142
|
if (parts.extended.length) {
|
|
@@ -2125,7 +2190,7 @@ var IndicatorRenderer = class {
|
|
|
2125
2190
|
const anchor = this.anchor(p, false);
|
|
2126
2191
|
const first = list[0].time;
|
|
2127
2192
|
const last = list[list.length - 1].time;
|
|
2128
|
-
|
|
2193
|
+
this.setData(anchor, (first === last ? [first] : [first, last]).map((time) => ({ time, value: 0 })));
|
|
2129
2194
|
const primitive = new BgColorPrimitive();
|
|
2130
2195
|
this.attach(anchor, primitive);
|
|
2131
2196
|
primitive.setData(list);
|
|
@@ -2134,7 +2199,7 @@ var IndicatorRenderer = class {
|
|
|
2134
2199
|
/** plotcandle: a candlestick series (force_overlay candles go to the price pane) */
|
|
2135
2200
|
drawCandles(_id, data, pane) {
|
|
2136
2201
|
const p = data.some((d) => d.forceOverlay) ? 0 : pane;
|
|
2137
|
-
const series = this.own(this.
|
|
2202
|
+
const series = this.own(this.addSeries(CandlestickSeries, {
|
|
2138
2203
|
upColor: "#26a69a",
|
|
2139
2204
|
downColor: "#ef5350",
|
|
2140
2205
|
borderVisible: true,
|
|
@@ -2144,7 +2209,7 @@ var IndicatorRenderer = class {
|
|
|
2144
2209
|
priceLineVisible: false,
|
|
2145
2210
|
...this.scaleOptions(p)
|
|
2146
2211
|
}, p));
|
|
2147
|
-
|
|
2212
|
+
this.setData(series, data.map((d) => {
|
|
2148
2213
|
const time = d.time;
|
|
2149
2214
|
if (![d.open, d.high, d.low, d.close].every((v) => Number.isFinite(v)))
|
|
2150
2215
|
return { time };
|
|
@@ -2161,7 +2226,7 @@ var IndicatorRenderer = class {
|
|
|
2161
2226
|
/** plotbar: an OHLC bar series in the bar colour (PineScript default colour when none) */
|
|
2162
2227
|
drawBars(data, pane) {
|
|
2163
2228
|
const p = data.some((d) => d.forceOverlay) ? 0 : pane;
|
|
2164
|
-
const series = this.own(this.
|
|
2229
|
+
const series = this.own(this.addSeries(BarSeries, {
|
|
2165
2230
|
upColor: "#2962FF",
|
|
2166
2231
|
downColor: "#2962FF",
|
|
2167
2232
|
openVisible: true,
|
|
@@ -2170,7 +2235,7 @@ var IndicatorRenderer = class {
|
|
|
2170
2235
|
priceLineVisible: false,
|
|
2171
2236
|
...this.scaleOptions(p)
|
|
2172
2237
|
}, p));
|
|
2173
|
-
|
|
2238
|
+
this.setData(series, data.map((d) => {
|
|
2174
2239
|
const time = d.time;
|
|
2175
2240
|
if (![d.open, d.high, d.low, d.close].every((v) => Number.isFinite(v)))
|
|
2176
2241
|
return { time };
|
|
@@ -2192,7 +2257,7 @@ var IndicatorRenderer = class {
|
|
|
2192
2257
|
}
|
|
2193
2258
|
for (const [p, group] of groups) {
|
|
2194
2259
|
const anchor = this.anchor(p, autoscale);
|
|
2195
|
-
|
|
2260
|
+
this.setData(anchor, anchorData(group.flatMap(points), this.grid));
|
|
2196
2261
|
this.attach(anchor, new DrawingPrimitive(this.grid, group, draw, zOrder));
|
|
2197
2262
|
}
|
|
2198
2263
|
}
|
|
@@ -2231,7 +2296,7 @@ var IndicatorRenderer = class {
|
|
|
2231
2296
|
const data = [];
|
|
2232
2297
|
for (let i = 1; i <= k; i++)
|
|
2233
2298
|
data.push({ time: this.grid.lastTime + i * this.grid.interval });
|
|
2234
|
-
|
|
2299
|
+
this.setData(series, data);
|
|
2235
2300
|
}
|
|
2236
2301
|
// ─── Tables ───────────────────────────────────────────────────────────────
|
|
2237
2302
|
/**
|
|
@@ -2290,6 +2355,36 @@ function segmentColors(data, base) {
|
|
|
2290
2355
|
return next ? { ...d, color: next.color ?? base } : d;
|
|
2291
2356
|
});
|
|
2292
2357
|
}
|
|
2358
|
+
var TAIL_POINTS = 2;
|
|
2359
|
+
function changedTail(old, next) {
|
|
2360
|
+
const m = old.length;
|
|
2361
|
+
if (next.length < m || next.length - m > TAIL_POINTS)
|
|
2362
|
+
return -1;
|
|
2363
|
+
let i = 0;
|
|
2364
|
+
while (i < m && samePoint(old[i], next[i]))
|
|
2365
|
+
i++;
|
|
2366
|
+
if (i < m - TAIL_POINTS)
|
|
2367
|
+
return -1;
|
|
2368
|
+
for (let j = i; j < m; j++)
|
|
2369
|
+
if (old[j].time !== next[j].time)
|
|
2370
|
+
return -1;
|
|
2371
|
+
return i;
|
|
2372
|
+
}
|
|
2373
|
+
function samePoint(a, b) {
|
|
2374
|
+
if (a === b)
|
|
2375
|
+
return true;
|
|
2376
|
+
const x = a;
|
|
2377
|
+
const y = b;
|
|
2378
|
+
let n = 0;
|
|
2379
|
+
for (const k in y) {
|
|
2380
|
+
if (x[k] !== y[k])
|
|
2381
|
+
return false;
|
|
2382
|
+
n++;
|
|
2383
|
+
}
|
|
2384
|
+
for (const _ in x)
|
|
2385
|
+
n--;
|
|
2386
|
+
return n === 0;
|
|
2387
|
+
}
|
|
2293
2388
|
function lastOutputTime(r) {
|
|
2294
2389
|
let max = -Infinity;
|
|
2295
2390
|
const see = (t) => {
|