@pond-ts/process 0.66.0 → 0.68.0

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.
Files changed (4) hide show
  1. package/AGENTS.md +244 -0
  2. package/API.md +146 -123
  3. package/CHANGELOG.md +188 -1
  4. package/package.json +24 -4
package/AGENTS.md ADDED
@@ -0,0 +1,244 @@
1
+ # Using pond from a coding agent
2
+
3
+ You are reading this because a project depends on `pond-ts` or one of the
4
+ `@pond-ts/*` packages, or because you are deciding whether it should. This
5
+ file is the shortest route to correct code. It ships inside every pond
6
+ tarball as `AGENTS.md`, next to `API.md` (every public export, one line
7
+ each, with its source file) and `CHANGELOG.md`.
8
+
9
+ Docs: <https://pond-ts.org> · index for agents: <https://pond-ts.org/llms.txt>
10
+ · source: <https://github.com/pond-ts/pond>.
11
+
12
+ ## What pond is, in three lines
13
+
14
+ - A **typed, immutable time series** (`TimeSeries`) whose schema is declared
15
+ once `as const` and narrows every downstream transform — no casts.
16
+ - The **same operator vocabulary on a streaming buffer** (`LiveSeries`):
17
+ push events in, subscribe to incremental `rolling` / `aggregate` views,
18
+ bounded by retention.
19
+ - **Domain packages on top**: React hooks, canvas charts that read a series
20
+ directly, financial studies + trading calendars, fitness analytics, and an
21
+ experimental processing-graph runtime.
22
+
23
+ ## Which package
24
+
25
+ | You need to… | Install | Import from |
26
+ | ----------------------------------------------------------------------- | ------------------------------------ | ----------------------------------------------------- |
27
+ | Load timestamped rows; bucket, regrid, roll, fill, join, partition them | `pond-ts` | `'pond-ts'` |
28
+ | Ingest a live feed and keep rolling stats over the last N minutes | `pond-ts` | `'pond-ts'` (`LiveSeries`) |
29
+ | Share a series' type across a wire boundary with zero runtime | `pond-ts` | `'pond-ts/types'` |
30
+ | Own / subscribe to a series inside React | `@pond-ts/react` | `'@pond-ts/react'` |
31
+ | Draw it (line, area, band, bar, scatter, box, candlestick, heat map) | `@pond-ts/charts` (+ react, pond-ts) | `'@pond-ts/charts'` |
32
+ | OHLCV bars, SMA/EMA/RSI/MACD/Bollinger/ATR/VWAP…, market-hours calendar | `@pond-ts/financial` | `'@pond-ts/financial'`, `'@pond-ts/financial/fluent'` |
33
+ | GPS / power / heart-rate activity analytics | `@pond-ts/fit` | `'@pond-ts/fit'` |
34
+ | Computations as JSON plans with caching + provenance (experimental) | `@pond-ts/process` | `'@pond-ts/process'` |
35
+
36
+ All six release together under one version and release often. Install with
37
+ `@latest` rather than a version written from memory (a cold-start agent once
38
+ wrote `^0.3.0` and spent turns on a 2024 API); keep their ranges in step — a
39
+ pre-1.0 caret (`^0.67.0`) does **not** span minors.
40
+
41
+ ## The idioms that cover most jobs
42
+
43
+ ### 1. Declare the schema, build the series
44
+
45
+ ```ts
46
+ import { TimeSeries, Sequence } from 'pond-ts';
47
+
48
+ const schema = [
49
+ { name: 'time', kind: 'time' },
50
+ { name: 'host', kind: 'string' },
51
+ { name: 'latencyMs', kind: 'number' },
52
+ ] as const; // ← load-bearing. Without it every column widens to string.
53
+
54
+ const s = TimeSeries.fromJSON({
55
+ name: 'latency',
56
+ schema,
57
+ rows, // positional tuples [time, host, latencyMs] or objects { time, host, latencyMs }
58
+ sort: true, // input not already time-ordered? sort on construction (stable)
59
+ });
60
+ ```
61
+
62
+ Time cells accept ms-since-epoch numbers, `Date`s, or ISO strings **with an
63
+ offset** (`…Z`, `…+01:00`). A wall-clock string with no offset throws unless
64
+ you pass `parse: { timeZone: 'America/New_York' }`.
65
+
66
+ Other doors: `TimeSeries.fromPoints(points)` for wide `{ ts, a, b }` rows,
67
+ `fromColumns` for struct-of-arrays / `Float64Array`, `fromArrow` for an Arrow
68
+ table, `fromEvents`. `toJSON()` round-trips.
69
+
70
+ ### 2. Downsample, regrid, slide — three different verbs
71
+
72
+ ```ts
73
+ // Fewer rows out than in: one row per bucket.
74
+ const perMin = s.aggregate(Sequence.every('1m'), {
75
+ latencyMs: 'avg', // reducer by column …
76
+ p95: { from: 'latencyMs', using: 'p95' }, // … or a named output; reducers: sum avg min max count first last median stdev pNN
77
+ host: 'last',
78
+ });
79
+
80
+ // Same information, on a regular grid (hold / interpolate). No reduction.
81
+ const gridded = s.align(Sequence.every('10s'), { method: 'hold' });
82
+
83
+ // One output per input event, looking back over a window.
84
+ const rolled = s.rolling('5m', {
85
+ latencyMs: 'avg',
86
+ sd: { from: 'latencyMs', using: 'stdev' },
87
+ });
88
+ ```
89
+
90
+ `Sequence.every()` takes fixed durations only (`'10s'`, `'5m'`, `'1h'`,
91
+ `'1d'`). Months, weeks-in-a-zone, calendar days: `Sequence.calendar('month',
92
+ { timeZone })`. Common shortcuts: `s.baseline('latencyMs', { window: '1h',
93
+ sigma: 2 })` appends avg / sd / upper / lower in one pass;
94
+ `s.outliers(col, { window, sigma })` keeps only the rows outside the band.
95
+
96
+ ### 3. Per-entity, then flatten
97
+
98
+ ```ts
99
+ const perHost = s
100
+ .partitionBy('host') // every stateful operator below runs per host
101
+ .rolling('5m', { latencyMs: 'avg' })
102
+ .collect(); // one flat TimeSeries, `host` carried through (type and runtime)
103
+ // or .toMap() → Map<host, TimeSeries>
104
+ ```
105
+
106
+ `aggregate` and `rolling` under `partitionBy` carry the partition column
107
+ through in both the runtime **and** the static type (since 0.68), so
108
+ `e.get('host')` works on the collected result without naming it. On 0.67 or
109
+ older, name it in the mapping — `{ host: 'first', … }`.
110
+
111
+ ### 4. Clean, fill, join, read out
112
+
113
+ ```ts
114
+ const clean = s.dedupe().fill({ latencyMs: 'hold' }); // also 'linear', 'zero', gap caps
115
+ const joined = a.join(b); // on the time key; see API.md for options
116
+ clean.toPoints(); // [{ ts, host, latencyMs }, …] — chart-library friendly
117
+ clean.toRows(); // positional tuples
118
+ clean.column('latencyMs').mean(); // typed column: min/max/sum/mean/stdev/median/percentile
119
+ clean.column('latencyMs').toFloat64Array(); // zero-copy for canvas / WebGL loops
120
+ ```
121
+
122
+ Everything returns a **new** series. There is no `push` on a `TimeSeries`;
123
+ if you are appending, you want a `LiveSeries`.
124
+
125
+ ### 5. Streaming
126
+
127
+ ```ts
128
+ import { LiveSeries, Sequence } from 'pond-ts';
129
+
130
+ const live = new LiveSeries({
131
+ name: 'latency',
132
+ schema,
133
+ retention: { maxAge: '15m' }, // or { maxEvents: 10_000 }
134
+ ordering: 'reorder', // tolerate late rows …
135
+ graceWindow: '5s', // … up to this late
136
+ });
137
+
138
+ const view = live.partitionBy('host').rolling('5m', { latencyMs: 'avg' });
139
+ const stop = view.on('event', (e) => render(e.get('host'), e.get('latencyMs')));
140
+
141
+ live.push([Date.now(), 'api-1', 42]); // validated against the schema
142
+ live.pushMany(batch);
143
+ const snapshot = live.toTimeSeries(); // immutable batch copy for analytics
144
+ ```
145
+
146
+ `live.aggregate(Sequence.every('1m'), …)` emits `'bucket'` (partial) and
147
+ `'close'` (final) events. Retention bounds memory; `sample({ stride })`
148
+ between `partitionBy` and a long `rolling` bounds it further at firehose
149
+ rates.
150
+
151
+ ### React and charts
152
+
153
+ ```tsx
154
+ import { useLiveSeries } from '@pond-ts/react';
155
+ import {
156
+ ChartContainer,
157
+ ChartRow,
158
+ Layers,
159
+ LineChart,
160
+ YAxis,
161
+ } from '@pond-ts/charts';
162
+
163
+ const [live, snap] = useLiveSeries({
164
+ name: 'latency',
165
+ schema,
166
+ retention: { maxAge: '10m' },
167
+ });
168
+
169
+ <ChartContainer width={800} cursor="crosshair" panZoom>
170
+ <ChartRow height={240}>
171
+ <YAxis id="ms" />
172
+ <Layers>
173
+ {snap && <LineChart series={snap} column="latencyMs" axis="ms" />}
174
+ </Layers>
175
+ </ChartRow>
176
+ </ChartContainer>;
177
+ ```
178
+
179
+ Charts read a pond series directly — do the maths in pond (`rolling`,
180
+ `aggregate`, `align`) and hand the result to a layer. `useLiveSeries`'s snapshot is `null` before the first
181
+ push, hence the guard. `width` is a pixel
182
+ number or `'auto'` (the parent then needs a definite width, or nothing draws).
183
+ Hooks: `useTimeSeries`, `useLiveSeries`, `useSnapshot`, `useLiveQuery`,
184
+ `useDerived`, `useWindow`, `useCurrent`, `useLatest`.
185
+
186
+ ### Financial
187
+
188
+ ```ts
189
+ import '@pond-ts/financial/fluent'; // once, anywhere: adds studies to TimeSeries
190
+ import { TradingCalendar } from '@pond-ts/financial';
191
+
192
+ const studied = bars
193
+ .sma({ period: 20 })
194
+ .rsi({ period: 14 })
195
+ .bollinger({ period: 20 });
196
+ // or, function form: sma(bars, { period: 20 })
197
+ const cal = TradingCalendar.fromRules(
198
+ { timeZone: 'America/New_York', open: '09:30', close: '16:00' },
199
+ { from: '2026-01-05', to: '2026-02-13' },
200
+ );
201
+ ```
202
+
203
+ Studies read `'close'` by default, take **bar-count** periods, append
204
+ columns, preserve row count (warm-up rows are `undefined`). Sixty-plus of
205
+ them; `import { STUDIES } from '@pond-ts/financial/catalog'` lists them at runtime. Session-aligned bars: `ticks.aggregate(cal.barSequence('5m'), {...})`.
206
+
207
+ ## Mistakes agents actually make
208
+
209
+ 1. **Dropping `as const` on the schema.** Everything compiles and every
210
+ column is `string`. If `.get('x')` is not `number | undefined`, this is
211
+ why.
212
+ 2. **`aggregate` when you meant `rolling`, or vice versa.** `aggregate`
213
+ changes the row count (one per bucket); `rolling` keeps it (one per
214
+ event); `align` puts rows on a grid without reducing.
215
+ 3. **`Sequence.every('1M')` for months.** Not fixed-length → use
216
+ `Sequence.calendar('month', { timeZone })`.
217
+ 4. **Wall-clock strings without a zone.** `'2025-01-01T09:00'` throws; add
218
+ `parse: { timeZone }` or use offset strings / ms numbers.
219
+ 5. **Unsorted rows.** The constructor throws and names the row; pass
220
+ `sort: true` rather than sorting by hand.
221
+ 6. **Mutating.** Nothing mutates. Capture the return value.
222
+ 7. **Iterating events in a hot loop for a chart.** Use `column(name)` /
223
+ `toFloat64Array()` or hand the series to `@pond-ts/charts` — do not
224
+ rebuild point arrays per frame.
225
+ 8. **Mismatched package versions.** All `pond-ts` / `@pond-ts/*` at the same
226
+ version, always.
227
+ 9. **Reaching for a chart-library adapter first.** If the project uses React,
228
+ `@pond-ts/charts` consumes the series with no adapter; `toPoints()` is the
229
+ bridge for other libraries.
230
+
231
+ ## Where to read next
232
+
233
+ - `API.md` (this folder) — find any export and its source file.
234
+ - <https://pond-ts.org/llms.txt> — every docs page with a one-line
235
+ description; `https://pond-ts.org/llms-<area>.txt` for a single-fetch dump
236
+ of one area (`pond-ts`, `charts`, `financial`, …).
237
+ - <https://pond-ts.org/docs/pond-ts/mental-model> — one picture, and the
238
+ pandas / pondjs translation tables.
239
+ - <https://pond-ts.org/docs/how-to-guides> — end-to-end builds with the
240
+ friction already ironed out (dashboard, messy CSV ingest, histograms,
241
+ large series).
242
+ - Claude Code users: `/plugin marketplace add pond-ts/pond` then
243
+ `/plugin install pond-ts@pond-ts` installs skills for core, charts and
244
+ financial.
package/API.md CHANGED
@@ -30,7 +30,7 @@ next door is the point.
30
30
  | `packages/core` | `pond-ts` | `.` and `./types` (zero-runtime schema contract) | `website/docs/pond-ts/` |
31
31
  | `packages/react` | `@pond-ts/react` | `.` | `website/docs/react/` |
32
32
  | `packages/charts` | `@pond-ts/charts` | `.` | `website/docs/charts/` |
33
- | `packages/financial` | `@pond-ts/financial` | `.` and `./fluent` (prototype augmentation) | `website/docs/financial/` |
33
+ | `packages/financial` | `@pond-ts/financial` | `.`, `./fluent` (prototype augmentation), `./catalog` | `website/docs/financial/` |
34
34
  | `packages/fit` | `@pond-ts/fit` | `.` | `website/docs/fit/` |
35
35
  | `packages/process` | `@pond-ts/process` | `.` and `./pool` (Node worker pool) — **experimental** | `website/docs/process/` |
36
36
 
@@ -40,13 +40,13 @@ next door is the point.
40
40
 
41
41
  ### Series classes & construction
42
42
 
43
- | Export | Purpose | Source |
44
- | ----------------------- | ------------------------------------------------------ | ---------------------------------------------------- |
45
- | `TimeSeries` | Immutable time-indexed collection, columnar storage | `packages/core/src/batch/time-series.ts` |
46
- | `ValueSeries` | Series keyed by a monotonic non-time value axis | `packages/core/src/batch/value-series.ts` |
47
- | `PartitionedTimeSeries` | Scoped view for per-partition stateful transforms | `packages/core/src/batch/partitioned-time-series.ts` |
48
- | `Sequence` | Infinite grid of time buckets (daily, hourly, every N) | `packages/core/src/sequence/sequence.ts` |
49
- | `BoundedSequence` | Finite ordered list of explicit interval buckets | `packages/core/src/sequence/bounded-sequence.ts` |
43
+ | Export | Purpose | Source |
44
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
45
+ | `TimeSeries` | Immutable time-indexed collection, columnar storage | `packages/core/src/batch/time-series.ts` |
46
+ | `ValueSeries` | Series keyed by a monotonic non-time value axis | `packages/core/src/batch/value-series.ts` |
47
+ | `PartitionedTimeSeries` | Scoped view for per-partition stateful transforms; `<S, K, By>` — `By` is the partition column names, carried into `aggregate` / `rolling` result types | `packages/core/src/batch/partitioned-time-series.ts` |
48
+ | `Sequence` | Infinite grid of time buckets (daily, hourly, every N) | `packages/core/src/sequence/sequence.ts` |
49
+ | `BoundedSequence` | Finite ordered list of explicit interval buckets | `packages/core/src/sequence/bounded-sequence.ts` |
50
50
 
51
51
  Static constructors on `TimeSeries`: `fromJSON()` (row tuples/objects),
52
52
  `fromColumns()` (struct-of-arrays; `number` + `string` value columns),
@@ -125,10 +125,11 @@ Value-axis wire types
125
125
  `arrayContainsAny()`, `arrayAggregate()`, `arrayExplode()`
126
126
  - **Gap fill / dedupe**: `fill()`, `materialize()`, `dedupe()`
127
127
  - **Aggregate/group**: `aggregate(sequence, spec)`, `reduce()`, `groupBy()`,
128
- `partitionBy()`, `byColumn()` (order-free, by column value),
128
+ `partitionBy()`, `byColumn(col, bins, mapping)` (numeric binning of a column into
129
+ fixed-`width` or explicit-`edges` bins, then reduce per bin — histograms),
129
130
  `rollingByColumn()`, `byValue(axis)` (project onto a `ValueSeries`)
130
131
  - **Windowing/smoothing**: `rolling(window, spec, opts)`, `smooth(column,
131
- method)` (EMA / Butterworth / Savitzky-Golay), `align(method, opts)`
132
+ method, opts)` (`'ema'` / `'movingAverage'` / `'loess'`), `align(method, opts)`
132
133
  - **Differential/statistical**: `diff()`, `rate()`, `pctChange()`,
133
134
  `cumulative()`, `scan()` (custom stateful reducer), `shift()`, `baseline()`
134
135
  (rolling avg/sd/bands), `outliers()` (deviation from baseline)
@@ -441,112 +442,117 @@ study whose centre line is the caller's own field
441
442
  appends only the bands (`atrBands`: no `Middle`), since the middle is already
442
443
  on the series.
443
444
 
444
- | Study | Output column(s) | Options gist | Source |
445
- | --------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
446
- | `sma` | `sma` | `{ period, column?, output? }` | `packages/financial/src/studies/moving-average.ts` |
447
- | `ema` | `ema` | `{ period, column?, output? }` (α = 2/(period+1)) | `packages/financial/src/studies/moving-average.ts` |
448
- | `movingAverage` | `ma` | `{ period, type?, column?, output? }` — the shared `MaType` menu (default `'sma'`) | `packages/financial/src/studies/moving-average.ts` |
449
- | `bollinger` | `bbMiddle`, `bbUpper`, `bbLower` | `{ period, stdDev?, column?, prefix? }` | `packages/financial/src/studies/bollinger.ts` |
450
- | `envelope` | `envMiddle`, `envUpper`, `envLower` | `{ period, percent?, maType?, column?, prefix? }` | `packages/financial/src/studies/envelope.ts` |
451
- | `rollingStdev` | `stdev` | `{ period, column?, output? }` (population, ddof=0) | `packages/financial/src/studies/rolling-stat.ts` |
452
- | `rollingMin` / `rollingMax` | `min` / `max` | `{ period, column?, output? }` (one edge; `donchian` gives the channel) | `packages/financial/src/studies/rolling-stat.ts` |
453
- | `rollingPercentile` | `p{q}` (e.g. `p90`) | `{ period, q, column?, output? }` | `packages/financial/src/studies/rolling-stat.ts` |
454
- | `zScore` | `zscore` | `{ period, column?, output? }` | `packages/financial/src/studies/z-score.ts` |
455
- | `percentChange` | `pctChange` | `{ periods?, column?, output? }` (= ROC; TA-Lib-verified) | `packages/financial/src/studies/percent-change.ts` |
456
- | `rsi` | `rsi` | `{ period?, column?, output? }` (Wilder, default 14) | `packages/financial/src/studies/rsi.ts` |
457
- | `macd` | `macdLine`, `macdSignal`, `macdHist` | `{ fastPeriod?, slowPeriod?, signalPeriod?, column?, prefix? }` (12/26/9) | `packages/financial/src/studies/macd.ts` |
458
- | `atr` | `atr` | `{ period?, high?, low?, close?, output? }` (Wilder, default 14) | `packages/financial/src/studies/atr.ts` |
459
- | `momentum` | `momentum` | `{ period?, column?, output? }` (`v − v[−period]`, default 10) | `packages/financial/src/studies/momentum.ts` |
460
- | `historicalVolatility` | `hv` | `{ period?, annualize?, column?, output? }` (σ of log returns, ×√252) | `packages/financial/src/studies/volatility.ts` |
461
- | `stochastic` | `stochK`, `stochD` | `{ kPeriod?, slowing?, dPeriod?, high?, low?, close?, prefix? }` (14/3/3; `slowing: 1` = fast) | `packages/financial/src/studies/stochastic.ts` |
462
- | `williamsR` | `williamsR` | `{ period?, high?, low?, close?, output? }` (default 14, bounded −100..0) | `packages/financial/src/studies/williams-r.ts` |
463
- | `donchian` | `dcUpper`, `dcLower`, `dcMiddle` | `{ period?, high?, low?, prefix? }` (default 20) | `packages/financial/src/studies/donchian.ts` |
464
- | `obv` | `obv` | `{ close?, volume?, output? }` (no period; TA-Lib seed `volume[0]`) | `packages/financial/src/studies/obv.ts` |
465
- | `vwap` | `vwap` | `{ period, high?, low?, close?, volume?, output? }` (rolling, typical px) | `packages/financial/src/studies/vwap.ts` |
466
- | `keltner` | `kcMiddle`, `kcUpper`, `kcLower` | `{ period?, atrPeriod?, multiplier?, maType?, high?, low?, close?, prefix? }` (modern variant: EMA(20) of typical price ± 2·ATR(10)) | `packages/financial/src/studies/keltner.ts` |
467
- | `atrBands` | `atrbUpper`, `atrbLower` | `{ period?, multiplier?, column?, high?, low?, close?, prefix? }` (14/2; **no middle** — it is `column`) | `packages/financial/src/studies/atr-bands.ts` |
468
- | `qstick` | `qstick` | `{ period?, maType?, open?, close?, output? }` (MA of `close − open`, default 8/sma) | `packages/financial/src/studies/qstick.ts` |
469
- | `trix` | `trix`, `trixSignal` | `{ period?, signalPeriod?, column?, prefix? }` (1-bar % ROC of EMA³, 15/9; the line takes the prefix itself) | `packages/financial/src/studies/trix.ts` |
470
- | `coppock` | `coppock` | `{ longPeriod?, shortPeriod?, wmaPeriod?, column?, output? }` (WMA of ROC₁₄+ROC₁₁, 14/11/10 — monthly by convention) | `packages/financial/src/studies/coppock.ts` |
471
- | `priceOscillator` | `priceOsc` | `{ fastPeriod?, slowPeriod?, maType?, mode?, column?, output? }` (12/26/ema, percent = PPO, `mode: 'absolute'` = APO) | `packages/financial/src/studies/price-oscillator.ts` |
472
- | `disparityIndex` | `disparity` | `{ period?, maType?, column?, output? }` (`100·(price − MA)/MA`, default 14/sma) | `packages/financial/src/studies/disparity-index.ts` |
473
- | `detrendedPriceOscillator` | `dpo` | `{ period?, maType?, column?, output? }` (`price − MA[i − ⌊period/2⌋−1]`, default 20/sma) | `packages/financial/src/studies/detrended-price-oscillator.ts` |
474
- | `elderRay` | `elderBull`, `elderBear` | `{ period?, high?, low?, close?, prefix? }` (`high/low − EMA(close)`, default 13) | `packages/financial/src/studies/elder-ray.ts` |
475
- | `awesomeOscillator` | `ao` | `{ fastPeriod?, slowPeriod?, high?, low?, output? }` (SMA 5 − SMA 34 of `(high+low)/2`) | `packages/financial/src/studies/awesome-oscillator.ts` |
476
- | `accumulationDistribution` | `ad` | `{ high?, low?, close?, volume?, output? }` (no period; cumulative CLV·volume, = TA-Lib `AD`) | `packages/financial/src/studies/accumulation-distribution.ts` |
477
- | `chaikinOscillator` | `chaikinOsc` | `{ fastPeriod?, slowPeriod?, high?, low?, close?, volume?, output? }` (EMA 3 − EMA 10 of A/D, = TA-Lib `ADOSC`) | `packages/financial/src/studies/chaikin-oscillator.ts` |
478
- | `priceVolumeTrend` | `pvt` | `{ close?, volume?, output? }` (no period; cumulative fractional-change·volume; bar 0 undefined) | `packages/financial/src/studies/price-volume-trend.ts` |
479
- | `chaikinMoneyFlow` | `cmf` | `{ period?, high?, low?, close?, volume?, output? }` (Σ CLV·vol / Σ vol over 20, bounded −1..+1) | `packages/financial/src/studies/chaikin-money-flow.ts` |
480
- | `moneyFlowIndex` | `mfi` | `{ period?, high?, low?, close?, volume?, output? }` (RSI form on typical-price·volume, default 14, = TA-Lib `MFI`) | `packages/financial/src/studies/money-flow-index.ts` |
481
- | `forceIndex` | `force` | `{ period?, close?, volume?, output? }` (EMA of Δclose·volume, Elder's 13; `period: 1` is the raw force) | `packages/financial/src/studies/force-index.ts` |
482
- | `easeOfMovement` | `eom` | `{ period?, maType?, scale?, high?, low?, volume?, output? }` (Arms' box ratio, 14/sma/1e8; quadratic in price) | `packages/financial/src/studies/ease-of-movement.ts` |
483
- | `volumeOscillator` | `volOsc` | `{ fastPeriod?, slowPeriod?, maType?, volume?, output? }` (5/10/sma; `priceOscillator` percent-mode over volume) | `packages/financial/src/studies/volume-oscillator.ts` |
484
- | `chandeMomentum` | `cmo` | `{ period?, column?, output? }` (Chande's **unsmoothed** up/down sums, default 14 — _not_ TA-Lib's CMO, which is `2·rsi − 100`) | `packages/financial/src/studies/chande-momentum.ts` |
485
- | `ultimateOscillator` | `uo` | `{ shortPeriod?, mediumPeriod?, longPeriod?, high?, low?, close?, output? }` (7/14/28 weighted 4/2/1; TA-Lib `ULTOSC`) | `packages/financial/src/studies/ultimate-oscillator.ts` |
486
- | `commodityChannelIndex` | `cci` | `{ period?, high?, low?, close?, output? }` (`(tp − SMA)/(0.015 · meanAbsDev)`, default 20; TA-Lib `CCI`) | `packages/financial/src/studies/commodity-channel-index.ts` |
487
- | `intradayMomentumIndex` | `imi` | `{ period?, open?, close?, output? }` (RSI's form over `close − open`, **plain** sums, default 14) | `packages/financial/src/studies/intraday-momentum-index.ts` |
488
- | `relativeVigorIndex` | `rvi`, `rviSignal` | `{ period?, open?, high?, low?, close?, prefix? }` (SWMA `(1,2,2,1)/6` body/range sums + SWMA signal, default 10) | `packages/financial/src/studies/relative-vigor-index.ts` |
489
- | `psychologicalLine` | `psy` | `{ period?, column?, output? }` (percent of **up** closes, strict `>`, default 12) | `packages/financial/src/studies/psychological-line.ts` |
490
- | `directionalMovement` | `dmiPlusDi`, `dmiMinusDi`, `dmiDx`, `dmiAdx`, `dmiAdxr` | `{ period?, high?, low?, close?, prefix? }` (Wilder's DMS — `+DI`/`−DI`/`DX`/`ADX`/`ADXR`, default 14; per-column warm-up; Wilder's seed, so a decaying transient vs TA-Lib) | `packages/financial/src/studies/directional-movement.ts` |
491
- | `aroon` | `aroonUp`, `aroonDown`, `aroonOsc` | `{ period?, high?, low?, prefix? }` (`100·(period − bars since extreme)/period` over a **`period + 1`**-bar window, default 25; = TA-Lib `AROON`/`AROONOSC`) | `packages/financial/src/studies/aroon.ts` |
492
- | `vortex` | `viPlus`, `viMinus` | `{ period?, high?, low?, close?, prefix? }` (`Σ\|H − prevL\| / Σ TR` and `Σ\|L − prevH\| / Σ TR`, default 14; positive, not bounded by 1) | `packages/financial/src/studies/vortex.ts` |
493
- | `chaikinVolatility` | `chaikinVol` | `{ period?, rocPeriod?, high?, low?, output? }` (percent ROC of EMA(`high − low`), 10/10; **plain** range) | `packages/financial/src/studies/chaikin-volatility.ts` |
494
- | `massIndex` | `mass` | `{ emaPeriod?, sumPeriod?, high?, low?, output? }` (Σ EMA(range)/EMA² over 25, Dorsey's 9/25; a **sum**, reads ≈ `sumPeriod`) | `packages/financial/src/studies/mass-index.ts` |
495
- | `choppinessIndex` | `chop` | `{ period?, high?, low?, close?, output? }` (`100·log10(ΣTR/(HH−LL))/log10(period)`, default 14, bounded 0..100; `period ≥ 2`) | `packages/financial/src/studies/choppiness-index.ts` |
496
- | `ulcerIndex` | `ulcer` | `{ period?, column?, output? }` (RMS % drawdown from the rolling peak, StockCharts' rolling form, default 14; warm-up `2·period−2`) | `packages/financial/src/studies/ulcer-index.ts` |
497
- | `verticalHorizontalFilter` | `vhf` | `{ period?, column?, output? }` ((HH−LL)/Σ\|Δcolumn\| over 28, Adam White's; a **fraction** in (0, 1], warm-up `period`) | `packages/financial/src/studies/vertical-horizontal-filter.ts` |
498
- | `gopalakrishnanRangeIndex` | `gapo` | `{ period?, high?, low?, output? }` (`ln(HH−LL)/ln(period)` = log base `period` of the range, default 10; `period ≥ 2`) | `packages/financial/src/studies/gopalakrishnan-range-index.ts` |
499
- | `relativeVolatilityIndex` | `relVol` | `{ period?, stdevPeriod?, column?, output? }` (RSI's form on σ, Wilder-smoothed, Dorsey's 14/10 — **not** `rvi`, see below) | `packages/financial/src/studies/relative-volatility-index.ts` |
500
- | `linearRegression` | `linregValue`, `linregSlope`, `linregIntercept`, `linregAngle`, `linregR2` | `{ period?, column?, prefix? }` (one rolling OLS fit against the bar index, default 14, `period ≥ 2`; `Value` = TA-Lib `LINEARREG`, `Intercept` = the fit at the window's **first** bar, `Angle` = degrees and **scale-dependent**) | `packages/financial/src/studies/linear-regression.ts` |
501
- | `timeSeriesForecast` | `tsf` | `{ period?, column?, output? }` (the same fit one bar **past** the window, default 14; = TA-Lib `TSF`; deliberately not a `MaType`) | `packages/financial/src/studies/time-series-forecast.ts` |
502
- | `chandeForecastOscillator` | `cfo` | `{ period?, column?, output? }` (`100·(price − TSF)/price`, default 14; scale-invariant, **not** shift-invariant) | `packages/financial/src/studies/chande-forecast-oscillator.ts` |
503
- | `centerOfGravity` | `cog` | `{ period?, column?, output? }` (Ehlers' position-weighted balance point, default 10; **negative**, in `[−period, −1]` on positive prices, flat reads `−(period+1)/2` — TradingView's uncentred convention) | `packages/financial/src/studies/center-of-gravity.ts` |
504
- | `correlation` | `corr` | `{ period?, column?, benchmark, output? }` (Pearson r of two columns over 30 bars, = TA-Lib `CORREL`; `benchmark` is a **column on the same joined series**, required) | `packages/financial/src/studies/correlation.ts` |
505
- | `beta` | `beta` | `{ period?, column?, benchmark, output? }` (slope of `column`'s 1-bar returns on `benchmark`'s over 5 bars, = TA-Lib `BETA(benchmark, column)`; pass **prices**, returns taken inside) | `packages/financial/src/studies/beta.ts` |
506
- | `priceRelative` | `priceRel` | `{ column?, benchmark, output? }` (`column / benchmark`, no period — ChartIQ's Price Relative / Relative Strength **comparative**; not `rsi`) | `packages/financial/src/studies/price-relative.ts` |
507
- | `performanceIndex` | `perf` | `{ period?, column?, benchmark, output? }` (each side's own `period`-bar growth, divided; 1 = parity, default 20; `(x−1)·100` == `percentChange(priceRelative)`) | `packages/financial/src/studies/performance-index.ts` |
508
- | `guppy` | `gmmaS3`…`gmmaS15`, `gmmaL30`…`gmmaL60` | `{ column?, type?, prefix? }` (Guppy's GMMA — the **fixed** twelve averages, short 3/5/8/10/12/15, long 30/35/40/45/50/60, default `ema`; the lists ship as `GUPPY_SHORT_PERIODS` / `GUPPY_LONG_PERIODS`) | `packages/financial/src/studies/guppy.ts` |
509
- | `rainbow` | `rainbow1`…`rainbow10` | `{ column?, period?, type?, prefix? }` (Widner's Rainbow — ten **recursive** averages, each smoothing the previous; default period 2 / `sma`; stage `k` warms up at `k·(period−1)`) | `packages/financial/src/studies/rainbow.ts` |
510
- | `rainbowOscillator` | `rbo`, `rboUpper`, `rboLower` | `{ column?, period?, lookback?, type?, prefix? }` (ChartIQ's — `100·(price − mean of the ten)/(HH−LL)` with the stack's own width as mirrored bands; default 2 / 10) | `packages/financial/src/studies/rainbow.ts` |
511
- | `kst` | `kst`, `kstSignal` | `{ column?, signalPeriod?, prefix? }` (Pring's Know Sure Thing — ROC 10/15/20/30 smoothed 10/10/10/15, weighted 1/2/3/4; the twelve numbers are **not** options, only the signal SMA is, default 9) | `packages/financial/src/studies/kst.ts` |
512
- | `priceMomentumOscillator` | `pmo`, `pmoSignal` | `{ column?, prefix? }` (DecisionPoint's PMO — two stages of **custom** `α = 2/n` smoothing over a 1-bar percent ROC, ×10, with a **span** EMA(10) signal; no period options) | `packages/financial/src/studies/price-momentum-oscillator.ts` |
513
- | `stochasticRsi` | `stochRsiK`, `stochRsiD` | `{ column?, rsiPeriod?, stochPeriod?, kPeriod?, dPeriod?, prefix? }` (the stochastic construction over the RSI, 14/14/3/3; `stochRsiK` == TA-Lib `STOCHRSI`'s **fastd**, `stochRsiD` has no TA-Lib counterpart) | `packages/financial/src/studies/stochastic-rsi.ts` |
514
- | `trueStrengthIndex` | `tsi`, `tsiSignal` | `{ column?, longPeriod?, shortPeriod?, signalPeriod?, prefix? }` (Blau's TSI — `100·EMA(EMA(Δ,long),short)/EMA(EMA(\|Δ\|,long),short)`, 25/13/7; bounded −100…100, long applied **first**) | `packages/financial/src/studies/true-strength-index.ts` |
515
- | `movingAverageDeviation` | `maDev` | `{ period?, maType?, column?, output? }` (`price − MA`, in **price units**, default 20/sma — the points half of the pair whose percent half IS `disparityIndex`; no `mode` flag) | `packages/financial/src/studies/moving-average-deviation.ts` |
516
- | `parabolicSar` | `psar`, `psarTrend` | `{ step?, maxStep?, high?, low?, prefix? }` (Wilder's stop-and-reverse, defaults 0.02 / 0.2; **= TA-Lib `SAR` exactly**; `Trend` is `+1` long / `−1` short — the stop can print ON an extreme, so the side is not derivable from the value) | `packages/financial/src/studies/parabolic-sar.ts` |
517
- | `superTrend` | `st`, `stTrend` | `{ period?, multiplier?, high?, low?, close?, prefix? }` (Seban's ratcheting ATR band as TradingView's `ta.supertrend`, defaults 10 / 3; `st` **is** the live band, so the bands are not emitted; the seed side is DOWN) | `packages/financial/src/studies/super-trend.ts` |
518
- | `atrTrailingStop` | `ats`, `atsTrend` | `{ period?, multiplier?, high?, low?, close?, prefix? }` (close-anchored ratcheting stop, Vervoort's, defaults 14 / 3; a close exactly ON the stop flips **short**; the Chandelier anchor is `donchian` + `atr`, not a knob) | `packages/financial/src/studies/atr-trailing-stop.ts` |
519
- | `negativeVolumeIndex` | `nvi` | `{ column?, volume?, output?, start? }` (Fosback: compound the close return only on a **lower**-volume bar, base 1000; no period, no warm-up; a **flat** volume holds on both indices) | `packages/financial/src/studies/volume-index.ts` |
520
- | `positiveVolumeIndex` | `pvi` | `{ column?, volume?, output?, start? }` (the same on a **higher**-volume bar) | `packages/financial/src/studies/volume-index.ts` |
521
- | `klinger` | `kvo`, `kvoSignal` | `{ fastPeriod?, slowPeriod?, signalPeriod?, high?, low?, close?, volume?, prefix? }` (Klinger's ORIGINAL volume force through an EMA pair, defaults 34 / 55 / 13; **F-AMBIG** — TradingView's simplified `ta.kvo` is a different indicator) | `packages/financial/src/studies/klinger.ts` |
522
- | `typicalPrice` | `typicalPrice` | `{ high?, low?, close?, output? }` (`(h+l+c)/3` = TA-Lib `TYPPRICE`, exact; **no warm-up**) | `packages/financial/src/studies/price-transform.ts` |
523
- | `medianPrice` | `medianPrice` | `{ high?, low?, output? }` (`(h+l)/2` = `MEDPRICE`, exact; `close` on the shared options type is ignored) | `packages/financial/src/studies/price-transform.ts` |
524
- | `weightedClose` | `weightedClose` | `{ high?, low?, close?, output? }` (`(h+l+2c)/4` = `WCLPRICE`, exact) | `packages/financial/src/studies/price-transform.ts` |
525
- | `averagePrice` | `averagePrice` | `{ open?, high?, low?, close?, output? }` (`(o+h+l+c)/4` = `AVGPRICE`, exact — the only transform that reads the open) | `packages/financial/src/studies/price-transform.ts` |
526
- | `balanceOfPower` | `bop` | `{ period?, maType?, open?, high?, low?, close?, output? }` (`(c−o)/(h−l)`, bounded −1…1; **raw by default** = TA-Lib `BOP` exact, `period` gives ChartIQ's smoothed form; a flat bar is `0`; `maType` without `period` throws) | `packages/financial/src/studies/balance-of-power.ts` |
527
- | `starcBands` | `starcMiddle`, `starcUpper`, `starcLower` | `{ period?, atrPeriod?, multiplier?, maType?, high?, low?, close?, prefix? }` (Stoller: MA(**close**) ± mult·ATR, 20 / 15 / 2 / sma — the close-centred sibling of `keltner`'s typical-price centre) | `packages/financial/src/studies/starc-bands.ts` |
528
- | `highLowBands` | `hlbMiddle`, `hlbUpper`, `hlbLower` | `{ period?, percent?, maType?, high?, low?, prefix? }` (MA(**median price**) × (1 ± percent%), 10 / 1% / trima; it **is** `envelope` over a `medianPrice` column — same `percent`, same units; ChartIQ labels the knob "shift") | `packages/financial/src/studies/high-low-bands.ts` |
529
- | `bollingerBandwidth` | `bbWidth` | `{ period?, stdDev?, column?, output? }` (`100·(upper − lower)/middle`, 20 / 2 — the **×100** StockCharts form; a flat window is `0`, not missing; a zero-centre window — flat at zero or zero-mean — is missing) | `packages/financial/src/studies/bollinger-derived.ts` |
530
- | `bollingerPercentB` | `percentB` | `{ period?, stdDev?, column?, output? }` (`(price − lower)/(upper − lower)`, 20 / 2 — the **decimal** form, unbounded; a flat window is a genuine `0/0` → missing) | `packages/financial/src/studies/bollinger-derived.ts` |
531
- | `primeNumberBands` | `pnbUpper`, `pnbLower` | `{ high?, low?, prefix? }` (smallest prime ≥ high / largest ≤ low — a step function of the price LEVEL, no warm-up; a price below 2 is outside the domain; cost grows with price magnitude) | `packages/financial/src/studies/prime-number.ts` |
532
- | `primeNumberOscillator` | `pno` | `{ column?, output? }` (`price − nearestPrime(price)`, signed; a tie goes to the **lower** prime; no warm-up; neither scale- nor shift-invariant) | `packages/financial/src/studies/prime-number.ts` |
533
- | `marketFacilitationIndex` | `bwmfi` | `{ high?, low?, volume?, output? }` (Bill Williams' `(h−l)/volume`, raw — **`bwmfi`, not `mfi`**, which `moneyFlowIndex` owns; zero volume → missing, flat bar → `0`) | `packages/financial/src/studies/market-facilitation-index.ts` |
534
- | `twiggsMoneyFlow` | `tmf` | `{ period?, high?, low?, close?, volume?, output? }` (Twiggs: CMF rebuilt on the **true** range and Wilder-smoothed, default 21; bounded −1…1; **F-AMBIG** — the window-sum form is 0.0706 away; warm-up `period`, and an interior gap ends it) | `packages/financial/src/studies/twiggs-money-flow.ts` |
535
- | `tradeVolumeIndex` | `tvi` | `{ minTick, column?, volume?, output? }` (tick-direction accumulation; `minTick` — the instrument's minimum tick — is **required**; an undecided bar keeps the LAST direction, no first direction is invented, base 0, no warm-up; an interior gap **ends** the level, `obv`'s rule) | `packages/financial/src/studies/trade-volume-index.ts` |
536
- | `shinoharaIntensityRatio` | `sirStrong`, `sirWeak` | `{ period?, open?, high?, low?, close?, prefix? }` (Shinohara's A and B ratios, `100·Σup/Σdown` over 26 bars — A against the bar's own open, B against the previous close; **F-AMBIG** on which is charted "strong"; neither is bounded and B inverts on a gappy tape; per-column warm-up 25 / 26) | `packages/financial/src/studies/shinohara-intensity-ratio.ts` |
537
- | `elderImpulse` | `impulse` | `{ emaPeriod?, fastPeriod?, slowPeriod?, signalPeriod?, column?, output? }` (Elder: `+1` when EMA(13) **and** the MACD histogram both rise, `−1` when both fall, `0` otherwise — a **numeric** column, `withColumn` has no string door; ties are `0`; warm-up 34) | `packages/financial/src/studies/elder-impulse.ts` |
538
- | `movingAverageCross` | `maCross` | `{ fastPeriod?, slowPeriod?, maType?, column?, output? }` (a **signal** column: `+1` on the bar the fast MA crosses above the slow, `−1` below, `0` otherwise — the averages themselves are `movingAverage`'s; an exact tie is no cross and a touch-and-retreat is no cross; `maType`, not `type`; warm-up `slowPeriod`) | `packages/financial/src/studies/moving-average-cross.ts` |
539
- | `anchoredVwap` | `avwap` | `{ anchor, high?, low?, close?, volume?, output? }` (cumulative `Σ tp·vol / Σ vol` from the first bar **at or after** `anchor` — a `Date` or epoch ms, **required**; earlier bars `undefined`; an interior gap ends the line, `obv`'s rule; the session-reset form waits on [PND-TCAL]) | `packages/financial/src/studies/anchored-vwap.ts` |
540
- | `stochasticMomentumIndex` | `smi`, `smiSignal` | `{ period?, longPeriod?, shortPeriod?, signalPeriod?, high?, low?, close?, prefix? }` (Blau's SMI — the close against the **midpoint** of the HH/LL range, double-EMA smoothed above and below, ×100; Blau's 13 / 25 / 2 / 3; bounded −100…100) | `packages/financial/src/studies/stochastic-momentum-index.ts` |
541
- | `fisherTransform` | `fisher`, `fisherSignal` | `{ period?, high?, low?, prefix? }` (Ehlers' transform of the **median price's** own range position, default 10; the `0.33/0.67`, `±0.99→±0.999` clamp and `0.5/0.5` constants are Ehlers', not options; the signal is the line delayed one bar) | `packages/financial/src/studies/fisher-transform.ts` |
542
- | `schaffTrendCycle` | `stc` | `{ fastPeriod?, slowPeriod?, cyclePeriod?, column?, output? }` (Schaff's double stochastic of a MACD with a fixed `0.5` smoothing between, 23 / 50 / 10, bounded 0…100; a pinned first stochastic leaves the second window flat `undefined`) | `packages/financial/src/studies/schaff-trend-cycle.ts` |
543
- | `prettyGoodOscillator` | `pgo` | `{ period?, column?, high?, low?, close?, output? }` (Johnson's `(close SMA)/EMA(TR)`, default 14, in average-daily-ranges; **F-AMBIG** the Wilder-ATR denominator port is a different study, measured) | `packages/financial/src/studies/pretty-good-oscillator.ts` |
544
- | `swingIndex` | `si` | `{ limit, open?, high?, low?, close?, output? }` (Wilder 1978; `limit` the instrument's limit move is **required**, there being no defensible default; bounded −100…100 at a `limit` above the largest gap; `R = 0` `undefined`) | `packages/financial/src/studies/swing-index.ts` |
545
- | `accumulativeSwingIndex` | `asi` | `{ limit, open?, high?, low?, close?, output? }` (the running total of `swingIndex`; a running sum, so an interior gap a halted bar pair included ends it) | `packages/financial/src/studies/swing-index.ts` |
546
- | `randomWalkIndex` | `rwiHigh`, `rwiLow` | `{ period?, high?, low?, close?, prefix? }` (Poulos: the max over horizons `2 period` of `(high − low[−n])/(meanTR(n)·√n)`, default 14; the **`n`-bar mean** TR, not Wilder's ATR; O(N·period), and it goes negative) | `packages/financial/src/studies/random-walk-index.ts` |
547
- | `ravi` | `ravi` | `{ shortPeriod?, longPeriod?, column?, output? }` (Chande: `100·\|SMA(7) SMA(65)\|/SMA(65)`; **absolute**, so it answers "is there a trend", not "which way"; trending above 3%) | `packages/financial/src/studies/ravi.ts` |
548
- | `trendIntensityIndex` | `tii` | `{ period?, maPeriod?, column?, output? }` (M. H. Pee: `100·Σpos/(Σpos + Σneg)` of the deviations from an SMA, 30 / 60, bounded 0…100; **F-AMBIG** — the count form is a different study; warm-up 88) | `packages/financial/src/studies/trend-intensity-index.ts` |
549
- | `specialK` | `specialK` | `{ column?, output? }` (Pring's extended KSTtwelve weighted smoothed ROCs across three groups; the thirty-six constants ARE the study, so there are no period options; **warm-up 724 bars**) | `packages/financial/src/studies/special-k.ts` |
445
+ | Study | Output column(s) | Options gist | Source |
446
+ | --------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
447
+ | `sma` | `sma` | `{ period, column?, output? }` | `packages/financial/src/studies/moving-average.ts` |
448
+ | `ema` | `ema` | `{ period, column?, output? }` (α = 2/(period+1)) | `packages/financial/src/studies/moving-average.ts` |
449
+ | `movingAverage` | `ma` | `{ period, type?, column?, output? }` — the shared `MaType` menu (default `'sma'`) | `packages/financial/src/studies/moving-average.ts` |
450
+ | `bollinger` | `bbMiddle`, `bbUpper`, `bbLower` | `{ period, stdDev?, column?, prefix? }` | `packages/financial/src/studies/bollinger.ts` |
451
+ | `envelope` | `envMiddle`, `envUpper`, `envLower` | `{ period, percent?, maType?, column?, prefix? }` | `packages/financial/src/studies/envelope.ts` |
452
+ | `rollingStdev` | `stdev` | `{ period, column?, output? }` (population, ddof=0) | `packages/financial/src/studies/rolling-stat.ts` |
453
+ | `rollingMin` / `rollingMax` | `min` / `max` | `{ period, column?, output? }` (one edge; `donchian` gives the channel) | `packages/financial/src/studies/rolling-stat.ts` |
454
+ | `rollingPercentile` | `p{q}` (e.g. `p90`) | `{ period, q, column?, output? }` | `packages/financial/src/studies/rolling-stat.ts` |
455
+ | `zScore` | `zscore` | `{ period, column?, output? }` | `packages/financial/src/studies/z-score.ts` |
456
+ | `percentChange` | `pctChange` | `{ periods?, column?, output? }` (= ROC; TA-Lib-verified) | `packages/financial/src/studies/percent-change.ts` |
457
+ | `rsi` | `rsi` | `{ period?, column?, output? }` (Wilder, default 14) | `packages/financial/src/studies/rsi.ts` |
458
+ | `macd` | `macdLine`, `macdSignal`, `macdHist` | `{ fastPeriod?, slowPeriod?, signalPeriod?, column?, prefix? }` (12/26/9) | `packages/financial/src/studies/macd.ts` |
459
+ | `atr` | `atr` | `{ period?, high?, low?, close?, output? }` (Wilder, default 14) | `packages/financial/src/studies/atr.ts` |
460
+ | `momentum` | `momentum` | `{ period?, column?, output? }` (`v − v[−period]`, default 10) | `packages/financial/src/studies/momentum.ts` |
461
+ | `historicalVolatility` | `hv` | `{ period?, annualize?, column?, output? }` (σ of log returns, ×√252) | `packages/financial/src/studies/volatility.ts` |
462
+ | `stochastic` | `stochK`, `stochD` | `{ kPeriod?, slowing?, dPeriod?, high?, low?, close?, prefix? }` (14/3/3; `slowing: 1` = fast) | `packages/financial/src/studies/stochastic.ts` |
463
+ | `williamsR` | `williamsR` | `{ period?, high?, low?, close?, output? }` (default 14, bounded −100..0) | `packages/financial/src/studies/williams-r.ts` |
464
+ | `donchian` | `dcUpper`, `dcLower`, `dcMiddle` | `{ period?, high?, low?, prefix? }` (default 20) | `packages/financial/src/studies/donchian.ts` |
465
+ | `obv` | `obv` | `{ close?, volume?, output? }` (no period; TA-Lib seed `volume[0]`) | `packages/financial/src/studies/obv.ts` |
466
+ | `vwap` | `vwap` | `{ period, high?, low?, close?, volume?, output? }` (rolling, typical px) | `packages/financial/src/studies/vwap.ts` |
467
+ | `keltner` | `kcMiddle`, `kcUpper`, `kcLower` | `{ period?, atrPeriod?, multiplier?, maType?, high?, low?, close?, prefix? }` (modern variant: EMA(20) of typical price ± 2·ATR(10)) | `packages/financial/src/studies/keltner.ts` |
468
+ | `atrBands` | `atrbUpper`, `atrbLower` | `{ period?, multiplier?, column?, high?, low?, close?, prefix? }` (14/2; **no middle** — it is `column`) | `packages/financial/src/studies/atr-bands.ts` |
469
+ | `qstick` | `qstick` | `{ period?, maType?, open?, close?, output? }` (MA of `close − open`, default 8/sma) | `packages/financial/src/studies/qstick.ts` |
470
+ | `trix` | `trix`, `trixSignal` | `{ period?, signalPeriod?, column?, prefix? }` (1-bar % ROC of EMA³, 15/9; the line takes the prefix itself) | `packages/financial/src/studies/trix.ts` |
471
+ | `coppock` | `coppock` | `{ longPeriod?, shortPeriod?, wmaPeriod?, column?, output? }` (WMA of ROC₁₄+ROC₁₁, 14/11/10 — monthly by convention) | `packages/financial/src/studies/coppock.ts` |
472
+ | `priceOscillator` | `priceOsc` | `{ fastPeriod?, slowPeriod?, maType?, mode?, column?, output? }` (12/26/ema, percent = PPO, `mode: 'absolute'` = APO) | `packages/financial/src/studies/price-oscillator.ts` |
473
+ | `disparityIndex` | `disparity` | `{ period?, maType?, column?, output? }` (`100·(price − MA)/MA`, default 14/sma) | `packages/financial/src/studies/disparity-index.ts` |
474
+ | `detrendedPriceOscillator` | `dpo` | `{ period?, maType?, column?, output? }` (`price − MA[i − ⌊period/2⌋−1]`, default 20/sma) | `packages/financial/src/studies/detrended-price-oscillator.ts` |
475
+ | `elderRay` | `elderBull`, `elderBear` | `{ period?, high?, low?, close?, prefix? }` (`high/low − EMA(close)`, default 13) | `packages/financial/src/studies/elder-ray.ts` |
476
+ | `awesomeOscillator` | `ao` | `{ fastPeriod?, slowPeriod?, high?, low?, output? }` (SMA 5 − SMA 34 of `(high+low)/2`) | `packages/financial/src/studies/awesome-oscillator.ts` |
477
+ | `accumulationDistribution` | `ad` | `{ high?, low?, close?, volume?, output? }` (no period; cumulative CLV·volume, = TA-Lib `AD`) | `packages/financial/src/studies/accumulation-distribution.ts` |
478
+ | `chaikinOscillator` | `chaikinOsc` | `{ fastPeriod?, slowPeriod?, high?, low?, close?, volume?, output? }` (EMA 3 − EMA 10 of A/D, = TA-Lib `ADOSC`) | `packages/financial/src/studies/chaikin-oscillator.ts` |
479
+ | `priceVolumeTrend` | `pvt` | `{ close?, volume?, output? }` (no period; cumulative fractional-change·volume; bar 0 undefined) | `packages/financial/src/studies/price-volume-trend.ts` |
480
+ | `chaikinMoneyFlow` | `cmf` | `{ period?, high?, low?, close?, volume?, output? }` (Σ CLV·vol / Σ vol over 20, bounded −1..+1) | `packages/financial/src/studies/chaikin-money-flow.ts` |
481
+ | `moneyFlowIndex` | `mfi` | `{ period?, high?, low?, close?, volume?, output? }` (RSI form on typical-price·volume, default 14, = TA-Lib `MFI`) | `packages/financial/src/studies/money-flow-index.ts` |
482
+ | `forceIndex` | `force` | `{ period?, close?, volume?, output? }` (EMA of Δclose·volume, Elder's 13; `period: 1` is the raw force) | `packages/financial/src/studies/force-index.ts` |
483
+ | `easeOfMovement` | `eom` | `{ period?, maType?, scale?, high?, low?, volume?, output? }` (Arms' box ratio, 14/sma/1e8; quadratic in price) | `packages/financial/src/studies/ease-of-movement.ts` |
484
+ | `volumeOscillator` | `volOsc` | `{ fastPeriod?, slowPeriod?, maType?, volume?, output? }` (5/10/sma; `priceOscillator` percent-mode over volume) | `packages/financial/src/studies/volume-oscillator.ts` |
485
+ | `chandeMomentum` | `cmo` | `{ period?, column?, output? }` (Chande's **unsmoothed** up/down sums, default 14 — _not_ TA-Lib's CMO, which is `2·rsi − 100`) | `packages/financial/src/studies/chande-momentum.ts` |
486
+ | `ultimateOscillator` | `uo` | `{ shortPeriod?, mediumPeriod?, longPeriod?, high?, low?, close?, output? }` (7/14/28 weighted 4/2/1; TA-Lib `ULTOSC`) | `packages/financial/src/studies/ultimate-oscillator.ts` |
487
+ | `commodityChannelIndex` | `cci` | `{ period?, high?, low?, close?, output? }` (`(tp − SMA)/(0.015 · meanAbsDev)`, default 20; TA-Lib `CCI`) | `packages/financial/src/studies/commodity-channel-index.ts` |
488
+ | `intradayMomentumIndex` | `imi` | `{ period?, open?, close?, output? }` (RSI's form over `close − open`, **plain** sums, default 14) | `packages/financial/src/studies/intraday-momentum-index.ts` |
489
+ | `relativeVigorIndex` | `rvi`, `rviSignal` | `{ period?, open?, high?, low?, close?, prefix? }` (SWMA `(1,2,2,1)/6` body/range sums + SWMA signal, default 10) | `packages/financial/src/studies/relative-vigor-index.ts` |
490
+ | `psychologicalLine` | `psy` | `{ period?, column?, output? }` (percent of **up** closes, strict `>`, default 12) | `packages/financial/src/studies/psychological-line.ts` |
491
+ | `directionalMovement` | `dmiPlusDi`, `dmiMinusDi`, `dmiDx`, `dmiAdx`, `dmiAdxr` | `{ period?, high?, low?, close?, prefix? }` (Wilder's DMS — `+DI`/`−DI`/`DX`/`ADX`/`ADXR`, default 14; per-column warm-up; Wilder's seed, so a decaying transient vs TA-Lib) | `packages/financial/src/studies/directional-movement.ts` |
492
+ | `aroon` | `aroonUp`, `aroonDown`, `aroonOsc` | `{ period?, high?, low?, prefix? }` (`100·(period − bars since extreme)/period` over a **`period + 1`**-bar window, default 25; = TA-Lib `AROON`/`AROONOSC`) | `packages/financial/src/studies/aroon.ts` |
493
+ | `vortex` | `viPlus`, `viMinus` | `{ period?, high?, low?, close?, prefix? }` (`Σ\|H − prevL\| / Σ TR` and `Σ\|L − prevH\| / Σ TR`, default 14; positive, not bounded by 1) | `packages/financial/src/studies/vortex.ts` |
494
+ | `chaikinVolatility` | `chaikinVol` | `{ period?, rocPeriod?, high?, low?, output? }` (percent ROC of EMA(`high − low`), 10/10; **plain** range) | `packages/financial/src/studies/chaikin-volatility.ts` |
495
+ | `massIndex` | `mass` | `{ emaPeriod?, sumPeriod?, high?, low?, output? }` (Σ EMA(range)/EMA² over 25, Dorsey's 9/25; a **sum**, reads ≈ `sumPeriod`) | `packages/financial/src/studies/mass-index.ts` |
496
+ | `choppinessIndex` | `chop` | `{ period?, high?, low?, close?, output? }` (`100·log10(ΣTR/(HH−LL))/log10(period)`, default 14, bounded 0..100; `period ≥ 2`) | `packages/financial/src/studies/choppiness-index.ts` |
497
+ | `ulcerIndex` | `ulcer` | `{ period?, column?, output? }` (RMS % drawdown from the rolling peak, StockCharts' rolling form, default 14; warm-up `2·period−2`) | `packages/financial/src/studies/ulcer-index.ts` |
498
+ | `verticalHorizontalFilter` | `vhf` | `{ period?, column?, output? }` ((HH−LL)/Σ\|Δcolumn\| over 28, Adam White's; a **fraction** in (0, 1], warm-up `period`) | `packages/financial/src/studies/vertical-horizontal-filter.ts` |
499
+ | `gopalakrishnanRangeIndex` | `gapo` | `{ period?, high?, low?, output? }` (`ln(HH−LL)/ln(period)` = log base `period` of the range, default 10; `period ≥ 2`) | `packages/financial/src/studies/gopalakrishnan-range-index.ts` |
500
+ | `relativeVolatilityIndex` | `relVol` | `{ period?, stdevPeriod?, column?, output? }` (RSI's form on σ, Wilder-smoothed, Dorsey's 14/10 — **not** `rvi`, see below) | `packages/financial/src/studies/relative-volatility-index.ts` |
501
+ | `linearRegression` | `linregValue`, `linregSlope`, `linregIntercept`, `linregAngle`, `linregR2` | `{ period?, column?, prefix? }` (one rolling OLS fit against the bar index, default 14, `period ≥ 2`; `Value` = TA-Lib `LINEARREG`, `Intercept` = the fit at the window's **first** bar, `Angle` = degrees and **scale-dependent**) | `packages/financial/src/studies/linear-regression.ts` |
502
+ | `timeSeriesForecast` | `tsf` | `{ period?, column?, output? }` (the same fit one bar **past** the window, default 14; = TA-Lib `TSF`; deliberately not a `MaType`) | `packages/financial/src/studies/time-series-forecast.ts` |
503
+ | `chandeForecastOscillator` | `cfo` | `{ period?, column?, output? }` (`100·(price − TSF)/price`, default 14; scale-invariant, **not** shift-invariant) | `packages/financial/src/studies/chande-forecast-oscillator.ts` |
504
+ | `centerOfGravity` | `cog` | `{ period?, column?, output? }` (Ehlers' position-weighted balance point, default 10; **negative**, in `[−period, −1]` on positive prices, flat reads `−(period+1)/2` — TradingView's uncentred convention) | `packages/financial/src/studies/center-of-gravity.ts` |
505
+ | `correlation` | `corr` | `{ period?, column?, benchmark, output? }` (Pearson r of two columns over 30 bars, = TA-Lib `CORREL`; `benchmark` is a **column on the same joined series**, required) | `packages/financial/src/studies/correlation.ts` |
506
+ | `beta` | `beta` | `{ period?, column?, benchmark, output? }` (slope of `column`'s 1-bar returns on `benchmark`'s over 5 bars, = TA-Lib `BETA(benchmark, column)`; pass **prices**, returns taken inside) | `packages/financial/src/studies/beta.ts` |
507
+ | `priceRelative` | `priceRel` | `{ column?, benchmark, output? }` (`column / benchmark`, no period — ChartIQ's Price Relative / Relative Strength **comparative**; not `rsi`) | `packages/financial/src/studies/price-relative.ts` |
508
+ | `performanceIndex` | `perf` | `{ period?, column?, benchmark, output? }` (each side's own `period`-bar growth, divided; 1 = parity, default 20; `(x−1)·100` == `percentChange(priceRelative)`) | `packages/financial/src/studies/performance-index.ts` |
509
+ | `guppy` | `gmmaS3`…`gmmaS15`, `gmmaL30`…`gmmaL60` | `{ column?, type?, prefix? }` (Guppy's GMMA — the **fixed** twelve averages, short 3/5/8/10/12/15, long 30/35/40/45/50/60, default `ema`; the lists ship as `GUPPY_SHORT_PERIODS` / `GUPPY_LONG_PERIODS`) | `packages/financial/src/studies/guppy.ts` |
510
+ | `rainbow` | `rainbow1`…`rainbow10` | `{ column?, period?, type?, prefix? }` (Widner's Rainbow — ten **recursive** averages, each smoothing the previous; default period 2 / `sma`; stage `k` warms up at `k·(period−1)`) | `packages/financial/src/studies/rainbow.ts` |
511
+ | `rainbowOscillator` | `rbo`, `rboUpper`, `rboLower` | `{ column?, period?, lookback?, type?, prefix? }` (ChartIQ's — `100·(price − mean of the ten)/(HH−LL)` with the stack's own width as mirrored bands; default 2 / 10) | `packages/financial/src/studies/rainbow.ts` |
512
+ | `kst` | `kst`, `kstSignal` | `{ column?, signalPeriod?, prefix? }` (Pring's Know Sure Thing — ROC 10/15/20/30 smoothed 10/10/10/15, weighted 1/2/3/4; the twelve numbers are **not** options, only the signal SMA is, default 9) | `packages/financial/src/studies/kst.ts` |
513
+ | `priceMomentumOscillator` | `pmo`, `pmoSignal` | `{ column?, prefix? }` (DecisionPoint's PMO — two stages of **custom** `α = 2/n` smoothing over a 1-bar percent ROC, ×10, with a **span** EMA(10) signal; no period options) | `packages/financial/src/studies/price-momentum-oscillator.ts` |
514
+ | `stochasticRsi` | `stochRsiK`, `stochRsiD` | `{ column?, rsiPeriod?, stochPeriod?, kPeriod?, dPeriod?, prefix? }` (the stochastic construction over the RSI, 14/14/3/3; `stochRsiK` == TA-Lib `STOCHRSI`'s **fastd**, `stochRsiD` has no TA-Lib counterpart) | `packages/financial/src/studies/stochastic-rsi.ts` |
515
+ | `trueStrengthIndex` | `tsi`, `tsiSignal` | `{ column?, longPeriod?, shortPeriod?, signalPeriod?, prefix? }` (Blau's TSI — `100·EMA(EMA(Δ,long),short)/EMA(EMA(\|Δ\|,long),short)`, 25/13/7; bounded −100…100, long applied **first**) | `packages/financial/src/studies/true-strength-index.ts` |
516
+ | `movingAverageDeviation` | `maDev` | `{ period?, maType?, column?, output? }` (`price − MA`, in **price units**, default 20/sma — the points half of the pair whose percent half IS `disparityIndex`; no `mode` flag) | `packages/financial/src/studies/moving-average-deviation.ts` |
517
+ | `parabolicSar` | `psar`, `psarTrend` | `{ step?, maxStep?, high?, low?, prefix? }` (Wilder's stop-and-reverse, defaults 0.02 / 0.2; **= TA-Lib `SAR` exactly**; `Trend` is `+1` long / `−1` short — the stop can print ON an extreme, so the side is not derivable from the value) | `packages/financial/src/studies/parabolic-sar.ts` |
518
+ | `superTrend` | `st`, `stTrend` | `{ period?, multiplier?, high?, low?, close?, prefix? }` (Seban's ratcheting ATR band as TradingView's `ta.supertrend`, defaults 10 / 3; `st` **is** the live band, so the bands are not emitted; the seed side is DOWN) | `packages/financial/src/studies/super-trend.ts` |
519
+ | `atrTrailingStop` | `ats`, `atsTrend` | `{ period?, multiplier?, high?, low?, close?, prefix? }` (close-anchored ratcheting stop, Vervoort's, defaults 14 / 3; a close exactly ON the stop flips **short**; the Chandelier anchor is `donchian` + `atr`, not a knob) | `packages/financial/src/studies/atr-trailing-stop.ts` |
520
+ | `negativeVolumeIndex` | `nvi` | `{ column?, volume?, output?, start? }` (Fosback: compound the close return only on a **lower**-volume bar, base 1000; no period, no warm-up; a **flat** volume holds on both indices) | `packages/financial/src/studies/volume-index.ts` |
521
+ | `positiveVolumeIndex` | `pvi` | `{ column?, volume?, output?, start? }` (the same on a **higher**-volume bar) | `packages/financial/src/studies/volume-index.ts` |
522
+ | `klinger` | `kvo`, `kvoSignal` | `{ fastPeriod?, slowPeriod?, signalPeriod?, high?, low?, close?, volume?, prefix? }` (Klinger's ORIGINAL volume force through an EMA pair, defaults 34 / 55 / 13; **F-AMBIG** — TradingView's simplified `ta.kvo` is a different indicator) | `packages/financial/src/studies/klinger.ts` |
523
+ | `typicalPrice` | `typicalPrice` | `{ high?, low?, close?, output? }` (`(h+l+c)/3` = TA-Lib `TYPPRICE`, exact; **no warm-up**) | `packages/financial/src/studies/price-transform.ts` |
524
+ | `medianPrice` | `medianPrice` | `{ high?, low?, output? }` (`(h+l)/2` = `MEDPRICE`, exact; `close` on the shared options type is ignored) | `packages/financial/src/studies/price-transform.ts` |
525
+ | `weightedClose` | `weightedClose` | `{ high?, low?, close?, output? }` (`(h+l+2c)/4` = `WCLPRICE`, exact) | `packages/financial/src/studies/price-transform.ts` |
526
+ | `averagePrice` | `averagePrice` | `{ open?, high?, low?, close?, output? }` (`(o+h+l+c)/4` = `AVGPRICE`, exact — the only transform that reads the open) | `packages/financial/src/studies/price-transform.ts` |
527
+ | `balanceOfPower` | `bop` | `{ period?, maType?, open?, high?, low?, close?, output? }` (`(c−o)/(h−l)`, bounded −1…1; **raw by default** = TA-Lib `BOP` exact, `period` gives ChartIQ's smoothed form; a flat bar is `0`; `maType` without `period` throws) | `packages/financial/src/studies/balance-of-power.ts` |
528
+ | `starcBands` | `starcMiddle`, `starcUpper`, `starcLower` | `{ period?, atrPeriod?, multiplier?, maType?, high?, low?, close?, prefix? }` (Stoller: MA(**close**) ± mult·ATR, 20 / 15 / 2 / sma — the close-centred sibling of `keltner`'s typical-price centre) | `packages/financial/src/studies/starc-bands.ts` |
529
+ | `highLowBands` | `hlbMiddle`, `hlbUpper`, `hlbLower` | `{ period?, percent?, maType?, high?, low?, prefix? }` (MA(**median price**) × (1 ± percent%), 10 / 1% / trima; it **is** `envelope` over a `medianPrice` column — same `percent`, same units; ChartIQ labels the knob "shift") | `packages/financial/src/studies/high-low-bands.ts` |
530
+ | `bollingerBandwidth` | `bbWidth` | `{ period?, stdDev?, column?, output? }` (`100·(upper − lower)/middle`, 20 / 2 — the **×100** StockCharts form; a flat window is `0`, not missing; a zero-centre window — flat at zero or zero-mean — is missing) | `packages/financial/src/studies/bollinger-derived.ts` |
531
+ | `bollingerPercentB` | `percentB` | `{ period?, stdDev?, column?, output? }` (`(price − lower)/(upper − lower)`, 20 / 2 — the **decimal** form, unbounded; a flat window is a genuine `0/0` → missing) | `packages/financial/src/studies/bollinger-derived.ts` |
532
+ | `primeNumberBands` | `pnbUpper`, `pnbLower` | `{ high?, low?, prefix? }` (smallest prime ≥ high / largest ≤ low — a step function of the price LEVEL, no warm-up; a price below 2 is outside the domain; cost grows with price magnitude) | `packages/financial/src/studies/prime-number.ts` |
533
+ | `primeNumberOscillator` | `pno` | `{ column?, output? }` (`price − nearestPrime(price)`, signed; a tie goes to the **lower** prime; no warm-up; neither scale- nor shift-invariant) | `packages/financial/src/studies/prime-number.ts` |
534
+ | `marketFacilitationIndex` | `bwmfi` | `{ high?, low?, volume?, output? }` (Bill Williams' `(h−l)/volume`, raw — **`bwmfi`, not `mfi`**, which `moneyFlowIndex` owns; zero volume → missing, flat bar → `0`) | `packages/financial/src/studies/market-facilitation-index.ts` |
535
+ | `twiggsMoneyFlow` | `tmf` | `{ period?, high?, low?, close?, volume?, output? }` (Twiggs: CMF rebuilt on the **true** range and Wilder-smoothed, default 21; bounded −1…1; **F-AMBIG** — the window-sum form is 0.0706 away; warm-up `period`, and an interior gap ends it) | `packages/financial/src/studies/twiggs-money-flow.ts` |
536
+ | `tradeVolumeIndex` | `tvi` | `{ minTick, column?, volume?, output? }` (tick-direction accumulation; `minTick` — the instrument's minimum tick — is **required**; an undecided bar keeps the LAST direction, no first direction is invented, base 0, no warm-up; an interior gap **ends** the level, `obv`'s rule) | `packages/financial/src/studies/trade-volume-index.ts` |
537
+ | `shinoharaIntensityRatio` | `sirStrong`, `sirWeak` | `{ period?, open?, high?, low?, close?, prefix? }` (Shinohara's A and B ratios, `100·Σup/Σdown` over 26 bars — A against the bar's own open, B against the previous close; **F-AMBIG** on which is charted "strong"; neither is bounded and B inverts on a gappy tape; per-column warm-up 25 / 26) | `packages/financial/src/studies/shinohara-intensity-ratio.ts` |
538
+ | `elderImpulse` | `impulse` | `{ emaPeriod?, fastPeriod?, slowPeriod?, signalPeriod?, column?, output? }` (Elder: `+1` when EMA(13) **and** the MACD histogram both rise, `−1` when both fall, `0` otherwise — a **numeric** column, `withColumn` has no string door; ties are `0`; warm-up 34) | `packages/financial/src/studies/elder-impulse.ts` |
539
+ | `movingAverageCross` | `maCross` | `{ fastPeriod?, slowPeriod?, maType?, column?, output? }` (a **signal** column: `+1` on the bar the fast MA crosses above the slow, `−1` below, `0` otherwise — the averages themselves are `movingAverage`'s; an exact tie is no cross and a touch-and-retreat is no cross; `maType`, not `type`; warm-up `slowPeriod`) | `packages/financial/src/studies/moving-average-cross.ts` |
540
+ | `anchoredVwap` | `avwap` | `{ anchor, high?, low?, close?, volume?, output? }` (cumulative `Σ tp·vol / Σ vol` from the first bar **at or after** `anchor` — a `Date` or epoch ms, **required**; earlier bars `undefined`; an interior gap ends the line, `obv`'s rule; the session-reset form is `sessionVwap`, on the same kernel) | `packages/financial/src/studies/anchored-vwap.ts` |
541
+ | `ichimoku` | `ichiTenkan`, `ichiKijun`, `ichiSenkouA`, `ichiSenkouB`, `ichiChikou` | `{ conversionPeriod?, basePeriod?, spanBPeriod?, displacement?, high?, low?, close?, prefix? }` (Hosoda's five lines, 9/26/52/26 each the window's HH/LL midpoint; `Chikou` is the close. **`displacement` shifts nothing**: every column is keyed to the bar it is _computed from_ (**G5**); warm-up 8/25/25/51/0) | `packages/financial/src/studies/ichimoku.ts` |
542
+ | `ichimokuOffsets` | | `{ displacement?, prefix? }` (**not a study** the per-column x-offset in **bars** a chart applies to `ichimoku`: `+displacement` on the two Senkou spans, `−displacement` on `Chikou`, `0` on the rest; pass it the study's own options) | `packages/financial/src/studies/ichimoku.ts` |
543
+ | `zigZag` | `zzPivot`, `zzDirection`, `zzLine` | `{ deviation?, high?, low?, prefix? }` (percent-reversal pivots, 5% of the leg's extreme by default; `zzPivot` sits on the extreme's **own** bar, `zzDirection` is the leg's `+1`/`−1`, `zzLine` joins them. **All three repaint** (**G6**); the last leg is provisional. A gap discards the leg in force) | `packages/financial/src/studies/zig-zag.ts` |
544
+ | `sessionVwap` | `svwap` | `{ sessions \| session, stamped?, high?, low?, close?, volume?, output? }` (`anchoredVwap` **re-anchored at every session open**; exactly one of `sessions` (a `TradingCalendar` or `Session[]` — the primary door) and `session` (a session-id column, e.g. from `tagSessions`); a bar in closed time is `undefined`; an interior gap ends **that session's** line and the next open re-seeds; vol = 0` `undefined`) | `packages/financial/src/studies/session-vwap.ts` |
545
+ | `pivotPoints` | `ppPivot`, `ppR1–R3`, `ppS1–S3` (+ `ppR4`/`ppS4` on `'camarilla'`) | `{ sessions \| session, stamped?, method?, high?, low?, close?, prefix? }` (each session's ladder from the **previous session with bars**' high/low/close, held flat; `method` = `'standard'` (floor) \| `'fibonacci'` (0.382/0.618/1.000) \| `'woodie'` (`(H+L+2C)/4` centre) \| `'camarilla'` (1.1/12, 1.1/6, 1.1/4, 1.1/2 from the **close**, and the only set with a fourth pair the column set and the return type follow `method`); the first session and closed time are `undefined`) | `packages/financial/src/studies/pivot-points.ts` |
546
+ | `stochasticMomentumIndex` | `smi`, `smiSignal` | `{ period?, longPeriod?, shortPeriod?, signalPeriod?, high?, low?, close?, prefix? }` (Blau's SMI — the close against the **midpoint** of the HH/LL range, double-EMA smoothed above and below, ×100; Blau's 13 / 25 / 2 / 3; bounded −100…100) | `packages/financial/src/studies/stochastic-momentum-index.ts` |
547
+ | `fisherTransform` | `fisher`, `fisherSignal` | `{ period?, high?, low?, prefix? }` (Ehlers' transform of the **median price's** own range position, default 10; the `0.33/0.67`, `±0.99→±0.999` clamp and `0.5/0.5` constants are Ehlers', not options; the signal is the line delayed one bar) | `packages/financial/src/studies/fisher-transform.ts` |
548
+ | `schaffTrendCycle` | `stc` | `{ fastPeriod?, slowPeriod?, cyclePeriod?, column?, output? }` (Schaff's double stochastic of a MACD with a fixed `0.5` smoothing between, 23 / 50 / 10, bounded 0…100; a pinned first stochastic leaves the second window flat → `undefined`) | `packages/financial/src/studies/schaff-trend-cycle.ts` |
549
+ | `prettyGoodOscillator` | `pgo` | `{ period?, column?, high?, low?, close?, output? }` (Johnson's `(close SMA)/EMA(TR)`, default 14, in average-daily-ranges; **F-AMBIG** — the Wilder-ATR denominator port is a different study, measured) | `packages/financial/src/studies/pretty-good-oscillator.ts` |
550
+ | `swingIndex` | `si` | `{ limit, open?, high?, low?, close?, output? }` (Wilder 1978; `limit` — the instrument's limit moveis **required**, there being no defensible default; bounded −100…100 at a `limit` above the largest gap; `R = 0` `undefined`) | `packages/financial/src/studies/swing-index.ts` |
551
+ | `accumulativeSwingIndex` | `asi` | `{ limit, open?, high?, low?, close?, output? }` (the running total of `swingIndex`; a running sum, so an interior gap — a halted bar pair included — ends it) | `packages/financial/src/studies/swing-index.ts` |
552
+ | `randomWalkIndex` | `rwiHigh`, `rwiLow` | `{ period?, high?, low?, close?, prefix? }` (Poulos: the max over horizons `2 … period` of `(high − low[−n])/(meanTR(n)·√n)`, default 14; the **`n`-bar mean** TR, not Wilder's ATR; O(N·period), and it goes negative) | `packages/financial/src/studies/random-walk-index.ts` |
553
+ | `ravi` | `ravi` | `{ shortPeriod?, longPeriod?, column?, output? }` (Chande: `100·\|SMA(7) − SMA(65)\|/SMA(65)`; **absolute**, so it answers "is there a trend", not "which way"; trending above 3%) | `packages/financial/src/studies/ravi.ts` |
554
+ | `trendIntensityIndex` | `tii` | `{ period?, maPeriod?, column?, output? }` (M. H. Pee: `100·Σpos/(Σpos + Σneg)` of the deviations from an SMA, 30 / 60, bounded 0…100; **F-AMBIG** — the count form is a different study; warm-up 88) | `packages/financial/src/studies/trend-intensity-index.ts` |
555
+ | `specialK` | `specialK` | `{ column?, output? }` (Pring's extended KST — twelve weighted smoothed ROCs across three groups; the thirty-six constants ARE the study, so there are no period options; **warm-up 724 bars**) | `packages/financial/src/studies/special-k.ts` |
550
556
 
551
557
  **The two-series family takes a benchmark COLUMN, never a second
552
558
  `TimeSeries`.** `correlation`, `beta`, `priceRelative` and `performanceIndex`
@@ -596,15 +602,32 @@ names it separately, but the formula is identical (and TA-Lib-verified through
596
602
  Adding a study? Follow `packages/financial/src/studies/README.md` (uniform
597
603
  shape + pandas oracle case + fluent method are all REQUIRED).
598
604
 
605
+ ### Study catalog (`@pond-ts/financial/catalog`)
606
+
607
+ Every study, described at runtime — the facts a `@pond-ts/process` registry
608
+ or a picker needs that the options interfaces and return types carry only in
609
+ erased types. A separate subpath: importing it pulls in every study.
610
+
611
+ | Export | Purpose | Source |
612
+ | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
613
+ | `STUDIES` | `readonly StudyDescriptor[]` — one per fluent method, in family order then menu order (the catalog test pins the set equal to the fluent methods) | `packages/financial/src/catalog/index.ts` |
614
+ | `studyDescriptor(name)` | Look one up by its exported name | `packages/financial/src/catalog/index.ts` |
615
+ | `STUDY_FAMILIES` / `StudyFamily` | The nine picker groups (`moving-average`, `bands`, `momentum`, `trend`, `volatility`, `volume`, `statistical`, `price`, `session`) | `packages/financial/src/catalog/types.ts` |
616
+ | `StudyDescriptor`, `StudyInput`, `StudyParam` (`StudyNumberParam` \| `StudyEnumParam`), `StudyOutput`, `StudyNaming`, `StudyUnit`, `StudyRun` | The descriptor: `name`, `family`, `summary`, `inputs` (`role` + `default`, absent ⇒ required), `params` keyed by option (`kind`, `default` or `example`, `min`/`max` where validated, `suggest`), `naming` (`output` or `prefix` + its default), `outputs` (`id` suffix + `unit` — the axis-membership vocabulary), `optional: true` + `requires` for a switch-style option and a menu that needs it, `anchor: 'session' \| 'time'` for the session-anchored pair and `anchoredVwap`, `run` | `packages/financial/src/catalog/types.ts` |
617
+ | `defineStudy` / `StudySpec` | Author a descriptor against the study's options interface; the compiler classifies every key and rejects a missed one, a default on a required option or an undescribed option shape | `packages/financial/src/catalog/define.ts` |
618
+
599
619
  ### Trading calendars & sessions
600
620
 
601
- | Export | Purpose | Source |
602
- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------- |
603
- | `TradingCalendar` | Query API: `.sessions()`, `.sessionOn()`, `.isTradingDay()`, `.isOpen()`, `.sessionsInRange()`, `.sessionSequence()`, `.barSequence(period)`, `.tagSessions()`, `.discontinuities()` | `packages/financial/src/calendar/` |
604
- | `generateSessions` | `Session[]` from `SessionRules` over a date range (DST-correct) | `packages/financial/src/calendar/` |
605
- | `normalizeSessions` | Validate + sort an explicit session list | `packages/financial/src/calendar/` |
606
- | `identityDiscontinuity` / `segmentDiscontinuity` / `weekendSkip` | `DiscontinuityProvider`s for the trading-time axis | `packages/financial/src/calendar/` |
607
- | Types | `Session`, `SessionBreak`, `SessionRules`, `DateRange`, `InstantRange`, `TaggedSchema`, `LiveSegment`, `DiscontinuityProvider` | `packages/financial/src/calendar/` |
621
+ | Export | Purpose | Source |
622
+ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------- |
623
+ | `TradingCalendar` | Query API: `.sessions()`, `.sessionOn()`, `.isTradingDay()`, `.isOpen()`, `.sessionsInRange()`, `.sessionSequence()`, `.barSequence(period)`, `.tagSessions()`, `.discontinuities()` | `packages/financial/src/calendar/` |
624
+ | `generateSessions` | `Session[]` from `SessionRules` over a date range (DST-correct) | `packages/financial/src/calendar/` |
625
+ | `normalizeSessions` | Validate + sort an explicit session list | `packages/financial/src/calendar/` |
626
+ | `identityDiscontinuity` / `segmentDiscontinuity` / `weekendSkip` | `DiscontinuityProvider`s for the trading-time axis | `packages/financial/src/calendar/` |
627
+ | Types | `Session`, `SessionBreak`, `SessionRules`, `DateRange`, `InstantRange`, `TaggedSchema`, `LiveSegment`, `DiscontinuityProvider` | `packages/financial/src/calendar/` |
628
+ | `SessionSource` / `SessionAnchorOptions` | The session-anchored studies' input: `TradingCalendar \| Session[]` (`sessions`), or a session-id column name (`session`), plus `stamped` | `packages/financial/src/contract/session-anchor.ts` |
629
+ | `PIVOT_METHODS` / `PivotMethod` | The four pivot formula sets (`standard`, `fibonacci`, `woodie`, `camarilla`) | `packages/financial/src/kernels/pivot.ts` |
630
+ | `PivotPointsSchema` / `CamarillaPivotPointsSchema` / `PivotPointsResult` | `pivotPoints`' method-dependent appended-schema types (7 columns, or 9 for Camarilla) | `packages/financial/src/studies/pivot-points.ts` |
608
631
 
609
632
  ### Contract & constants
610
633
 
package/CHANGELOG.md CHANGED
@@ -8,7 +8,9 @@ The `@pond-ts` packages — `pond-ts`, `@pond-ts/react`, `@pond-ts/charts`,
8
8
  under a single `v*` tag, so this file covers them all. Pre-1.0: minor bumps may
9
9
  include new features and type-level changes; patch bumps are strictly additive.
10
10
 
11
- [Unreleased]: https://github.com/pond-ts/pond/compare/v0.66.0...HEAD
11
+ [Unreleased]: https://github.com/pond-ts/pond/compare/v0.68.0...HEAD
12
+ [0.68.0]: https://github.com/pond-ts/pond/compare/v0.67.0...v0.68.0
13
+ [0.67.0]: https://github.com/pond-ts/pond/compare/v0.66.0...v0.67.0
12
14
  [0.66.0]: https://github.com/pond-ts/pond/compare/v0.65.0...v0.66.0
13
15
  [0.65.0]: https://github.com/pond-ts/pond/compare/v0.64.0...v0.65.0
14
16
  [0.64.0]: https://github.com/pond-ts/pond/compare/v0.63.0...v0.64.0
@@ -69,10 +71,195 @@ include new features and type-level changes; patch bumps are strictly additive.
69
71
 
70
72
  ## [Unreleased]
71
73
 
74
+ ## [0.68.0] — 2026-09-13
75
+
76
+ ### Added
77
+
78
+ - **Agent adoption tranche ([PND-ADOPTMETA] / [PND-ADOPTLINKS] /
79
+ [PND-LLMSTXT] / [PND-AGENTGUIDE] / [PND-SKILL] / [PND-CONTEXT7]).** Every
80
+ package now declares `keywords`, `homepage` and `bugs` (there were none —
81
+ `pond-ts` ranked last in `npm search "time series"`). Every tarball ships an
82
+ `AGENTS.md` (source `docs/agents/USING_POND.md`): which package for which
83
+ task, the core idioms, the mistakes agents make. `pond-ts.org/llms.txt` is
84
+ now llmstxt.org-shaped (titles + descriptions per page, one section per
85
+ docs area, `Optional` links to `API.md` / the agent guide) with per-area
86
+ `llms-<area>.txt` dumps so a single fetch stays small. A Claude Code plugin
87
+ marketplace lives in the repo (`/plugin marketplace add pond-ts/pond`) with
88
+ `pond-ts`, `pond-charts` and `pond-financial` skills. `context7.json`
89
+ configures docs-MCP indexing. Plan and baseline:
90
+ `docs/plans/PND_ADOPTION_PLAN.md`.
91
+
92
+ - **Agent guide + skill hardened by the first cold-start run** (`docs/agents/USING_POND.md`, shipped as `AGENTS.md`; `plugins/pond-ts/skills/pond-ts`): install with `@latest` and the `.d.ts` paths that carry signatures. Cold-start harness committed at `docs/adoption/cold-start/`.
93
+
94
+ ### Fixed
95
+
96
+ - **`pond-ts`: the partition column is now in the static type after a partitioned `aggregate` / `rolling` ([PND-PARTCOL]).** `series.partitionBy('host').aggregate(seq, { p95: { from: 'ms', using: 'p95' } }).collect()` always carried `host` at runtime (auto-injected as `'first'`) but the result type omitted it, so `e.get('host')` failed to compile — every fresh agent in the cold-start experiment hit or pre-empted it. `PartitionedTimeSeries` gains a third type parameter `By` (the partition column names, captured by `partitionBy`, default `never`), and the two schema-replacing operators are typed over `WithPartitionColumns<Mapping, By>` — the user's keys win, kind and all; missing partition columns are added as `'first'`. Composite partitions and typed `groups` carry through; `smooth` / `baseline` under `partitionBy` now also keep `K`. Additive: untyped views are unchanged.
97
+ - `@pond-ts/charts` and `@pond-ts/fit` READMEs (rendered on npm) and eight
98
+ docs pages pointed at the retired `pjm17971.github.io/pond-ts` site /
99
+ `pjm17971/pond-ts` repo; now `pond-ts.org` / `pond-ts/pond`.
100
+
101
+ ## [0.67.0] — 2026-09-11
102
+
103
+ ### Added
104
+
105
+ - `@pond-ts/financial`: **a runtime study catalog** — `import { STUDIES } from
106
+ '@pond-ts/financial/catalog'`. One `StudyDescriptor` per study (all 109
107
+ fluent methods): the columns it reads (`inputs`, with defaults — absent
108
+ means required, as a `benchmark` is), its numeric and menu options
109
+ (`params`: `kind`, `default` or an `example` for a required one,
110
+ `min`/`max` — inclusive, and only where the study validates a constant
111
+ bound — and a `suggest` range a control is drawn on, legal throughout at
112
+ the other options' defaults), how it names what it appends (`naming`: `output` or `prefix`
113
+ and the default), the columns it appends (`outputs`, each with a `unit`
114
+ from a closed vocabulary — `inherit` / `delta` / `percent` / `ratio` /
115
+ `signal` / `volume` / `index` / `bars` — that answers whether the column
116
+ may share the source's axis), a `family` and one-line `summary` for a
117
+ picker, `anchor: 'session' | 'time'` for the two session-anchored studies
118
+ and `anchoredVwap` (an input the consumer supplies from context, not a
119
+ control), `optional: true` for an option whose absence is a switch rather
120
+ than a value (`balanceOfPower`'s `period`) with `requires` for a menu
121
+ that is only legal alongside it, and `run`. The shape is modelled on `@pond-ts/process`'s `OpDef` (`role`, `id`,
122
+ `unit`, `suggest` are its words) so a registry maps it rather than
123
+ interprets it — with two deliberate differences: an input carries its
124
+ `default`, and a required option carries an `example` where process
125
+ requires a `default`. Asked for by a consumer that was otherwise
126
+ hand-transcribing ~400 facts from `.d.ts` files and re-checking them per
127
+ release. Guarded two ways so it cannot drift from the studies:
128
+ `defineStudy<Options>()` classifies every key of the options interface at
129
+ compile time and rejects a missed or misspelt key, a default claimed on a
130
+ required option, a menu value outside the union, a menu `of` that omits a
131
+ member, or an option shape it does not know; and `test/catalog.test.ts` runs every descriptor against its
132
+ study — the appended columns are exactly those declared and every one
133
+ has a value on the fixture, stating every default explicitly changes
134
+ nothing, every menu value and both `suggest` endpoints run, a declared
135
+ `min`/`max` is accepted and one past it throws, and the catalog is exactly
136
+ the set of fluent methods. A separate subpath, so the main entry's tree-shaking is untouched.
137
+ The `API map` workflow now guards `catalog/index.ts` too.
138
+ - `@pond-ts/financial`: **the session-anchored studies** (corpus §6.6 / §6.9 —
139
+ the **G4** pair the trading calendar was gating). Both take the session as a
140
+ first-class input through one shared option shape, `SessionAnchorOptions`:
141
+ exactly one of **`sessions`** (a `TradingCalendar` or a `Session[]` — the
142
+ primary door — a calendar is narrowed with `sessionsInRange`, an explicit
143
+ list validated per call — and walked once, `O(N +
144
+ sessions)`) or **`session`** (the name of a session-id column, what
145
+ `TradingCalendar.tagSessions` appends — the door for a series already
146
+ partitioned by session), plus `stamped: 'open' | 'close'` on the calendar
147
+ door. A bar in **closed time** — between sessions, a weekend print on a 24/7
148
+ feed, outside the schedule — reads `undefined` in both studies. Both doors
149
+ run the **same** `sessionIdValues` walk `tagSessions` now runs, so they are
150
+ the same anchoring by construction, and a test pins the two routes equal
151
+ under both stamp conventions.
152
+ - **`sessionVwap({ sessions | session, stamped, high, low, close, volume,
153
+ output = 'svwap' })`** — the VWAP an intraday desk means: `Σ tp·vol / Σ vol`
154
+ accumulated from each session's open and **reset at the next**. This is the
155
+ third VWAP form `vwap` named and deliberately left open. It composes on
156
+ `anchoredVwap`'s arithmetic literally rather than by resemblance — both
157
+ studies now call one `anchoredVwapValues(typical, volume, anchors)` kernel
158
+ and differ only in what they pass as the anchor group. An interior gap ends
159
+ **that session's** line (`obv`'s rule; the two sums are blanked together so
160
+ a bar with volume but a missing `high` cannot bias the average) and the
161
+ next session open re-seeds — the reset is the recovery `anchoredVwap` makes
162
+ the caller do by hand. `Σ vol = 0` → `undefined`, live at the output.
163
+ - **`pivotPoints({ sessions | session, stamped, method = 'standard', high,
164
+ low, close, prefix = 'pp' })`** — each session's support/resistance ladder
165
+ from the **previous session's** aggregate high / low / close, held flat
166
+ across the session. Four formula sets, all reading the same three inputs
167
+ and differing in constants: `'standard'` (floor-trader), `'fibonacci'`
168
+ (0.382 / 0.618 / 1.000 of the range), `'woodie'` (the standard ladder over
169
+ the close-weighted centre `(H + L + 2C)/4`) and `'camarilla'` (Nick Scott's
170
+ 1.1/12, 1.1/6, 1.1/4, 1.1/2, measured from the **close**, not the pivot).
171
+ **The column set follows `method`**: seven columns (`${prefix}Pivot`,
172
+ `R1–R3`, `S1–S3`) for the first three and **nine** for Camarilla, which is
173
+ the only set defining a fourth pair — the return type is conditional on
174
+ `method` rather than shipping three methods with two permanently-`undefined`
175
+ columns. The first session with bars and every closed-time bar read
176
+ `undefined`; "previous session" means the previous session **with bars in
177
+ this series**, not the previous entry on the calendar.
178
+ - Two deliberate definition deltas, both documented on the study: Woodie's
179
+ ships the previous-**close** centre `(H + L + 2C)/4` rather than the
180
+ current-open variant also in circulation, and Camarilla's levels are
181
+ centred on the close rather than on the pivot (which is the definition, and
182
+ is what makes its ladder asymmetric about `ppPivot`).
183
+ - Oracle: five new cases on a new **session-keyed** input
184
+ (`input.sessionTimes`) — the same 80 OHLCV bars re-keyed onto a real
185
+ 09:30–16:00 America/New_York 30-minute grid over six sessions, with two
186
+ bars in no session. The references are pandas `groupby`-`cumsum` and
187
+ `groupby().agg().shift(1).reindex()`, a different formulation from our
188
+ sequential loops; the vitest side rebuilds the calendar from the same rules
189
+ rather than from a table, so a Temporal/`zoneinfo` disagreement about a
190
+ session boundary fails the case rather than hiding.
191
+ - `@pond-ts/financial`: **Ichimoku Cloud and ZigZag** (corpus §6.4) — the two
192
+ most-used studies left in the corpus, each shipped in the form that needs no
193
+ core change. Both take the uniform shape (bar columns plus a `prefix`,
194
+ bar-count periods, a length-preserving per-column warm-up, a fluent method)
195
+ and both have pandas oracle cases. One internal kernel helper rides with
196
+ them: **`rollingBarExtremesValues`** (the max of one array beside the min of
197
+ another over a strict window, in one deque walk), which the perf check
198
+ surfaced — Ichimoku on the single-array door spent 414 ms of its ~404 ms at
199
+ 1M bars in six deque passes where three suffice; on the package bench the
200
+ study went 433.6 → 280.7 ms at 1M.
201
+ - **`ichimoku({ conversionPeriod = 9, basePeriod = 26, spanBPeriod = 52,
202
+ displacement = 26, high, low, close, prefix = 'ichi' })`** — Hosoda's five
203
+ lines as `ichiTenkan` / `ichiKijun` / `ichiSenkouA` / `ichiSenkouB` /
204
+ `ichiChikou`, each the midpoint of the highest `high` and lowest `low` of
205
+ its own window (the Chikou span is the close). Per-column warm-up 8 / 25 /
206
+ 25 / 51 / 0. **`displacement` changes no value**: the study keys every
207
+ column to the bar it is _computed from_ and shifts nothing — the forward
208
+ spans have no rows past the last bar to land on (assessment gap **G5**),
209
+ and a pre-shifted Chikou would be a look-ahead column, the one thing no
210
+ other column in the package is. The new **`ichimokuOffsets(options)`**
211
+ returns the per-column x-offset in bars (`+displacement` on the two spans,
212
+ `−displacement` on Chikou, `0` on the rest) for a chart to apply — the
213
+ data-side half of the charts ask **C2**. Measured against the common slip
214
+ (taking the ranges over the close): up to 0.2281 / 0.2383 / 0.2226 /
215
+ 0.2328 on the oracle's deliberately narrow bars.
216
+ - **`zigZag({ deviation = 5, high, low, prefix = 'zz' })`** — the price path
217
+ reduced to its swings: `zzPivot` (the pivot price on its own bar),
218
+ `zzDirection` (`+1` rising / `−1` falling leg) and `zzLine` (the straight
219
+ line between consecutive pivots). A leg turns when price retraces
220
+ `deviation` **percent** from the leg's running extreme — measured against
221
+ the peak on a fall, the trough on a rise. **Every column repaints**
222
+ (assessment gap **G6**): a pivot is written at the bar its extreme
223
+ occurred but is not known until a later bar confirms it, so none of the
224
+ three may be fed to a backtest unlagged. The **last leg is provisional**
225
+ and therefore has no pivot and no line — only a direction. A gap resets
226
+ the machine _and_ discards the leg in force, and no line is drawn across
227
+ it. The close-based fork needs no option (`{ high: 'close', low: 'close' }`)
228
+ and ships as its own oracle case; the absolute-deviation fork is measured
229
+ at a whole extra pivot on the fixture.
230
+
231
+ ### Changed
232
+
233
+ - `@pond-ts/financial`: **`bollinger` draws the degenerate band on a flat
234
+ window** — `upper = lower = middle` where `σ = 0`, instead of blanking
235
+ both bands around an unbroken middle line. `undefined` now means warm-up
236
+ only, as it does for `keltner`'s zero-range channel. A consumer's
237
+ "outside the band" test is `bbUpper > bbLower`, not a hole in the data.
238
+ `bollingerBandwidth` is still `0` there (its numerator is forced to zero)
239
+ and `bollingerPercentB` still `undefined` (a genuine 0/0), and `bbWidth`
240
+ is now recoverable from the `bollinger` columns on every bar the bands
241
+ are set. Asked for by a consumer whose band over a stale stretch broke
242
+ into segments ([PND-BBFLAT]).
243
+ - `@pond-ts/financial`: **`TradingCalendar.tagSessions` is ~4.7× faster** and
244
+ its output is unchanged on every row. It was materializing `series.toArray()`
245
+ and reading `event.begin()` — one `Event` plus one data object per row, the
246
+ cost PR #536 removed from the study kernel — where it now reads
247
+ `keyColumn().begin` columnar through the shared `sessionIdValues` walk the
248
+ session-anchored studies use. Measured at 1M bars: **120.90 ms → 25.69 ms**.
249
+ The session column it appends is now a `Float64Array` rather than an
250
+ `Array<number | undefined>`; `withColumn` maps `NaN` to missing, so readers
251
+ still see `number | undefined` and the declared `TaggedSchema` is unchanged.
252
+ - `@pond-ts/financial`: `anchoredVwap` now runs the shared
253
+ `anchoredVwapValues` kernel rather than composing two `cumulativeValues`
254
+ passes over two blanked arrays. Bit-identical output; the kernel arithmetic
255
+ measures **23.51 ms → 16.62 ms** at 1M rows.
256
+
72
257
  ## [0.66.0] — 2026-09-07
73
258
 
74
259
  ### Added
75
260
 
261
+ ### Changed
262
+
76
263
  - `@pond-ts/financial`: **the volume and miscellaneous leftovers** (corpus
77
264
  §6.6 / §6.4 / §6.1) — six studies in the uniform shape (bar columns plus an
78
265
  `output` or `prefix`, bar-count periods, a length-preserving per-column
package/package.json CHANGED
@@ -1,7 +1,26 @@
1
1
  {
2
2
  "name": "@pond-ts/process",
3
- "version": "0.66.0",
3
+ "version": "0.68.0",
4
4
  "description": "Computations as data over pond-ts: processing graphs authored fluently or composed as JSON, resolved against a declared op vocabulary with content-addressed caching, provenance, and per-node timings. Experimental, pre-1.0.",
5
+ "keywords": [
6
+ "time-series",
7
+ "timeseries",
8
+ "typescript",
9
+ "streaming",
10
+ "analytics",
11
+ "dataflow",
12
+ "pipeline",
13
+ "dag",
14
+ "processing-graph",
15
+ "cache",
16
+ "provenance",
17
+ "worker-threads",
18
+ "pond-ts"
19
+ ],
20
+ "homepage": "https://pond-ts.org/docs/process/",
21
+ "bugs": {
22
+ "url": "https://github.com/pond-ts/pond/issues"
23
+ },
5
24
  "license": "MIT",
6
25
  "repository": {
7
26
  "type": "git",
@@ -28,13 +47,14 @@
28
47
  "files": [
29
48
  "dist",
30
49
  "CHANGELOG.md",
31
- "API.md"
50
+ "API.md",
51
+ "AGENTS.md"
32
52
  ],
33
53
  "scripts": {
34
54
  "build": "tsc -p tsconfig.json",
35
55
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"test-dts/**/*.ts\"",
36
56
  "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\" \"test-dts/**/*.ts\"",
37
- "prepack": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md && cp ../../API.md ./API.md && npm run build && cp cjs-fallback.cjs dist/cjs-fallback.cjs && find dist -name '*.map' -delete",
57
+ "prepack": "cp ../../LICENSE ./LICENSE && cp ../../CHANGELOG.md ./CHANGELOG.md && cp ../../API.md ./API.md && cp ../../docs/agents/USING_POND.md ./AGENTS.md && npm run build && cp cjs-fallback.cjs dist/cjs-fallback.cjs && find dist -name '*.map' -delete",
38
58
  "test": "npm run test:type && npm run test:dts && npm run test:runtime",
39
59
  "test:type": "tsc -p tsconfig.types.json",
40
60
  "test:dts": "npm run build && tsc -p tsconfig.dts.json",
@@ -42,7 +62,7 @@
42
62
  "verify": "npm run format:check && npm run build && npm test"
43
63
  },
44
64
  "peerDependencies": {
45
- "pond-ts": "^0.66.0"
65
+ "pond-ts": "^0.68.0"
46
66
  },
47
67
  "devDependencies": {
48
68
  "typescript": "^5.6.3",