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.
- package/README.md +298 -3
- package/package.json +20 -3
- package/src/core.js +763 -5
- package/src/react-core.js +191 -0
- package/src/react.js +21 -0
- package/src/wick-chart.js +1021 -34
- package/types/core.d.ts +362 -0
- package/types/react-core.d.ts +64 -0
- package/types/react.d.ts +3 -0
- package/types/wick-chart.d.ts +307 -8
package/types/wick-chart.d.ts
CHANGED
|
@@ -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.
|
|
353
|
-
* (
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
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
|
|
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
|
-
/**
|
|
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;
|