[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
| Field | Rule |
|---|---|
plots / series | Equal length; null ↔ Python None; finite numbers match |
events | Kind, direction, bar, id — same contract as strategy events |
error_kind | Same class of failure (parse vs runtime) |
| TradingView screenshots | Out 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
| Path | Role |
|---|---|
test/interpret_*.test.ts | Focused interpret cases |
test/compile_*.test.ts | JS emit vs interpret |
test/helpers/first_party.ts | First-party fixtures (live in PYNE) |
PYNE src/pynescript/ast/evaluator/builtins/ | Handler SoT |
PYNE tests/test_first_party_ta_goldens.py | Python 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
- Python wins ties. If TS and Python disagree, fix TS (unless Python is proven wrong — then fix both + tests).
- Do not "improve" semantics. Port
na, lookback, and call-site keys as Python implements them. - Same-symbol
request.securitymay passthrough; foreign without data isnaon both sides. - Compile-vs-interpret inside PyneTS can pass while TS-vs-Python still fails — check both.
- 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
- Read
src/pynescript/ast/evaluator/builtins/…(Python). - Port into
src/runtime/ta.ts/math.ts/ … andevalCallininterpret.ts. - Add
test/interpret_<area>.test.ts. - If PYNE is present, compare
Runtime.runplots on the same bars. bun testandbun run typecheck.
Failure modes
| Symptom | Cause | Fix |
|---|---|---|
| Off-by-one vs Python | Lookback / bar_index | Match PineSeries to Python |
null vs 0 | na collapsed | Keep null; do not coerce |
| Foreign security equals chart | Invented bars | Return na |
| Compile matches interpret, both wrong | Shared host bug | Fix interpret first (Python SoT) |
| Copied sources into PYNE | Submodule rule | PYNE consumes pynets/ only |