Numerical validation
Methodology and error bounds for PYNE technical and math builtins versus reference Pine Script™ implementations.
This page
Numerical validation
Abstract
PYNE’s technical and mathematical builtins are validated for numerical agreement with reference Pine Script™ implementations under IEEE 754 realities. The long-form report (docs/numerical_validation_report.md, v1.0, Nov 2025) documents methodology, per-family error tables, and edge cases.
Headline (from that report): max observed relative error 0.0022% (ADX, extreme volatility); average error < 0.0005%; deterministic ops (SMA, OBV, discrete math) often exact.
Treat percentages as report-era measurements, not eternal SLAs — re-validate after changing smoothers or bar-mode semantics.
Conceptual model
Rendering…
Interface surface
Acceptable thresholds (report)
| Band | Relative error | Verdict |
|---|---|---|
| Excellent | < 0.001% | Pass |
| Good | < 0.01% | Pass |
| Acceptable | < 0.1% | Review |
| Unacceptable | ≥ 0.1% | Fail |
Metric definitions
- Absolute error:
|ref − pyne| - Relative error:
|ref − pyne| / |ref| × 100%(guard zero refs) - Max / mean / std over bars and scenarios
Category highlights
| Family | Notes |
|---|---|
| Moving averages | SMA exact; EMA/WMA/… tiny FP error |
| Oscillators | RSI/stoch slightly higher smoothing error still ≪ 0.01% |
| Trend | ADX highest in report (0.0022% max) |
| Volume | OBV exact cumulative; MFI inherits typical-price FP |
| Stats | percentrank exact; variance/stdev excellent |
| Math | Discrete exact; transcendentals ~1e-15 class |
Dual-host formula alignment (interpret ↔ compile)
Where fixed, these kernels share one formula contract across interpret (evaluator / incremental) and compile (numba_builtins) so plot series match bit-identical or maxdiff ≈ 0 on dual-run goldens:
| Builtin | Shared contract (summary) |
|---|---|
ta.rsi | Wilder: SMA seed of first period deltas, then RMA gain/loss; first valid at bar period |
ta.roc | Standard lookback % change; na until lookback (no early 0.0) |
ta.wma | Full non-na window required; no partial-window reweight (nested ROC/WMA safe) |
ta.cum | Running sum; NaNs as 0; user series (ad = ta.cum(...)) must not alias builtin A/D |
ta.highestbars / lowestbars | Negative bars-back offset; short/all-NaN → -1; oldest extreme on ties |
Goldens: tests/test_compiler_numba.py (TestInterpCompilePlotParityFixes) and scripts/compare_interp_compile.py. Residual dual-host drift (if any) tends to cluster in nested EMA seed families (DEMA/TEMA SMA-seed vs first-value) rather than these aligned kernels — see Compatibility.
Error distribution (report aggregate)
| Error range | Share (approx.) |
|---|---|
| Exact 0 | ~38% |
| < 0.0001% | ~46% |
| 0.0001–0.001% | ~14% |
| 0.001–0.01% | ~2% |
| ≥ 0.1% | 0% |
Internals
| Path | Role |
|---|---|
docs/numerical_validation_report.md | Full tables + bias analysis |
tests/test_ta_indicators_*.py | Executable TA tests |
tests/test_indicators.py / builtins tests | Additional numeric guards |
tests/test_compiler_numba.py | Interpret ↔ compile formula goldens (RSI/ROC/WMA/…) |
scripts/compare_interp_compile.py | Corpus plot-series parity harness |
Bar-mode vs list-mode (_pine_bar_mode) | Scalar-per-bar vs full series — compare like with like |
Methodology (report)
- Generate synthetic 1k-bar OHLCV across regimes (trend, range, vol, gaps)
- Validate with real histories (equities, crypto, FX samples)
- Export reference outputs; run PYNE; element-wise compare
- Search systematic bias; inspect tails
Invariants & edge cases
- na propagation must match Pine truthiness — numerical compare should mask
napairs. - Bar-mode scalars vs full-series list mode can look like “bugs” if misaligned.
- Seeded mocks (
request.seed) stabilize stochastic feeds for regression. - Recursive smoothers accumulate FP differently across languages; bounds > bits.
- Extreme prices (near-zero, huge) tested; still within excellent band in report.
Worked examples
Relative error helper
def rel_err(a: float, b: float) -> float:
if a == 0 and b == 0:
return 0.0
denom = abs(a) if a != 0 else abs(b)
return abs(a - b) / denom * 100.0
Run TA tests
pytest tests/test_ta_indicators_1.py tests/test_ta_indicators_2.py -q
Failure modes
| Symptom | Investigation |
|---|---|
| Sudden ADX drift | Check Wilder smoothing / seed bars |
| SMA not exact | Off-by-one window or float input casts |
| Good unit tests, bad TV export compare | Timezone/session alignment of bars |
| Only bar 0 differs | Warm-up / na initialization |