wickchart 1.4.0 → 1.5.0
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 +28 -8
- package/package.json +9 -2
- package/src/core.js +353 -11
- package/src/wick-chart.js +13 -3
- package/types/core.d.ts +243 -3
- package/types/wick-chart.d.ts +158 -3
package/README.md
CHANGED
|
@@ -6,6 +6,9 @@ A TradingView-style financial chart as a single framework-agnostic Web Component
|
|
|
6
6
|
One file, zero dependencies, one HTML tag. Canvas-rendered, fast, themeable, and
|
|
7
7
|
streaming-ready.
|
|
8
8
|
|
|
9
|
+
<img width="759" height="390" alt="image" src="https://github.com/user-attachments/assets/f335cecc-d5b3-4d27-a982-600b6bc72d6f" />
|
|
10
|
+
|
|
11
|
+
|
|
9
12
|
## Install
|
|
10
13
|
|
|
11
14
|
```bash
|
|
@@ -226,7 +229,7 @@ chart.setData([
|
|
|
226
229
|
| ------------- | ---------- | ------------------------------------------------------------------ |
|
|
227
230
|
| `theme` | `dark` | `dark` or `light` |
|
|
228
231
|
| `type` | `candles` | `candles`, `line`, `area`, `bars` (OHLC), `hollow` (hollow up-candles), `heikin` (Heikin-Ashi) |
|
|
229
|
-
| `indicators` | `volume`* | Space/comma-separated: `sma:20`, `ema:50`, `bb:20`, `rsi:14`, `macd:12/26/9`, `volume`, or any registered indicator |
|
|
232
|
+
| `indicators` | `volume`* | Space/comma-separated: `sma:20`, `ema:50`, `bb:20`, `vwap`, `supertrend:10/3`, `donchian:20`, `keltner:20/2`, `rsi:14`, `macd:12/26/9`, `stoch:14/3`, `atr:14`, `obv`, `cci:20`, `wr:14`, `volume`, or any registered indicator |
|
|
230
233
|
| `label` | – | Text shown in the legend (e.g. `"BTC · 1h"`) |
|
|
231
234
|
| `log` | off | Logarithmic price scale |
|
|
232
235
|
| `auto` | on | Keep the right edge pinned to the latest bar while streaming |
|
|
@@ -247,8 +250,17 @@ chart.setData([
|
|
|
247
250
|
| `sma` | overlay | `period` (20) | |
|
|
248
251
|
| `ema` | overlay | `period` (50) | |
|
|
249
252
|
| `bb` | overlay | `period`, `mult` (20, 2) | Bollinger bands (3 lines) |
|
|
253
|
+
| `vwap` | overlay | – | hlc3 VWAP, resets each UTC day |
|
|
254
|
+
| `supertrend` | overlay | `period`, `mult` (10, 3) | ATR trend line, breaks at flips |
|
|
255
|
+
| `donchian` | overlay | `period` (20) | high/low channel + mid |
|
|
256
|
+
| `keltner` | overlay | `period`, `mult` (20, 2) | EMA ± mult×ATR channel |
|
|
250
257
|
| `rsi` | pane | `period` (14) | fixed 0–100 scale, 30/70 guides |
|
|
251
258
|
| `macd` | pane | `fast/slow/signal` (12/26/9) | 2 lines + histogram |
|
|
259
|
+
| `stoch` | pane | `period`, `smooth` (14, 3) | %K + %D, fixed 0–100, 20/80 guides |
|
|
260
|
+
| `atr` | pane | `period` (14) | Wilder ATR |
|
|
261
|
+
| `obv` | pane | – | on-balance volume |
|
|
262
|
+
| `cci` | pane | `period` (20) | ±100 guides |
|
|
263
|
+
| `wr` | pane | `period` (14) | Williams %R, fixed −100–0, −80/−20 guides |
|
|
252
264
|
| `volume` | overlay | – | histogram at the bottom of the price pane |
|
|
253
265
|
|
|
254
266
|
### Custom indicators
|
|
@@ -257,9 +269,9 @@ Register your own — anything from a one-liner moving average to a multi-line
|
|
|
257
269
|
pane:
|
|
258
270
|
|
|
259
271
|
```js
|
|
260
|
-
WickChart.registerIndicator('
|
|
272
|
+
WickChart.registerIndicator('cvwap', { // cumulative VWAP over the whole dataset
|
|
261
273
|
kind: 'overlay', // or 'pane'
|
|
262
|
-
params: { period: 20 }, // defaults; set via indicators="
|
|
274
|
+
params: { period: 20 }, // defaults; set via indicators="cvwap:30"
|
|
263
275
|
compute(bars, params) { // bars: normalized {time,open,high,low,close,volume}
|
|
264
276
|
const out = new Array(bars.length).fill(null);
|
|
265
277
|
let pv = 0, vv = 0;
|
|
@@ -270,9 +282,9 @@ WickChart.registerIndicator('vwap', {
|
|
|
270
282
|
}
|
|
271
283
|
return out; // single series — or { lines:[{name,values}], histogram }
|
|
272
284
|
},
|
|
273
|
-
// pane-only extras: guides:[30,70], range:[0,100], fmt:'price'|'fixed1'
|
|
285
|
+
// pane-only extras: guides:[30,70], range:[0,100], fmt:'price'|'fixed1'|'compact'
|
|
274
286
|
});
|
|
275
|
-
chart.indicators = '
|
|
287
|
+
chart.indicators = 'cvwap';
|
|
276
288
|
```
|
|
277
289
|
|
|
278
290
|
`import WickChart from 'wickchart'` gives you the class for
|
|
@@ -306,6 +318,7 @@ shareable URLs.
|
|
|
306
318
|
| `prev(x[,k])` `change(x)` | shifted series / bar-to-bar delta |
|
|
307
319
|
| `abs(x)` `sqrt(x)` `log(x)` `min(a,b)` `max(a,b)` | element-wise math |
|
|
308
320
|
| `crossup(a,b)` `crossdown(a,b)` | 1 on a strict cross, else 0 |
|
|
321
|
+
| `vwap()` `obv()` `atr(n)` | bar-level series — callable anywhere, e.g. `crossup(close, vwap())` in alerts |
|
|
309
322
|
|
|
310
323
|
Operators are `+ - * / %` with usual precedence, unary `-`, and parentheses.
|
|
311
324
|
Values before a window fills are `NaN` (not drawn), division by zero yields
|
|
@@ -661,7 +674,7 @@ chart.removeLayer('flags'); // detach by handle or id
|
|
|
661
674
|
A claimed gesture delivers `move`/`up` (and `cancel` on Escape) to the layer
|
|
662
675
|
while the chart suppresses pan/brush/measure. Markers, watermarks, signal
|
|
663
676
|
badges — or a whole drawing toolkit — plug in without the core growing a
|
|
664
|
-
single tool. The main entry is covered by a CI gzip budget (
|
|
677
|
+
single tool. The main entry is covered by a CI gzip budget (68 KB) so it
|
|
665
678
|
stays that way.
|
|
666
679
|
|
|
667
680
|
### Drawings — the `wickchart-draw` plugin
|
|
@@ -673,19 +686,26 @@ data that rides zoom & pan, survives reloads, extrapolates into future
|
|
|
673
686
|
space, and serializes to JSON. Anchors magnet-snap to bar times and OHLC.
|
|
674
687
|
|
|
675
688
|
```js
|
|
689
|
+
npm install wickchart wickchart-draw // drawings are a separate opt-in package
|
|
690
|
+
|
|
676
691
|
import { attachDrawings } from 'wickchart-draw';
|
|
677
692
|
|
|
678
693
|
const draw = attachDrawings(chart);
|
|
679
694
|
draw.setTool('trendline'); // drag to draw; setTool(null) = select/move mode
|
|
680
695
|
draw.getDrawings(); // → JSON array (save it); setDrawings(saved)
|
|
681
696
|
draw.undo(); draw.clear();
|
|
697
|
+
draw.setShare(true); // shared drawings: draw on one tab, appears on all
|
|
682
698
|
chart.addEventListener('wick:drawings', (e) => save(e.detail.drawings));
|
|
683
699
|
```
|
|
684
700
|
|
|
685
701
|
Select mode: click a drawing to select it, drag to move, drag the square
|
|
686
702
|
handles to re-anchor, `Delete` removes, `Esc` cancels a gesture; clicks on
|
|
687
|
-
empty space fall through to the chart.
|
|
688
|
-
|
|
703
|
+
empty space fall through to the chart. Placing a note opens an inline editor
|
|
704
|
+
(type + `Enter`); click a selected note again to re-edit. `setShare(true)`
|
|
705
|
+
reuses the chart's `co-view` room (or pass an explicit room name) — last
|
|
706
|
+
writer wins, remote updates never touch the local undo stack. Peer
|
|
707
|
+
dependency: wickchart ≥ 1.4. See the live playground in the docs (Drawings
|
|
708
|
+
section — it shares a room, so open it twice and draw on either chart).
|
|
689
709
|
|
|
690
710
|
## Methods
|
|
691
711
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wickchart",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "<wick-chart> — a modern, dependency-free financial charting web component. Candles, line & area charts, crosshair, zoom/pan, indicators (incl. a safe expression mini-language), live streaming via <wick-feed>, theming.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/wick-chart.js",
|
|
@@ -57,7 +57,14 @@
|
|
|
57
57
|
"custom-element",
|
|
58
58
|
"canvas",
|
|
59
59
|
"zero-dependency",
|
|
60
|
-
"tradingview"
|
|
60
|
+
"tradingview",
|
|
61
|
+
"vwap",
|
|
62
|
+
"supertrend",
|
|
63
|
+
"bollinger-bands",
|
|
64
|
+
"macd",
|
|
65
|
+
"rsi",
|
|
66
|
+
"stochastic",
|
|
67
|
+
"technical-analysis"
|
|
61
68
|
],
|
|
62
69
|
"license": "MIT",
|
|
63
70
|
"repository": {
|
package/src/core.js
CHANGED
|
@@ -462,6 +462,259 @@ export function calcMACD(closes, fast = 12, slow = 26, signal = 9) {
|
|
|
462
462
|
return { macd, signal: sig, hist };
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
+
/** True range: max(h−l, |h−prev close|, |l−prev close|); first bar is h−l.
|
|
466
|
+
* @param {Bar[]} bars
|
|
467
|
+
* @returns {Array<number|null>}
|
|
468
|
+
*/
|
|
469
|
+
export function calcTrueRange(bars) {
|
|
470
|
+
const out = new Array(bars.length).fill(null);
|
|
471
|
+
for (let i = 0; i < bars.length; i++) {
|
|
472
|
+
const b = bars[i];
|
|
473
|
+
out[i] =
|
|
474
|
+
i === 0
|
|
475
|
+
? b.high - b.low
|
|
476
|
+
: Math.max(b.high - b.low, Math.abs(b.high - bars[i - 1].close), Math.abs(b.low - bars[i - 1].close));
|
|
477
|
+
}
|
|
478
|
+
return out;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Average True Range (Wilder smoothing; seeded with the SMA of the first
|
|
483
|
+
* `period` true ranges).
|
|
484
|
+
* @param {Bar[]} bars
|
|
485
|
+
* @param {number} period
|
|
486
|
+
* @returns {Array<number|null>}
|
|
487
|
+
*/
|
|
488
|
+
export function calcATR(bars, period = 14) {
|
|
489
|
+
const out = new Array(bars.length).fill(null);
|
|
490
|
+
if (period < 1 || bars.length < period) return out;
|
|
491
|
+
const tr = calcTrueRange(bars);
|
|
492
|
+
let sum = 0;
|
|
493
|
+
for (let i = 0; i < period; i++) sum += tr[i];
|
|
494
|
+
let prev = sum / period;
|
|
495
|
+
out[period - 1] = prev;
|
|
496
|
+
for (let i = period; i < bars.length; i++) {
|
|
497
|
+
prev = (prev * (period - 1) + tr[i]) / period;
|
|
498
|
+
out[i] = prev;
|
|
499
|
+
}
|
|
500
|
+
return out;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Volume-weighted average price over the hlc3 typical price, anchored to
|
|
505
|
+
* each UTC day (resets at the session boundary).
|
|
506
|
+
* @param {Bar[]} bars
|
|
507
|
+
* @returns {Array<number|null>}
|
|
508
|
+
*/
|
|
509
|
+
export function calcVWAP(bars) {
|
|
510
|
+
const out = new Array(bars.length).fill(null);
|
|
511
|
+
let pv = 0;
|
|
512
|
+
let vv = 0;
|
|
513
|
+
let day = null;
|
|
514
|
+
for (let i = 0; i < bars.length; i++) {
|
|
515
|
+
const b = bars[i];
|
|
516
|
+
const ms = b.time < 1e12 ? b.time * 1000 : b.time;
|
|
517
|
+
const d = Math.floor(ms / DAY);
|
|
518
|
+
if (d !== day) {
|
|
519
|
+
day = d;
|
|
520
|
+
pv = 0;
|
|
521
|
+
vv = 0;
|
|
522
|
+
}
|
|
523
|
+
pv += ((b.high + b.low + b.close) / 3) * b.volume;
|
|
524
|
+
vv += b.volume;
|
|
525
|
+
out[i] = vv > 0 ? pv / vv : null;
|
|
526
|
+
}
|
|
527
|
+
return out;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* On-balance volume: cumulative volume signed by close-to-close direction.
|
|
532
|
+
* @param {Bar[]} bars
|
|
533
|
+
* @returns {Array<number|null>}
|
|
534
|
+
*/
|
|
535
|
+
export function calcOBV(bars) {
|
|
536
|
+
const out = new Array(bars.length).fill(null);
|
|
537
|
+
let obv = 0;
|
|
538
|
+
for (let i = 0; i < bars.length; i++) {
|
|
539
|
+
if (i > 0) {
|
|
540
|
+
const d = bars[i].close - bars[i - 1].close;
|
|
541
|
+
obv += d > 0 ? bars[i].volume : d < 0 ? -bars[i].volume : 0;
|
|
542
|
+
}
|
|
543
|
+
out[i] = obv;
|
|
544
|
+
}
|
|
545
|
+
return out;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/** Highest-high / lowest-low window ending at `i` (shared by stoch/wr/donchian). */
|
|
549
|
+
function winHL(bars, i, period) {
|
|
550
|
+
let hh = -Infinity;
|
|
551
|
+
let ll = Infinity;
|
|
552
|
+
for (let j = i - period + 1; j <= i; j++) {
|
|
553
|
+
if (bars[j].high > hh) hh = bars[j].high;
|
|
554
|
+
if (bars[j].low < ll) ll = bars[j].low;
|
|
555
|
+
}
|
|
556
|
+
return [hh, ll];
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/** SMA that tolerates leading nulls (windows over sparse raw series). */
|
|
560
|
+
function smaSparse(values, period) {
|
|
561
|
+
const out = new Array(values.length).fill(null);
|
|
562
|
+
let sum = 0;
|
|
563
|
+
let count = 0;
|
|
564
|
+
for (let i = 0; i < values.length; i++) {
|
|
565
|
+
const v = values[i];
|
|
566
|
+
if (isNum(v)) {
|
|
567
|
+
sum += v;
|
|
568
|
+
count++;
|
|
569
|
+
}
|
|
570
|
+
if (i >= period && isNum(values[i - period])) {
|
|
571
|
+
sum -= values[i - period];
|
|
572
|
+
count--;
|
|
573
|
+
}
|
|
574
|
+
if (count === period) out[i] = sum / period;
|
|
575
|
+
}
|
|
576
|
+
return out;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* Stochastic oscillator (slow): raw %K over `period`, smoothed by `smooth`;
|
|
581
|
+
* %D is the SMA of %K.
|
|
582
|
+
* @param {Bar[]} bars
|
|
583
|
+
* @param {number} period
|
|
584
|
+
* @param {number} smooth
|
|
585
|
+
* @returns {{k:Array<number|null>, d:Array<number|null>}}
|
|
586
|
+
*/
|
|
587
|
+
export function calcStoch(bars, period = 14, smooth = 3) {
|
|
588
|
+
const n = bars.length;
|
|
589
|
+
const raw = new Array(n).fill(null);
|
|
590
|
+
for (let i = period - 1; i < n; i++) {
|
|
591
|
+
const [hh, ll] = winHL(bars, i, period);
|
|
592
|
+
const span = hh - ll;
|
|
593
|
+
raw[i] = span > 0 ? ((bars[i].close - ll) / span) * 100 : null;
|
|
594
|
+
}
|
|
595
|
+
const k = smooth > 1 ? smaSparse(raw, smooth) : raw;
|
|
596
|
+
const d = smooth > 1 ? smaSparse(k, smooth) : k;
|
|
597
|
+
return { k, d };
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Commodity Channel Index: typical price vs its SMA, scaled by mean deviation.
|
|
602
|
+
* @param {Bar[]} bars
|
|
603
|
+
* @param {number} period
|
|
604
|
+
* @returns {Array<number|null>}
|
|
605
|
+
*/
|
|
606
|
+
export function calcCCI(bars, period = 20) {
|
|
607
|
+
const n = bars.length;
|
|
608
|
+
const out = new Array(n).fill(null);
|
|
609
|
+
if (period < 1 || n < period) return out;
|
|
610
|
+
const tp = bars.map((b) => (b.high + b.low + b.close) / 3);
|
|
611
|
+
const ma = calcSMA(tp, period);
|
|
612
|
+
for (let i = period - 1; i < n; i++) {
|
|
613
|
+
let md = 0;
|
|
614
|
+
for (let j = i - period + 1; j <= i; j++) md += Math.abs(tp[j] - ma[i]);
|
|
615
|
+
md /= period;
|
|
616
|
+
out[i] = md > 0 ? (tp[i] - ma[i]) / (0.015 * md) : 0;
|
|
617
|
+
}
|
|
618
|
+
return out;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Williams %R: −100 at the period low, 0 at the period high.
|
|
623
|
+
* @param {Bar[]} bars
|
|
624
|
+
* @param {number} period
|
|
625
|
+
* @returns {Array<number|null>}
|
|
626
|
+
*/
|
|
627
|
+
export function calcWilliamsR(bars, period = 14) {
|
|
628
|
+
const n = bars.length;
|
|
629
|
+
const out = new Array(n).fill(null);
|
|
630
|
+
for (let i = period - 1; i < n; i++) {
|
|
631
|
+
const [hh, ll] = winHL(bars, i, period);
|
|
632
|
+
const span = hh - ll;
|
|
633
|
+
if (span <= 0) continue;
|
|
634
|
+
const r = ((hh - bars[i].close) / span) * -100;
|
|
635
|
+
out[i] = r === 0 ? 0 : r; // avoid −0 on the axis
|
|
636
|
+
}
|
|
637
|
+
return out;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Donchian channels: highest high / lowest low over `period`, plus mid.
|
|
642
|
+
* @param {Bar[]} bars
|
|
643
|
+
* @param {number} period
|
|
644
|
+
* @returns {{upper:Array<number|null>, mid:Array<number|null>, lower:Array<number|null>}}
|
|
645
|
+
*/
|
|
646
|
+
export function calcDonchian(bars, period = 20) {
|
|
647
|
+
const n = bars.length;
|
|
648
|
+
const upper = new Array(n).fill(null);
|
|
649
|
+
const mid = new Array(n).fill(null);
|
|
650
|
+
const lower = new Array(n).fill(null);
|
|
651
|
+
for (let i = period - 1; i < n; i++) {
|
|
652
|
+
const [hh, ll] = winHL(bars, i, period);
|
|
653
|
+
upper[i] = hh;
|
|
654
|
+
lower[i] = ll;
|
|
655
|
+
mid[i] = (hh + ll) / 2;
|
|
656
|
+
}
|
|
657
|
+
return { upper, mid, lower };
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* Keltner channels: EMA mid ± mult × ATR.
|
|
662
|
+
* @param {Bar[]} bars
|
|
663
|
+
* @param {number} period
|
|
664
|
+
* @param {number} [mult]
|
|
665
|
+
* @returns {{upper:Array<number|null>, mid:Array<number|null>, lower:Array<number|null>}}
|
|
666
|
+
*/
|
|
667
|
+
export function calcKeltner(bars, period = 20, mult = 2) {
|
|
668
|
+
const mid = calcEMA(bars.map((b) => b.close), period);
|
|
669
|
+
const atr = calcATR(bars, period);
|
|
670
|
+
const band = (f) => mid.map((m, i) => (isNum(m) && isNum(atr[i]) ? f(m, atr[i]) : null));
|
|
671
|
+
return { upper: band((m, a) => m + mult * a), mid, lower: band((m, a) => m - mult * a) };
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* SuperTrend: ATR bands that flip with the trend. Returns the trend line
|
|
676
|
+
* (support in uptrends, resistance in downtrends) with a one-bar null gap
|
|
677
|
+
* at flips so the renderer breaks the line.
|
|
678
|
+
* @param {Bar[]} bars
|
|
679
|
+
* @param {number} period
|
|
680
|
+
* @param {number} [mult]
|
|
681
|
+
* @returns {Array<number|null>}
|
|
682
|
+
*/
|
|
683
|
+
export function calcSuperTrend(bars, period = 10, mult = 3) {
|
|
684
|
+
const n = bars.length;
|
|
685
|
+
const out = new Array(n).fill(null);
|
|
686
|
+
if (period < 1 || n < period) return out;
|
|
687
|
+
const atr = calcATR(bars, period);
|
|
688
|
+
let dir = 1;
|
|
689
|
+
let fUp = Infinity;
|
|
690
|
+
let fLo = -Infinity;
|
|
691
|
+
let started = false;
|
|
692
|
+
for (let i = 0; i < n; i++) {
|
|
693
|
+
if (!isNum(atr[i])) continue;
|
|
694
|
+
const b = bars[i];
|
|
695
|
+
const hl2 = (b.high + b.low) / 2;
|
|
696
|
+
const bUp = hl2 + mult * atr[i];
|
|
697
|
+
const bLo = hl2 - mult * atr[i];
|
|
698
|
+
if (!started) {
|
|
699
|
+
started = true;
|
|
700
|
+
fUp = bUp;
|
|
701
|
+
fLo = bLo;
|
|
702
|
+
dir = b.close >= hl2 ? 1 : -1;
|
|
703
|
+
out[i] = dir > 0 ? fLo : fUp;
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
const pc = bars[i - 1].close;
|
|
707
|
+
// carry a band forward unless it tightened, or the previous close broke it
|
|
708
|
+
fUp = bUp < fUp || pc > fUp ? bUp : fUp;
|
|
709
|
+
fLo = bLo > fLo || pc < fLo ? bLo : fLo;
|
|
710
|
+
const prevDir = dir;
|
|
711
|
+
if (b.close > fUp) dir = 1;
|
|
712
|
+
else if (b.close < fLo) dir = -1;
|
|
713
|
+
out[i] = dir === prevDir ? (dir > 0 ? fLo : fUp) : null;
|
|
714
|
+
}
|
|
715
|
+
return out;
|
|
716
|
+
}
|
|
717
|
+
|
|
465
718
|
/* ------------------------------------------------------------------ *
|
|
466
719
|
* Data merging & gaps
|
|
467
720
|
* ------------------------------------------------------------------ */
|
|
@@ -823,6 +1076,44 @@ export const BUILTIN_INDICATORS = new Map(
|
|
|
823
1076
|
params: { period: 50 },
|
|
824
1077
|
compute: (bars, p) => calcEMA(closesOf(bars), p.period),
|
|
825
1078
|
},
|
|
1079
|
+
vwap: {
|
|
1080
|
+
kind: 'overlay',
|
|
1081
|
+
params: {},
|
|
1082
|
+
compute: (bars) => calcVWAP(bars),
|
|
1083
|
+
},
|
|
1084
|
+
supertrend: {
|
|
1085
|
+
kind: 'overlay',
|
|
1086
|
+
params: { period: 10, mult: 3 },
|
|
1087
|
+
compute: (bars, p) => calcSuperTrend(bars, p.period, p.mult),
|
|
1088
|
+
},
|
|
1089
|
+
donchian: {
|
|
1090
|
+
kind: 'overlay',
|
|
1091
|
+
params: { period: 20 },
|
|
1092
|
+
compute: (bars, p) => {
|
|
1093
|
+
const c = calcDonchian(bars, p.period);
|
|
1094
|
+
return {
|
|
1095
|
+
lines: [
|
|
1096
|
+
{ name: 'upper', values: c.upper },
|
|
1097
|
+
{ name: 'mid', values: c.mid },
|
|
1098
|
+
{ name: 'lower', values: c.lower },
|
|
1099
|
+
],
|
|
1100
|
+
};
|
|
1101
|
+
},
|
|
1102
|
+
},
|
|
1103
|
+
keltner: {
|
|
1104
|
+
kind: 'overlay',
|
|
1105
|
+
params: { period: 20, mult: 2 },
|
|
1106
|
+
compute: (bars, p) => {
|
|
1107
|
+
const c = calcKeltner(bars, p.period, p.mult);
|
|
1108
|
+
return {
|
|
1109
|
+
lines: [
|
|
1110
|
+
{ name: 'upper', values: c.upper },
|
|
1111
|
+
{ name: 'mid', values: c.mid },
|
|
1112
|
+
{ name: 'lower', values: c.lower },
|
|
1113
|
+
],
|
|
1114
|
+
};
|
|
1115
|
+
},
|
|
1116
|
+
},
|
|
826
1117
|
bb: {
|
|
827
1118
|
kind: 'overlay',
|
|
828
1119
|
params: { period: 20, mult: 2 },
|
|
@@ -862,6 +1153,49 @@ export const BUILTIN_INDICATORS = new Map(
|
|
|
862
1153
|
};
|
|
863
1154
|
},
|
|
864
1155
|
},
|
|
1156
|
+
atr: {
|
|
1157
|
+
kind: 'pane',
|
|
1158
|
+
params: { period: 14 },
|
|
1159
|
+
fmt: 'price',
|
|
1160
|
+
compute: (bars, p) => calcATR(bars, p.period),
|
|
1161
|
+
},
|
|
1162
|
+
stoch: {
|
|
1163
|
+
kind: 'pane',
|
|
1164
|
+
params: { period: 14, smooth: 3 },
|
|
1165
|
+
guides: [20, 80],
|
|
1166
|
+
range: [0, 100],
|
|
1167
|
+
fmt: 'fixed1',
|
|
1168
|
+
compute: (bars, p) => {
|
|
1169
|
+
const r = calcStoch(bars, p.period, p.smooth);
|
|
1170
|
+
return {
|
|
1171
|
+
lines: [
|
|
1172
|
+
{ name: 'k', values: r.k },
|
|
1173
|
+
{ name: 'd', values: r.d },
|
|
1174
|
+
],
|
|
1175
|
+
};
|
|
1176
|
+
},
|
|
1177
|
+
},
|
|
1178
|
+
obv: {
|
|
1179
|
+
kind: 'pane',
|
|
1180
|
+
params: {},
|
|
1181
|
+
fmt: 'compact',
|
|
1182
|
+
compute: (bars) => calcOBV(bars),
|
|
1183
|
+
},
|
|
1184
|
+
cci: {
|
|
1185
|
+
kind: 'pane',
|
|
1186
|
+
params: { period: 20 },
|
|
1187
|
+
guides: [-100, 100],
|
|
1188
|
+
fmt: 'fixed1',
|
|
1189
|
+
compute: (bars, p) => calcCCI(bars, p.period),
|
|
1190
|
+
},
|
|
1191
|
+
wr: {
|
|
1192
|
+
kind: 'pane',
|
|
1193
|
+
params: { period: 14 },
|
|
1194
|
+
guides: [-80, -20],
|
|
1195
|
+
range: [-100, 0],
|
|
1196
|
+
fmt: 'fixed1',
|
|
1197
|
+
compute: (bars, p) => calcWilliamsR(bars, p.period),
|
|
1198
|
+
},
|
|
865
1199
|
})
|
|
866
1200
|
);
|
|
867
1201
|
|
|
@@ -977,6 +1311,10 @@ const SCRIPT_FUNCS = {
|
|
|
977
1311
|
max: { min: 2, max: 2 },
|
|
978
1312
|
crossup: { min: 2, max: 2 },
|
|
979
1313
|
crossdown: { min: 2, max: 2 },
|
|
1314
|
+
// bar-level functions — no leading series argument, they read OHLCV directly
|
|
1315
|
+
vwap: { min: 0, max: 0 },
|
|
1316
|
+
obv: { min: 0, max: 0 },
|
|
1317
|
+
atr: { min: 1, max: 1, scalar: [0] },
|
|
980
1318
|
};
|
|
981
1319
|
|
|
982
1320
|
const scriptErr = (msg) => new Error('script: ' + msg);
|
|
@@ -1219,20 +1557,20 @@ function binOp(op, a, b) {
|
|
|
1219
1557
|
return NaN;
|
|
1220
1558
|
}
|
|
1221
1559
|
|
|
1222
|
-
function evalScriptNode(node, vars, n) {
|
|
1560
|
+
function evalScriptNode(node, vars, n, bars) {
|
|
1223
1561
|
switch (node.type) {
|
|
1224
1562
|
case 'num':
|
|
1225
1563
|
return node.v;
|
|
1226
1564
|
case 'var':
|
|
1227
1565
|
return vars[node.name];
|
|
1228
1566
|
case 'neg': {
|
|
1229
|
-
const e = evalScriptNode(node.e, vars, n);
|
|
1567
|
+
const e = evalScriptNode(node.e, vars, n, bars);
|
|
1230
1568
|
if (!Array.isArray(e)) return -e;
|
|
1231
1569
|
return e.map((x) => (x == null ? NaN : -x));
|
|
1232
1570
|
}
|
|
1233
1571
|
case 'bin': {
|
|
1234
|
-
const l = evalScriptNode(node.l, vars, n);
|
|
1235
|
-
const r = evalScriptNode(node.r, vars, n);
|
|
1572
|
+
const l = evalScriptNode(node.l, vars, n, bars);
|
|
1573
|
+
const r = evalScriptNode(node.r, vars, n, bars);
|
|
1236
1574
|
if (!Array.isArray(l) && !Array.isArray(r)) return binOp(node.op, l, r);
|
|
1237
1575
|
const a = Array.isArray(l) ? l : new Array(n).fill(l);
|
|
1238
1576
|
const b = Array.isArray(r) ? r : new Array(n).fill(r);
|
|
@@ -1241,14 +1579,18 @@ function evalScriptNode(node, vars, n) {
|
|
|
1241
1579
|
return out;
|
|
1242
1580
|
}
|
|
1243
1581
|
case 'call':
|
|
1244
|
-
return evalScriptCall(node, vars, n);
|
|
1582
|
+
return evalScriptCall(node, vars, n, bars);
|
|
1245
1583
|
}
|
|
1246
1584
|
return NaN;
|
|
1247
1585
|
}
|
|
1248
1586
|
|
|
1249
|
-
function evalScriptCall(node, vars, n) {
|
|
1587
|
+
function evalScriptCall(node, vars, n, bars) {
|
|
1250
1588
|
const { name, args } = node;
|
|
1251
|
-
|
|
1589
|
+
// bar-level functions read several series at once — no leading series argument
|
|
1590
|
+
if (name === 'vwap') return calcVWAP(bars);
|
|
1591
|
+
if (name === 'obv') return calcOBV(bars);
|
|
1592
|
+
if (name === 'atr') return calcATR(bars, args[0].type === 'num' ? args[0].v : 1);
|
|
1593
|
+
const s0 = evalScriptNode(args[0], vars, n, bars);
|
|
1252
1594
|
const a = Array.isArray(s0) ? s0 : new Array(n).fill(s0);
|
|
1253
1595
|
// window functions must not read leading nulls as 0 — NaN them so results stay honest
|
|
1254
1596
|
const clean = a.map((x) => (x == null ? NaN : x));
|
|
@@ -1287,13 +1629,13 @@ function evalScriptCall(node, vars, n) {
|
|
|
1287
1629
|
case 'log': return clean.map((x) => (x <= 0 ? NaN : Math.log(x)));
|
|
1288
1630
|
case 'min':
|
|
1289
1631
|
case 'max': {
|
|
1290
|
-
const b0 = evalScriptNode(args[1], vars, n);
|
|
1632
|
+
const b0 = evalScriptNode(args[1], vars, n, bars);
|
|
1291
1633
|
const b = Array.isArray(b0) ? b0 : new Array(n).fill(b0);
|
|
1292
1634
|
return a.map((x, i) => (name === 'min' ? Math.min(scriptNum(x), scriptNum(b[i])) : Math.max(scriptNum(x), scriptNum(b[i]))));
|
|
1293
1635
|
}
|
|
1294
1636
|
case 'crossup':
|
|
1295
1637
|
case 'crossdown': {
|
|
1296
|
-
const b0 = evalScriptNode(args[1], vars, n);
|
|
1638
|
+
const b0 = evalScriptNode(args[1], vars, n, bars);
|
|
1297
1639
|
const b = Array.isArray(b0) ? b0 : new Array(n).fill(b0);
|
|
1298
1640
|
const out = new Array(n).fill(0);
|
|
1299
1641
|
for (let i = 1; i < n; i++) {
|
|
@@ -1331,7 +1673,7 @@ export function evalScript(compiled, bars) {
|
|
|
1331
1673
|
hlc3: bars.map((b) => (b.high + b.low + b.close) / 3),
|
|
1332
1674
|
ohlc4: bars.map((b) => (b.open + b.high + b.low + b.close) / 4),
|
|
1333
1675
|
};
|
|
1334
|
-
const res = evalScriptNode(c.ast, vars, n);
|
|
1676
|
+
const res = evalScriptNode(c.ast, vars, n, bars);
|
|
1335
1677
|
const arr = Array.isArray(res) ? res : new Array(n).fill(res);
|
|
1336
1678
|
for (let i = 0; i < n; i++) {
|
|
1337
1679
|
const v = arr[i];
|
|
@@ -2395,7 +2737,7 @@ export const AI_TOOLS = [
|
|
|
2395
2737
|
{
|
|
2396
2738
|
tool: 'set_indicators',
|
|
2397
2739
|
description:
|
|
2398
|
-
'Replace the indicators. Tokens: sma:20 ema:50 bb:20 vwap rsi:14 macd:12/26/9 volume, @hexcolor suffixes, or WickScript expressions like expr:{close - sma(close,20)} / pexpr:{rsi(close,14)}. Empty string clears all.',
|
|
2740
|
+
'Replace the indicators. Tokens: sma:20 ema:50 bb:20 vwap supertrend:10/3 donchian:20 keltner:20 rsi:14 macd:12/26/9 stoch:14/3 atr:14 obv cci:20 wr:14 volume, @hexcolor suffixes, or WickScript expressions like expr:{close - sma(close,20)} / pexpr:{rsi(close,14)}. Empty string clears all.',
|
|
2399
2741
|
args: { indicators: 'string — space/comma-separated tokens' },
|
|
2400
2742
|
},
|
|
2401
2743
|
{
|
package/src/wick-chart.js
CHANGED
|
@@ -2331,6 +2331,8 @@ class WickChart extends HTMLElementBase {
|
|
|
2331
2331
|
const fmtV = (v) =>
|
|
2332
2332
|
entry.def.fmt === 'fixed1'
|
|
2333
2333
|
? numberFmt(1).format(v)
|
|
2334
|
+
: entry.def.fmt === 'compact'
|
|
2335
|
+
? fmtCompact(v)
|
|
2334
2336
|
: numberFmt(this._prec(scale.rawHi || 1)).format(v);
|
|
2335
2337
|
|
|
2336
2338
|
// pane scale (fixed range or autoscaled from visible values)
|
|
@@ -2455,13 +2457,19 @@ class WickChart extends HTMLElementBase {
|
|
|
2455
2457
|
ctx.lineWidth = 1;
|
|
2456
2458
|
ctx.restore();
|
|
2457
2459
|
|
|
2458
|
-
// right-axis labels
|
|
2460
|
+
// right-axis labels: guide levels, or the pane's own min/max when
|
|
2461
|
+
// an autoscaled pane has no guides (atr / obv / pexpr)
|
|
2459
2462
|
ctx.font = axisFont(400);
|
|
2460
2463
|
ctx.fillStyle = pal.text;
|
|
2461
2464
|
ctx.textAlign = 'right';
|
|
2462
2465
|
ctx.textBaseline = 'middle';
|
|
2463
|
-
|
|
2464
|
-
|
|
2466
|
+
if ((entry.def.guides || []).length) {
|
|
2467
|
+
for (const g of entry.def.guides) {
|
|
2468
|
+
ctx.fillText(fmtV(g), W - 6, pyOf(g));
|
|
2469
|
+
}
|
|
2470
|
+
} else {
|
|
2471
|
+
ctx.fillText(fmtV(pmax), W - 6, pyOf(pmax) + 6);
|
|
2472
|
+
if (pmax !== pmin) ctx.fillText(fmtV(pmin), W - 6, pyOf(pmin) - 6);
|
|
2465
2473
|
}
|
|
2466
2474
|
|
|
2467
2475
|
// pane label + live values (script panes show their expression label)
|
|
@@ -2580,6 +2588,8 @@ class WickChart extends HTMLElementBase {
|
|
|
2580
2588
|
const fmtV =
|
|
2581
2589
|
paneUnder.entry.def.fmt === 'fixed1'
|
|
2582
2590
|
? (v) => v.toFixed(1)
|
|
2591
|
+
: paneUnder.entry.def.fmt === 'compact'
|
|
2592
|
+
? (v) => fmtCompact(v)
|
|
2583
2593
|
: (v) => f.format(v);
|
|
2584
2594
|
this._pill(
|
|
2585
2595
|
plotRight + 2,
|
package/types/core.d.ts
CHANGED
|
@@ -294,6 +294,91 @@ export declare function calcMACD(closes: number[], fast?: number, slow?: number,
|
|
|
294
294
|
signal: Array<number | null>;
|
|
295
295
|
hist: Array<number | null>;
|
|
296
296
|
};
|
|
297
|
+
/** True range: max(h−l, |h−prev close|, |l−prev close|); first bar is h−l.
|
|
298
|
+
* @param {Bar[]} bars
|
|
299
|
+
* @returns {Array<number|null>}
|
|
300
|
+
*/
|
|
301
|
+
export declare function calcTrueRange(bars: Bar[]): Array<number | null>;
|
|
302
|
+
/**
|
|
303
|
+
* Average True Range (Wilder smoothing; seeded with the SMA of the first
|
|
304
|
+
* `period` true ranges).
|
|
305
|
+
* @param {Bar[]} bars
|
|
306
|
+
* @param {number} period
|
|
307
|
+
* @returns {Array<number|null>}
|
|
308
|
+
*/
|
|
309
|
+
export declare function calcATR(bars: Bar[], period?: number): Array<number | null>;
|
|
310
|
+
/**
|
|
311
|
+
* Volume-weighted average price over the hlc3 typical price, anchored to
|
|
312
|
+
* each UTC day (resets at the session boundary).
|
|
313
|
+
* @param {Bar[]} bars
|
|
314
|
+
* @returns {Array<number|null>}
|
|
315
|
+
*/
|
|
316
|
+
export declare function calcVWAP(bars: Bar[]): Array<number | null>;
|
|
317
|
+
/**
|
|
318
|
+
* On-balance volume: cumulative volume signed by close-to-close direction.
|
|
319
|
+
* @param {Bar[]} bars
|
|
320
|
+
* @returns {Array<number|null>}
|
|
321
|
+
*/
|
|
322
|
+
export declare function calcOBV(bars: Bar[]): Array<number | null>;
|
|
323
|
+
/**
|
|
324
|
+
* Stochastic oscillator (slow): raw %K over `period`, smoothed by `smooth`;
|
|
325
|
+
* %D is the SMA of %K.
|
|
326
|
+
* @param {Bar[]} bars
|
|
327
|
+
* @param {number} period
|
|
328
|
+
* @param {number} smooth
|
|
329
|
+
* @returns {{k:Array<number|null>, d:Array<number|null>}}
|
|
330
|
+
*/
|
|
331
|
+
export declare function calcStoch(bars: Bar[], period?: number, smooth?: number): {
|
|
332
|
+
k: Array<number | null>;
|
|
333
|
+
d: Array<number | null>;
|
|
334
|
+
};
|
|
335
|
+
/**
|
|
336
|
+
* Commodity Channel Index: typical price vs its SMA, scaled by mean deviation.
|
|
337
|
+
* @param {Bar[]} bars
|
|
338
|
+
* @param {number} period
|
|
339
|
+
* @returns {Array<number|null>}
|
|
340
|
+
*/
|
|
341
|
+
export declare function calcCCI(bars: Bar[], period?: number): Array<number | null>;
|
|
342
|
+
/**
|
|
343
|
+
* Williams %R: −100 at the period low, 0 at the period high.
|
|
344
|
+
* @param {Bar[]} bars
|
|
345
|
+
* @param {number} period
|
|
346
|
+
* @returns {Array<number|null>}
|
|
347
|
+
*/
|
|
348
|
+
export declare function calcWilliamsR(bars: Bar[], period?: number): Array<number | null>;
|
|
349
|
+
/**
|
|
350
|
+
* Donchian channels: highest high / lowest low over `period`, plus mid.
|
|
351
|
+
* @param {Bar[]} bars
|
|
352
|
+
* @param {number} period
|
|
353
|
+
* @returns {{upper:Array<number|null>, mid:Array<number|null>, lower:Array<number|null>}}
|
|
354
|
+
*/
|
|
355
|
+
export declare function calcDonchian(bars: Bar[], period?: number): {
|
|
356
|
+
upper: Array<number | null>;
|
|
357
|
+
mid: Array<number | null>;
|
|
358
|
+
lower: Array<number | null>;
|
|
359
|
+
};
|
|
360
|
+
/**
|
|
361
|
+
* Keltner channels: EMA mid ± mult × ATR.
|
|
362
|
+
* @param {Bar[]} bars
|
|
363
|
+
* @param {number} period
|
|
364
|
+
* @param {number} [mult]
|
|
365
|
+
* @returns {{upper:Array<number|null>, mid:Array<number|null>, lower:Array<number|null>}}
|
|
366
|
+
*/
|
|
367
|
+
export declare function calcKeltner(bars: Bar[], period?: number, mult?: number): {
|
|
368
|
+
upper: Array<number | null>;
|
|
369
|
+
mid: Array<number | null>;
|
|
370
|
+
lower: Array<number | null>;
|
|
371
|
+
};
|
|
372
|
+
/**
|
|
373
|
+
* SuperTrend: ATR bands that flip with the trend. Returns the trend line
|
|
374
|
+
* (support in uptrends, resistance in downtrends) with a one-bar null gap
|
|
375
|
+
* at flips so the renderer breaks the line.
|
|
376
|
+
* @param {Bar[]} bars
|
|
377
|
+
* @param {number} period
|
|
378
|
+
* @param {number} [mult]
|
|
379
|
+
* @returns {Array<number|null>}
|
|
380
|
+
*/
|
|
381
|
+
export declare function calcSuperTrend(bars: Bar[], period?: number, mult?: number): Array<number | null>;
|
|
297
382
|
/**
|
|
298
383
|
* Merge older (backfilled) bars in front of `existing`.
|
|
299
384
|
* Dedupes by time (existing bars win); only strictly older bars are prepended.
|
|
@@ -435,11 +520,12 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
435
520
|
fast?: undefined;
|
|
436
521
|
slow?: undefined;
|
|
437
522
|
signal?: undefined;
|
|
523
|
+
smooth?: undefined;
|
|
438
524
|
};
|
|
439
525
|
compute: (bars: any, p: any) => number[];
|
|
440
|
-
range?: undefined;
|
|
441
526
|
color?: undefined;
|
|
442
527
|
guides?: undefined;
|
|
528
|
+
range?: undefined;
|
|
443
529
|
fmt?: undefined;
|
|
444
530
|
} | {
|
|
445
531
|
kind: string;
|
|
@@ -449,11 +535,27 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
449
535
|
fast?: undefined;
|
|
450
536
|
slow?: undefined;
|
|
451
537
|
signal?: undefined;
|
|
538
|
+
smooth?: undefined;
|
|
452
539
|
};
|
|
453
540
|
compute: (bars: any, p: any) => number[];
|
|
541
|
+
color?: undefined;
|
|
542
|
+
guides?: undefined;
|
|
454
543
|
range?: undefined;
|
|
544
|
+
fmt?: undefined;
|
|
545
|
+
} | {
|
|
546
|
+
kind: string;
|
|
547
|
+
params: {
|
|
548
|
+
mult?: undefined;
|
|
549
|
+
fast?: undefined;
|
|
550
|
+
slow?: undefined;
|
|
551
|
+
signal?: undefined;
|
|
552
|
+
smooth?: undefined;
|
|
553
|
+
period?: undefined;
|
|
554
|
+
};
|
|
555
|
+
compute: (bars: any) => number[];
|
|
455
556
|
color?: undefined;
|
|
456
557
|
guides?: undefined;
|
|
558
|
+
range?: undefined;
|
|
457
559
|
fmt?: undefined;
|
|
458
560
|
} | {
|
|
459
561
|
kind: string;
|
|
@@ -463,6 +565,22 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
463
565
|
fast?: undefined;
|
|
464
566
|
slow?: undefined;
|
|
465
567
|
signal?: undefined;
|
|
568
|
+
smooth?: undefined;
|
|
569
|
+
};
|
|
570
|
+
compute: (bars: any, p: any) => number[];
|
|
571
|
+
color?: undefined;
|
|
572
|
+
guides?: undefined;
|
|
573
|
+
range?: undefined;
|
|
574
|
+
fmt?: undefined;
|
|
575
|
+
} | {
|
|
576
|
+
kind: string;
|
|
577
|
+
params: {
|
|
578
|
+
period: number;
|
|
579
|
+
mult?: undefined;
|
|
580
|
+
fast?: undefined;
|
|
581
|
+
slow?: undefined;
|
|
582
|
+
signal?: undefined;
|
|
583
|
+
smooth?: undefined;
|
|
466
584
|
};
|
|
467
585
|
compute: (bars: any, p: any) => {
|
|
468
586
|
lines: {
|
|
@@ -470,9 +588,49 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
470
588
|
values: number[];
|
|
471
589
|
}[];
|
|
472
590
|
};
|
|
591
|
+
color?: undefined;
|
|
592
|
+
guides?: undefined;
|
|
473
593
|
range?: undefined;
|
|
594
|
+
fmt?: undefined;
|
|
595
|
+
} | {
|
|
596
|
+
kind: string;
|
|
597
|
+
params: {
|
|
598
|
+
period: number;
|
|
599
|
+
mult: number;
|
|
600
|
+
fast?: undefined;
|
|
601
|
+
slow?: undefined;
|
|
602
|
+
signal?: undefined;
|
|
603
|
+
smooth?: undefined;
|
|
604
|
+
};
|
|
605
|
+
compute: (bars: any, p: any) => {
|
|
606
|
+
lines: {
|
|
607
|
+
name: string;
|
|
608
|
+
values: number[];
|
|
609
|
+
}[];
|
|
610
|
+
};
|
|
474
611
|
color?: undefined;
|
|
475
612
|
guides?: undefined;
|
|
613
|
+
range?: undefined;
|
|
614
|
+
fmt?: undefined;
|
|
615
|
+
} | {
|
|
616
|
+
kind: string;
|
|
617
|
+
params: {
|
|
618
|
+
period: number;
|
|
619
|
+
mult: number;
|
|
620
|
+
fast?: undefined;
|
|
621
|
+
slow?: undefined;
|
|
622
|
+
signal?: undefined;
|
|
623
|
+
smooth?: undefined;
|
|
624
|
+
};
|
|
625
|
+
compute: (bars: any, p: any) => {
|
|
626
|
+
lines: {
|
|
627
|
+
name: string;
|
|
628
|
+
values: number[];
|
|
629
|
+
}[];
|
|
630
|
+
};
|
|
631
|
+
color?: undefined;
|
|
632
|
+
guides?: undefined;
|
|
633
|
+
range?: undefined;
|
|
476
634
|
fmt?: undefined;
|
|
477
635
|
} | {
|
|
478
636
|
kind: string;
|
|
@@ -482,6 +640,7 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
482
640
|
fast?: undefined;
|
|
483
641
|
slow?: undefined;
|
|
484
642
|
signal?: undefined;
|
|
643
|
+
smooth?: undefined;
|
|
485
644
|
};
|
|
486
645
|
guides: number[];
|
|
487
646
|
range: number[];
|
|
@@ -489,15 +648,15 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
489
648
|
color: string;
|
|
490
649
|
compute: (bars: any, p: any) => number[];
|
|
491
650
|
} | {
|
|
492
|
-
range?: undefined;
|
|
493
651
|
color?: undefined;
|
|
494
652
|
kind: string;
|
|
495
653
|
params: {
|
|
496
654
|
mult?: undefined;
|
|
497
|
-
period?: undefined;
|
|
498
655
|
fast: number;
|
|
499
656
|
slow: number;
|
|
500
657
|
signal: number;
|
|
658
|
+
smooth?: undefined;
|
|
659
|
+
period?: undefined;
|
|
501
660
|
};
|
|
502
661
|
guides: number[];
|
|
503
662
|
fmt: string;
|
|
@@ -508,6 +667,87 @@ export declare const BUILTIN_INDICATORS: Map<string, {
|
|
|
508
667
|
}[];
|
|
509
668
|
histogram: number[];
|
|
510
669
|
};
|
|
670
|
+
range?: undefined;
|
|
671
|
+
} | {
|
|
672
|
+
color?: undefined;
|
|
673
|
+
kind: string;
|
|
674
|
+
params: {
|
|
675
|
+
mult?: undefined;
|
|
676
|
+
fast?: undefined;
|
|
677
|
+
slow?: undefined;
|
|
678
|
+
signal?: undefined;
|
|
679
|
+
period: number;
|
|
680
|
+
smooth?: undefined;
|
|
681
|
+
};
|
|
682
|
+
fmt: string;
|
|
683
|
+
compute: (bars: any, p: any) => number[];
|
|
684
|
+
guides?: undefined;
|
|
685
|
+
range?: undefined;
|
|
686
|
+
} | {
|
|
687
|
+
color?: undefined;
|
|
688
|
+
kind: string;
|
|
689
|
+
params: {
|
|
690
|
+
mult?: undefined;
|
|
691
|
+
fast?: undefined;
|
|
692
|
+
slow?: undefined;
|
|
693
|
+
signal?: undefined;
|
|
694
|
+
period: number;
|
|
695
|
+
smooth: number;
|
|
696
|
+
};
|
|
697
|
+
guides: number[];
|
|
698
|
+
range: number[];
|
|
699
|
+
fmt: string;
|
|
700
|
+
compute: (bars: any, p: any) => {
|
|
701
|
+
lines: {
|
|
702
|
+
name: string;
|
|
703
|
+
values: number[];
|
|
704
|
+
}[];
|
|
705
|
+
};
|
|
706
|
+
} | {
|
|
707
|
+
color?: undefined;
|
|
708
|
+
kind: string;
|
|
709
|
+
params: {
|
|
710
|
+
mult?: undefined;
|
|
711
|
+
fast?: undefined;
|
|
712
|
+
slow?: undefined;
|
|
713
|
+
signal?: undefined;
|
|
714
|
+
smooth?: undefined;
|
|
715
|
+
period?: undefined;
|
|
716
|
+
};
|
|
717
|
+
fmt: string;
|
|
718
|
+
compute: (bars: any) => number[];
|
|
719
|
+
guides?: undefined;
|
|
720
|
+
range?: undefined;
|
|
721
|
+
} | {
|
|
722
|
+
color?: undefined;
|
|
723
|
+
kind: string;
|
|
724
|
+
params: {
|
|
725
|
+
mult?: undefined;
|
|
726
|
+
fast?: undefined;
|
|
727
|
+
slow?: undefined;
|
|
728
|
+
signal?: undefined;
|
|
729
|
+
smooth?: undefined;
|
|
730
|
+
period: number;
|
|
731
|
+
};
|
|
732
|
+
guides: number[];
|
|
733
|
+
fmt: string;
|
|
734
|
+
compute: (bars: any, p: any) => number[];
|
|
735
|
+
range?: undefined;
|
|
736
|
+
} | {
|
|
737
|
+
color?: undefined;
|
|
738
|
+
kind: string;
|
|
739
|
+
params: {
|
|
740
|
+
mult?: undefined;
|
|
741
|
+
fast?: undefined;
|
|
742
|
+
slow?: undefined;
|
|
743
|
+
signal?: undefined;
|
|
744
|
+
smooth?: undefined;
|
|
745
|
+
period: number;
|
|
746
|
+
};
|
|
747
|
+
guides: number[];
|
|
748
|
+
range: number[];
|
|
749
|
+
fmt: string;
|
|
750
|
+
compute: (bars: any, p: any) => number[];
|
|
511
751
|
}>;
|
|
512
752
|
/**
|
|
513
753
|
* Parse an `indicators` attribute string against a registry.
|
package/types/wick-chart.d.ts
CHANGED
|
@@ -246,11 +246,12 @@ declare class WickChart extends HTMLElementBase {
|
|
|
246
246
|
fast?: undefined;
|
|
247
247
|
slow?: undefined;
|
|
248
248
|
signal?: undefined;
|
|
249
|
+
smooth?: undefined;
|
|
249
250
|
};
|
|
250
251
|
compute: (bars: any, p: any) => number[];
|
|
251
|
-
range?: undefined;
|
|
252
252
|
color?: undefined;
|
|
253
253
|
guides?: undefined;
|
|
254
|
+
range?: undefined;
|
|
254
255
|
fmt?: undefined;
|
|
255
256
|
} | {
|
|
256
257
|
kind: string;
|
|
@@ -260,11 +261,27 @@ declare class WickChart extends HTMLElementBase {
|
|
|
260
261
|
fast?: undefined;
|
|
261
262
|
slow?: undefined;
|
|
262
263
|
signal?: undefined;
|
|
264
|
+
smooth?: undefined;
|
|
263
265
|
};
|
|
264
266
|
compute: (bars: any, p: any) => number[];
|
|
267
|
+
color?: undefined;
|
|
268
|
+
guides?: undefined;
|
|
265
269
|
range?: undefined;
|
|
270
|
+
fmt?: undefined;
|
|
271
|
+
} | {
|
|
272
|
+
kind: string;
|
|
273
|
+
params: {
|
|
274
|
+
mult?: undefined;
|
|
275
|
+
fast?: undefined;
|
|
276
|
+
slow?: undefined;
|
|
277
|
+
signal?: undefined;
|
|
278
|
+
smooth?: undefined;
|
|
279
|
+
period?: undefined;
|
|
280
|
+
};
|
|
281
|
+
compute: (bars: any) => number[];
|
|
266
282
|
color?: undefined;
|
|
267
283
|
guides?: undefined;
|
|
284
|
+
range?: undefined;
|
|
268
285
|
fmt?: undefined;
|
|
269
286
|
} | {
|
|
270
287
|
kind: string;
|
|
@@ -274,6 +291,22 @@ declare class WickChart extends HTMLElementBase {
|
|
|
274
291
|
fast?: undefined;
|
|
275
292
|
slow?: undefined;
|
|
276
293
|
signal?: undefined;
|
|
294
|
+
smooth?: undefined;
|
|
295
|
+
};
|
|
296
|
+
compute: (bars: any, p: any) => number[];
|
|
297
|
+
color?: undefined;
|
|
298
|
+
guides?: undefined;
|
|
299
|
+
range?: undefined;
|
|
300
|
+
fmt?: undefined;
|
|
301
|
+
} | {
|
|
302
|
+
kind: string;
|
|
303
|
+
params: {
|
|
304
|
+
period: number;
|
|
305
|
+
mult?: undefined;
|
|
306
|
+
fast?: undefined;
|
|
307
|
+
slow?: undefined;
|
|
308
|
+
signal?: undefined;
|
|
309
|
+
smooth?: undefined;
|
|
277
310
|
};
|
|
278
311
|
compute: (bars: any, p: any) => {
|
|
279
312
|
lines: {
|
|
@@ -281,9 +314,49 @@ declare class WickChart extends HTMLElementBase {
|
|
|
281
314
|
values: number[];
|
|
282
315
|
}[];
|
|
283
316
|
};
|
|
317
|
+
color?: undefined;
|
|
318
|
+
guides?: undefined;
|
|
284
319
|
range?: undefined;
|
|
320
|
+
fmt?: undefined;
|
|
321
|
+
} | {
|
|
322
|
+
kind: string;
|
|
323
|
+
params: {
|
|
324
|
+
period: number;
|
|
325
|
+
mult: number;
|
|
326
|
+
fast?: undefined;
|
|
327
|
+
slow?: undefined;
|
|
328
|
+
signal?: undefined;
|
|
329
|
+
smooth?: undefined;
|
|
330
|
+
};
|
|
331
|
+
compute: (bars: any, p: any) => {
|
|
332
|
+
lines: {
|
|
333
|
+
name: string;
|
|
334
|
+
values: number[];
|
|
335
|
+
}[];
|
|
336
|
+
};
|
|
337
|
+
color?: undefined;
|
|
338
|
+
guides?: undefined;
|
|
339
|
+
range?: undefined;
|
|
340
|
+
fmt?: undefined;
|
|
341
|
+
} | {
|
|
342
|
+
kind: string;
|
|
343
|
+
params: {
|
|
344
|
+
period: number;
|
|
345
|
+
mult: number;
|
|
346
|
+
fast?: undefined;
|
|
347
|
+
slow?: undefined;
|
|
348
|
+
signal?: undefined;
|
|
349
|
+
smooth?: undefined;
|
|
350
|
+
};
|
|
351
|
+
compute: (bars: any, p: any) => {
|
|
352
|
+
lines: {
|
|
353
|
+
name: string;
|
|
354
|
+
values: number[];
|
|
355
|
+
}[];
|
|
356
|
+
};
|
|
285
357
|
color?: undefined;
|
|
286
358
|
guides?: undefined;
|
|
359
|
+
range?: undefined;
|
|
287
360
|
fmt?: undefined;
|
|
288
361
|
} | {
|
|
289
362
|
kind: string;
|
|
@@ -293,6 +366,7 @@ declare class WickChart extends HTMLElementBase {
|
|
|
293
366
|
fast?: undefined;
|
|
294
367
|
slow?: undefined;
|
|
295
368
|
signal?: undefined;
|
|
369
|
+
smooth?: undefined;
|
|
296
370
|
};
|
|
297
371
|
guides: number[];
|
|
298
372
|
range: number[];
|
|
@@ -300,15 +374,15 @@ declare class WickChart extends HTMLElementBase {
|
|
|
300
374
|
color: string;
|
|
301
375
|
compute: (bars: any, p: any) => number[];
|
|
302
376
|
} | {
|
|
303
|
-
range?: undefined;
|
|
304
377
|
color?: undefined;
|
|
305
378
|
kind: string;
|
|
306
379
|
params: {
|
|
307
380
|
mult?: undefined;
|
|
308
|
-
period?: undefined;
|
|
309
381
|
fast: number;
|
|
310
382
|
slow: number;
|
|
311
383
|
signal: number;
|
|
384
|
+
smooth?: undefined;
|
|
385
|
+
period?: undefined;
|
|
312
386
|
};
|
|
313
387
|
guides: number[];
|
|
314
388
|
fmt: string;
|
|
@@ -319,6 +393,87 @@ declare class WickChart extends HTMLElementBase {
|
|
|
319
393
|
}[];
|
|
320
394
|
histogram: number[];
|
|
321
395
|
};
|
|
396
|
+
range?: undefined;
|
|
397
|
+
} | {
|
|
398
|
+
color?: undefined;
|
|
399
|
+
kind: string;
|
|
400
|
+
params: {
|
|
401
|
+
mult?: undefined;
|
|
402
|
+
fast?: undefined;
|
|
403
|
+
slow?: undefined;
|
|
404
|
+
signal?: undefined;
|
|
405
|
+
period: number;
|
|
406
|
+
smooth?: undefined;
|
|
407
|
+
};
|
|
408
|
+
fmt: string;
|
|
409
|
+
compute: (bars: any, p: any) => number[];
|
|
410
|
+
guides?: undefined;
|
|
411
|
+
range?: undefined;
|
|
412
|
+
} | {
|
|
413
|
+
color?: undefined;
|
|
414
|
+
kind: string;
|
|
415
|
+
params: {
|
|
416
|
+
mult?: undefined;
|
|
417
|
+
fast?: undefined;
|
|
418
|
+
slow?: undefined;
|
|
419
|
+
signal?: undefined;
|
|
420
|
+
period: number;
|
|
421
|
+
smooth: number;
|
|
422
|
+
};
|
|
423
|
+
guides: number[];
|
|
424
|
+
range: number[];
|
|
425
|
+
fmt: string;
|
|
426
|
+
compute: (bars: any, p: any) => {
|
|
427
|
+
lines: {
|
|
428
|
+
name: string;
|
|
429
|
+
values: number[];
|
|
430
|
+
}[];
|
|
431
|
+
};
|
|
432
|
+
} | {
|
|
433
|
+
color?: undefined;
|
|
434
|
+
kind: string;
|
|
435
|
+
params: {
|
|
436
|
+
mult?: undefined;
|
|
437
|
+
fast?: undefined;
|
|
438
|
+
slow?: undefined;
|
|
439
|
+
signal?: undefined;
|
|
440
|
+
smooth?: undefined;
|
|
441
|
+
period?: undefined;
|
|
442
|
+
};
|
|
443
|
+
fmt: string;
|
|
444
|
+
compute: (bars: any) => number[];
|
|
445
|
+
guides?: undefined;
|
|
446
|
+
range?: undefined;
|
|
447
|
+
} | {
|
|
448
|
+
color?: undefined;
|
|
449
|
+
kind: string;
|
|
450
|
+
params: {
|
|
451
|
+
mult?: undefined;
|
|
452
|
+
fast?: undefined;
|
|
453
|
+
slow?: undefined;
|
|
454
|
+
signal?: undefined;
|
|
455
|
+
smooth?: undefined;
|
|
456
|
+
period: number;
|
|
457
|
+
};
|
|
458
|
+
guides: number[];
|
|
459
|
+
fmt: string;
|
|
460
|
+
compute: (bars: any, p: any) => number[];
|
|
461
|
+
range?: undefined;
|
|
462
|
+
} | {
|
|
463
|
+
color?: undefined;
|
|
464
|
+
kind: string;
|
|
465
|
+
params: {
|
|
466
|
+
mult?: undefined;
|
|
467
|
+
fast?: undefined;
|
|
468
|
+
slow?: undefined;
|
|
469
|
+
signal?: undefined;
|
|
470
|
+
smooth?: undefined;
|
|
471
|
+
period: number;
|
|
472
|
+
};
|
|
473
|
+
guides: number[];
|
|
474
|
+
range: number[];
|
|
475
|
+
fmt: string;
|
|
476
|
+
compute: (bars: any, p: any) => number[];
|
|
322
477
|
}>;
|
|
323
478
|
/**
|
|
324
479
|
* Register a custom indicator.
|