[PyneTS parity]

How to compare @hoox-sh/pynets Runtime.run plots against Python pynescript.runtime. Python wins ties.

PyneTS parity

Abstract

Parity here means TypeScript Runtime.run vs Python Runtime.run on the same source and the same bars — not vs TradingView. Interpret↔compile alignment inside PyneTS is a second, narrower check (test/compile_*.test.ts).

Workflow when adding or fixing a builtin: read the Python handler, port na / lookback / call-site semantics, wire the name, add a focused test/interpret_*.test.ts, compare plots if PYNE is present.

Conceptual model

Interface surface

Commands

# PyneTS
cd /path/to/pynets
bun test
bun test test/interpret_ta.test.ts
bun run typecheck

# Python oracle (sister checkout)
cd /path/to/pynescript
python -c "from pynescript.runtime import Runtime; ..."

Use /pynets-parity when adding or fixing builtins. Use /pynets-generate when touching grammar output.

What to compare

FieldRule
plots / seriesEqual length; null ↔ Python None; finite numbers match
eventsKind, direction, bar, id — same contract as strategy events
error_kindSame class of failure (parse vs runtime)
TradingView screenshotsOut of scope as an oracle

na encoding: Python interpret uses None; JSON / TS uses null; Python Numba uses nan. Compare after normalizing non-finite → na.

Internals

PathRole
test/interpret_*.test.tsFocused interpret cases
test/compile_*.test.tsJS emit vs interpret
test/helpers/first_party.tsFirst-party fixtures (live in PYNE)
PYNE src/pynescript/ast/evaluator/builtins/Handler SoT
PYNE tests/test_first_party_ta_goldens.pyPython goldens

Do not treat historical pine-worker/test/parity/ JSON as the PyneTS harness. That tree lives in the leftover TypeScript Worker sister (hoox-sh/pine-worker), not here.

This PYNE pynets/ pin (v0.2.0) includes interpret tests and compile-vs-interpret cases (test/compile_*.test.ts). Python Runtime remains the oracle.

Invariants & edge cases

  1. Python wins ties. If TS and Python disagree, fix TS (unless Python is proven wrong — then fix both + tests).
  2. Do not "improve" semantics. Port na, lookback, and call-site keys as Python implements them.
  3. Same-symbol request.security may passthrough; foreign without data is na on both sides.
  4. Compile-vs-interpret inside PyneTS can pass while TS-vs-Python still fails — check both.
  5. First-party fixtures live in PYNE; do not copy corpora into hoox-sh/pyne.

Worked examples

Minimal Python vs TS

Python:

from pynescript.runtime import Runtime

src = 'indicator("t")\nplot(close[1])'
bars = [{"close": 10}, {"close": 20}]
print(Runtime(symbol="TEST").run(src, bars))

TypeScript:

import { Runtime } from "@hoox-sh/pynets";

const src = 'indicator("t")\nplot(close[1])';
const bars = [{ close: 10 }, { close: 20 }];
console.log(new Runtime("TEST").run(src, bars));

Last-bar plot should be 10 on both.

Adding a builtin

  1. Read src/pynescript/ast/evaluator/builtins/… (Python).
  2. Port into src/runtime/ta.ts / math.ts / … and evalCall in interpret.ts.
  3. Add test/interpret_<area>.test.ts.
  4. If PYNE is present, compare Runtime.run plots on the same bars.
  5. bun test and bun run typecheck.

Failure modes

SymptomCauseFix
Off-by-one vs PythonLookback / bar_indexMatch PineSeries to Python
null vs 0na collapsedKeep null; do not coerce
Foreign security equals chartInvented barsReturn na
Compile matches interpret, both wrongShared host bugFix interpret first (Python SoT)
Copied sources into PYNESubmodule rulePYNE consumes pynets/ only

See also