wickchart 0.3.0 → 1.0.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.
@@ -1,10 +1,10 @@
1
1
  /* ==========================================================================
2
- * <hab-feed> — declarative data feeds for <hab-chart>.
2
+ * <wick-feed> — declarative data feeds for <wick-chart>.
3
3
  *
4
- * <script type="module" src="https://unpkg.com/hab-view/feed"></script>
4
+ * <script type="module" src="https://unpkg.com/wickchart/feed"></script>
5
5
  *
6
- * <hab-feed for="chart" binance="BTCUSDT" tf="1h"></hab-feed>
7
- * <hab-chart id="chart" indicators="sma:20 volume"></hab-chart>
6
+ * <wick-feed for="chart" binance="BTCUSDT" tf="1h"></wick-feed>
7
+ * <wick-chart id="chart" indicators="sma:20 volume"></wick-chart>
8
8
  *
9
9
  * A fully live chart with zero JavaScript written. Sources:
10
10
  * binance="SYMBOL" live via WebSocket (REST klines + backfill; falls back
@@ -17,11 +17,12 @@
17
17
  * Attributes: for (chart id; auto-pairs with the first chart otherwise),
18
18
  * tf (1m…1w), limit (initial bars, default 500), live="false" to disable
19
19
  * streaming. Status is reflected in the `status` attribute and via
20
- * `hab-feed:status` events (loading / live / polling / fallback / loaded /
21
- * waiting / idle). `hab-feed:fallback` fires when a live source degrades.
20
+ * `wick-feed:status` events (loading / live / polling / fallback / loaded /
21
+ * waiting / idle). `wick-feed:fallback` fires when a live source degrades.
22
+ * (The 0.x event names `hab-feed:*` still fire as deprecated aliases.)
22
23
  * ========================================================================== */
23
24
 
24
- import './hab-chart.js';
25
+ import './wick-chart.js';
25
26
  import {
26
27
  genSynthetic,
27
28
  makeSynthStream,
@@ -35,7 +36,7 @@ const LIVE_TICK_MS = 650;
35
36
 
36
37
  const HTMLElementBase = typeof HTMLElement !== 'undefined' ? HTMLElement : class {};
37
38
 
38
- class HabFeed extends HTMLElementBase {
39
+ class WickFeed extends HTMLElementBase {
39
40
  static get observedAttributes() {
40
41
  return ['for', 'binance', 'demo', 'url', 'tf', 'limit', 'poll', 'live'];
41
42
  }
@@ -86,17 +87,24 @@ class HabFeed extends HTMLElementBase {
86
87
  _setStatus(status, detail) {
87
88
  if (!this.isConnected) return;
88
89
  this.setAttribute('status', status);
89
- this.dispatchEvent(new CustomEvent('hab-feed:status', { detail: { status, ...detail } }));
90
+ this._fire('status', { status, ...detail });
90
91
  }
91
92
 
92
- /** Resolve the target chart (by `for` id, else the first <hab-chart>). */
93
+ /** Dispatch `wick-feed:name` plus the deprecated `hab-feed:name` alias. */
94
+ _fire(name, detail) {
95
+ this.dispatchEvent(new CustomEvent('wick-feed:' + name, { detail }));
96
+ this.dispatchEvent(new CustomEvent('hab-feed:' + name, { detail }));
97
+ }
98
+
99
+ /** Resolve the target chart (by `for` id, else the first chart element —
100
+ * <wick-chart> or the deprecated <hab-chart>). */
93
101
  _resolveChart() {
94
102
  const id = this.getAttribute('for');
95
103
  if (id) {
96
104
  const el = document.getElementById(id);
97
- return el && el.tagName === 'HAB-CHART' ? el : null;
105
+ return el && (el.tagName === 'WICK-CHART' || el.tagName === 'HAB-CHART') ? el : null;
98
106
  }
99
- return document.querySelector('hab-chart');
107
+ return document.querySelector('wick-chart') || document.querySelector('hab-chart');
100
108
  }
101
109
 
102
110
  _restart() {
@@ -105,7 +113,7 @@ class HabFeed extends HTMLElementBase {
105
113
  if (!chart || typeof chart.setData !== 'function') {
106
114
  // chart not in the DOM yet (or not upgraded) — watch for it
107
115
  this._setStatus('waiting');
108
- customElements.whenDefined('hab-chart').then(() => {
116
+ customElements.whenDefined('wick-chart').then(() => {
109
117
  if (!this.isConnected) return;
110
118
  this._observer = this._observer || new MutationObserver(() => {
111
119
  const c = this._resolveChart();
@@ -208,9 +216,7 @@ class HabFeed extends HTMLElementBase {
208
216
  }
209
217
 
210
218
  _degrade(gen, chart, sym, tfId, limit, live, err) {
211
- this.dispatchEvent(
212
- new CustomEvent('hab-feed:fallback', { detail: { reason: err && err.message } })
213
- );
219
+ this._fire('fallback', { reason: err && err.message });
214
220
  this._synthetic(gen, chart, sym, tfId, limit, live, 'fallback');
215
221
  }
216
222
 
@@ -248,8 +254,17 @@ class HabFeed extends HTMLElementBase {
248
254
  }
249
255
  }
250
256
 
251
- if (typeof customElements !== 'undefined' && !customElements.get('hab-feed')) {
252
- customElements.define('hab-feed', HabFeed);
257
+ if (typeof customElements !== 'undefined') {
258
+ if (!customElements.get('wick-feed')) {
259
+ customElements.define('wick-feed', WickFeed);
260
+ }
261
+ // 0.x alias: same element under its old tag name (deprecated, removed in 2.0)
262
+ if (!customElements.get('hab-feed')) {
263
+ /** @deprecated use <wick-feed> */
264
+ class HabFeed extends WickFeed {}
265
+ customElements.define('hab-feed', HabFeed);
266
+ }
253
267
  }
254
268
 
255
- export default HabFeed;
269
+ export default WickFeed;
270
+ export { WickFeed };
package/types/core.d.ts CHANGED
@@ -263,6 +263,12 @@ export declare function calcEMASparse(values: Array<number | null>, period: numb
263
263
  export declare function calcRSI(closes: number[], period: number): Array<number | null>;
264
264
  /** Rolling standard deviation (population) over `period`, aligned like SMA. */
265
265
  export declare function calcStdDev(values: any, period: any): any[];
266
+ /** Linear-weighted moving average (most recent bar weighs `period`), aligned like SMA.
267
+ * @param {number[]} values
268
+ * @param {number} period
269
+ * @returns {Array<number|null>}
270
+ */
271
+ export declare function calcWMA(values: number[], period: number): Array<number | null>;
266
272
  /**
267
273
  * Bollinger Bands.
268
274
  * @param {number[]} closes
@@ -505,7 +511,8 @@ export declare const BUILTIN_INDICATORS: Map<string, {
505
511
  }>;
506
512
  /**
507
513
  * Parse an `indicators` attribute string against a registry.
508
- * Token: `name[:param[/param…]][@color]`, plus the `volume` keyword.
514
+ * Token: `name[:param[/param…]][@color]`, the `volume` keyword, and
515
+ * WickScript blobs `expr:{…}` (overlay) / `pexpr:{…}` (separate pane).
509
516
  * @param {string|null|undefined} str
510
517
  * @param {Map<string, IndicatorDef>} registry
511
518
  * @returns {{overlays: IndicatorEntry[], panes: IndicatorEntry[], volume: boolean, unknown: string[]}}
@@ -516,6 +523,46 @@ export declare function parseIndicators(str: string | null | undefined, registry
516
523
  volume: boolean;
517
524
  unknown: string[];
518
525
  };
526
+ /**
527
+ * Split an indicators string into tokens, keeping `expr:{…}` / `pexpr:{…}`
528
+ * blobs atomic — spaces and commas inside the braces are preserved, and an
529
+ * optional `@color` suffix directly after `}` stays attached.
530
+ * Separators are whitespace, `,` and `;`.
531
+ * @param {string|null|undefined} str
532
+ * @returns {string[]}
533
+ */
534
+ export declare function splitIndicatorTokens(str: string | null | undefined): string[];
535
+ /**
536
+ * Compile a WickScript expression. Throws a descriptive error on any syntax
537
+ * or semantic problem — never evaluates strings at runtime.
538
+ * @param {string} src
539
+ * @returns {{src: string, ast: object}}
540
+ */
541
+ export declare function compileScript(src: string): {
542
+ src: string;
543
+ ast: object;
544
+ };
545
+ /**
546
+ * Evaluate a compiled script (or a raw expression string) over bars.
547
+ * @param {{src:string, ast:object}|string} compiled
548
+ * @param {Bar[]} bars
549
+ * @returns {number[]} length `bars.length`; non-finite values become NaN
550
+ */
551
+ export declare function evalScript(compiled: {
552
+ src: string;
553
+ ast: object;
554
+ } | string, bars: Bar[]): number[];
555
+ /**
556
+ * Build an indicator definition from a WickScript expression — used inline by
557
+ * `indicators="expr:{…}"` / `pexpr:{…}"`, or register it under a name:
558
+ * `HabChart.registerIndicator('myspread', scriptIndicator('close - ema(close,21)'))`.
559
+ * @param {string} src
560
+ * @param {{pane?: boolean}} [opts]
561
+ * @returns {IndicatorDef}
562
+ */
563
+ export declare function scriptIndicator(src: string, opts?: {
564
+ pane?: boolean;
565
+ }): IndicatorDef;
519
566
  /**
520
567
  * Unrealized P&L of a position at `price`.
521
568
  * @param {{side?: 'long'|'short', entry: number, qty?: number}} pos
@@ -557,6 +604,66 @@ export declare function computeStats(bars: Bar[], i0: number, i1: number, dtMs:
557
604
  dn: number;
558
605
  avgVolume: number;
559
606
  };
607
+ /**
608
+ * Rolling realized volatility: population stddev of log returns over the
609
+ * last `period` bars (per-bar value, aligned like SMA — null until the
610
+ * window fills).
611
+ * @param {number[]} closes
612
+ * @param {number} [period=20]
613
+ * @returns {Array<number|null>}
614
+ */
615
+ export declare function calcRealizedVol(closes: number[], period?: number): Array<number | null>;
616
+ /**
617
+ * Classify a realized-vol series into regimes by empirical percentile over
618
+ * the whole series: 0 = calm (≤ qLow), 1 = normal, 2 = hot (≥ qHigh),
619
+ * -1 = unknown (null input). A degenerate spread (qHigh ≤ qLow, e.g. a
620
+ * flat series) classifies everything as normal.
621
+ * @param {Array<number|null>} vol
622
+ * @param {number} [qLow=30]
623
+ * @param {number} [qHigh=70]
624
+ * @returns {{regimes:number[], sorted:number[], q1:number, q2:number}}
625
+ */
626
+ export declare function volRegimeBands(vol: Array<number | null>, qLow?: number, qHigh?: number): {
627
+ regimes: number[];
628
+ sorted: number[];
629
+ q1: number;
630
+ q2: number;
631
+ };
632
+ /**
633
+ * Percentile (0–100) of `v` within an ascending `sorted` array.
634
+ * @param {number[]} sorted
635
+ * @param {number} v
636
+ * @returns {number}
637
+ */
638
+ export declare function percentileOfSorted(sorted: number[], v: number): number;
639
+ /**
640
+ * Parse a `volshading` attribute value: `""` / `"true"` → defaults (30/70,
641
+ * period 20); `"30/70"` custom cutoffs; `"30/70/14"` cutoffs + period.
642
+ * Inputs are clamped so qLow always stays at least 2 points below qHigh.
643
+ * @param {string|null|undefined} val
644
+ * @returns {{p1:number, p2:number, period:number}}
645
+ */
646
+ export declare function parseVolShading(val: string | null | undefined): {
647
+ p1: number;
648
+ p2: number;
649
+ period: number;
650
+ };
651
+ export declare const tfLabelOf: (dtMs: any) => string;
652
+ /**
653
+ * Compact, LLM-friendly summary of a bar window: structured fields plus a
654
+ * ready-to-paste markdown rendering (`text`). Built entirely from local
655
+ * data — nothing leaves the page until the user pastes it somewhere.
656
+ *
657
+ * @param {Bar[]} bars full dataset
658
+ * @param {number} i0 first index of the window
659
+ * @param {number} i1 last index of the window
660
+ * @param {{dtMs?: number, label?: string}} [opts] bar spacing (ms) + chart label
661
+ * @returns {object|null} null when the window is empty or out of range
662
+ */
663
+ export declare function windowSummary(bars: Bar[], i0: number, i1: number, opts?: {
664
+ dtMs?: number;
665
+ label?: string;
666
+ }): object | null;
560
667
  /**
561
668
  * Encode a chart state (from getState()) as a compact query string.
562
669
  * View times are encoded in whole seconds.
@@ -1,7 +1,7 @@
1
1
  declare const HTMLElementBase: {
2
2
  new (): {};
3
3
  };
4
- declare class HabChart extends HTMLElementBase {
4
+ declare class WickChart extends HTMLElementBase {
5
5
  _canvas: any;
6
6
  _ctx: any;
7
7
  _legend: any;
@@ -93,6 +93,11 @@ declare class HabChart extends HTMLElementBase {
93
93
  i: number;
94
94
  note: string;
95
95
  }[];
96
+ _volshade: {
97
+ p1: number;
98
+ p2: number;
99
+ period: number;
100
+ };
96
101
  _coviewName: any;
97
102
  _coviewCh: BroadcastChannel;
98
103
  _coviewPeer: string;
@@ -167,13 +172,93 @@ declare class HabChart extends HTMLElementBase {
167
172
  connectedCallback(): void;
168
173
  disconnectedCallback(): void;
169
174
  attributeChangedCallback(name: any, _old: any, val: any): void;
170
- static _registryMap: any;
171
- /** Lazily-built registry, seeded with the built-in indicators. */
172
- static _registry(): any;
175
+ /** Indicator registry (module scope — shared with the legacy alias tag). */
176
+ static _registry(): Map<string, {
177
+ kind: string;
178
+ params: {
179
+ period: number;
180
+ mult?: undefined;
181
+ fast?: undefined;
182
+ slow?: undefined;
183
+ signal?: undefined;
184
+ };
185
+ compute: (bars: any, p: any) => number[];
186
+ range?: undefined;
187
+ color?: undefined;
188
+ guides?: undefined;
189
+ fmt?: undefined;
190
+ } | {
191
+ kind: string;
192
+ params: {
193
+ period: number;
194
+ mult?: undefined;
195
+ fast?: undefined;
196
+ slow?: undefined;
197
+ signal?: undefined;
198
+ };
199
+ compute: (bars: any, p: any) => number[];
200
+ range?: undefined;
201
+ color?: undefined;
202
+ guides?: undefined;
203
+ fmt?: undefined;
204
+ } | {
205
+ kind: string;
206
+ params: {
207
+ period: number;
208
+ mult: number;
209
+ fast?: undefined;
210
+ slow?: undefined;
211
+ signal?: undefined;
212
+ };
213
+ compute: (bars: any, p: any) => {
214
+ lines: {
215
+ name: string;
216
+ values: number[];
217
+ }[];
218
+ };
219
+ range?: undefined;
220
+ color?: undefined;
221
+ guides?: undefined;
222
+ fmt?: undefined;
223
+ } | {
224
+ kind: string;
225
+ params: {
226
+ mult?: undefined;
227
+ period: number;
228
+ fast?: undefined;
229
+ slow?: undefined;
230
+ signal?: undefined;
231
+ };
232
+ guides: number[];
233
+ range: number[];
234
+ fmt: string;
235
+ color: string;
236
+ compute: (bars: any, p: any) => number[];
237
+ } | {
238
+ range?: undefined;
239
+ color?: undefined;
240
+ kind: string;
241
+ params: {
242
+ mult?: undefined;
243
+ period?: undefined;
244
+ fast: number;
245
+ slow: number;
246
+ signal: number;
247
+ };
248
+ guides: number[];
249
+ fmt: string;
250
+ compute: (bars: any, p: any) => {
251
+ lines: {
252
+ name: string;
253
+ values: number[];
254
+ }[];
255
+ histogram: number[];
256
+ };
257
+ }>;
173
258
  /**
174
259
  * Register a custom indicator.
175
260
  *
176
- * HabChart.registerIndicator('vwap', {
261
+ * WickChart.registerIndicator('vwap', {
177
262
  * kind: 'overlay', // or 'pane'
178
263
  * params: { period: 20 }, // defaults; settable via name:period
179
264
  * compute(bars, params) { // bars: normalized {time,o,h,l,c,v}
@@ -228,6 +313,13 @@ declare class HabChart extends HTMLElementBase {
228
313
  }): void;
229
314
  /** Current canvas as a PNG data URL. */
230
315
  exportPNG(): any;
316
+ /**
317
+ * AI-ready summary of the visible window: structured fields plus a
318
+ * ready-to-paste markdown rendering (`text`). Computed locally —
319
+ * nothing leaves the page until the user copies it somewhere.
320
+ * @returns {object|null}
321
+ */
322
+ getDataWindow(): object | null;
231
323
  /**
232
324
  * Serializable snapshot of the chart's configuration and view.
233
325
  * Feed it to setState() (or encodeStateQuery for shareable URLs).
@@ -257,7 +349,8 @@ declare class HabChart extends HTMLElementBase {
257
349
  removePosition(id: any): void;
258
350
  clearPositions(): void;
259
351
  /**
260
- * Price alert. Fires `hab:alert` ({id, price, bar}) on an edge crossing
352
+ * Price alert. Fires `wick:alert` ({id, price, bar}) on an edge crossing
353
+ * (plus the deprecated `hab:alert` alias)
261
354
  * during streaming updates.
262
355
  * @param {{id?: string, price: number, direction?: 'above'|'below'|'cross',
263
356
  * once?: boolean}} alert
@@ -313,6 +406,8 @@ declare class HabChart extends HTMLElementBase {
313
406
  _renderBars(): any;
314
407
  /** RSI(14) over raw closes, cached per data version (annotation input). */
315
408
  _cachedRSI14(): any;
409
+ /** Volatility-regime data (realized vol + percentile bands), cached per data version. */
410
+ _volShadeCache(): any;
316
411
  /** Compute (and cache per data version) an indicator entry's series. */
317
412
  _indicatorSeries(entry: any): any;
318
413
  /** Resolve a line color: #hex / rgb() / CSS name / palette key ('rsi', 'up', …) / cycle.
@@ -372,6 +467,10 @@ declare class HabChart extends HTMLElementBase {
372
467
  _setupCoView(): void;
373
468
  _coviewSend(msg: any): void;
374
469
  _onCoMessage(m: any): void;
470
+ /** Dispatch `wick:name` (canonical) plus the deprecated `hab:name` alias,
471
+ * so 0.x listeners keep working until 2.0. */
472
+ _fire(name: any, detail: any): void;
375
473
  _emitRange(): void;
376
474
  }
377
- export default HabChart;
475
+ export default WickChart;
476
+ export { WickChart };
@@ -1,8 +1,8 @@
1
- import './hab-chart.js';
1
+ import './wick-chart.js';
2
2
  declare const HTMLElementBase: {
3
3
  new (): {};
4
4
  };
5
- declare class HabFeed extends HTMLElementBase {
5
+ declare class WickFeed extends HTMLElementBase {
6
6
  _gen: number;
7
7
  _closers: any[];
8
8
  _timer: number;
@@ -15,7 +15,10 @@ declare class HabFeed extends HTMLElementBase {
15
15
  _scheduleRestart(): void;
16
16
  _teardown(): void;
17
17
  _setStatus(status: any, detail: any): void;
18
- /** Resolve the target chart (by `for` id, else the first <hab-chart>). */
18
+ /** Dispatch `wick-feed:name` plus the deprecated `hab-feed:name` alias. */
19
+ _fire(name: any, detail: any): void;
20
+ /** Resolve the target chart (by `for` id, else the first chart element —
21
+ * <wick-chart> or the deprecated <hab-chart>). */
19
22
  _resolveChart(): Element;
20
23
  _restart(): void;
21
24
  _synthetic(gen: any, chart: any, key: any, tfId: any, limit: any, live: any, status?: string): void;
@@ -24,4 +27,5 @@ declare class HabFeed extends HTMLElementBase {
24
27
  _degrade(gen: any, chart: any, sym: any, tfId: any, limit: any, live: any, err: any): void;
25
28
  _rest(gen: any, chart: any, url: any, limit: any, live: any): Promise<void>;
26
29
  }
27
- export default HabFeed;
30
+ export default WickFeed;
31
+ export { WickFeed };