wickchart 1.3.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 +83 -5
- package/package.json +11 -4
- package/src/core.js +353 -11
- package/src/wick-chart.js +257 -3
- package/types/core.d.ts +243 -3
- package/types/wick-chart.d.ts +233 -3
package/src/wick-chart.js
CHANGED
|
@@ -235,6 +235,11 @@ class WickChart extends HTMLElementBase {
|
|
|
235
235
|
this._pan = null;
|
|
236
236
|
this._pinch = null;
|
|
237
237
|
|
|
238
|
+
// plugin layers: external draw hooks + pointer claims (see addLayer)
|
|
239
|
+
this._layers = [];
|
|
240
|
+
this._layerClaim = null; // { layer, pointerId } while a layer owns a drag
|
|
241
|
+
this._layerSeq = 0;
|
|
242
|
+
|
|
238
243
|
// history backfill state (onloadmore declared as a class field above)
|
|
239
244
|
this._loadingMore = false;
|
|
240
245
|
this._noMore = false;
|
|
@@ -303,6 +308,7 @@ class WickChart extends HTMLElementBase {
|
|
|
303
308
|
this._connected = false;
|
|
304
309
|
this.stopWalk(true);
|
|
305
310
|
this.stopStory(true);
|
|
311
|
+
this._layerClaim = null;
|
|
306
312
|
if (this._coviewCh) {
|
|
307
313
|
this._coviewSend({ type: 'bye' });
|
|
308
314
|
try {
|
|
@@ -2325,6 +2331,8 @@ class WickChart extends HTMLElementBase {
|
|
|
2325
2331
|
const fmtV = (v) =>
|
|
2326
2332
|
entry.def.fmt === 'fixed1'
|
|
2327
2333
|
? numberFmt(1).format(v)
|
|
2334
|
+
: entry.def.fmt === 'compact'
|
|
2335
|
+
? fmtCompact(v)
|
|
2328
2336
|
: numberFmt(this._prec(scale.rawHi || 1)).format(v);
|
|
2329
2337
|
|
|
2330
2338
|
// pane scale (fixed range or autoscaled from visible values)
|
|
@@ -2449,13 +2457,19 @@ class WickChart extends HTMLElementBase {
|
|
|
2449
2457
|
ctx.lineWidth = 1;
|
|
2450
2458
|
ctx.restore();
|
|
2451
2459
|
|
|
2452
|
-
// 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)
|
|
2453
2462
|
ctx.font = axisFont(400);
|
|
2454
2463
|
ctx.fillStyle = pal.text;
|
|
2455
2464
|
ctx.textAlign = 'right';
|
|
2456
2465
|
ctx.textBaseline = 'middle';
|
|
2457
|
-
|
|
2458
|
-
|
|
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);
|
|
2459
2473
|
}
|
|
2460
2474
|
|
|
2461
2475
|
// pane label + live values (script panes show their expression label)
|
|
@@ -2532,6 +2546,9 @@ class WickChart extends HTMLElementBase {
|
|
|
2532
2546
|
);
|
|
2533
2547
|
}
|
|
2534
2548
|
|
|
2549
|
+
/* plugin layers — above chart content, under the pointer-following UI */
|
|
2550
|
+
if (this._layers.length) this._drawLayers(ctx, pal, ly, d);
|
|
2551
|
+
|
|
2535
2552
|
/* crosshair */
|
|
2536
2553
|
if (this._hover && this._hover.index < d.length) {
|
|
2537
2554
|
const h = this._hover;
|
|
@@ -2571,6 +2588,8 @@ class WickChart extends HTMLElementBase {
|
|
|
2571
2588
|
const fmtV =
|
|
2572
2589
|
paneUnder.entry.def.fmt === 'fixed1'
|
|
2573
2590
|
? (v) => v.toFixed(1)
|
|
2591
|
+
: paneUnder.entry.def.fmt === 'compact'
|
|
2592
|
+
? (v) => fmtCompact(v)
|
|
2574
2593
|
: (v) => f.format(v);
|
|
2575
2594
|
this._pill(
|
|
2576
2595
|
plotRight + 2,
|
|
@@ -2912,6 +2931,207 @@ class WickChart extends HTMLElementBase {
|
|
|
2912
2931
|
poss.innerHTML = html;
|
|
2913
2932
|
}
|
|
2914
2933
|
|
|
2934
|
+
/* ------------------------------------------------------------ *
|
|
2935
|
+
* Plugin layers — external draw hooks + pointer claims
|
|
2936
|
+
* ------------------------------------------------------------ */
|
|
2937
|
+
|
|
2938
|
+
/**
|
|
2939
|
+
* Register a plugin layer. `layer.draw(api)` runs on every render, above
|
|
2940
|
+
* chart content and under the crosshair; `layer.onPointer(pev)` is asked
|
|
2941
|
+
* first on pointerdown and claims the gesture by returning true — the
|
|
2942
|
+
* layer then receives that pointer's move/up/cancel events (plus a
|
|
2943
|
+
* 'cancel' on Escape) and the chart suppresses its own pan/measure/brush
|
|
2944
|
+
* for the duration.
|
|
2945
|
+
* @param {{id?: string, draw: Function, onPointer?: Function}} layer
|
|
2946
|
+
* @returns {object|null} the normalized layer handle (with `id`), or null
|
|
2947
|
+
* if the layer was rejected (no draw fn, or 16 layers already added)
|
|
2948
|
+
*/
|
|
2949
|
+
addLayer(layer) {
|
|
2950
|
+
if (!layer || typeof layer !== 'object' || typeof layer.draw !== 'function') return null;
|
|
2951
|
+
if (this._layers.length >= 16) return null;
|
|
2952
|
+
const id =
|
|
2953
|
+
layer.id != null && String(layer.id).trim()
|
|
2954
|
+
? String(layer.id).slice(0, 64)
|
|
2955
|
+
: 'layer-' + ++this._layerSeq;
|
|
2956
|
+
const entry = {
|
|
2957
|
+
id,
|
|
2958
|
+
draw: layer.draw,
|
|
2959
|
+
onPointer: typeof layer.onPointer === 'function' ? layer.onPointer : null,
|
|
2960
|
+
};
|
|
2961
|
+
const at = this._layers.findIndex((l) => l.id === id);
|
|
2962
|
+
if (at >= 0) this._layers[at] = entry; // same id replaces
|
|
2963
|
+
else this._layers.push(entry);
|
|
2964
|
+
this._invalidate();
|
|
2965
|
+
return entry;
|
|
2966
|
+
}
|
|
2967
|
+
|
|
2968
|
+
/**
|
|
2969
|
+
* Remove a layer added via addLayer (pass the returned handle or its id).
|
|
2970
|
+
* @param {object|string} idOrLayer
|
|
2971
|
+
* @returns {boolean} true if a layer was removed
|
|
2972
|
+
*/
|
|
2973
|
+
removeLayer(idOrLayer) {
|
|
2974
|
+
const id = idOrLayer != null && typeof idOrLayer === 'object' ? idOrLayer.id : idOrLayer;
|
|
2975
|
+
if (id == null) return false;
|
|
2976
|
+
const at = this._layers.findIndex((l) => l.id === String(id));
|
|
2977
|
+
if (at < 0) return false;
|
|
2978
|
+
const [gone] = this._layers.splice(at, 1);
|
|
2979
|
+
if (this._layerClaim && this._layerClaim.layer === gone) this._layerClaim = null;
|
|
2980
|
+
this._invalidate();
|
|
2981
|
+
return true;
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
/** Ask for a repaint on the next frame (interactive layers call this). */
|
|
2985
|
+
requestDraw() {
|
|
2986
|
+
this._invalidate();
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
/** Paint every registered layer. Called from _render with live state. */
|
|
2990
|
+
_drawLayers(ctx, pal, ly, d) {
|
|
2991
|
+
for (const layer of this._layers) {
|
|
2992
|
+
try {
|
|
2993
|
+
layer.draw({
|
|
2994
|
+
ctx, // 2D context, already DPR-scaled — draw in CSS pixels
|
|
2995
|
+
layout: ly,
|
|
2996
|
+
palette: pal,
|
|
2997
|
+
data: d,
|
|
2998
|
+
view: this._view,
|
|
2999
|
+
timeToX: (t) => this.timeToX(t),
|
|
3000
|
+
xToTime: (x) => this.xToTime(x),
|
|
3001
|
+
priceToY: (p) => this.priceToY(p),
|
|
3002
|
+
yToPrice: (y) => this.yToPrice(y),
|
|
3003
|
+
});
|
|
3004
|
+
} catch (err) {
|
|
3005
|
+
console.warn('wick-chart: layer "' + layer.id + '" threw in draw', err);
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
/** Ask layers, in order, whether one claims this pointerdown. */
|
|
3011
|
+
_layerHit(e, pt) {
|
|
3012
|
+
for (const layer of this._layers) {
|
|
3013
|
+
if (!layer.onPointer) continue;
|
|
3014
|
+
let claimed = false;
|
|
3015
|
+
try {
|
|
3016
|
+
claimed = layer.onPointer(this._layerPointerEvent(e, pt, 'down')) === true;
|
|
3017
|
+
} catch (err) {
|
|
3018
|
+
console.warn('wick-chart: layer "' + layer.id + '" threw in onPointer', err);
|
|
3019
|
+
}
|
|
3020
|
+
if (claimed) return layer;
|
|
3021
|
+
}
|
|
3022
|
+
return null;
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
/** Deliver a pointer event to a claiming layer; never throws outward. */
|
|
3026
|
+
_routeLayer(layer, e, pt, type) {
|
|
3027
|
+
const ev = pt
|
|
3028
|
+
? this._layerPointerEvent(e, pt, type)
|
|
3029
|
+
: {
|
|
3030
|
+
type,
|
|
3031
|
+
x: null,
|
|
3032
|
+
y: null,
|
|
3033
|
+
pointerId: e.pointerId == null ? 0 : e.pointerId,
|
|
3034
|
+
button: 0,
|
|
3035
|
+
shiftKey: !!e.shiftKey,
|
|
3036
|
+
ctrlKey: !!e.ctrlKey,
|
|
3037
|
+
altKey: !!e.altKey,
|
|
3038
|
+
metaKey: !!e.metaKey,
|
|
3039
|
+
};
|
|
3040
|
+
try {
|
|
3041
|
+
if (layer.onPointer) layer.onPointer(ev);
|
|
3042
|
+
} catch (err) {
|
|
3043
|
+
console.warn('wick-chart: layer "' + layer.id + '" threw in onPointer', err);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
|
|
3047
|
+
_layerPointerEvent(e, pt, type) {
|
|
3048
|
+
return {
|
|
3049
|
+
type,
|
|
3050
|
+
x: pt.x,
|
|
3051
|
+
y: pt.y,
|
|
3052
|
+
pointerId: e.pointerId,
|
|
3053
|
+
button: e.button == null ? 0 : e.button,
|
|
3054
|
+
shiftKey: !!e.shiftKey,
|
|
3055
|
+
ctrlKey: !!e.ctrlKey,
|
|
3056
|
+
altKey: !!e.altKey,
|
|
3057
|
+
metaKey: !!e.metaKey,
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
|
|
3061
|
+
/**
|
|
3062
|
+
* x-pixel for a bar time (ms or s, auto-detected). Extrapolates past the
|
|
3063
|
+
* last bar into future space using the median bar interval, so layers can
|
|
3064
|
+
* anchor trendlines to tomorrow, not just to history.
|
|
3065
|
+
* @param {number} time
|
|
3066
|
+
* @returns {number|null}
|
|
3067
|
+
*/
|
|
3068
|
+
timeToX(time) {
|
|
3069
|
+
const ly = this._ly;
|
|
3070
|
+
const d = this._data;
|
|
3071
|
+
if (!ly || !d.length || !isNum(time)) return null;
|
|
3072
|
+
const t = time < 1e12 ? time * 1000 : time;
|
|
3073
|
+
const last = d.length - 1;
|
|
3074
|
+
if (t >= d[last].time) {
|
|
3075
|
+
return this._xFor(last + (t - d[last].time) / (this._dt || HOUR));
|
|
3076
|
+
}
|
|
3077
|
+
const i = WickChart._indexForTime(d, t);
|
|
3078
|
+
if (i === 0 && t < d[0].time) {
|
|
3079
|
+
return this._xFor((t - d[0].time) / (this._dt || HOUR));
|
|
3080
|
+
}
|
|
3081
|
+
if (i > 0 && t < d[i].time) {
|
|
3082
|
+
// between two bars: fractional index
|
|
3083
|
+
const a = d[i - 1];
|
|
3084
|
+
const b = d[i];
|
|
3085
|
+
return this._xFor(i - 1 + (t - a.time) / (b.time - a.time || 1));
|
|
3086
|
+
}
|
|
3087
|
+
return this._xFor(i);
|
|
3088
|
+
}
|
|
3089
|
+
|
|
3090
|
+
/**
|
|
3091
|
+
* Bar time (ms) at an x-pixel — the inverse of timeToX, interpolating
|
|
3092
|
+
* between bars and extrapolating beyond both data edges.
|
|
3093
|
+
* @param {number} x
|
|
3094
|
+
* @returns {number|null}
|
|
3095
|
+
*/
|
|
3096
|
+
xToTime(x) {
|
|
3097
|
+
const ly = this._ly;
|
|
3098
|
+
const d = this._data;
|
|
3099
|
+
if (!ly || !d.length || !isNum(x)) return null;
|
|
3100
|
+
const idx = this._indexForX(x);
|
|
3101
|
+
const last = d.length - 1;
|
|
3102
|
+
if (idx >= last) return d[last].time + (idx - last) * (this._dt || HOUR);
|
|
3103
|
+
if (idx <= 0) return d[0].time + idx * (this._dt || HOUR);
|
|
3104
|
+
const i0 = Math.floor(idx);
|
|
3105
|
+
const a = d[i0];
|
|
3106
|
+
const b = d[Math.min(i0 + 1, last)];
|
|
3107
|
+
return a.time + (b.time - a.time) * (idx - i0);
|
|
3108
|
+
}
|
|
3109
|
+
|
|
3110
|
+
/**
|
|
3111
|
+
* y-pixel for a price in the main pane (current scale; log-aware).
|
|
3112
|
+
* Unclamped — values off-screen still map, layers decide how to clip.
|
|
3113
|
+
* @param {number} price
|
|
3114
|
+
* @returns {number|null}
|
|
3115
|
+
*/
|
|
3116
|
+
priceToY(price) {
|
|
3117
|
+
const ly = this._ly;
|
|
3118
|
+
const scale = this._lastScale;
|
|
3119
|
+
if (!ly || !scale || !isNum(price)) return null;
|
|
3120
|
+
const { min, max, useLog } = scale;
|
|
3121
|
+
const v = useLog ? Math.log10(Math.max(price, 1e-12)) : price;
|
|
3122
|
+
return ly.main.y0 + ((max - v) / (max - min)) * ly.main.h;
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
/**
|
|
3126
|
+
* Price at a y-pixel in the main pane — the inverse of priceToY.
|
|
3127
|
+
* @param {number} y
|
|
3128
|
+
* @returns {number|null}
|
|
3129
|
+
*/
|
|
3130
|
+
yToPrice(y) {
|
|
3131
|
+
if (!isNum(y)) return null;
|
|
3132
|
+
return this._yToPrice(y);
|
|
3133
|
+
}
|
|
3134
|
+
|
|
2915
3135
|
/* ------------------------------------------------------------ *
|
|
2916
3136
|
* Interaction
|
|
2917
3137
|
* ------------------------------------------------------------ */
|
|
@@ -2927,6 +3147,19 @@ class WickChart extends HTMLElementBase {
|
|
|
2927
3147
|
this._canvas.setPointerCapture(e.pointerId);
|
|
2928
3148
|
const pt = this._localPoint(e);
|
|
2929
3149
|
this._pointers.set(e.pointerId, pt);
|
|
3150
|
+
if (this._layerClaim) return; // a layer owns a gesture: extra pointers are inert
|
|
3151
|
+
if (this._layers.length) {
|
|
3152
|
+
// layers get first claim on the pointer (hit-test their content);
|
|
3153
|
+
// a claim suppresses pinch/measure/brush/pan for this gesture
|
|
3154
|
+
const layer = this._layerHit(e, pt);
|
|
3155
|
+
if (layer) {
|
|
3156
|
+
this._pan = null;
|
|
3157
|
+
this._measuring = false;
|
|
3158
|
+
this._brushDrag = null;
|
|
3159
|
+
this._layerClaim = { layer, pointerId: e.pointerId };
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
}
|
|
2930
3163
|
if (this._pointers.size === 2) {
|
|
2931
3164
|
const [a, b] = [...this._pointers.values()];
|
|
2932
3165
|
const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
|
|
@@ -2967,6 +3200,12 @@ class WickChart extends HTMLElementBase {
|
|
|
2967
3200
|
}
|
|
2968
3201
|
|
|
2969
3202
|
_pointerMove(e) {
|
|
3203
|
+
if (this._layerClaim) {
|
|
3204
|
+
if (this._layerClaim.pointerId === e.pointerId) {
|
|
3205
|
+
this._routeLayer(this._layerClaim.layer, e, this._localPoint(e), 'move');
|
|
3206
|
+
}
|
|
3207
|
+
return; // inert while a layer owns the gesture
|
|
3208
|
+
}
|
|
2970
3209
|
const pt = this._localPoint(e);
|
|
2971
3210
|
if (this._pointers.has(e.pointerId)) this._pointers.set(e.pointerId, pt);
|
|
2972
3211
|
const ly = this._ly;
|
|
@@ -3026,6 +3265,14 @@ class WickChart extends HTMLElementBase {
|
|
|
3026
3265
|
}
|
|
3027
3266
|
|
|
3028
3267
|
_pointerUp(e) {
|
|
3268
|
+
const claim = this._layerClaim;
|
|
3269
|
+
if (claim && claim.pointerId === e.pointerId) {
|
|
3270
|
+
this._layerClaim = null;
|
|
3271
|
+
this._pointers.delete(e.pointerId);
|
|
3272
|
+
this._canvas.classList.remove('grabbing');
|
|
3273
|
+
this._routeLayer(claim.layer, e, this._localPoint(e), e.type === 'pointercancel' ? 'cancel' : 'up');
|
|
3274
|
+
return;
|
|
3275
|
+
}
|
|
3029
3276
|
const had = this._pointers.delete(e.pointerId);
|
|
3030
3277
|
if (this._pointers.size < 2) this._pinch = null;
|
|
3031
3278
|
if (this._pointers.size === 0) {
|
|
@@ -3113,6 +3360,13 @@ class WickChart extends HTMLElementBase {
|
|
|
3113
3360
|
const ly = this._ly;
|
|
3114
3361
|
if (!ly || !this._data.length) return;
|
|
3115
3362
|
this._stopPlayback();
|
|
3363
|
+
if (e.key === 'Escape' && this._layerClaim) {
|
|
3364
|
+
const claim = this._layerClaim;
|
|
3365
|
+
this._layerClaim = null;
|
|
3366
|
+
this._routeLayer(claim.layer, { pointerId: claim.pointerId }, null, 'cancel');
|
|
3367
|
+
this._invalidate();
|
|
3368
|
+
return;
|
|
3369
|
+
}
|
|
3116
3370
|
if (e.key === 'Escape' && (this._brushSel || this._brushDrag)) {
|
|
3117
3371
|
this.clearBrush();
|
|
3118
3372
|
return;
|
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.
|