wickchart 1.0.0 → 1.3.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,3 +1,4 @@
1
+ import { PresenceTracker } from './core.js';
1
2
  declare const HTMLElementBase: {
2
3
  new (): {};
3
4
  };
@@ -108,6 +109,10 @@ declare class WickChart extends HTMLElementBase {
108
109
  at: number;
109
110
  };
110
111
  _ghostTimer: number;
112
+ _coviewLabel: any;
113
+ _presence: PresenceTracker;
114
+ _coviewBeat: number;
115
+ _coviewViewLast: number;
111
116
  _sonify: boolean;
112
117
  _actx: any;
113
118
  _lastToneIdx: number;
@@ -120,6 +125,36 @@ declare class WickChart extends HTMLElementBase {
120
125
  done: boolean;
121
126
  };
122
127
  _measuring: boolean;
128
+ _walkTimer: number;
129
+ _storyToken: number;
130
+ _story: object[];
131
+ _brush: boolean;
132
+ _brushSel: {
133
+ i0: number;
134
+ i1: number;
135
+ stats: {
136
+ bars: number;
137
+ from: {
138
+ index: number;
139
+ time: number;
140
+ };
141
+ to: {
142
+ index: number;
143
+ time: number;
144
+ };
145
+ firstOpen: number;
146
+ lastClose: number;
147
+ delta: number;
148
+ deltaPct: number;
149
+ high: number;
150
+ low: number;
151
+ volume: number;
152
+ };
153
+ };
154
+ _brushDrag: {
155
+ i0: any;
156
+ i1: any;
157
+ };
123
158
  _ind: {
124
159
  overlays: any[];
125
160
  panes: any[];
@@ -142,6 +177,30 @@ declare class WickChart extends HTMLElementBase {
142
177
  _positions: any[];
143
178
  _alerts: any[];
144
179
  _seq: number;
180
+ _overlays: any[];
181
+ _scenario: {
182
+ path: {
183
+ h: number;
184
+ price: number;
185
+ }[];
186
+ horizon: number;
187
+ cone: boolean;
188
+ levels: number[];
189
+ color: string | null;
190
+ label: string;
191
+ };
192
+ _riskPlan: {
193
+ entry: number;
194
+ stop: number;
195
+ risk: number;
196
+ direction: 'long' | 'short';
197
+ levels: {
198
+ k: number;
199
+ price: number;
200
+ }[];
201
+ maxK: number;
202
+ label: string;
203
+ };
145
204
  _onResize: () => void;
146
205
  _onPointerDown: (e: any) => void;
147
206
  _onPointerMove: (e: any) => void;
@@ -349,23 +408,148 @@ declare class WickChart extends HTMLElementBase {
349
408
  removePosition(id: any): void;
350
409
  clearPositions(): void;
351
410
  /**
352
- * Price alert. Fires `wick:alert` ({id, price, bar}) on an edge crossing
353
- * (plus the deprecated `hab:alert` alias)
354
- * during streaming updates.
355
- * @param {{id?: string, price: number, direction?: 'above'|'below'|'cross',
356
- * once?: boolean}} alert
357
- * @returns {string|null} the alert id
411
+ * Price or scripted alert. Price alerts fire `wick:alert`
412
+ * ({id, price, bar}) on an edge crossing; scripted alerts evaluate a
413
+ * WickScript predicate (`when`) on every streamed bar and fire on its
414
+ * false→true edge e.g. `when: 'crossup(rsi(close,14), 30)'` or
415
+ * `when: 'volume > sma(volume,20) * 3'`. Scripted events carry the
416
+ * triggering close as `price` plus the `when` source (deprecated
417
+ * `hab:alert` alias still dispatched).
418
+ * @param {{id?: string, price?: number, direction?: 'above'|'below'|'cross',
419
+ * when?: string, once?: boolean}} alert
420
+ * @returns {string|null} the alert id (null when no valid price/when,
421
+ * or the predicate fails to compile)
358
422
  */
359
423
  addAlert(alert: {
360
424
  id?: string;
361
- price: number;
425
+ price?: number;
362
426
  direction?: 'above' | 'below' | 'cross';
427
+ when?: string;
363
428
  once?: boolean;
364
429
  }): string | null;
365
430
  removeAlert(id: any): void;
366
431
  clearAlerts(): void;
367
- /** Check alerts against an incoming bar (prev close → new close). */
432
+ /**
433
+ * Server-side overlays: zones & levels anchored in time × price — e.g.
434
+ * supply/demand zones from an analysis API. Zones with no `to` extend
435
+ * into future space past the last bar, like TradingView drawings.
436
+ *
437
+ * zone: { type:'zone', from?:ms, to?:ms|null, priceFrom, priceTo,
438
+ * color?, alpha?, border?, label?, id? }
439
+ * level: { type:'level', price, from?, to?, color?, width?, dash?,
440
+ * label?, id? }
441
+ *
442
+ * Invalid entries are dropped, never thrown. Colors accept hex/rgb()/CSS
443
+ * names plus the palette keys 'up' | 'down' | 'accent'.
444
+ * @param {object[]} list
445
+ * @returns {string[]} applied overlay ids
446
+ */
447
+ setOverlays(list: object[]): string[];
448
+ /** @returns {object[]} a copy of the current overlays */
449
+ get overlays(): object[];
450
+ /**
451
+ * Add or replace (upsert, by id) a single overlay.
452
+ * @returns {string|null} the overlay id, or null if invalid
453
+ */
454
+ addOverlay(ov: any): string | null;
455
+ removeOverlay(id: any): void;
456
+ clearOverlays(): void;
457
+ /**
458
+ * Scenario projection into future space: a ghost path of future prices
459
+ * plus optional σ-bands (vol cone) from realized volatility.
460
+ *
461
+ * chart.setScenario({ path: [64000, 65500, 68000], label: 'bull case' });
462
+ * chart.setScenario({ horizon: 48, cone: true }); // cone-only
463
+ *
464
+ * The path is an array of prices (or {price} objects) for future bars
465
+ * 1..N; horizon defaults to the path length (1–500). `cone` (default
466
+ * true) draws ±levels·σ bands widening with √h from the current realized
467
+ * vol; `color` accepts up|down|accent or safe CSS colors. Setting a
468
+ * scenario reserves future space on the right; analysis data — excluded
469
+ * from getState/setState.
470
+ * @param {object} spec
471
+ * @returns {object|null} the normalized scenario, or null when invalid
472
+ */
473
+ setScenario(spec: object): object | null;
474
+ clearScenario(): void;
475
+ /** @returns {object|null} a copy of the active scenario */
476
+ get scenario(): object | null;
477
+ /**
478
+ * Risk plan: an R-multiple grid anchored at entry/stop. 1R = |entry −
479
+ * stop| (the risk unit); reward lines are drawn at kR beyond the entry
480
+ * with the risk/reward zones shaded, so sizing and take-profit choices
481
+ * read directly off the chart.
482
+ *
483
+ * chart.setRiskPlan({ entry: 64500, stop: 63800, multiples: [1, 2, 3] });
484
+ * chart.setRiskPlan({ entry: 64500, stop: 63800, targets: [65900, 67300] });
485
+ *
486
+ * Direction is derived (stop below entry ⇒ long). Targets convert to
487
+ * their R multiple; `multiples` win when both are given. Invalid specs
488
+ * clear the plan (replace semantics, like setScenario); excluded from
489
+ * getState/setState — it is app state, not chart state.
490
+ * @param {object} spec
491
+ * @returns {object|null} the normalized plan, or null when invalid
492
+ */
493
+ setRiskPlan(spec: object): object | null;
494
+ clearRiskPlan(): void;
495
+ /** @returns {object|null} a copy of the active risk plan */
496
+ get riskPlan(): object | null;
497
+ /** σ-cone for the active scenario, cached per data version. */
498
+ _scenarioConeCache(): any;
499
+ /** Tool manifest for LLM control — JSON-safe copy of AI_TOOLS. */
500
+ aiTools(): any;
501
+ /** System prompt for agent control — paste into any LLM alongside aiTools(). */
502
+ aiPrompt(): string;
503
+ /** Grounding context for a model: current state + visible-window summary. */
504
+ aiContext(): {
505
+ state: import("./core.js").ChartState;
506
+ window: object;
507
+ };
508
+ /**
509
+ * Apply a list of {tool, args} ops (typically LLM output) through the
510
+ * validated dispatcher in core. Never throws — each op resolves
511
+ * {ok, tool, result} or {ok: false, tool, error} so an agent can
512
+ * self-correct.
513
+ * @param {any} ops
514
+ * @returns {Array<object>}
515
+ */
516
+ applyAI(ops: any): Array<object>;
517
+ /**
518
+ * Ask an AI to operate the chart. Builds the payload {system,
519
+ * instruction, chart, tools}; with a `run` async function (your model
520
+ * call — the chart itself never touches the network), applies the
521
+ * returned ops and resolves {payload, ops, results}. Without `run`,
522
+ * returns the payload for manual wiring — send it anywhere, then call
523
+ * chart.applyAI(ops) with the model's answer.
524
+ *
525
+ * const { results } = await chart.ask('add RSI and mark the demand zone', {
526
+ * run: async (payload) => (await callMyLLM(payload)).ops,
527
+ * });
528
+ *
529
+ * @param {string} instruction natural-language request
530
+ * @param {{run?: (payload: object) => Promise<any>}} [opts]
531
+ */
532
+ ask(instruction: string, opts?: {
533
+ run?: (payload: object) => Promise<any>;
534
+ }): Promise<{
535
+ payload: {
536
+ system: string;
537
+ instruction: string;
538
+ chart: {
539
+ state: import("./core.js").ChartState;
540
+ window: object;
541
+ };
542
+ tools: any;
543
+ };
544
+ ops: any;
545
+ results: object[];
546
+ }>;
547
+ /** Check alerts against an incoming bar (prev close → new close).
548
+ * Scripted (`when`) alerts evaluate their predicate series, cached per
549
+ * data version, and fire on the false→true edge. */
368
550
  _checkAlerts(prevClose: any, bar: any): void;
551
+ /** Cached boolean series for a scripted alert's predicate (per data version). */
552
+ _predicateCache(alert: any): any;
369
553
  get theme(): string;
370
554
  set theme(v: string);
371
555
  get type(): string;
@@ -465,11 +649,126 @@ declare class WickChart extends HTMLElementBase {
465
649
  _emitCrosshair(hover: any): void;
466
650
  /** Join/leave the co-view channel named by the `co-view` attribute. */
467
651
  _setupCoView(): void;
652
+ /** Broadcast our visible range for presence; throttled unless forced. */
653
+ _coviewSendView(force: any): void;
468
654
  _coviewSend(msg: any): void;
469
655
  _onCoMessage(m: any): void;
470
656
  /** Dispatch `wick:name` (canonical) plus the deprecated `hab:name` alias,
471
657
  * so 0.x listeners keep working until 2.0. */
472
658
  _fire(name: any, detail: any): void;
659
+ /**
660
+ * Live co-view peers: who else is in the room and the time window each
661
+ * one is looking at — [{ id, name, range: {from, to}, at }], oldest
662
+ * sighting first. Peers fade out ~12 s after their last sighting.
663
+ * @returns {object[]}
664
+ */
665
+ getPeers(): object[];
666
+ /**
667
+ * Narrated timeline for a window (default: the visible range) — pivot
668
+ * highs/lows, volume spikes, gaps, RSI divergences plus derived legs
669
+ * ("+12.4% over 38 bars"), sorted by index. Pure data, perfect for
670
+ * caption UIs or the walk player.
671
+ * chart.narrate(); // visible range
672
+ * chart.narrate({ from, to }); // times in ms (s accepted)
673
+ * @param {{from?: number, to?: number}} [range]
674
+ * @returns {{i: number, time: number, type: string, side: string, note: string,
675
+ * legPct?: number, legBars?: number}[]}
676
+ */
677
+ narrate(range?: {
678
+ from?: number;
679
+ to?: number;
680
+ }): {
681
+ i: number;
682
+ time: number;
683
+ type: string;
684
+ side: string;
685
+ note: string;
686
+ legPct?: number;
687
+ legBars?: number;
688
+ }[];
689
+ /**
690
+ * Walk the chart through history like a story: the viewport slides
691
+ * from `from` to `to` while `wick:walk` events announce every step and
692
+ * the narrator's events (spikes, gaps, pivots, legs) as they're crossed.
693
+ * Any user interaction — pointer, wheel, keys, double-click — stops it.
694
+ * chart.walk({ from: 0, to: 500, speed: 120, step: 10 });
695
+ * chart.addEventListener('wick:walk', (e) => showCaption(e.detail));
696
+ * // detail: { phase: 'step'|'end'|'stop', index, events: [...], from, to }
697
+ * @param {{from?: number, to?: number, speed?: number, step?: number}} [opts]
698
+ * from/to are bar indices (default: last ~500 bars → the end)
699
+ * @returns {boolean} true when the walk started
700
+ */
701
+ walk(opts?: {
702
+ from?: number;
703
+ to?: number;
704
+ speed?: number;
705
+ step?: number;
706
+ }): boolean;
707
+ /**
708
+ * Stop the running walk (if any). Fires a final `wick:walk`
709
+ * { phase: 'stop' } unless called internally.
710
+ */
711
+ stopWalk(silent: any): void;
712
+ /**
713
+ * Commit a brush selection over [i0, i1]: stores it (draws the band
714
+ * and delta chip) and fires `wick:brush` with the range statistics.
715
+ * @param {number} i0 first index
716
+ * @param {number} i1 last index
717
+ */
718
+ _brushFinish(i0: number, i1: number): void;
719
+ /** Clear the committed brush selection (if any). Escape does the same. */
720
+ clearBrush(): void;
721
+ /** @returns {object|null} the committed selection { i0, i1, stats } */
722
+ get brushSelection(): object | null;
723
+ /**
724
+ * Capture the current chart state as a story scene: view, series type,
725
+ * indicators, overlays, scenario and risk plan, plus a title/note.
726
+ * Build guided tours by capturing several and playing them back.
727
+ * const story = [
728
+ * chart.captureScene('Overview', 'The full picture'),
729
+ * { title: 'The breakout', range: { from, to }, indicators: 'sma:20' },
730
+ * ];
731
+ * chart.playStory(story);
732
+ * @param {string} [title]
733
+ * @param {string} [note]
734
+ * @returns {object} scene (plain data — snapshot of the moment)
735
+ */
736
+ captureScene(title?: string, note?: string): object;
737
+ /** @returns {object[]|null} a copy of the last played story */
738
+ getStory(): object[] | null;
739
+ /**
740
+ * Play a story: each scene applies its state (type / indicators /
741
+ * overlays / scenario / risk plan — set or clear), the camera eases
742
+ * to its range, then holds for its dwell. `wick:story` events narrate:
743
+ * { phase: 'scene' | 'end' | 'stop', index, total, scene, title, note }
744
+ * Any user interaction — pointer, wheel, keys, double-click — stops it.
745
+ * @param {object[]} story scenes (invalid entries dropped, max 20)
746
+ * @param {{dwell?: number, panMs?: number, loop?: boolean}} [opts]
747
+ * panMs clamps 100–5000 (default 900); loop replays forever
748
+ * @returns {boolean} true when playback started
749
+ */
750
+ playStory(story: object[], opts?: {
751
+ dwell?: number;
752
+ panMs?: number;
753
+ loop?: boolean;
754
+ }): boolean;
755
+ /**
756
+ * Stop story playback (if running). Fires a final `wick:story`
757
+ * { phase: 'stop' } unless called internally.
758
+ */
759
+ stopStory(silent: any): void;
760
+ /** Apply a scene's state (only the fields it carries). */
761
+ _applyScene(sc: any): void;
762
+ /** Map a scene's time range to bar indices (null when not applicable). */
763
+ _sceneTarget(sc: any): {
764
+ i0: number;
765
+ i1: number;
766
+ };
767
+ /** Ease the viewport to { i0, i1 } over `ms`; resolves early if the
768
+ * token changes (superseded or stopped). rAF when available. */
769
+ _storyTween(target: any, ms: any, token: any): Promise<any>;
770
+ /** Interrupt narrated playback (walk / story) on user input. */
771
+ _stopPlayback(): void;
473
772
  _emitRange(): void;
474
773
  }
475
774
  export default WickChart;