openalgo-charts 2.5.7 → 2.5.8
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 +18 -16
- package/dist/index.d.ts +136 -22
- package/dist/openalgo-charts.indicators.mjs +1 -1
- package/dist/openalgo-charts.indicators.mjs.map +1 -1
- package/dist/openalgo-charts.mjs +1 -1
- package/dist/openalgo-charts.mjs.map +1 -1
- package/dist/openalgo-charts.standalone.js +1 -1
- package/dist/openalgo-charts.standalone.js.map +1 -1
- package/dist/openalgo-charts.webgl.mjs +1 -1
- package/dist/openalgo-charts.webgl.mjs.map +1 -1
- package/dist/webgl/index.d.ts +4 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ with no runtime dependencies.
|
|
|
12
12
|
[](https://www.npmjs.com/package/openalgo-charts)
|
|
13
13
|
[](./LICENSE)
|
|
14
14
|
[](https://www.npmjs.com/package/openalgo-charts)
|
|
15
|
-
[](#develop)
|
|
16
16
|
[](#principles)
|
|
17
17
|
|
|
18
18
|
[**Documentation**](https://marketcalls.github.io/openalgo-charts/) · [**Live examples**](https://marketcalls.github.io/openalgo-charts/examples) · [**Getting started**](./docs/getting-started.md) · [**Migrating to 2.0**](./docs/migrating-to-2.md) · [**Architecture**](./ARCHITECTURE.md)
|
|
@@ -25,7 +25,7 @@ with no runtime dependencies.
|
|
|
25
25
|
npm install openalgo-charts
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
Current version: **2.5.
|
|
28
|
+
Current version: **2.5.8**, a rendering performance release: a live tick no longer rebuilds the time index or rewrites every study plot, sixteen common built-in studies update without a pass over the whole history, a tick or a study recompute repaints only the panes it changes, a zoomed-out chart draws one stick per pixel column (the level of detail, now on by default), primitives can bound their hit tests, and a render bench holds frame budgets per bar count in CI. 2.5.7 split the chart's code by responsibility with no change to the API or to what it paints.
|
|
29
29
|
See the [changelog](./CHANGELOG.md) for release notes.
|
|
30
30
|
|
|
31
31
|
## Quick start
|
|
@@ -56,7 +56,7 @@ for live data, or [the widget example](#the-whole-terminal-in-one-call) for char
|
|
|
56
56
|
|
|
57
57
|
## Architecture
|
|
58
58
|
|
|
59
|
-
<a href="docs/architecture-diagram.svg"><img src="docs/architecture-diagram.svg" alt="OpenAlgo Charts 2.5.
|
|
59
|
+
<a href="docs/architecture-diagram.svg"><img src="docs/architecture-diagram.svg" alt="OpenAlgo Charts 2.5.8 architecture: host responsibilities, the base data-to-rendering pipeline with alerts and shared replay, and eight optional tiers including workspace storage, trading tools and the widget" width="920" /></a>
|
|
60
60
|
|
|
61
61
|
How data reaches the chart, what your app owns, and which features you can import.
|
|
62
62
|
[Open the full-size diagram](docs/architecture-diagram.svg).
|
|
@@ -107,7 +107,7 @@ You can also load the library from a CDN in a plain HTML page:
|
|
|
107
107
|
```html
|
|
108
108
|
<div id="chart" style="width:100vw;height:100vh"></div>
|
|
109
109
|
<script type="module">
|
|
110
|
-
import { createChart, generateBars } from 'https://unpkg.com/openalgo-charts@2.5.
|
|
110
|
+
import { createChart, generateBars } from 'https://unpkg.com/openalgo-charts@2.5.8/dist/openalgo-charts.mjs';
|
|
111
111
|
const chart = createChart(document.getElementById('chart'), { timezone: 'Asia/Kolkata' });
|
|
112
112
|
chart.addSeries('candlestick').setData(generateBars(1700000000, 200, 3600));
|
|
113
113
|
chart.fitContent();
|
|
@@ -165,8 +165,8 @@ Unused optional tiers stay out of the base chart download.
|
|
|
165
165
|
|
|
166
166
|
| Import | Contents | Brotli |
|
|
167
167
|
|---|---|---|
|
|
168
|
-
| `openalgo-charts` | Engine, 13 chart types, panes and scales, custom indicator registry, primitives, alerts, replay, comparisons, chart linking, state, feeds, bar cache, trading overlays, CSV and SVG export |
|
|
169
|
-
| `openalgo-charts/indicators` | 105 built-in indicators, calculation helpers and helpers for studies that use external data |
|
|
168
|
+
| `openalgo-charts` | Engine, 13 chart types, panes and scales, custom indicator registry, primitives, alerts, replay, comparisons, chart linking, state, feeds, bar cache, trading overlays, CSV and SVG export | 130.37 kB |
|
|
169
|
+
| `openalgo-charts/indicators` | 105 built-in indicators, calculation helpers and helpers for studies that use external data | 40.38 kB |
|
|
170
170
|
| `openalgo-charts/draw` | 87 drawing tools + a headless drawing controller, clipboard, settings schema, level palette, freehand geometry and SVG icons | 48.42 kB |
|
|
171
171
|
| `openalgo-charts/transform` | Heikin Ashi, Renko, Range bars, Line Break, Point & Figure, Kagi, and symbol arithmetic (`AAPL/MSFT`) | 4.50 kB |
|
|
172
172
|
| `openalgo-charts/profile` | Volume Profile, Market Profile (TPO) with compact pixel letters, Footprint, order flow | 14.96 kB |
|
|
@@ -175,7 +175,7 @@ Unused optional tiers stay out of the base chart download.
|
|
|
175
175
|
| `openalgo-charts/widget` | `createWidget`: toolbar, Data, Objects, Watchlist and News dock, account summary, symbol search, dialogs, mobile controls, shortcuts and optional layout persistence | 92.72 kB |
|
|
176
176
|
| `openalgo-charts/workspace` | Validated workspace and indicator-template documents, named watchlists, named catalogs with revision checks, asynchronous storage and an IndexedDB adapter; no DOM | 10.47 kB |
|
|
177
177
|
|
|
178
|
-
Everything together is **
|
|
178
|
+
Everything together is **364.91 kB Brotli**; a widget terminal with built-in indicators (base + draw + indicators + widget) is 311.90 kB. Figures are measured from the 2.5.8 release build. The trade tier is 16.69 kB on its own; base + trade costs 147.06 kB. Sizes use decimal kB.
|
|
179
179
|
|
|
180
180
|
## What's built
|
|
181
181
|
|
|
@@ -501,17 +501,17 @@ Enforced in CI by [`size-limit`](./.size-limit.json). Nothing is excluded, becau
|
|
|
501
501
|
|
|
502
502
|
| Bundle | Limit | Actual |
|
|
503
503
|
|---|---|---|
|
|
504
|
-
| Base engine |
|
|
505
|
-
| Base + trade |
|
|
506
|
-
| Indicators tier |
|
|
504
|
+
| Base engine | 130.38 kB | 130.37 kB |
|
|
505
|
+
| Base + trade | 147.07 kB | 147.06 kB |
|
|
506
|
+
| Indicators tier | 40.39 kB | 40.38 kB |
|
|
507
507
|
| Draw tier | 48.42 kB | 48.42 kB |
|
|
508
508
|
| Transform tier | 6 kB | 4.50 kB |
|
|
509
509
|
| Profile tier | 15 kB | 14.96 kB |
|
|
510
510
|
| WebGL2 tier | 7 kB | 6.39 kB |
|
|
511
511
|
| Widget tier | 92.72 kB | 92.72 kB |
|
|
512
|
-
| Widget terminal (base + draw + indicators + widget) |
|
|
512
|
+
| Widget terminal (base + draw + indicators + widget) | 311.90 kB | 311.90 kB |
|
|
513
513
|
| Workspace tier | 10.47 kB | 10.47 kB |
|
|
514
|
-
| **Everything** |
|
|
514
|
+
| **Everything** | 364.91 kB | 364.91 kB |
|
|
515
515
|
|
|
516
516
|
## Documentation
|
|
517
517
|
|
|
@@ -556,18 +556,20 @@ See [Contributing](./CONTRIBUTING.md) for setup, targeted checks, documentation
|
|
|
556
556
|
```bash
|
|
557
557
|
npm install # install dev toolchain
|
|
558
558
|
npm run typecheck # strict TypeScript check
|
|
559
|
-
npm test # engine unit tests (Vitest):
|
|
559
|
+
npm test # engine unit tests (Vitest): 9374 across 418 files
|
|
560
560
|
npm run test:demo # reference-host tests: 653 across 62 files
|
|
561
561
|
npm run test:endurance # node endurance-harness tests: 7 cases
|
|
562
562
|
npm run build # Rollup -> dist/ (minified ESM per tier + types)
|
|
563
563
|
npm run size # size-limit (Brotli) against the budget
|
|
564
564
|
npm run e2e # Playwright Chromium smoke tests
|
|
565
|
+
npm run bench:render # render bench: pan, zoom-out and tick frame budgets per bar count
|
|
565
566
|
npm run verify # lint + types + unit + endurance harness + build + demo + dts + size + shake
|
|
566
567
|
```
|
|
567
568
|
|
|
568
569
|
## Principles
|
|
569
570
|
|
|
570
|
-
- **Canvas rendering, two canvases per pane**: a base canvas for the chart, its axes and the price lines (order and position lines included), and an overlay canvas for the crosshair, the drawings and the other top-layer primitives, so a crosshair move repaints only the overlay. No SVG and no DOM element per bar; SVG appears only in `exportSVG` output and in the icon markup of the draw and widget tiers. The optional WebGL tier draws on a shared offscreen surface and copies into the base canvas. Frame times are recorded
|
|
571
|
+
- **Canvas rendering, two canvases per pane**: a base canvas for the chart, its axes and the price lines (order and position lines included), and an overlay canvas for the crosshair, the drawings and the other top-layer primitives, so a crosshair move repaints only the overlay. No SVG and no DOM element per bar; SVG appears only in `exportSVG` output and in the icon markup of the draw and widget tiers. The optional WebGL tier draws on a shared offscreen surface and copies into the base canvas. Frame times are budgeted per bar count by the render bench ([performance notes](./docs/performance-notes.md)) and recorded over long sessions by [browser endurance](./docs/browser-endurance.md).
|
|
572
|
+
- **Repaint what changed, on one loop**: a live tick repaints the price pane and the panes of the studies computed from it, and a study recompute repaints only the panes its output lands on; a write that moves the shared time scale, such as an appended bar, repaints every pane. The bottom pane repaints with them while the corner clock is on, and every pane with a price series while the bar countdown is on, since both read the time as their pane paints. Kinetic scroll and the eased wheel zoom are stepped inside the chart's own animation frame, so each frame paints the step it made.
|
|
571
573
|
- **Gapless time axis by default**: weekends, holidays, and session breaks collapse.
|
|
572
574
|
- **Registries, not switches**: chart types, indicators, and drawing tools are all descriptors. Adding one is a registration, never a core change.
|
|
573
575
|
- **Zero runtime dependencies**: nothing is excluded from the size budget.
|
|
@@ -575,14 +577,14 @@ npm run verify # lint + types + unit + endurance harness + build + demo + dt
|
|
|
575
577
|
|
|
576
578
|
## Status & limitations
|
|
577
579
|
|
|
578
|
-
Version **2.5.
|
|
580
|
+
Version **2.5.8**. All engine build phases are implemented. Upgrading a 1.9.x host: [Migrating to 2.0](./docs/migrating-to-2.md).
|
|
579
581
|
|
|
580
582
|
Known gaps, stated plainly:
|
|
581
583
|
|
|
582
584
|
- **Footprint and order flow need trade-by-trade data classified bid/ask.** OpenAlgo does not store this by default, so it is live-session-only unless you add a tick recorder: `FootprintAggregator` is the live path. See [`ARCHITECTURE.md`](./ARCHITECTURE.md) §6A.
|
|
583
585
|
- **Only `Footprint` is theme-aware among the profile primitives.** `VolumeProfile`, `MarketProfile` and `HorizontalProfile` never read `rc.theme`; their defaults are dark-tuned, so a light theme needs explicit colours. `HorizontalProfile` also hardcodes its POC / value-area line colours and has no `setOptions`.
|
|
584
586
|
- The OpenAlgo **WS/trade adapter wire schemas** ship with injectable transports and offline tests, but the exact field names should be verified against your running OpenAlgo build.
|
|
585
|
-
- **Large histories slow the live path.** With 150 bars in view, two charts and five studies each, the
|
|
587
|
+
- **Large histories slow the live path.** With 150 bars in view, two charts and five studies each, the frame-interval p95 recorded on 2.5.5 was 17 ms at 2,000 bars per chart and 717 ms at 50,000. The view is the same in both, so the extra time is work over the whole history, such as recomputing every study on each tick. The workload, machine and commands are in [browser endurance](./docs/browser-endurance.md); that workload has not been rerun since. 2.5.8 cut the tick: a study writes only the plot points that moved and sixteen common built-ins step from the last bar, and on the render bench a ten-study tick at 50,000 bars fell from a p95 of 1166.3 ms to 49.2 ms on `canvas2d` ([performance notes](./docs/performance-notes.md)). It still grows with the loaded history rather than the view, so bound retained history for sustained sessions.
|
|
586
588
|
- **The WebGL2 backend draws the standard chart types.** Kagi, point-and-figure and custom chart types, drawings, text and every primitive stay on the 2D context; `renderer: 'auto'` moves the series pass of the standard types to the GPU and is not a second renderer for everything. Its frame time against Canvas2D has not been measured.
|
|
587
589
|
|
|
588
590
|
See [`ARCHITECTURE.md`](./ARCHITECTURE.md) §13a for the full deferred list.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Library version string. Matches package.json (including locally prepared releases). */
|
|
2
|
-
declare const VERSION = "2.5.
|
|
2
|
+
declare const VERSION = "2.5.8";
|
|
3
3
|
/** Returns the current library version. */
|
|
4
4
|
declare function version(): string;
|
|
5
5
|
|
|
@@ -7,9 +7,10 @@ declare function version(): string;
|
|
|
7
7
|
* Invalidation model (ARCHITECTURE.md §3.2).
|
|
8
8
|
*
|
|
9
9
|
* A single global level is too coarse for multi-pane indicators and trade
|
|
10
|
-
* overlays, so the mask carries a **global level + a per-pane map
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* overlays, so the mask carries a **global level + a per-pane map**. Multiple
|
|
11
|
+
* invalidations within one frame coalesce via {@link InvalidateMask.merge}. It
|
|
12
|
+
* also keeps a queue of time-scale operations that nothing in the chart reads
|
|
13
|
+
* (see {@link TimeScaleOp}).
|
|
13
14
|
*/
|
|
14
15
|
/** How much of a pane (or the whole chart) must be repainted this frame. */
|
|
15
16
|
declare const InvalidationLevel: {
|
|
@@ -29,9 +30,11 @@ interface PaneInvalidation {
|
|
|
29
30
|
autoScale: boolean;
|
|
30
31
|
}
|
|
31
32
|
/**
|
|
32
|
-
* Discrete time-scale operations
|
|
33
|
-
* and merges them,
|
|
34
|
-
* fit and reset change the shared time scale directly
|
|
33
|
+
* Discrete time-scale operations a mask can queue, kept for compatibility.
|
|
34
|
+
* The mask queues and merges them, and the chart never reads the queue: pan,
|
|
35
|
+
* zoom, fit and reset change the shared time scale directly, and the kinetic
|
|
36
|
+
* and wheel-zoom glides are stepped at the top of the render loop's frame
|
|
37
|
+
* (ARCHITECTURE.md §3.2).
|
|
35
38
|
*/
|
|
36
39
|
type TimeScaleOp = {
|
|
37
40
|
type: 'fitContent';
|
|
@@ -56,6 +59,7 @@ declare class InvalidateMask {
|
|
|
56
59
|
invalidatePane(paneIndex: number, invalidation: PaneInvalidation): void;
|
|
57
60
|
paneInvalidation(paneIndex: number): PaneInvalidation | undefined;
|
|
58
61
|
panes(): ReadonlyMap<number, PaneInvalidation>;
|
|
62
|
+
/** Queue an operation. The chart never reads the queue; see {@link TimeScaleOp}. */
|
|
59
63
|
addTimeScaleOp(op: TimeScaleOp): void;
|
|
60
64
|
timeScaleOps(): readonly TimeScaleOp[];
|
|
61
65
|
isEmpty(): boolean;
|
|
@@ -739,10 +743,26 @@ declare class DataLayer {
|
|
|
739
743
|
createSeries(): SeriesId;
|
|
740
744
|
removeSeries(id: SeriesId): void;
|
|
741
745
|
/**
|
|
742
|
-
* Bulk-load (full replace) one series' data
|
|
743
|
-
*
|
|
746
|
+
* Bulk-load (full replace) one series' data. Input is sorted and
|
|
747
|
+
* de-duplicated by time by a private `sortedUniqueByTime`.
|
|
748
|
+
*
|
|
749
|
+
* The shared index is rebuilt only when the set of times changes. A rebuild
|
|
750
|
+
* re-merges every series on the chart, and most whole writes do not change
|
|
751
|
+
* the set: a study's plots carry the source's own times, which the source
|
|
752
|
+
* put in the index before any study recomputed, and a colour overlay on the
|
|
753
|
+
* source keeps its times. Ten studies on a long history used to pay for the
|
|
754
|
+
* index two dozen times per tick while it came out unchanged.
|
|
744
755
|
*/
|
|
745
756
|
setSeriesData(id: SeriesId, bars: readonly Bar[]): void;
|
|
757
|
+
/**
|
|
758
|
+
* Bring the index up to date without a rebuild for a series whose bars went
|
|
759
|
+
* from `previous` to `next`, when the set of times cannot have changed but
|
|
760
|
+
* for times past the right edge: every time of `previous` is still in
|
|
761
|
+
* `next`, and every time of `next` is in the index already or later than all
|
|
762
|
+
* of it. False when a time went away (another series may or may not still
|
|
763
|
+
* hold it) or a new one lands inside the axis, and the caller rebuilds.
|
|
764
|
+
*/
|
|
765
|
+
private _extendIndex;
|
|
746
766
|
/**
|
|
747
767
|
* Upsert bars into a series by time (used for history paging / backfill /
|
|
748
768
|
* out-of-order corrections — ARCHITECTURE.md §4.2). Existing times are
|
|
@@ -789,8 +809,8 @@ declare class DataLayer {
|
|
|
789
809
|
timeToIndexFloat(time: number): number;
|
|
790
810
|
/**
|
|
791
811
|
* The future plan for the current last bars and calendar. A rebuild that
|
|
792
|
-
* leaves the recent bars as they were (
|
|
793
|
-
*
|
|
812
|
+
* leaves the recent bars as they were (a page of older history, a gap filled
|
|
813
|
+
* well to the left) keeps the plan and the times it already generated.
|
|
794
814
|
*/
|
|
795
815
|
private _plan;
|
|
796
816
|
/**
|
|
@@ -1049,7 +1069,11 @@ interface PrimitiveHit {
|
|
|
1049
1069
|
/** Distinguishes hover regions which share one external click ID. Omission uses externalId. */
|
|
1050
1070
|
hoverKey?: string;
|
|
1051
1071
|
zOrder: ZOrder;
|
|
1052
|
-
/**
|
|
1072
|
+
/**
|
|
1073
|
+
* Pixel distance from the cursor (smaller wins ties before z-order). Never
|
|
1074
|
+
* negative: zero is a hit on the shape itself, and the pane stops asking
|
|
1075
|
+
* once the front band has one.
|
|
1076
|
+
*/
|
|
1053
1077
|
distance: number;
|
|
1054
1078
|
cursor?: string;
|
|
1055
1079
|
/** Coordinate scale for a bound primitive's drag prices. Unbound hits omit it. */
|
|
@@ -1114,6 +1138,30 @@ interface IPrimitive {
|
|
|
1114
1138
|
afterAutoscale?(): void;
|
|
1115
1139
|
/** Optional: topmost hit under (x,y) in media px (relative to the pane plot). */
|
|
1116
1140
|
hitTest?(x: number, y: number, rc: PrimitiveRenderContext): PrimitiveHit | null;
|
|
1141
|
+
/**
|
|
1142
|
+
* Optional: the box, in the coordinates `hitTest` receives, outside which it
|
|
1143
|
+
* answers null, or null when nothing of this primitive can be hit at all.
|
|
1144
|
+
* Edges are inclusive, and an unbounded side may be infinite.
|
|
1145
|
+
*
|
|
1146
|
+
* A pointer move then asks `hitTest` only of primitives whose box it is in,
|
|
1147
|
+
* so a pane carrying hundreds of them pays for the few near the pointer.
|
|
1148
|
+
* The pane asks for the box once and reuses it while nothing it can follow
|
|
1149
|
+
* changes: the time scale and the bars' times, the pane's price scales, its
|
|
1150
|
+
* size and axes, the pixel ratio, the hover and drag state, and the
|
|
1151
|
+
* primitive's own state, which it announces through `requestUpdate`. A box
|
|
1152
|
+
* that follows anything else, such as bar prices, has to request an update
|
|
1153
|
+
* when that changes, or leave this out. Work the box out from the same
|
|
1154
|
+
* geometry `hitTest` answers from, `rc` or what the last `draw` recorded: a
|
|
1155
|
+
* box asked for between a change and the frame that paints it is asked for
|
|
1156
|
+
* again once that frame is painted. Absent, every pointer move asks
|
|
1157
|
+
* `hitTest`.
|
|
1158
|
+
*/
|
|
1159
|
+
hitBounds?(rc: PrimitiveRenderContext): {
|
|
1160
|
+
left: number;
|
|
1161
|
+
top: number;
|
|
1162
|
+
right: number;
|
|
1163
|
+
bottom: number;
|
|
1164
|
+
} | null;
|
|
1117
1165
|
attached?(host: PrimitiveHost): void;
|
|
1118
1166
|
detached?(): void;
|
|
1119
1167
|
}
|
|
@@ -2167,6 +2215,11 @@ interface IndicatorHost {
|
|
|
2167
2215
|
legendRowsOn(paneIndex: number): number;
|
|
2168
2216
|
/** The instrument's own series, for a descriptor anchoring marks to price. */
|
|
2169
2217
|
primarySeries?(): SeriesApi | null;
|
|
2218
|
+
/**
|
|
2219
|
+
* A series for one plot. The study writes it with `setData` for a whole pass
|
|
2220
|
+
* and, from 2.5.8, with `update` for the points a live tick moved (older
|
|
2221
|
+
* points included), so a host's own series must implement both as documented.
|
|
2222
|
+
*/
|
|
2170
2223
|
addIndicatorSeries(type: string, paneIndex: number, style: Record<string, unknown> | undefined, priceScaleId: string | undefined,
|
|
2171
2224
|
/** Axis/crosshair formatting for the scale this plot maps to. */
|
|
2172
2225
|
priceFormat?: PriceFormat): SeriesApi;
|
|
@@ -3932,6 +3985,10 @@ interface IRenderBackend {
|
|
|
3932
3985
|
* Paint one series. Same contract as `RendererEntry.draw` minus the context:
|
|
3933
3986
|
* `priceToY` and `items[].x` are media px, and the renderer snaps to device
|
|
3934
3987
|
* pixels with `dpr` itself.
|
|
3988
|
+
*
|
|
3989
|
+
* `items` and the objects in it belong to the pane, which rewrites them in
|
|
3990
|
+
* place the next time it draws this series, so a backend that keeps any of
|
|
3991
|
+
* it past that (a batch held across frames, say) copies what it keeps.
|
|
3935
3992
|
*/
|
|
3936
3993
|
drawSeries(entry: RendererEntry, items: readonly DrawItem[], priceToY: (price: number) => number, barSpacing: number, dpr: number, style: SeriesStyle, rc: SeriesRenderContext): void;
|
|
3937
3994
|
/** Finish the frame: flush whatever the backend batched. */
|
|
@@ -4058,9 +4115,12 @@ interface PaneRenderContext {
|
|
|
4058
4115
|
* neither paint nor hit-test until it opens again.
|
|
4059
4116
|
*/
|
|
4060
4117
|
collapsed?: boolean;
|
|
4061
|
-
/**
|
|
4118
|
+
/**
|
|
4119
|
+
* Draw one OHLC-preserving stick per device-pixel column once bars are
|
|
4120
|
+
* narrower than a column (§4.4); false draws every bar at every zoom.
|
|
4121
|
+
*/
|
|
4062
4122
|
conflate: boolean;
|
|
4063
|
-
/**
|
|
4123
|
+
/** Columns this many sticks wide (1 = one stick, the default; higher = coarser). */
|
|
4064
4124
|
conflationFactor: number;
|
|
4065
4125
|
/** Active palette — drives chrome, series defaults, and trade colors. */
|
|
4066
4126
|
theme: ChartTheme;
|
|
@@ -4154,6 +4214,12 @@ declare class Pane {
|
|
|
4154
4214
|
private _destroyed;
|
|
4155
4215
|
private _width;
|
|
4156
4216
|
private _height;
|
|
4217
|
+
/** Each series' draw items, reused from frame to frame (src/render/draw-items.ts). */
|
|
4218
|
+
private readonly _drawItems;
|
|
4219
|
+
/** Hit boxes of the primitives that declare one, kept while nothing they follow changes (src/render/hit-boxes.ts). */
|
|
4220
|
+
private readonly _hitBoxes;
|
|
4221
|
+
/** Bumped by every change on this pane that can move a primitive's context: series, scales, axes, primitives. */
|
|
4222
|
+
private _hitEpoch;
|
|
4157
4223
|
/**
|
|
4158
4224
|
* `backend` defaults to the 2D one so a pane built on its own (tests, a host
|
|
4159
4225
|
* composing panes by hand) paints the way it always has; the chart passes
|
|
@@ -4335,8 +4401,26 @@ declare class Pane {
|
|
|
4335
4401
|
* band order, as `bestHit` ranks them. A hit painted by a primitive placed
|
|
4336
4402
|
* in the series band names it (`paintedBy`), so the chart can rank it
|
|
4337
4403
|
* against a series painted over it too.
|
|
4404
|
+
*
|
|
4405
|
+
* Two things keep a pointer move from asking every primitive. One that
|
|
4406
|
+
* declares a hit box is skipped when the point is outside it; the boxes are
|
|
4407
|
+
* kept while nothing they depend on changes (`_checkHitBoxes`). And the
|
|
4408
|
+
* walk stops at an exact hit in the front band, which nothing after it can
|
|
4409
|
+
* outrank: a later primitive would need a smaller distance than zero or a
|
|
4410
|
+
* band above the front one, and the order the walk visits primitives in
|
|
4411
|
+
* only ever breaks exact ties, which the first hit wins.
|
|
4338
4412
|
*/
|
|
4339
4413
|
hitTestPrimitives(x: number, y: number, ctx: PaneRenderContext, except?: IPrimitive | null): PrimitiveHit | null;
|
|
4414
|
+
/** After an on-screen paint: what the pane shows now is what the key describes (src/render/hit-boxes.ts). */
|
|
4415
|
+
private _paintedHitBoxes;
|
|
4416
|
+
/**
|
|
4417
|
+
* Read the key the kept hit boxes are checked against: what a primitive's
|
|
4418
|
+
* render context can map with (the time scale and the bars' times, every
|
|
4419
|
+
* price scale here, the pane's size and axes, the pixel ratio, the readout
|
|
4420
|
+
* scale, hover and drag, the theme, the session calendar) and this pane's
|
|
4421
|
+
* own count of changes.
|
|
4422
|
+
*/
|
|
4423
|
+
private _checkHitBoxes;
|
|
4340
4424
|
/**
|
|
4341
4425
|
* Draw the rule over this pane's top edge in `color` at device pixel ratio
|
|
4342
4426
|
* `dpr`, or none with a null colour.
|
|
@@ -5132,9 +5216,25 @@ interface ChartOptions {
|
|
|
5132
5216
|
* tool is being placed a double-click finishes the shape whatever this says.
|
|
5133
5217
|
*/
|
|
5134
5218
|
doubleClick?: DoubleClickAction;
|
|
5135
|
-
/**
|
|
5219
|
+
/**
|
|
5220
|
+
* Level of detail for a zoomed-out chart (§4.4). Default true: once bars are
|
|
5221
|
+
* narrower than the stick a candle is drawn with (about one CSS px; exactly
|
|
5222
|
+
* one at a whole pixel ratio), the bars sharing a device-pixel column are
|
|
5223
|
+
* drawn as one OHLC-preserving stick (open of the first, close of the last,
|
|
5224
|
+
* the column's high and low), and line and histogram series keep each
|
|
5225
|
+
* column's first, lowest, highest and last values. A frame then costs the
|
|
5226
|
+
* plot's width, not the number of bars in view. Above that spacing nothing
|
|
5227
|
+
* changes. Data, autoscale, indicators and the crosshair still see every
|
|
5228
|
+
* bar. `false` draws every bar at every zoom.
|
|
5229
|
+
*
|
|
5230
|
+
* The default time scale never zooms out past one bar per CSS px
|
|
5231
|
+
* (`timeScale.minBarSpacing: 1`), so it matters once a host lowers that floor.
|
|
5232
|
+
*/
|
|
5136
5233
|
conflate?: boolean;
|
|
5137
|
-
/**
|
|
5234
|
+
/**
|
|
5235
|
+
* Column width in sticks (default 1). Higher merges into wider columns, and
|
|
5236
|
+
* from spacings that many times wider, for a coarser, cheaper picture.
|
|
5237
|
+
*/
|
|
5138
5238
|
conflationFactor?: number;
|
|
5139
5239
|
/**
|
|
5140
5240
|
* Which backend paints the series. `'canvas2d'` (the default) is the 2D
|
|
@@ -5918,6 +6018,8 @@ declare class Chart {
|
|
|
5918
6018
|
private readonly _priceAxisWidth;
|
|
5919
6019
|
private readonly _timeAxisHeight;
|
|
5920
6020
|
private _pending;
|
|
6021
|
+
/** While a frame steps the glides and the studies: what they invalidate is painted by that frame. */
|
|
6022
|
+
private _framing;
|
|
5921
6023
|
private _scaleMutationDepth;
|
|
5922
6024
|
/** Size and device-pixel-ratio observation; see chart-pixels.ts. */
|
|
5923
6025
|
private readonly _pixels;
|
|
@@ -6915,6 +7017,7 @@ declare class Chart {
|
|
|
6915
7017
|
*/
|
|
6916
7018
|
private _paintNow;
|
|
6917
7019
|
private _onFrame;
|
|
7020
|
+
private _paintFrame;
|
|
6918
7021
|
private readonly _onPointerEnter;
|
|
6919
7022
|
private readonly _onContextMenu;
|
|
6920
7023
|
private readonly _onPointerDown;
|
|
@@ -9250,12 +9353,23 @@ declare function supertrendSeries(bars: readonly Bar[], period?: number, multipl
|
|
|
9250
9353
|
};
|
|
9251
9354
|
|
|
9252
9355
|
/**
|
|
9253
|
-
*
|
|
9254
|
-
*
|
|
9255
|
-
*
|
|
9256
|
-
*
|
|
9257
|
-
*
|
|
9258
|
-
* bars
|
|
9356
|
+
* OHLC-preserving conflation (ARCHITECTURE.md §4.4): what a zoomed-out series
|
|
9357
|
+
* pass draws instead of one mark per bar.
|
|
9358
|
+
*
|
|
9359
|
+
* Once bars are narrower than the stick a candle is drawn with, several of them
|
|
9360
|
+
* land in the same device-pixel column, and drawing each one paints the same
|
|
9361
|
+
* pixels over and over: 200,000 bars on a 1,000 px plot put two hundred marks
|
|
9362
|
+
* in every column where one would do. The level of detail at the end of this
|
|
9363
|
+
* file merges what shares a column into one OHLC-preserving stick (open =
|
|
9364
|
+
* first, close = last, high = max, low = min, volume = sum; never a lossy
|
|
9365
|
+
* average), so a frame costs the plot's width rather than the history's
|
|
9366
|
+
* length. It is on by default (`conflate`) and inert above its threshold: a
|
|
9367
|
+
* chart zoomed in far enough that every bar has a column of its own paints
|
|
9368
|
+
* exactly what it always did.
|
|
9369
|
+
*
|
|
9370
|
+
* The group helpers (`conflationGroupSize`, `conflateBars`, `conflateItems`,
|
|
9371
|
+
* `mergeBars`) merge fixed-size groups, for a host that downsamples bars
|
|
9372
|
+
* itself; the pane merges by column.
|
|
9259
9373
|
*/
|
|
9260
9374
|
|
|
9261
9375
|
/**
|