openalgo-charts 2.4.5 → 2.4.6
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 +25 -21
- package/dist/index.d.ts +93 -5
- package/dist/openalgo-charts.draw.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.trade.mjs.map +1 -1
- package/dist/openalgo-charts.widget.mjs +1 -1
- package/dist/openalgo-charts.widget.mjs.map +1 -1
- package/dist/widget/index.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
**A from-scratch, dependency-free HTML5-canvas charting engine for OpenAlgo.**
|
|
6
6
|
|
|
7
|
-
Professional interactive charts, 105 built-in indicators plus your own custom ones, 85 drawing tools, order flow, market replay, linked chart grids, on-chart trading, vector SVG export and an optional WebGL2 backend. Nine lazy-loaded tiers, zero runtime dependencies, 91.
|
|
7
|
+
Professional interactive charts, 105 built-in indicators plus your own custom ones, 85 drawing tools, order flow, market replay, linked chart grids, on-chart trading, vector SVG export and an optional WebGL2 backend. Nine lazy-loaded tiers, zero runtime dependencies, 91.55 kB Brotli for the base engine, and a one-call widget tier that adds the toolbar, drawing rail, dialogs and shortcuts.
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/openalgo-charts)
|
|
10
10
|
[](./LICENSE)
|
|
11
|
-
[](#size-budget)
|
|
12
|
+
[](#develop)
|
|
13
13
|
[](#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) · [**Migrating to 2.0**](./docs/migrating-to-2.md) · [**Architecture**](./ARCHITECTURE.md)
|
|
@@ -53,13 +53,17 @@ Every chart in the [live gallery](https://marketcalls.github.io/openalgo-charts/
|
|
|
53
53
|
|
|
54
54
|
## Install
|
|
55
55
|
|
|
56
|
-
Current version: **2.4.
|
|
56
|
+
Current version: **2.4.6**.
|
|
57
57
|
|
|
58
|
-
This release adds
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
See the [2.4.
|
|
58
|
+
This release adds optional study source buttons, candle-anchored signal markers
|
|
59
|
+
and configurable legend controls. It fixes missing markers at plot gaps, marker
|
|
60
|
+
price scales and transparent legend readings. Existing studies keep plot anchoring
|
|
61
|
+
by default; hosts opt in to price anchoring and supply their own source editor.
|
|
62
|
+
See the [2.4.6 changelog](./CHANGELOG.md#246).
|
|
63
|
+
|
|
64
|
+
To try these controls locally, run the [yfinance reference host](./examples/yfinance/README.md)
|
|
65
|
+
and add **Source signal sample** from Indicators. Its source button opens the
|
|
66
|
+
host-owned code, and Readout settings include **Legend button size** for each chart.
|
|
63
67
|
|
|
64
68
|
```bash
|
|
65
69
|
npm install openalgo-charts
|
|
@@ -88,7 +92,7 @@ in front of npm rather than being places you upload to. A chart is one HTML file
|
|
|
88
92
|
```html
|
|
89
93
|
<div id="chart" style="width:100vw;height:100vh"></div>
|
|
90
94
|
<script type="module">
|
|
91
|
-
import { createChart } from 'https://unpkg.com/openalgo-charts@2.4.
|
|
95
|
+
import { createChart } from 'https://unpkg.com/openalgo-charts@2.4.6/dist/openalgo-charts.mjs';
|
|
92
96
|
const chart = createChart(document.getElementById('chart'), { timezone: 'Asia/Kolkata' });
|
|
93
97
|
chart.addSeries('candlestick').setData(bars);
|
|
94
98
|
</script>
|
|
@@ -130,17 +134,17 @@ Import only what you use. Each tier is a separate bundle that registers into the
|
|
|
130
134
|
|
|
131
135
|
| Import | Contents | Brotli |
|
|
132
136
|
|---|---|---|
|
|
133
|
-
| `openalgo-charts` | Engine, 13 chart types, panes & scales, primitives, registries, chart state, chart linking, bar cache, interval registry, trading overlay, SVG export, render backend port, OpenAlgo feeds | 91.
|
|
137
|
+
| `openalgo-charts` | Engine, 13 chart types, panes & scales, primitives, registries, chart state, chart linking, bar cache, interval registry, trading overlay, SVG export, render backend port, OpenAlgo feeds | 91.55 kB |
|
|
134
138
|
| `openalgo-charts/indicators` | 105 built-in indicators, the `registerIndicator` contract for your own, and the Tier-2 (external-data) contract | 29.84 kB |
|
|
135
139
|
| `openalgo-charts/draw` | 85 drawing tools + a headless drawing controller, clipboard, settings schema, level palette, freehand geometry and SVG icons | 35.43 kB |
|
|
136
140
|
| `openalgo-charts/transform` | Heikin Ashi, Renko, Range bars, Line Break, Point & Figure, Kagi, and symbol arithmetic (`AAPL/MSFT`) | 4.50 kB |
|
|
137
141
|
| `openalgo-charts/profile` | Volume Profile, Market Profile (TPO) with compact pixel letters, Footprint, order flow | 14.96 kB |
|
|
138
142
|
| `openalgo-charts/trade` | Order / position / bracket tools + DOM ladder | 8.01 kB |
|
|
139
143
|
| `openalgo-charts/webgl` | WebGL2 series backend: batched, analytically anti-aliased GPU rendering of the standard chart types behind `renderer: 'auto'`, with a session-long fallback to the 2D path | 6.39 kB |
|
|
140
|
-
| `openalgo-charts/widget` | The chart with its chrome in one call: `createWidget` adds a top bar, the drawing rail, a status line, the settings and indicator dialogs, drawing properties, a right-click menu, a keymap with a `?` panel and optional layout persistence. The only tier that ships DOM |
|
|
144
|
+
| `openalgo-charts/widget` | The chart with its chrome in one call: `createWidget` adds a top bar, the drawing rail, a status line, the settings and indicator dialogs, drawing properties, a right-click menu, a keymap with a `?` panel and optional layout persistence. The only tier that ships DOM | 49.00 kB |
|
|
141
145
|
| `openalgo-charts/workspace` | Validated workspace and indicator-template documents, named catalogs with revision checks, asynchronous storage and an IndexedDB adapter; no DOM | 5.52 kB |
|
|
142
146
|
|
|
143
|
-
Everything together is **
|
|
147
|
+
Everything together is **245.21 kB Brotli**; a widget terminal with built-in indicators (base + draw + indicators + widget) is 205.83 kB. Figures are measured from the 2.4.6 release build. The trade tier is 8.01 kB on its own; base + trade costs 99.56 kB. Sizes use decimal kB.
|
|
144
148
|
|
|
145
149
|
## What's built
|
|
146
150
|
|
|
@@ -445,17 +449,17 @@ Enforced in CI by [`size-limit`](./.size-limit.json). Nothing is excluded, becau
|
|
|
445
449
|
|
|
446
450
|
| Bundle | Limit | Actual |
|
|
447
451
|
|---|---|---|
|
|
448
|
-
| Base engine |
|
|
449
|
-
| Base + trade | 100 kB | 99.
|
|
452
|
+
| Base engine | 92 kB | 91.55 kB |
|
|
453
|
+
| Base + trade | 100 kB | 99.56 kB |
|
|
450
454
|
| Indicators tier | 30 kB | 29.84 kB |
|
|
451
455
|
| Draw tier | 36 kB | 35.43 kB |
|
|
452
456
|
| Transform tier | 6 kB | 4.50 kB |
|
|
453
457
|
| Profile tier | 15 kB | 14.96 kB |
|
|
454
458
|
| WebGL2 tier | 7 kB | 6.39 kB |
|
|
455
|
-
| Widget tier |
|
|
456
|
-
| Widget terminal (base + draw + indicators + widget) |
|
|
459
|
+
| Widget tier | 49.25 kB | 49.00 kB |
|
|
460
|
+
| Widget terminal (base + draw + indicators + widget) | 206 kB | 205.83 kB |
|
|
457
461
|
| Workspace tier | 6 kB | 5.52 kB |
|
|
458
|
-
| **Everything** | 245 kB |
|
|
462
|
+
| **Everything** | 245.5 kB | 245.21 kB |
|
|
459
463
|
|
|
460
464
|
## Documentation
|
|
461
465
|
|
|
@@ -500,8 +504,8 @@ See [Contributing](./CONTRIBUTING.md) for setup, targeted checks, documentation
|
|
|
500
504
|
```bash
|
|
501
505
|
npm install # install dev toolchain
|
|
502
506
|
npm run typecheck # strict TypeScript check
|
|
503
|
-
npm test # engine unit tests (Vitest):
|
|
504
|
-
npm run test:demo # reference-host tests:
|
|
507
|
+
npm test # engine unit tests (Vitest): 5804 across 246 files
|
|
508
|
+
npm run test:demo # reference-host tests: 401 across 31 files
|
|
505
509
|
npm run test:endurance # node endurance-harness tests: 7 cases
|
|
506
510
|
npm run build # Rollup -> dist/ (minified ESM per tier + types)
|
|
507
511
|
npm run size # size-limit (Brotli) against the budget
|
|
@@ -519,7 +523,7 @@ npm run verify # lint + types + unit + endurance harness + build + demo + dt
|
|
|
519
523
|
|
|
520
524
|
## Status & limitations
|
|
521
525
|
|
|
522
|
-
Version **2.4.
|
|
526
|
+
Version **2.4.6**. All engine build phases are implemented. Upgrading a 1.9.x host: [Migrating to 2.0](./docs/migrating-to-2.md).
|
|
523
527
|
|
|
524
528
|
Known gaps, stated plainly:
|
|
525
529
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TradingCapabilitySource as TradingCapabilitySource$1 } from 'openalgo-charts';
|
|
2
2
|
|
|
3
3
|
/** Library version string. Matches package.json (including locally prepared releases). */
|
|
4
|
-
declare const VERSION = "2.4.
|
|
4
|
+
declare const VERSION = "2.4.6";
|
|
5
5
|
/** Returns the current library version. */
|
|
6
6
|
declare function version(): string;
|
|
7
7
|
|
|
@@ -859,6 +859,11 @@ interface IPrimitive {
|
|
|
859
859
|
/** Pick the best hit across primitives: nearest distance, then z-order priority. */
|
|
860
860
|
declare function bestHit(hits: readonly (PrimitiveHit | null)[]): PrimitiveHit | null;
|
|
861
861
|
|
|
862
|
+
/**
|
|
863
|
+
* Series markers (ARCHITECTURE.md §8.1): buy/sell signals and shapes anchored
|
|
864
|
+
* to bars. Visible-range culled, per-bar stacked, four discrete sizes.
|
|
865
|
+
*/
|
|
866
|
+
|
|
862
867
|
/**
|
|
863
868
|
* `labelUp` / `labelDown` are text plates with a tail, for named signals ("Buy",
|
|
864
869
|
* "Sell") rather than bare glyphs. The tail points *at* the anchor price and the
|
|
@@ -900,10 +905,23 @@ declare function drawShape(ctx: CanvasRenderingContext2D, shape: MarkerShape, cx
|
|
|
900
905
|
declare function drawLabel(ctx: CanvasRenderingContext2D, up: boolean, cx: number, anchorY: number, text: string, color: string, fontPx: number): void;
|
|
901
906
|
declare class SeriesMarkers implements IPrimitive {
|
|
902
907
|
private readonly _seriesId;
|
|
908
|
+
private readonly _fallbackBars;
|
|
909
|
+
private readonly _priceScale;
|
|
903
910
|
private _markers;
|
|
904
911
|
private _host;
|
|
905
912
|
private _lastPositions;
|
|
906
|
-
|
|
913
|
+
/**
|
|
914
|
+
* @param seriesId The series whose pane and price scale the marks live on.
|
|
915
|
+
* @param fallbackBars Bars to position against where that series has none.
|
|
916
|
+
*
|
|
917
|
+
* The second argument exists because a marker's series decides *where* it is
|
|
918
|
+
* drawn while the bar under it decides *how high*, and those are not always
|
|
919
|
+
* the same row of data. An indicator that draws one line in an uptrend and
|
|
920
|
+
* another in a downtrend has a gap in each, and a mark that lands in a gap
|
|
921
|
+
* had no bar to measure from and was dropped without a word. The caller
|
|
922
|
+
* passes the instrument's own bars, which have no gaps.
|
|
923
|
+
*/
|
|
924
|
+
constructor(seriesId: SeriesId, fallbackBars?: () => readonly Bar[], priceScale?: () => PriceScale);
|
|
907
925
|
attached(host: PrimitiveHost): void;
|
|
908
926
|
detached(): void;
|
|
909
927
|
zOrder(): ZOrder;
|
|
@@ -975,8 +993,14 @@ interface SeriesApi {
|
|
|
975
993
|
remove(): void;
|
|
976
994
|
/** The price scale this series maps to (call `.setOptions({ marginTop, marginBottom })` on it). */
|
|
977
995
|
priceScale(): PriceScale;
|
|
978
|
-
/**
|
|
979
|
-
|
|
996
|
+
/**
|
|
997
|
+
* Create a markers layer (buy/sell signals, shapes) bound to this series.
|
|
998
|
+
*
|
|
999
|
+
* `fallbackBars` positions a mark whose time this series has no point for,
|
|
1000
|
+
* which happens whenever the series is drawn with gaps. Without it such a
|
|
1001
|
+
* mark is dropped silently.
|
|
1002
|
+
*/
|
|
1003
|
+
createMarkers(fallbackBars?: () => readonly Bar[]): SeriesMarkers;
|
|
980
1004
|
}
|
|
981
1005
|
|
|
982
1006
|
/**
|
|
@@ -1679,7 +1703,7 @@ declare class PriceLine implements IPrimitive {
|
|
|
1679
1703
|
* placeholder.
|
|
1680
1704
|
*/
|
|
1681
1705
|
|
|
1682
|
-
type PaneLegendAction = 'hide' | 'settings' | 'up' | 'down' | 'maximize' | 'close';
|
|
1706
|
+
type PaneLegendAction = 'hide' | 'settings' | 'source' | 'up' | 'down' | 'maximize' | 'close';
|
|
1683
1707
|
/**
|
|
1684
1708
|
* One reading on a legend row. Multi-plot sources show one per plot, each in
|
|
1685
1709
|
* that plot's own color (an MA ribbon's four averages, MACD's three lines) —
|
|
@@ -1796,6 +1820,7 @@ interface PaneLegendOptions {
|
|
|
1796
1820
|
* `${id}::<action>`:
|
|
1797
1821
|
* - `up` / `down` — move this pane one slot (`::up` / `::down`)
|
|
1798
1822
|
* - `hide` — toggle visibility (`::hide`)
|
|
1823
|
+
* - `source`: show the code this source was written from (`::source`)
|
|
1799
1824
|
* - `maximize` — expand this pane to fill the chart (`::maximize`)
|
|
1800
1825
|
* - `close` — remove the source, and its pane if it empties (`::close`)
|
|
1801
1826
|
*
|
|
@@ -1810,6 +1835,15 @@ interface PaneLegendOptions {
|
|
|
1810
1835
|
maximized?: boolean;
|
|
1811
1836
|
/** Text size in media px. Default 11. */
|
|
1812
1837
|
font?: number;
|
|
1838
|
+
/**
|
|
1839
|
+
* Square side of one action button in media px. Default 16.
|
|
1840
|
+
*
|
|
1841
|
+
* The row grows to hold it, so raising this moves every legend row below it
|
|
1842
|
+
* down by the same amount and nothing overlaps. It is a chart-wide setting
|
|
1843
|
+
* for that reason: two legends on one pane with different button sizes would
|
|
1844
|
+
* stack against different row heights and collide.
|
|
1845
|
+
*/
|
|
1846
|
+
iconSize?: number;
|
|
1813
1847
|
/** Left inset from the plot edge in media px. Default 8. */
|
|
1814
1848
|
left?: number;
|
|
1815
1849
|
/** Top inset in media px. Default 6. */
|
|
@@ -2018,10 +2052,14 @@ interface IndicatorHost {
|
|
|
2018
2052
|
color?: string;
|
|
2019
2053
|
row: number;
|
|
2020
2054
|
paneIndex: number;
|
|
2055
|
+
/** The descriptor's `hasSource`, so the row can offer a source button. */
|
|
2056
|
+
hasSource?: boolean;
|
|
2021
2057
|
}): PaneLegend;
|
|
2022
2058
|
removeIndicatorLegend(legend: PaneLegend): void;
|
|
2023
2059
|
/** How many legends already sit on this pane, so rows stack. */
|
|
2024
2060
|
legendRowsOn(paneIndex: number): number;
|
|
2061
|
+
/** The instrument's own series, for a descriptor anchoring marks to price. */
|
|
2062
|
+
primarySeries?(): SeriesApi | null;
|
|
2025
2063
|
addIndicatorSeries(type: string, paneIndex: number, style: Record<string, unknown> | undefined, priceScaleId: string | undefined,
|
|
2026
2064
|
/** Axis/crosshair formatting for the scale this plot maps to. */
|
|
2027
2065
|
priceFormat?: PriceFormat): SeriesApi;
|
|
@@ -2920,6 +2958,20 @@ interface IndicatorDescriptor {
|
|
|
2920
2958
|
category?: string;
|
|
2921
2959
|
/** `'onchart'` overlays the price pane; `'pane'` gets its own pane. */
|
|
2922
2960
|
placement: 'onchart' | 'pane';
|
|
2961
|
+
/**
|
|
2962
|
+
* This indicator was written from code the host can show the user.
|
|
2963
|
+
*
|
|
2964
|
+
* Its legend row then carries a source button beside the gear, and pressing
|
|
2965
|
+
* it emits `indicatorSource` with the same payload `indicatorSettings`
|
|
2966
|
+
* carries. The engine does not hold the code and does not want to: a
|
|
2967
|
+
* descriptor may be compiled from a script, generated, or written by hand in
|
|
2968
|
+
* the host's own bundle, and only the host knows which of those it can put in
|
|
2969
|
+
* front of somebody. So this says a button is worth offering, and the host
|
|
2970
|
+
* decides what the button opens.
|
|
2971
|
+
*
|
|
2972
|
+
* Absent or false draws no button, which is every built-in study.
|
|
2973
|
+
*/
|
|
2974
|
+
hasSource?: boolean;
|
|
2923
2975
|
inputs: readonly IndicatorInput[];
|
|
2924
2976
|
plots: readonly IndicatorPlot[];
|
|
2925
2977
|
/**
|
|
@@ -2973,6 +3025,24 @@ interface IndicatorDescriptor {
|
|
|
2973
3025
|
values: IndicatorValues;
|
|
2974
3026
|
settings: Readonly<IndicatorSettings>;
|
|
2975
3027
|
}): readonly SeriesMarker[];
|
|
3028
|
+
/**
|
|
3029
|
+
* What `aboveBar` and `belowBar` are measured against.
|
|
3030
|
+
*
|
|
3031
|
+
* `'plot'`, the default, is this study's own first plot, which is right for a
|
|
3032
|
+
* mark that belongs to the line: an arrow on a moving average sits against
|
|
3033
|
+
* the average.
|
|
3034
|
+
*
|
|
3035
|
+
* `'price'` is the instrument's candles, so above is above the high and below
|
|
3036
|
+
* is below the low. That is what a buy or sell signal on an overlay study
|
|
3037
|
+
* means, and anchoring one to the study's own column instead puts it wherever
|
|
3038
|
+
* that column happens to sit: a study that anchors its marks to a mid-body
|
|
3039
|
+
* line draws every "below" mark through the middle of the candle.
|
|
3040
|
+
*
|
|
3041
|
+
* Ignored by a study in its own pane, which has no candles to measure
|
|
3042
|
+
* against, and ignored when the chart has no primary series yet. Both fall
|
|
3043
|
+
* back to the first plot rather than dropping the marker.
|
|
3044
|
+
*/
|
|
3045
|
+
markerAnchor?: 'plot' | 'price';
|
|
2976
3046
|
/**
|
|
2977
3047
|
* Optional summary grid pinned to a corner of the pane.
|
|
2978
3048
|
*
|
|
@@ -4112,6 +4182,11 @@ interface ChartOptions {
|
|
|
4112
4182
|
canvas?: CanvasOptions;
|
|
4113
4183
|
/** Per-field status-line switches applied to every pane legend on the chart. */
|
|
4114
4184
|
statusLine?: LegendStatusLineOptions;
|
|
4185
|
+
/**
|
|
4186
|
+
* Square side of a legend action button in media px. Default 16, held to
|
|
4187
|
+
* 12..28. Applied to every pane legend, because the rows stack against it.
|
|
4188
|
+
*/
|
|
4189
|
+
legendIconSize?: number;
|
|
4115
4190
|
/** Accessible label for the chart container (screen readers). */
|
|
4116
4191
|
ariaLabel?: string;
|
|
4117
4192
|
/**
|
|
@@ -4458,6 +4533,8 @@ declare class Chart {
|
|
|
4458
4533
|
private readonly _canvas;
|
|
4459
4534
|
/** Status-line switches pushed onto every pane legend, host-added ones included. */
|
|
4460
4535
|
private readonly _statusLine;
|
|
4536
|
+
/** Legend action-button side in media px; undefined leaves the primitive's default. */
|
|
4537
|
+
private _legendIconSize;
|
|
4461
4538
|
/** Axis-strip chrome switches. Empty is the shipped chart: neither drawn. */
|
|
4462
4539
|
private readonly _axisChrome;
|
|
4463
4540
|
/**
|
|
@@ -5012,6 +5089,16 @@ declare class Chart {
|
|
|
5012
5089
|
*/
|
|
5013
5090
|
setStatusLineOptions(patch: LegendStatusLineOptions): void;
|
|
5014
5091
|
statusLineOptions(): LegendStatusLineOptions;
|
|
5092
|
+
/**
|
|
5093
|
+
* How large a legend's action buttons are drawn, in media px.
|
|
5094
|
+
*
|
|
5095
|
+
* Chart-wide rather than per legend: the rows stack against the height the
|
|
5096
|
+
* buttons need, so two sizes on one pane would stack against two different
|
|
5097
|
+
* heights and overlap. The primitive holds it to a range it can actually
|
|
5098
|
+
* draw.
|
|
5099
|
+
*/
|
|
5100
|
+
setLegendIconSize(size: number): void;
|
|
5101
|
+
legendIconSize(): number | undefined;
|
|
5015
5102
|
/**
|
|
5016
5103
|
* Turn the axis-strip chrome on or off, and hand it a clock. Merges field by
|
|
5017
5104
|
* field, so switching the countdown on leaves the corner clock alone.
|
|
@@ -5151,6 +5238,7 @@ declare class Chart {
|
|
|
5151
5238
|
grid?: Partial<GridOptions>;
|
|
5152
5239
|
canvas?: CanvasOptions;
|
|
5153
5240
|
statusLine?: LegendStatusLineOptions;
|
|
5241
|
+
legendIconSize?: number;
|
|
5154
5242
|
priceScale?: Partial<PriceScaleOptions>;
|
|
5155
5243
|
priceFormatter?: ((price: number) => string) | null;
|
|
5156
5244
|
timeFormatter?: ((utcSeconds: number, tickMark?: TickMarkType) => string) | undefined;
|