Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,17 @@ jobs:
- run: python -m pip install --upgrade wickra numpy
- name: Check Python doc snippets
run: python scripts/check_doc_examples.py
# Naming every symbol correctly is not the same as working: twenty-five
# blocks resolved every name and still raised, by calling `update` with the
# whole derivatives tick, feeding a close-only series to an indicator that
# takes high/low/close, or reaching for `.shape` on a type without one.
- name: Run Python doc snippets
run: python scripts/run_doc_snippets.py
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 20
- run: npm install --no-save wickra
- name: Check Node.js doc snippets
run: node scripts/check-doc-examples.mjs
- name: Run Node.js doc snippets
run: node scripts/run-doc-snippets.mjs
5 changes: 4 additions & 1 deletion Data-Layer.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,10 @@ let five_min = resample_all(Timeframe::millis(5 * 60_000)?, one_min_candles)?;
let mut r = Resampler::new(Timeframe::millis(60 * 60_000)?); // 1-hour bars
let one_min_candles: Vec<wickra_data::Result<wickra::Candle>> = Vec::new();
for candle in one_min_candles {
if let Some(closed) = r.push(candle?)? {
// One push can close several bars at once: with gap filling on, a skipped
// bucket still gets a flat placeholder, so this is a list rather than an
// `Option`.
for closed in r.push(candle?)? {
// a coarser bar just closed
}
}
Expand Down
10 changes: 7 additions & 3 deletions FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ that overflows surfaces an error instead of producing a corrupted candle

## How fast is Wickra?

The streaming path is O(1) per `update` — the per-tick cost does not grow with
how much history you have already seen. Against the pure-Python libraries the
The streaming path is O(1) in the input length — the per-tick cost does not
grow with how much history you have already seen. It is bounded by the window
you configure instead: most indicators do constant work, and the ones that need
an order statistic or a full-window pass scale with the period, never with the
series. Against the pure-Python libraries the
gap is large: roughly 6–47× faster than `finta` on batch workloads and 11–56×
faster per tick than `talipp` (the only incremental Python peer). Against the
other Rust TA crates (`kand`, `ta-rs`, `yata`) it is an honest mixed picture —
Expand All @@ -115,7 +118,8 @@ with the latest market history via
## How is Wickra different from TA-Lib / pandas-ta / talipp?

- TA-Lib and pandas-ta are batch-only — every new tick triggers a full
recomputation. Wickra updates in O(1). The numerical results are the
recomputation. Wickra never revisits the history behind the tick. The
numerical results are the
same; the speed gap shows up in live trading and large backtests.
- talipp is streaming-first like Wickra but Python-only and slower per
update.
Expand Down
2 changes: 1 addition & 1 deletion Indicators-Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ family collects indicators that answer the same kind of question, so the
taxonomy here maps one-to-one onto the
`crates/wickra-core/src/indicators/` source layout.

Every indicator is an O(1) state machine that consumes one input at a time
Every indicator is an incremental state machine that consumes one input at a time
and produces either `Option<f64>` (Rust), `float | None` (Python), or
`number | null` (Node). Inputs are either a `f64` close price or an OHLCV
`Candle` (Rust) / dict-or-tuple (Python) / column arrays (Node). The full
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AbandonedBaby.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const _: fn(&mut AbandonedBaby, Candle) -> Option<f64> = <AbandonedBaby as Indic
- **Node.** `update(open, high, low, close)` → `number`; `batch(open, high, low,
close)` → `Array<number>`.
- **Python.** `update(candle)` → `float`; `batch(open, high, low, close)` → 1-D
`numpy.ndarray` (`0.0` on warmup / no-match).
`array.array('d')` (`0.0` on warmup / no-match).

## Warmup

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Abcd.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const _: fn(&mut wickra::Abcd, wickra::Candle) -> Option<f64> =
```

- **Python.** `update((o,h,l,c,v,ts))` → `float` (never `None`);
`batch(open, high, low, close)` → 1-D `ndarray`.
`batch(open, high, low, close)` → `array.array('d')`.
- **Node.** `update(open, high, low, close)` → `number`;
`batch(open, high, low, close)` → `number[]`.
- **WASM.** `update(open, high, low, close)` → `number`.
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AbsoluteBreadthIndex.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const _: fn(&mut AbsoluteBreadthIndex, CrossSection) -> Option<f64> =
The bindings pass a tick as four equal-length parallel arrays:

- **Python**: `update(change, volume, new_high, new_low)`; `batch(...)` returns a
1-D `ndarray`.
`array.array('d')`.
- **Node**: `update(change, volume, newHigh, newLow)`; `batch` returns `number[]`.
- **WASM**: `update(change, volume, newHigh, newLow)` only; flag arrays are numeric.

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AccelerationBands.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const _: fn(&mut AccelerationBands, Candle) -> Option<AccelerationBandsOutput> =

- **Python streaming.** `update(candle)` returns `(upper, middle, lower)` or `None`.
- **Python batch.** `AccelerationBands.batch(high, low, close)` returns an
`(n, 3)` `np.ndarray` with columns `[upper, middle, lower]`; warmup rows
`(n, 3)` `Matrix` with columns `[upper, middle, lower]`; warmup rows
are `NaN`.
- **Node streaming.** `update(high, low, close)` returns a
`{ upper, middle, lower }` object or `null`.
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdOscillator.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const _: fn(&mut AdOscillator, Candle) -> Option<f64> = <AdOscillator as Indicat

The native bindings expose this under the TA-Lib-style alias **`ADOSC`**. Python
streams as `float | None` and batches `ADOSC().batch(high, low, close)` to a 1-D
`numpy.ndarray` (`NaN` for warmup). Node streams as `number | null` via
`array.array('d')` (`NaN` for warmup). Node streams as `number | null` via
`update(high, low, close)` and batches `batch(high, low, close)` with `NaN`
placeholders.

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdVolumeLine.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ A `CrossSection` is one tick carrying the universe as a list of `Member`s. The
bindings pass a tick as four equal-length parallel arrays:

- **Python**: `update(change, volume, new_high, new_low)`; `batch(...)` takes one
array group per tick and returns a 1-D `ndarray`.
array group per tick and returns an `array.array('d')`.
- **Node**: `update(change, volume, newHigh, newLow)`; `batch` returns `number[]`.
- **WASM**: `update(change, volume, newHigh, newLow)` only; the flag arrays are
numeric (non-zero is true).
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdaptiveCycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ estimator; `Default` is also implemented.

`Indicator<Input = f64, Output = f64>`. Output is integer-valued
`f64` (e.g. `7.0`, `12.0`). Python: `AdaptiveCycle().batch(prices)`
returns a 1-D `np.ndarray`. Node: same shape; `update(value)`
returns an `array.array('d')`. Node: same shape; `update(value)`
returns `number | null`.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdaptiveLaguerreFilter.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const _: fn(&mut AdaptiveLaguerreFilter, f64) -> Option<f64> =
<AdaptiveLaguerreFilter as Indicator>::update;
```

Python returns `float | None` (streaming) / `numpy.ndarray` (batch, `NaN` for
Python returns `float | None` (streaming) / `array.array('d')` (batch, `NaN` for
warmup). Node returns `number | null` / `Array<number>` with `NaN`.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdvanceBlock.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const _: fn(&mut AdvanceBlock, Candle) -> Option<f64> = <AdvanceBlock as Indicat
- **Node.** `update(open, high, low, close)` → `number`; `batch(open, high, low,
close)` → `Array<number>`.
- **Python.** `update(candle)` → `float`; `batch(open, high, low, close)` → 1-D
`numpy.ndarray` (`0.0` on warmup / no-match).
`array.array('d')` (`0.0` on warmup / no-match).

## Warmup

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdvanceDecline.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ four equal-length parallel arrays:

- **Python**: `update(change, volume, new_high, new_low)` over one universe;
`batch(change, volume, new_high, new_low)` takes one such array group per tick
(lists of lists) and returns a 1-D `ndarray`.
(lists of lists) and returns an `array.array('d')`.
- **Node**: `update(change, volume, newHigh, newLow)`; `batch` takes the same
arrays nested one level per tick and returns `number[]`.
- **WASM**: `update(change, volume, newHigh, newLow)` only — the universe is
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AdvanceDeclineRatio.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ signed `change`, a `volume`, and `new_high` / `new_low` flags; the ratio reads o
`change`). The bindings pass a tick as four equal-length parallel arrays:

- **Python**: `update(change, volume, new_high, new_low)`; `batch(...)` takes one
array group per tick (lists of lists) and returns a 1-D `ndarray`.
array group per tick (lists of lists) and returns an `array.array('d')`.
- **Node**: `update(change, volume, newHigh, newLow)`; `batch` nests the arrays one
level per tick and returns `number[]`.
- **WASM**: `update(change, volume, newHigh, newLow)` only (the universe is ragged
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Adxr.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const _: fn(&mut Adxr, Candle) -> Option<f64> = <Adxr as Indicator>::update;
```

- **Python.** `update(candle)` returns `float | None`;
`batch(high, low, close)` returns a 1-D `float64` `np.ndarray` with `NaN`
`batch(high, low, close)` returns an `array.array('d')` with `NaN`
warmup.
- **Node.** `update(high, low, close)` returns `number | null`;
`batch(high, low, close)` returns an `Array<number>` with `NaN` warmup.
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Alligator.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const _: fn(&mut Alligator, Candle) -> Option<AlligatorOutput> = <Alligator as I
Uses `high` and `low` (the median price).

- **Python.** `update(candle)` returns `(jaw, teeth, lips)` or `None`;
`batch(high, low)` returns an `(n, 3)` `np.ndarray` with columns
`batch(high, low)` returns an `(n, 3)` `Matrix` with columns
`[jaw, teeth, lips]`; warmup rows are `NaN`.
- **Node.** `update(high, low)` returns a `{ jaw, teeth, lips }` object or
`null`; `batch(high, low)` returns a flat `Array<number>` of length `3n`,
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Alma.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const _: fn(&mut Alma, f64) -> Option<f64> = <Alma as Indicator>::update;
```

A single `f64` close in, an `Option<f64>` out. Python maps this to
`float | None` / a `float64` `np.ndarray` with `NaN` warmup; Node to
`float | None` / an `array.array('d')` with `NaN` warmup; Node to
`number | null` / `Array<number>`.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AmihudIlliquidity.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const _: fn(&mut AmihudIlliquidity, Trade) -> Option<f64> =
```

Node `update(price, size, isBuy)` and `batch(price[], size[], isBuy[])`; Python
`update(price, size, is_buy)` and `batch(price, size, is_buy)` → 1-D `ndarray`.
`update(price, size, is_buy)` and `batch(price, size, is_buy)` → `array.array('d')`.
(The aggressor side is accepted for a uniform trade API but does not affect the
value.)

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AnchoredRsi.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const _: fn(&mut AnchoredRsi, f64) -> Option<f64> = <AnchoredRsi as Indicator>::
```

Python streams as `float | None`, batches a close column to a 1-D
`numpy.ndarray` (`NaN` for warmup). Node streams as `number | null`, batches as
`array.array('d')` (`NaN` for warmup). Node streams as `number | null`, batches as
`Array<number>` with `NaN` placeholders.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AndrewsPitchfork.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ import wickra as ta

p = ta.AndrewsPitchfork(2)
base = 100 + np.sin(np.arange(120) * 0.5) * 10
median, upper, lower = p.batch(base + 1, base - 1).T
median, upper, lower = np.asarray(p.batch(base + 1, base - 1).tolist()).T
```

### Node
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Apo.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const _: fn(&mut Apo, f64) -> Option<f64> = <Apo as Indicator>::update;
```

A single `f64` close in, an `Option<f64>` out. The Python binding maps this
to `float | None` (streaming) or a `float64` `np.ndarray` with `NaN` warmup
to `float | None` (streaming) or an `array.array('d')` with `NaN` warmup
rows (batch). The Node binding maps it to `number | null` /
`Array<number>` with `NaN` warmup.

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Atr.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const _: fn(&mut Atr, Candle) -> Option<f64> = <Atr as Indicator>::update;
`(open, high, low, close, volume, timestamp)` or a dict with keys
`open`, `high`, `low`, `close`, `volume`, and optional `timestamp`.
- **Python batch.** `ATR.batch(high, low, close)` takes three equal-length
`numpy.ndarray` columns and returns a 1-D `np.ndarray` with `NaN` for
`array.array('d')` columns and returns an `array.array('d')` with `NaN` for
every warmup row.
- **Node streaming.** `atr.update(high, low, close)` returns `number | null`.
- **Node batch.** `atr.batch(high, low, close)` returns `Array<number>` of
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AtrBands.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const _: fn(&mut AtrBands, Candle) -> Option<AtrBandsOutput> = <AtrBands as Indi

- **Python streaming.** `update(candle)` returns `(upper, middle, lower)` or `None`.
- **Python batch.** `AtrBands.batch(high, low, close)` returns an `(n, 3)`
`np.ndarray` with columns `[upper, middle, lower]`; warmup rows are `NaN`.
`Matrix` with columns `[upper, middle, lower]`; warmup rows are `NaN`.
- **Node streaming.** `update(high, low, close)` returns a
`{ upper, middle, lower }` object or `null`.
- **Node batch.** `batch(high, low, close)` returns a flat `Array<number>`
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AtrRatchet.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ import wickra as ta
r = ta.AtrRatchet(14, 4.0, 0.1)
n = 60
base = np.arange(n, dtype=float) + 100.0
value, direction = r.batch(base + 2.0, base - 2.0, base + 1.0).T
value, direction = np.asarray(r.batch(base + 2.0, base - 2.0, base + 1.0).tolist()).T
print(value[-1], direction[-1])
```

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AutoFib.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const _: fn(&mut wickra::AutoFib, wickra::Candle) -> Option<wickra::AutoFibOutpu

- **Python.** `update((o,h,l,c,v,ts))` → `(level_0, level_236, level_382,
level_500, level_618, level_786, level_1000)` or `None`; `batch(high, low)` →
`(n, 7)` `ndarray` (`NaN` warmup).
`(n, 7)` `Matrix` (`NaN` warmup).
- **Node.** `update(high, low)` → `{ level0, level236, level382, level500,
level618, level786, level1000 }` or `null`; `batch(high, low)` → flat
`number[]` length `n*7`.
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AverageDailyRange.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const _: fn(&mut wickra::AverageDailyRange, wickra::Candle) -> Option<f64> =
```

- **Python.** `update((o,h,l,c,v,ts))` → `float | None`;
`batch(open, high, low, close, volume, timestamp)` → 1-D `ndarray` (`NaN` warmup).
`batch(open, high, low, close, volume, timestamp)` → `array.array('d')` (`NaN` warmup).
- **Node.** `update(...)` → `number | null`; `batch(...)` → `number[]`.
- **WASM.** `update(...)` → `number | undefined`.

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AverageDrawdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const _: fn(&mut AverageDrawdown, f64) -> Option<f64> = <AverageDrawdown as Indi
```

Python streams as `float | None` and batches `AverageDrawdown(period).batch(prices)`
to a 1-D `numpy.ndarray` (`NaN` for warmup). Node streams as `number | null` via
to an `array.array('d')` (`NaN` for warmup). Node streams as `number | null` via
`update(value)` and batches `batch(prices)`.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AvgPrice.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const _: fn(&mut AvgPrice, Candle) -> Option<f64> = <AvgPrice as Indicator>::upd
`AvgPrice` is a **candle-input** indicator that reads all four OHLC prices. In
Python the streaming `update` accepts a candle (dict or tuple); the batch helper
takes `open`, `high`, `low`, `close` numpy arrays and returns a 1-D
`numpy.ndarray` (`NaN` only never appears here, since warmup is a single bar).
`array.array('d')` (`NaN` only never appears here, since warmup is a single bar).
Node and WASM expose `update(open, high, low, close)` and the matching `batch`.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AwesomeOscillator.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ The `close` and `volume` fields on the input candle are ignored — only
`high` and `low` matter, via `Candle::median_price()`.

Python's `AwesomeOscillator.batch(high, low)` returns a 1-D `float64`
`np.ndarray`. Node's `AwesomeOscillator.batch(high, low)` returns a
`array.array('d')`. Node's `AwesomeOscillator.batch(high, low)` returns a
flat `number[]`. Both produce `NaN` during warmup; only Python exposes
a streaming `update(candle)` method.

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-AwesomeOscillatorHistogram.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const _: fn(&mut AwesomeOscillatorHistogram, Candle) -> Option<f64> =
Only `high` and `low` are read (the AO uses the median price), so both native
bindings take just those two series. Python streams as `float | None` and batches
`AwesomeOscillatorHistogram(fast, slow, lookback).batch(high, low)` to a 1-D
`numpy.ndarray` (`NaN` warmup). Node streams as `number | null` via
`array.array('d')` (`NaN` warmup). Node streams as `number | null` via
`update(high, low)` and batches `batch(high, low)`.

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Bat.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const _: fn(&mut wickra::Bat, wickra::Candle) -> Option<f64> =
```

- **Python.** `update((o,h,l,c,v,ts))` → `float` (never `None`);
`batch(open, high, low, close)` → 1-D `ndarray`.
`batch(open, high, low, close)` → `array.array('d')`.
- **Node.** `update(open, high, low, close)` → `number`;
`batch(open, high, low, close)` → `number[]`.
- **WASM.** `update(open, high, low, close)` → `number`.
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-BeltHold.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const _: fn(&mut BeltHold, Candle) -> Option<f64> = <BeltHold as Indicator>::upd
- **Node.** `update(open, high, low, close)` → `number`; `batch(open, high, low,
close)` → `Array<number>`.
- **Python.** `update(candle)` → `float`; `batch(open, high, low, close)` → 1-D
`numpy.ndarray` (`0.0` on no-match).
`array.array('d')` (`0.0` on no-match).

## Warmup

Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-Beta.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Population formulas (not sample). Each `update` is O(1). See
## Inputs / Outputs

`Indicator<Input = (f64, f64), Output = f64>`. Python:
`Beta(period).batch(asset, benchmark)` returns a 1-D `np.ndarray`
`Beta(period).batch(asset, benchmark)` returns an `array.array('d')`
with `NaN` warmup. Node: same.

## Warmup
Expand Down
4 changes: 3 additions & 1 deletion Indicators/Indicator-BetterVolume.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,12 @@ bv = ta.BetterVolume(20)
n = 60
high = np.array([105.0] * n)
low = np.array([100.0] * n)
close = np.array([102.0] * n)
volume = np.array([1000.0] * n)
volume[-1] = 5000.0 # churn bar
high[-1] = 100.5 # narrow range
print(bv.batch(high, low, volume)[-1] > 0) # True
close[-1] = 100.2 # keep the last candle valid (low <= close <= high)
print(bv.batch(high, low, close, volume)[-1] > 0) # True
```

### Node
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-BipowerVariation.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const _: fn(&mut BipowerVariation, f64) -> Option<f64> = <BipowerVariation as In
```

A single `f64` close in, an `Option<f64>` out. Python maps this to
`float | None` / `numpy.ndarray` (NaN warmup); Node to `number | null` /
`float | None` / `array.array('d')` (NaN warmup); Node to `number | null` /
`Array<number>` (NaN warmup).

## Warmup
Expand Down
2 changes: 1 addition & 1 deletion Indicators/Indicator-BodySizePct.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const _: fn(&mut BodySizePct, Candle) -> Option<f64> = <BodySizePct as Indicator
```

Node `update(open, high, low, close)` / `batch(open[], high[], low[], close[])`;
Python `update(candle)` / `batch(open, high, low, close)` → 1-D `ndarray`.
Python `update(candle)` / `batch(open, high, low, close)` → `array.array('d')`.

## Warmup

Expand Down
10 changes: 5 additions & 5 deletions Indicators/Indicator-BollingerBands.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const _: fn(&mut BollingerBands, f64) -> Option<BollingerOutput> = <BollingerBan

- **Python streaming** (`update`) returns the 4-tuple `(upper, middle, lower, stddev)`
or `None` during warmup.
- **Python batch** (`batch`) returns a 2-D `numpy.ndarray` of shape `(n, 4)` with
- **Python batch** (`batch`) returns a 2-D `Matrix` of shape `(n, 4)` with
columns `[upper, middle, lower, stddev]`; warmup rows are entirely `NaN`.
- **Node streaming** (`update`) returns a `{ upper, middle, lower, stddev }`
object or `null` during warmup.
Expand Down Expand Up @@ -117,10 +117,10 @@ i=0 -> None
i=1 -> None
i=2 -> None
i=3 -> None
i=4 -> Some(BollingerOutput { upper: 5.759591794226543, middle: 3.8, lower: 1.8404082057734565, stddev: 0.9797958971132716 })
i=5 -> Some(BollingerOutput { upper: 5.379795897113269, middle: 4.4, lower: 3.420204102886732, stddev: 0.48989794855663404 })
i=6 -> Some(BollingerOutput { upper: 7.190890230020663, middle: 5.0, lower: 2.809109769979336, stddev: 1.095445115010332 })
i=7 -> Some(BollingerOutput { upper: 9.577708763999665, middle: 6.0, lower: 2.422291236000335, stddev: 1.7888543819998326 })
i=4 -> Some(BollingerOutput { upper: 5.759591794226543, middle: 3.8, lower: 1.8404082057734574, stddev: 0.9797958971132712 })
i=5 -> Some(BollingerOutput { upper: 5.379795897113271, middle: 4.4, lower: 3.4202041028867294, stddev: 0.48989794855663554 })
i=6 -> Some(BollingerOutput { upper: 7.190890230020665, middle: 5.0, lower: 2.8091097699793353, stddev: 1.0954451150103324 })
i=7 -> Some(BollingerOutput { upper: 9.577708763999663, middle: 6.0, lower: 2.4222912360003366, stddev: 1.7888543819998317 })
```

The first emission at `i=4` uses the window `[2, 4, 4, 4, 5]` with mean
Expand Down
Loading
Loading