@alphacharts/indicators 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +106 -2
- package/dist/all-_xzUPrL7.js +21 -0
- package/dist/all-_xzUPrL7.js.map +1 -0
- package/dist/all.js +10 -0
- package/dist/all.js.map +1 -0
- package/dist/define-XUgQMhSl.js +687 -0
- package/dist/define-XUgQMhSl.js.map +1 -0
- package/dist/index.js +744 -0
- package/dist/index.js.map +1 -0
- package/dist/registry-DdYYyZN_.js +53 -0
- package/dist/registry-DdYYyZN_.js.map +1 -0
- package/dist/runner-B53M0IsJ.js +237 -0
- package/dist/runner-B53M0IsJ.js.map +1 -0
- package/dist/studies.js +1 -0
- package/dist/tv-volume-BYSbfrVk.js +3454 -0
- package/dist/tv-volume-BYSbfrVk.js.map +1 -0
- package/dist/types/all.d.ts +3 -0
- package/dist/types/chart/marker-floor.d.ts +9 -0
- package/dist/types/chart/studies.d.ts +192 -0
- package/dist/types/define.d.ts +46 -0
- package/dist/types/engine/feed.d.ts +88 -0
- package/dist/types/engine/graph.d.ts +136 -0
- package/dist/types/engine/kernels.d.ts +9 -0
- package/dist/types/engine/study.d.ts +40 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/registry.d.ts +7 -0
- package/dist/types/runner.d.ts +91 -0
- package/dist/types/studies/all.d.ts +2 -0
- package/dist/types/studies/cycle.d.ts +7 -0
- package/dist/types/studies/index.d.ts +13 -0
- package/dist/types/studies/ma.d.ts +26 -0
- package/dist/types/studies/math.d.ts +28 -0
- package/dist/types/studies/momentum.d.ts +30 -0
- package/dist/types/studies/overlap.d.ts +14 -0
- package/dist/types/studies/patterns.d.ts +62 -0
- package/dist/types/studies/price.d.ts +6 -0
- package/dist/types/studies/sar.d.ts +2 -0
- package/dist/types/studies/statistic.d.ts +9 -0
- package/dist/types/studies/tv-osc.d.ts +18 -0
- package/dist/types/studies/tv-trend.d.ts +20 -0
- package/dist/types/studies/tv-volume.d.ts +15 -0
- package/dist/types/studies/volatility.d.ts +3 -0
- package/dist/types/studies/volume.d.ts +3 -0
- package/dist/types/types.d.ts +169 -0
- package/dist/types/wasm.d.ts +2 -0
- package/dist/types/worker.d.ts +1 -0
- package/dist/worker.js +8 -0
- package/dist/worker.js.map +1 -0
- package/package.json +72 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alphabench
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,107 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @alphacharts/indicators
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Technical studies for alphacharts: a typed study model, an incremental engine over the core's
|
|
4
|
+
columnar data, a Web Worker runner, chart integration through the core plugin API, and
|
|
5
|
+
211 studies (TA-Lib's catalogue plus TradingView's built-ins).
|
|
6
|
+
|
|
7
|
+
## Use
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { addStudy } from "@alphacharts/indicators";
|
|
11
|
+
import { rsi, macd, bbands } from "@alphacharts/indicators/studies"; // import only what you use
|
|
12
|
+
|
|
13
|
+
const bb = addStudy(chart, candles, bbands, { length: 20 }); // overlay on the candles' pane
|
|
14
|
+
const r = addStudy(chart, candles, rsi, { length: 14 }); // own pane
|
|
15
|
+
addStudy(chart, candles, "obv", {}, { volume: volumeSeries }); // by id: needs registerAllStudies()
|
|
16
|
+
r.setInputs({ length: 21 }); r.setVisible(false); r.remove(); // re-parameterise, hide, remove
|
|
17
|
+
chart.saveState(); chart.restoreState(saved); // studies are in the layout (installStudies(chart) first on a fresh chart)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`addStudy` throws on an unknown input, a value outside min/max/step type, or a source that lacks what the
|
|
21
|
+
study needs (volume, OHLC). `await study.ready()` resolves when the last computation is on the chart.
|
|
22
|
+
Subpaths: `.` (engine, runner, plugin), `./studies` (every study as a named export), `./all`
|
|
23
|
+
(`ALL_STUDIES`, `registerAllStudies`), `./worker` (worker entry). Studies are plain objects in group modules
|
|
24
|
+
(`src/studies/*.ts`), so a bundler keeps only those imported (one module per family rather than per study).
|
|
25
|
+
|
|
26
|
+
## How it works
|
|
27
|
+
|
|
28
|
+
- **Model** (`src/types.ts`): `StudyDef { id, name, family, inputs (int/float/bool/source/select with default, min, max,
|
|
29
|
+
step, options), needs, pane: overlay|new, columns, plots (line, histogram, area, band, fill, hline, markers, zigzag),
|
|
30
|
+
build }`. `build(graph, params)` declares nodes and returns the output columns.
|
|
31
|
+
- **Engine** (`src/engine/graph.ts`): every value lives in a Float64Array column; a node writes only bar `i` and reads
|
|
32
|
+
`<= i` of its inputs and `<= i-1` of its own columns. So one code path is the batch (`run(0, n)`), an appended bar
|
|
33
|
+
(`run(n, n+1)`) and a tick revision (re-`run(n-1, n)`): per-bar cost does not depend on the series length
|
|
34
|
+
(O(1) for recursive and running-sum nodes, O(period) for window scans), and a revision recomputes from committed
|
|
35
|
+
state. Warm-up is NaN; absent values never become 0 (except where TA-Lib defines 0, noted in the study's reference).
|
|
36
|
+
setData/prepend on the source recompute fully.
|
|
37
|
+
- **Runner** (`src/runner.ts`): `createRunner(ids, factory)` gives a `WorkerRunner` on the worker `factory` makes (the host's bundler spells the worker URL out; the package never guesses it) (arrays transferred, chunks of 65,536
|
|
38
|
+
bars so a `cancel` is serviced within a chunk; protocol documented in the file header) or the `InlineRunner`
|
|
39
|
+
when no factory is given or the worker would not start. The worker returns every graph column; the main thread adopts them and keeps
|
|
40
|
+
streaming ticks. Studies not built in (defined at runtime) run inline (`canRun`).
|
|
41
|
+
- **Chart integration** (`src/chart/studies.ts`): one core series per drawn plot (pane = the source's for overlays,
|
|
42
|
+
the lowest free pane otherwise), the rest drawn on the overlay (fills, markers, ZigZag, lines shifted back in time
|
|
43
|
+
or joined across gaps; these do not take part in autoscale). Layout JSON is keyed by study instance id.
|
|
44
|
+
- **Outside series** (`src/engine/feed.ts`, `Study.setFeed` / `pushFeedBar`): a study can read bars the host gives it (another
|
|
45
|
+
instrument, another timeframe). Each is a graph of its own on its own bars; the study's graph reads it through a join by time
|
|
46
|
+
(`Graph.joined` / `external`): `"same"` is the bar with exactly the study bar's time, else NaN, `"closed"` the latest bar whose
|
|
47
|
+
open + length is not after the study bar's start (no value contains data from after its bar, and the live bar sees the last finished one).
|
|
48
|
+
Lookups walk forward from the last answer, so a run and a tick are O(1) amortised; `StudyEngine.pushFeed` re-evaluates the last bar only
|
|
49
|
+
when it sees a different row. Runners: `RunRequest.feeds`, `StudyRunner.feedBar`.
|
|
50
|
+
- **Bar colours, background shading, per-point line colour, left axis** (`src/chart/studies.ts`): `barcolor` plots colour the source's candles
|
|
51
|
+
(core `Series.setBarColors`; several studies compose on one source, the latest wins, removal restores exactly), `bgcolor` plots draw through core's
|
|
52
|
+
`BarShading` primitive (no part in autoscale), a line plot's `colorBy: { col, color }` colours its segments per bar, `StudyDef.scale: "left"`
|
|
53
|
+
puts the series on the left axis.
|
|
54
|
+
- **WASM** (`src/engine/kernels.ts`, `enableWasm()` from `src/wasm.ts`): optional batch kernels from `@alphacharts/wasm`
|
|
55
|
+
for running sum, variance/stddev, rolling highest/lowest (+ bars) and linear regression, the kernels that won at 1M
|
|
56
|
+
and 10M bars in its benchmark. They are bit-identical to the JS loops (test/wasm.test.ts runs every study both
|
|
57
|
+
ways). Not used: EMA/RMA/WMA (no win), chunked runs (worker), series under 4,096 bars.
|
|
58
|
+
|
|
59
|
+
## Verification
|
|
60
|
+
|
|
61
|
+
Run `pnpm -C packages/indicators test`.
|
|
62
|
+
- **TA-Lib** (`test/talib.test.ts`; `atr` and `natr` are not here, see below): fixtures generated offline by `scripts/gen_fixtures.py` (TA-Lib 0.8.2 in a
|
|
63
|
+
Python venv, see below) from `fixtures/cases/*.json` on a seeded 400-bar OHLCV set (`fixtures/dataset.json`;
|
|
64
|
+
3,000 bars of mixed candle shapes for the patterns). Compared at 1e-9 relative (+1e-12 absolute floor), NaN positions
|
|
65
|
+
must be identical; patterns are integers compared exactly. Case flags: `lead` (our study has valid values earlier
|
|
66
|
+
than TA-Lib's first output, e.g. MACD's line before its signal), `abs` (a value that is numerical noise around 0).
|
|
67
|
+
- **TradingView-only** studies: hand-computed fixtures with the arithmetic in the test comments, plus invariants
|
|
68
|
+
(`test/tv-*.test.ts`).
|
|
69
|
+
- **Incremental == batch** (`test/incremental.test.ts`): every study, seeded random appends with random last-bar
|
|
70
|
+
revisions, exact equality.
|
|
71
|
+
- Runner protocol, worker/inline parity and cancellation: `test/runner.test.ts`. Browser: `bench/tests/indicators.spec.ts`.
|
|
72
|
+
|
|
73
|
+
Where a study is not TA-Lib's arithmetic it says so in its `reference` field. Known differences:
|
|
74
|
+
`atr`/`natr` (and every ATR band: keltner, supertrend, chande-kroll-stop, median) are Wilder's: bar 0's true range is high - low and the first value is at bar `length - 1`, TA-Lib's skips bar 0 and starts one bar later (hand case and an independent loop in `test/atr.test.ts`; `trange` stays TA-Lib's); `rsi` (and `stochrsi`) report 100 where RS is 0/0, the first `length` changes all zero (TA-Lib: 0; charting packages: 100, `test/rsi-flat.test.ts`);
|
|
75
|
+
MACD/APO/PPO seed like TA-Lib (fast EMA at the slow EMA's first bar), TradingView seeds at bar 0 (gap < 1e-9 after
|
|
76
|
+
~150 bars); `cmo` defaults to TradingView's window-sum form (`method: "wilder"` is TA-Lib's); the linear regression
|
|
77
|
+
studies are TA-Lib's (checked against numpy polyfit); `ht-trendmode` reports TA-Lib's 0 inside its warm-up;
|
|
78
|
+
`mavp` (TA-Lib's moving average with a per-bar period series) is not implemented: it needs a second input series.
|
|
79
|
+
Not checked against TradingView itself (no access): the TradingView-only studies follow the definitions cited in their
|
|
80
|
+
`reference` field; pivot formulas, Klinger, Schaff, the Relative Volatility form and Fractals tie rules were written
|
|
81
|
+
from memory of TradingView's scripts and are verified only by the hand-computed tests.
|
|
82
|
+
|
|
83
|
+
## Studies (211)
|
|
84
|
+
|
|
85
|
+
- **Overlap (TA-Lib + MAs, bands, SAR)** (17): `sma`, `ema`, `wma`, `dema`, `tema`, `trima`, `kama`, `t3`, `ma`, `bbands`, `bbpb`, `bbw`, `midpoint`, `midprice`, `mama`, `sar`, `sarext`
|
|
86
|
+
- **Momentum (TA-Lib)** (30): `rsi`, `cmo`, `mom`, `roc`, `rocp`, `rocr`, `rocr100`, `trix`, `apo`, `ppo`, `macd`, `macdfix`, `macdext`, `stoch`, `stochf`, `stochrsi`, `willr`, `cci`, `bop`, `mfi`, `ultosc`, `aroon`, `aroonosc`, `adx`, `adxr`, `dx`, `plus-di`, `minus-di`, `plus-dm`, `minus-dm`
|
|
87
|
+
- **Volume (TA-Lib)** (3): `ad`, `adosc`, `obv`
|
|
88
|
+
- **Volatility** (3): `trange` (TA-Lib's), `atr`, `natr` (Wilder's, not TA-Lib's)
|
|
89
|
+
- **Price transforms (TA-Lib)** (4): `avgprice`, `medprice`, `typprice`, `wclprice`
|
|
90
|
+
- **Statistics (TA-Lib)** (9): `linearreg`, `linearreg-slope`, `linearreg-intercept`, `linearreg-angle`, `tsf`, `stddev`, `var`, `correl`, `beta`
|
|
91
|
+
- **Math transforms and operators (TA-Lib)** (26): `acos`, `asin`, `atan`, `ceil`, `cos`, `cosh`, `exp`, `floor`, `ln`, `log10`, `sin`, `sinh`, `sqrt`, `tan`, `tanh`, `add`, `sub`, `mult`, `div`, `max`, `min`, `sum`, `maxindex`, `minindex`, `minmax`, `minmaxindex`
|
|
92
|
+
- **Cycle / Hilbert (TA-Lib)** (6): `ht-dcperiod`, `ht-dcphase`, `ht-phasor`, `ht-sine`, `ht-trendline`, `ht-trendmode`
|
|
93
|
+
- **TradingView-only** (52): `smma`, `vwma`, `hma`, `alma`, `lsma`, `mcginley`, `ma-ribbon`, `ma-cross`, `envelopes`, `keltner`, `donchian`, `price-channel`, `chande-kroll-stop`, `linreg-channel`, `median`, `ichimoku`, `supertrend`, `alligator`, `fractals`, `zigzag`, `fisher`, `kst`, `tsi`, `vortex`, `coppock`, `connors-rsi`, `choppiness`, `rvi-vigor`, `rvi-volatility`, `smi-ergodic`, `rank-corr`, `bull-bear-power`, `awesome`, `accelerator`, `mass-index`, `dpo`, `schaff-tc`, `stoch-tv`, `volume`, `volume-osc`, `pvt`, `net-volume`, `elder-force`, `eom`, `chaikin-mf`, `klinger`, `vwap` (Session VWAP), `anchored-vwap`, `pivot-points`, `hist-vol`, `adr`, `bars-per-year`
|
|
94
|
+
- **Candlestick patterns (TA-Lib CDL*)** (61): `cdl-<name>` for every TA-Lib pattern, e.g. `cdl-2crows`, `cdl-3blackcrows`, `cdl-3inside`, `cdl-3linestrike`, `cdl-3outside`, ...
|
|
95
|
+
|
|
96
|
+
## Regenerating the TA-Lib fixtures
|
|
97
|
+
|
|
98
|
+
Only needed when a case changes. From `packages/indicators`:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
python -m venv .venv && . .venv/bin/activate
|
|
102
|
+
pip install TA-Lib numpy # TA-Lib needs the C library (brew install ta-lib)
|
|
103
|
+
pnpm fixtures # python scripts/gen_fixtures.py [group ...]
|
|
104
|
+
python scripts/gen_cdl_dataset.py # only to rebuild fixtures/dataset-cdl.json
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The fixtures are TA-Lib's output (BSD licence), see `NOTICE` at the repository root.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { $ as e, N as t, Nn as n, Nr as r, dn as i, er as a, f as o, fr as s, gr as c, ln as l, or as u, pn as d, ri as f } from "./tv-volume-BYSbfrVk.js";
|
|
2
|
+
//#region src/studies/all.ts
|
|
3
|
+
var p = (e) => typeof e == "object" && !!e && "build" in e && "columns" in e && "plots" in e, m = [
|
|
4
|
+
f,
|
|
5
|
+
r,
|
|
6
|
+
c,
|
|
7
|
+
s,
|
|
8
|
+
u,
|
|
9
|
+
a,
|
|
10
|
+
n,
|
|
11
|
+
d,
|
|
12
|
+
i,
|
|
13
|
+
l,
|
|
14
|
+
e,
|
|
15
|
+
t,
|
|
16
|
+
o
|
|
17
|
+
].flatMap((e) => Object.values(e).filter(p));
|
|
18
|
+
//#endregion
|
|
19
|
+
export { m as t };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=all-_xzUPrL7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"all-_xzUPrL7.js","names":["overlap","momentum","volume","volatility","price","statistic","math","cycle","sar","patterns","tvTrend","tvOsc","tvVolume","tv_trend_exports","tv_osc_exports","math_exports","momentum_exports","sar_exports","statistic_exports","tv_volume_exports","volatility_exports","volume_exports","patterns_exports","price_exports","cycle_exports","overlap_exports","isStudy","x","ALL_STUDIES","m"],"sources":["../src/studies/all.ts"],"sourcesContent":["// Every built-in study, collected from the group modules. Importing this pulls\n// them all in; import single studies from their group module to stay small.\n\nimport type { StudyDef } from \"../types.js\";\nimport * as overlap from \"./overlap.js\";\nimport * as momentum from \"./momentum.js\";\nimport * as volume from \"./volume.js\";\nimport * as volatility from \"./volatility.js\";\nimport * as price from \"./price.js\";\nimport * as statistic from \"./statistic.js\";\nimport * as math from \"./math.js\";\nimport * as cycle from \"./cycle.js\";\nimport * as sar from \"./sar.js\";\nimport * as patterns from \"./patterns.js\";\nimport * as tvTrend from \"./tv-trend.js\";\nimport * as tvOsc from \"./tv-osc.js\";\nimport * as tvVolume from \"./tv-volume.js\";\n\nconst isStudy = (x: unknown): x is StudyDef => typeof x === \"object\" && x !== null && \"build\" in x && \"columns\" in x && \"plots\" in x;\n\nexport const ALL_STUDIES: readonly StudyDef[] = [overlap, momentum, volume, volatility, price, statistic, math, cycle, sar, patterns, tvTrend, tvOsc, tvVolume].flatMap((m) =>\n Object.values(m).filter(isStudy),\n);\n"],"mappings":";;AAkBA,IAAM0B,KAAW,MAA8B,OAAOC,KAAM,cAAYA,KAAc,WAAWA,KAAK,aAAaA,KAAK,WAAWA,GAEtHC,IAAmC;CAAC5B;CAASC;CAAUC;CAAQC;CAAYC;CAAOC;CAAWC;CAAMC;CAAOC;CAAKC;CAAUC;CAASC;CAAOC;AAAQ,CAAC,CAAC,SAAS,MACvK,OAAO,OAAOiB,CAAC,CAAC,CAAC,OAAOH,CAAO,CACjC"}
|
package/dist/all.js
ADDED
package/dist/all.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"all.js","names":["registerStudies","registerAllStudies","ALL_STUDIES"],"sources":["../src/all.ts"],"sourcesContent":["// Everything: the study list and a registrar. Importing this module pulls every\n// study in; import single studies from \"@alphacharts/indicators/studies\" to stay small.\nimport { registerStudies } from \"./registry.js\";\nimport { ALL_STUDIES } from \"./studies/all.js\";\n\nexport { ALL_STUDIES };\nexport function registerAllStudies(): void {\n registerStudies(ALL_STUDIES);\n}\n"],"mappings":";;;AAMA,SAAgBC,IAA2B;CACzC,EAAgBC,CAAW;AAC7B"}
|