hyperprop-charting-library 0.1.131 → 0.1.133

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/docs/API.md CHANGED
@@ -543,3 +543,82 @@ Use `getDrawings()` / `setDrawings()` for persistence.
543
543
  - `setIndicators(indicators: IndicatorInstanceOptions[]): void`
544
544
  - `resize(width?: number, height?: number): void`
545
545
  - `destroy(): void`
546
+
547
+ ---
548
+
549
+ ## Script Indicators (user-authored)
550
+
551
+ `compileScriptIndicator(definition: ScriptIndicatorDefinition): IndicatorPlugin` — compiles a
552
+ user-authored "Hyperprop Script" into a regular indicator plugin. Register the result with
553
+ `chart.registerIndicator(...)` and add it with `chart.addIndicator(definition.id)`. Separate-pane
554
+ scripts automatically get the shared grid, legend, live values, value lines, drag-resize and the
555
+ hover controls (eye / gear / source / delete). Overlay scripts participate in price autoscale.
556
+
557
+ ```ts
558
+ import { createChart, compileScriptIndicator } from "hyperprop-charting-library";
559
+
560
+ const plugin = compileScriptIndicator({
561
+ id: "script:my-rsi",
562
+ name: "My RSI",
563
+ pane: "separate", // or "overlay"
564
+ inputs: [
565
+ { key: "length", label: "Length", type: "number", default: 14 },
566
+ { key: "color", label: "Color", type: "color", default: "#ab47bc" }
567
+ ],
568
+ source: `
569
+ function compute(bars, inputs, hp) {
570
+ const closes = bars.map(b => b.c);
571
+ const gains = closes.map((c, i) => i === 0 ? null : Math.max(0, c - closes[i - 1]));
572
+ const losses = closes.map((c, i) => i === 0 ? null : Math.max(0, closes[i - 1] - c));
573
+ const avgGain = hp.rma(gains, inputs.length);
574
+ const avgLoss = hp.rma(losses, inputs.length);
575
+ const rsi = avgGain.map((g, i) => {
576
+ const l = avgLoss[i];
577
+ if (g == null || l == null) return null;
578
+ return l === 0 ? 100 : 100 - 100 / (1 + g / l);
579
+ });
580
+ return {
581
+ plots: [{ title: "RSI", values: rsi, color: inputs.color }],
582
+ range: { min: 0, max: 100 },
583
+ guides: [30, 70]
584
+ };
585
+ }`
586
+ });
587
+
588
+ chart.registerIndicator(plugin);
589
+ chart.addIndicator("script:my-rsi");
590
+ ```
591
+
592
+ Script contract:
593
+
594
+ - The source must define `function compute(bars, inputs, hp)`.
595
+ - `bars`: `Array<{ time: Date, o, h, l, c, v? }>` — the full series.
596
+ - `inputs`: resolved input values (defaults merged with per-instance overrides). `showValueLine`
597
+ is injected automatically and honored by separate panes.
598
+ - `hp`: TA helpers, all `(values: Array<number|null>, length) => Array<number|null>` unless noted:
599
+ `sma`, `ema`, `rma`, `highest`, `lowest`, `stdev`, `change(values, length = 1)`,
600
+ `atr(bars, length)`.
601
+ - Return `{ plots, range?, guides?, decimals? }`:
602
+ - `plots`: `Array<{ title?, values, color?, width?, style?: "line" | "histogram", negativeColor? }>`
603
+ - `range`: `{ min?, max? }` fixes the pane scale (e.g. `0..100` for oscillators).
604
+ - `guides`: dashed horizontal guide levels (e.g. `[30, 70]`).
605
+ - `decimals`: axis/legend decimal places.
606
+
607
+ Errors never break the chart: compile or runtime errors render as an inline red message in the
608
+ pane. Scripts are plain JavaScript executed in the page context — treat them like any other code
609
+ you'd paste into your app (only run scripts you trust).
610
+
611
+ ### Execution budget
612
+
613
+ Loop conditions are instrumented at compile time, and each `compute()` invocation gets a
614
+ 1000 ms wall-clock budget. A script that exceeds it (e.g. `while (true) {}`) throws
615
+ `"Script exceeded the 1000ms execution budget"`, which renders as the usual inline pane error
616
+ instead of freezing the tab. After a budget trip the script is circuit-broken — it is not run
617
+ again for that compiled instance, so live ticks don't re-trigger the stall. Recompiling (editing
618
+ the source and calling `compileScriptIndicator` again) resets the breaker. String/template/comment
619
+ contents are never instrumented; `for...of` / `for...in` loops are left untouched.
620
+
621
+ `validateScriptSource(source: string): string | null` — compile-checks a script without
622
+ registering it, returning an error message or `null`. It runs under the same execution budget, so
623
+ validating a script with a top-level infinite loop returns a budget error instead of hanging the
624
+ caller. Use this for editor save-validation instead of running `new Function` yourself.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.131",
3
+ "version": "0.1.133",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",