openalgo-charts 1.8.8 → 1.8.9

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 CHANGED
@@ -9,7 +9,7 @@ Professional interactive charts, 102 built-in indicators plus your own custom on
9
9
  [![npm version](https://img.shields.io/npm/v/openalgo-charts.svg?color=cb3837&label=npm)](https://www.npmjs.com/package/openalgo-charts)
10
10
  [![license](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](./LICENSE)
11
11
  [![bundle](https://img.shields.io/badge/brotli-61%20KB%20base%20%C2%B7%20122%20KB%20all%20tiers-brightgreen.svg)](#size-budget)
12
- [![tests](https://img.shields.io/badge/tests-2466%20passing-brightgreen.svg)](#develop)
12
+ [![tests](https://img.shields.io/badge/tests-2586%20passing-brightgreen.svg)](#develop)
13
13
  [![dependencies](https://img.shields.io/badge/runtime%20deps-0-brightgreen.svg)](#principles)
14
14
 
15
15
  [**Documentation**](https://marketcalls.github.io/openalgo-charts/)  ·  [**Live examples**](https://marketcalls.github.io/openalgo-charts/examples)  ·  [**Getting started**](./docs/getting-started.md)  ·  [**Architecture**](./ARCHITECTURE.md)
@@ -62,7 +62,7 @@ in front of npm rather than being places you upload to. A chart is one HTML file
62
62
  ```html
63
63
  <div id="chart" style="width:100vw;height:100vh"></div>
64
64
  <script type="module">
65
- import { createChart } from 'https://unpkg.com/openalgo-charts@1.8.8/dist/openalgo-charts.mjs';
65
+ import { createChart } from 'https://unpkg.com/openalgo-charts@1.8.9/dist/openalgo-charts.mjs';
66
66
  const chart = createChart(document.getElementById('chart'), { timezone: 'Asia/Kolkata' });
67
67
  chart.addSeries('candlestick').setData(bars);
68
68
  </script>
@@ -79,14 +79,14 @@ Import only what you use. Each tier is a separate bundle that registers into the
79
79
 
80
80
  | Import | Contents | Brotli |
81
81
  |---|---|---|
82
- | `openalgo-charts` | Engine, 13 chart types, panes &amp; scales, primitives, registries, chart state, chart linking, bar cache, interval registry, trading overlay, OpenAlgo feeds | 60.6 KB |
82
+ | `openalgo-charts` | Engine, 13 chart types, panes &amp; scales, primitives, registries, chart state, chart linking, bar cache, interval registry, trading overlay, OpenAlgo feeds | 60.8 KB |
83
83
  | `openalgo-charts/indicators` | 102 built-in indicators, the `registerIndicator` contract for your own, and the Tier-2 (external-data) contract | 27.3 KB |
84
84
  | `openalgo-charts/draw` | 43 drawing tools + a headless drawing controller and clipboard | 13.1 KB |
85
85
  | `openalgo-charts/transform` | Heikin Ashi, Renko, Range bars, Line Break, Point &amp; Figure, Kagi | 2.7 KB |
86
86
  | `openalgo-charts/profile` | Volume Profile, Market Profile (TPO), Footprint, order flow | 10.7 KB |
87
87
  | `openalgo-charts/trade` | Order / position / bracket tools + DOM ladder | 7.6 KB |
88
88
 
89
- Everything together is **121.90 KB Brotli**. Figures are the measured `size-limit` output. The trade tier is listed as its delta over the base, so loading base + trade costs 68.18 KB.
89
+ Everything together is **122.15 KB Brotli**. Figures are the measured `size-limit` output. The trade tier is listed as its delta over the base, so loading base + trade costs 68.43 KB.
90
90
 
91
91
  ## What's built
92
92
 
@@ -227,13 +227,13 @@ Enforced in CI by [`size-limit`](./.size-limit.json). Nothing is excluded, becau
227
227
 
228
228
  | Bundle | Limit | Actual |
229
229
  |---|---|---|
230
- | Base engine | 62 KB | 60.57 KB |
231
- | Base + trade | 70 KB | 68.18 KB |
230
+ | Base engine | 62 KB | 60.83 KB |
231
+ | Base + trade | 70 KB | 68.43 KB |
232
232
  | Indicators tier | 30 KB | 27.27 KB |
233
233
  | Draw tier | 14 KB | 13.13 KB |
234
234
  | Transform tier | 5 KB | 2.66 KB |
235
235
  | Profile tier | 11 KB | 10.66 KB |
236
- | **Everything** | **124 KB** | **121.90 KB** |
236
+ | **Everything** | **124 KB** | **122.15 KB** |
237
237
 
238
238
  ## Documentation
239
239
 
@@ -273,7 +273,7 @@ cd examples/yfinance && pip install -r requirements.txt && python server.py
273
273
  ```bash
274
274
  npm install # install dev toolchain
275
275
  npm run typecheck # strict TypeScript check
276
- npm test # unit tests (vitest) - 2466 across 137 files
276
+ npm test # unit tests (vitest) - 2586 across 140 files
277
277
  npm run build # Rollup -> dist/ (minified ESM per tier + types)
278
278
  npm run size # size-limit (Brotli) against the budget
279
279
  npm run e2e # Playwright Chromium smoke tests
@@ -290,7 +290,7 @@ npm run verify # typecheck + test + build + size
290
290
 
291
291
  ## Status &amp; limitations
292
292
 
293
- Version **1.8.8**. All engine build phases are implemented with 2466 unit tests across 137 files.
293
+ Version **1.8.9**. All engine build phases are implemented with 2586 unit tests across 140 files.
294
294
 
295
295
  Known gaps, stated plainly:
296
296
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Library version string. Matches package.json (published npm release). */
2
- declare const VERSION = "1.8.8";
2
+ declare const VERSION = "1.8.9";
3
3
  /** Returns the current library version. */
4
4
  declare function version(): string;
5
5
 
@@ -125,8 +125,24 @@ interface PriceScaleOptions {
125
125
  /** Fraction of pane height kept empty at top/bottom (default 0.1 each). */
126
126
  marginTop: number;
127
127
  marginBottom: number;
128
- /** Instrument tick size (minMove), e.g. 0.05. 0 → infer from range. */
128
+ /**
129
+ * Instrument tick size (minMove), e.g. 0.05. 0 → infer from range.
130
+ *
131
+ * A property of the instrument and not of the axis, so it belongs only on a
132
+ * scale that quotes one. An oscillator's pane reads in its own units and is
133
+ * left at 0 there, which is why `Chart.setPriceScaleOptions` withholds it
134
+ * from those panes rather than broadcasting it like the rest of this block.
135
+ */
129
136
  minMove: number;
137
+ /**
138
+ * Least decimals a scale with no tick will print. 0 leaves the span to
139
+ * decide alone, which is right for a price axis and too coarse for a bounded
140
+ * oscillator: see `precision()`.
141
+ *
142
+ * Ignored once `minMove` is set, because a declared tick is a stronger
143
+ * statement about the instrument than a floor is about the axis.
144
+ */
145
+ minPrecision: number;
130
146
  /** Linear, logarithmic or rebased (percentage / indexed-to-100) price↔y mapping. */
131
147
  mode: PriceScaleMode;
132
148
  /** Flip the axis (price increases downward) — for spread/short views. */
@@ -293,6 +309,15 @@ declare class PriceScale {
293
309
  * price tick size means nothing: precision comes from the transformed span
294
310
  * instead, with two decimals as the floor traders expect of a percentage
295
311
  * ("+3.42%") and more only when the visible band is tighter than that.
312
+ *
313
+ * A scale carrying no tick is not quoting an instrument, so the span is all
314
+ * there is to go on. That alone reads too coarse on a bounded oscillator: an
315
+ * RSI spanning 0 to 100 implies a step of 1 and prints a whole-number ladder,
316
+ * so a reading of 62.24 lands on a rung labelled "62" and a trader comparing
317
+ * it to a 70 level is reading a number that has been rounded past the part
318
+ * they care about. `minPrecision` is the floor for that case, and it is the
319
+ * same two decimals the percent branch above already settles on for the same
320
+ * reason.
296
321
  */
297
322
  precision(): number;
298
323
  /**
@@ -1643,7 +1668,12 @@ interface IndicatorCalcContext {
1643
1668
  /** Chart wall clock in UTC seconds, the clock the countdown row reads. */
1644
1669
  now(): number;
1645
1670
  /**
1646
- * The instrument's tick size, from the pane's price scale `minMove`.
1671
+ * The instrument's tick size, from the **price pane's** `minMove`.
1672
+ *
1673
+ * The price pane and not the indicator's own, because `calc` runs on the
1674
+ * instrument's bars whichever pane the plot lands in, and a study pane is not
1675
+ * quoted in the instrument's tick: an RSI is a dimensionless 0..100 band, so
1676
+ * its scale carries no tick at all to read.
1647
1677
  *
1648
1678
  * `undefined` when the host has not told the chart what it is, which is the
1649
1679
  * honest answer rather than a guessed 0.01: an indicator sizing a range in
@@ -2349,8 +2379,12 @@ interface IndicatorHost {
2349
2379
  /** Emit on the chart's event bus (indicator alerts, and `attach`'s own events). */
2350
2380
  emit?(event: string, payload: unknown): void;
2351
2381
  /**
2352
- * Tick size of the pane's price scale, or undefined when none is set.
2382
+ * Tick size of the named pane's price scale, or undefined when none is set.
2353
2383
  * Optional so a host predating it still satisfies this interface.
2384
+ *
2385
+ * Per pane, and the panes genuinely differ: a pane that does not quote the
2386
+ * instrument has no tick to report. Pane 0 is the price pane, so it is the
2387
+ * one to ask for the instrument's own step.
2354
2388
  */
2355
2389
  tickSize?(paneIndex: number): number | undefined;
2356
2390
  /** Pin a pane's price scale to a fixed range, or release it with `null`. */
@@ -3139,7 +3173,8 @@ interface ChartOptions {
3139
3173
  /**
3140
3174
  * Default price-scale options applied to every pane (tick size `minMove`,
3141
3175
  * `mode: 'linear' | 'logarithmic' | 'percentage' | 'indexed-to-100'`,
3142
- * `inverted`, and top/bottom margins).
3176
+ * `inverted`, and top/bottom margins). `minMove` is the instrument's, so it
3177
+ * lands only on panes that quote it, see `setPriceScaleOptions`.
3143
3178
  * Tune a single pane later via `chart.panes()[n].priceScale.setOptions(...)`.
3144
3179
  */
3145
3180
  priceScale?: Partial<PriceScaleOptions>;
@@ -3350,6 +3385,8 @@ declare class Chart {
3350
3385
  private _dragStartX;
3351
3386
  private _dragStartY;
3352
3387
  private _lastDragY;
3388
+ /** Pointers whose gesture the missed-release recovery already ended. */
3389
+ private readonly _endedPointers;
3353
3390
  private readonly _pointers;
3354
3391
  private _pinch;
3355
3392
  private _pinchPane;
@@ -3417,6 +3454,16 @@ declare class Chart {
3417
3454
  private _axisStartSpacing;
3418
3455
  private _priceFormatter;
3419
3456
  private _priceScaleOptions;
3457
+ /**
3458
+ * The panes whose numbers are the instrument's price, which is what decides
3459
+ * whether a chart-wide `minMove` reaches them (see `_scalePatchFor`).
3460
+ *
3461
+ * Held by pane identity rather than by index, for the reason spelled out in
3462
+ * `_createSeries`: `removePane` splices the array and `movePane` swaps two
3463
+ * entries, so a pane's slot number is not the pane. Weak because a removed
3464
+ * pane is destroyed and nothing else keeps it alive.
3465
+ */
3466
+ private readonly _pricePanes;
3420
3467
  private _timeFormatter;
3421
3468
  private _timezone;
3422
3469
  private _leftAxisWidth;
@@ -3704,8 +3751,41 @@ declare class Chart {
3704
3751
  * the right. Plot margins want this.
3705
3752
  * - `'all'`: the hidden overlay scales too. Almost nothing should: an
3706
3753
  * overlay's margins are its creator's placement, see `Pane.axisScales`.
3754
+ *
3755
+ * `minMove` is the one field no scope carries onto a pane that does not quote
3756
+ * the instrument, whichever scope is asked for: see `_scalePatchFor`. Every
3757
+ * other field is a property of the axis and reaches exactly as far as `scope`
3758
+ * says.
3707
3759
  */
3708
3760
  setPriceScaleOptions(patch: Partial<PriceScaleOptions>, scope?: 'primary' | 'axes' | 'all'): void;
3761
+ /**
3762
+ * A chart-wide price-scale patch as one pane should receive it.
3763
+ *
3764
+ * Every field in it describes the axis, except `minMove`, which describes the
3765
+ * **instrument**: it is the step the symbol trades in, 0.05 on an NSE equity.
3766
+ * A pane that plots something else is quoted in its own units, so handing it
3767
+ * that step is not a coarse answer but an answer to a different question. It
3768
+ * shipped as one: a host setting the instrument's 0.10 tick chart-wide made
3769
+ * `PriceScale.precision` report one decimal on *every* pane, so a William VIX
3770
+ * Fix reading 0.61 was labelled "0.6" and an RSI ladder read "70.0, 50.0,
3771
+ * 30.0". Withheld, those axes fall back to inferring precision from the range
3772
+ * they actually cover, which is the reading their own numbers imply.
3773
+ *
3774
+ * Only the chart-wide setters filter. An axis named outright
3775
+ * (`setPriceAxisOptions`, a series' `priceFormat`) is the caller saying what
3776
+ * that one axis quotes, and is obeyed.
3777
+ */
3778
+ private _scalePatchFor;
3779
+ /**
3780
+ * Record that a pane quotes the instrument, and hand it the tick it was not
3781
+ * given while it did not.
3782
+ *
3783
+ * Pane 0 is one from birth. Any other pane starts out an indicator's, so a
3784
+ * host adding a second symbol to a pane of its own has to be able to promote
3785
+ * one after the fact, or the comparison would lose the tick-sized axis it has
3786
+ * always had.
3787
+ */
3788
+ private _claimPricePane;
3709
3789
  /** The primary pane's price-scale options (what the Scales tab reads). */
3710
3790
  priceScaleOptions(): PriceScaleOptions;
3711
3791
  /**