PyneTS missing features
Builtin and host gaps between @hoox-sh/pynets 0.5.0 and Python pynescript.runtime. Measured 2026-09-27.
This page
Manuals
Abstract
This page is the checklist of what @hoox-sh/pynets still does not match in Python pynescript.runtime. The oracle is Python Runtime.run on the same source and the same bars. It is not a TradingView® certification list.
Measured 2026-09-27 against @hoox-sh/pynets 0.5.0 (interpret and compile tests green, including test/interpret_footprint.test.ts, test/compile_footprint.test.ts, test/interpret_alert_freq.test.ts, and test/compile_plot_alert_const.test.ts). Published npm 0.5.0 includes this slice.
A raw scan of Python _*_builtin_map keys finds 706 names. About 280 of those strings are absent from the interpret sources. Many strategy.* series are false misses: they are attributes (strategy.netprofit), not quoted call names. The lists below are the scan plus that correction.
Conceptual model
Rendering…
Port order when closing an item: read the winning Python method (mixin MRO, not a later duplicate), port na / lookback / call-site state, wire evalCall or the matching eval*Call, add test/interpret_*.test.ts, compare plots. Do not edit src/runtime/compile/* in the same change as interpret.ts.
Interface surface
Closed on this working tree
Do not re-open these as missing.
| Area | What landed |
|---|---|
once [cond] | Parse, unparse, interpret, compile. Body runs the first time the test is true. Bare once runs on bar 0. Nested once inside if fires once. na does not fire. x = once … is a syntax error. |
Multi-value switch | 1, 2 => matches any element on interpret and compile. |
| Matrix row/col | sum_*, avg_*, min_*, max_*, mode_*, copy_row / copy_col, fill_row / fill_col / fill_diagonal, reverse_rows / reverse_cols, stdev, variance. |
| TA | ta.uo, ta.rci, ta.dpo, ta.kst, ta.stochrsi, ta.donchian, ta.ichimoku, ta.bb_pct, ta.emv, ta.fractal, ta.atr_stop, ta.zigzag, plus the bar-mode detectors ta.hammer, ta.gap_detector, ta.macd_signal, ta.acceleration_factor, ta.stoch_smooth, ta.engulfing, ta.inside_bar_pattern, ta.double_top_bottom, ta.voi, ta.bid_ask_imbalance, ta.rsi_oversold_overbought, ta.rsi_divergence, ta.cumulative_delta, ta.volume_momentum, ta.volume_profile_high, ta.volume_profile_low, ta.volume_thrust, and the v3/v4 bare aliases Python registers. Dict results use __taRecord (dc.high, stochrsi.signal, …). Several detectors are Python’s bar-mode sentinels (ta.engulfing is false every bar; ta.stoch_smooth is na unless both smooth lengths are 1). |
| Host helpers | timeframe.change, time_close / time_close(), syminfo.prefix and syminfo.prefix(tickerid), bare round_to_mintick, every Python array.new* spelling, plotcandle / plotbar (primary series is close), timenow / timenow(), max_bars_back, alertcondition, plot.linestyle_*, plot.style_*, alert.freq_*, alert() frequency gating (default once per bar, "all" every call, zero-arg is a no-op), bare random, bare security / security_lower_tf. |
| Footprint | request.footprint Python mock on interpret and compile. footprint.* and volume_row.* call accessors. request.seed seeds the mock RNG. Missing id is 0 / empty / na as Python. |
| JS compile | Emit for the TA / matrix / host / drawing / strategy / footprint names in this table, including the bar-mode detectors, so mode: "compile" matches interpret. array.from collects its arguments. No per-bar time_close column; the default path is next open / last+1d. |
| Drawings | Getters, remaining setters, *.all, *.copy, remaining deletes, chart.point.*, line.fill, on interpret and compile. Constructor coords snapshot so getters after new are not na. |
| Strategy | strategy.cash is free cash tagged _pine_qty_type="cash" on interpret and compile; account_currency, position_entry_name, default_entry_qty, convert_to_*, max_contracts_held_*, closed/open trade time/comment/drawdown/runup/commission/capital_held/first_index; oca.*, direction.*, commission.* constants; zero-arg series calls (strategy.netprofit()). |
ta.rci with length under 2 is a runtime error whose message contains ta.rci length must be at least 2.
Language the host does not have
| Item | Python | PyneTS |
|---|---|---|
Realtime once | Unconfirmed ticks do not commit the fired flag; rollback can re-fire. Confirmed bar latches. | barstate.isrealtime is 0. The flag commits as soon as the body runs. No interpret session, no tick rollback. |
strategy.*
Attribute and zero-arg call forms for the main series and the fields listed as closed above are implemented on interpret and compile. strategy.cash plots as a number; default_qty_type=strategy.cash still selects cash sizing.
Drawings
Interpret and compile cover the Python drawing.py map that the book already implements (getters, setters, *.all, *.copy, deletes, chart.point.*, line.fill). line.copy(na) is na here; Python returns an unregistered Line.
ta.* still absent
Leave these alone unless a Python plot is non-na. In bar mode the series argument is a one-element list, so Runtime.run stays na for the whole run. A windowed port would not match:
ta.beta, ta.r_squared, ta.comovement, ta.apo
Still unwired because a chart-series plot is na on every bar (a windowed port would disagree):
ta.atr_normalized, ta.garman_klass, ta.kurtosis, ta.parkinson, ta.skewness, ta.sma_weighted, ta.volume_weighted_momentum
PYNE extension analytics (present in the Python map, not the public TradingView® ta.* reference). Port only when a caller needs that name:
ta.advanced_breakout_detector, ta.breakeven_level, ta.breakout_detection, ta.contrarian_signal, ta.correlation_filter, ta.crowd_sentiment, ta.divergence_detector, ta.drawdown_recovery_level, ta.economic_impact_score, ta.ema_cross_signal, ta.employment_cycle_indicator, ta.expected_value, ta.fear_greed_index, ta.gamma_levels, ta.gdp_growth_proxy, ta.inflation_proxy_indicator, ta.intelligent_strategy_synthesizer, ta.kelly_criterion, ta.liquidity_score, ta.market_condition, ta.market_structure_pivot, ta.market_timing_index, ta.max_loss_level, ta.mean_reversion_entry, ta.mean_reversion_score, ta.momentum_divergence, ta.momentum_filter, ta.multi_timeframe_signal, ta.optimal_entry_zone, ta.order_flow_imbalance, ta.position_sizing, ta.position_sizing_score, ta.probability_of_movement, ta.profit_lock_level, ta.pullback_bounce_level, ta.regime_adaptive_signal, ta.risk_reward_asymmetry, ta.risk_reward_ratio, ta.signal_confluence, ta.smart_money_flow, ta.spread_analysis, ta.strategy_score, ta.trailing_exit_level, ta.trend_confirmation_score, ta.trend_strength, ta.volatility_regime, ta.volatility_regime_score
Request
request.security on a foreign symbol or HTF without data returns na on both sides. That is the Python policy, not a hole to fill with invented bars. request.footprint is the Python mock (not a live vendor feed).
JS compile lag
The names in the closed table emit, so mode: "compile" matches interpret for them. mode: "auto" still prefers compile when emit succeeds. A name compile does not know (the extension-analytics list, the all-na indicators above) becomes na even when a later interpret port would match Python.
Internals
| Path | Role |
|---|---|
PYNE src/pynescript/ast/evaluator/builtins/ | Handler source of truth. TechnicalAnalysisMixin MRO: Advanced, Basic, Common, MovingAverage, Oscillator, Pattern, Economics, Strategies, Synthesizer, Volatility, Volume. |
PYNE technical_submodules/core.py | Incremental kernels (_use_incremental_ta). |
pynets/src/runtime/interpret.ts | evalCall and eval*Call. |
pynets/src/runtime/ta.ts, matrix.ts, drawings.ts, strategy.ts, timeframe.ts, footprint.ts | State and values. |
pynets/src/runtime/compile/emit_call.ts | Compile dispatch. Do not edit it in the same change as interpret.ts. |
pynets/test/interpret_*.test.ts | Focused parity tests. |
last_bar_index, last_bar_time, and syminfo.ticker are not missing. The first two are written in beginBar. syminfo.ticker / tickerid return the runtime symbol.
Invariants & edge cases
- Python wins. If a port would plot a nicer series than
Runtime.run, do not land it. naisnull. Non-finite in or out isna.- TA state is one sample per bar, keyed by call site.
- Dict-shaped
ta.*results are__taRecordobjects.evalAttributereads only that brand. strategy.cashplots free cash and still tagsdefault_qty_type.- Numba, Worker packaging, and ASDL codegen are out of scope for this repo. They are not rows on this list.
Worked examples
Compare before closing a row:
# PyneTS
bun -e 'import { Runtime } from "./src/index.ts";
console.log(new Runtime("TEST").run(`//@version=5
indicator("t")
plot(ta.dpo(20))`, [{close:1},{close:2},{close:3}]))'
# Python
/path/to/pynescript/.venv/bin/python -c 'from pynescript.runtime import Runtime
print(Runtime("TEST").run("""//@version=5
indicator("t")
plot(ta.dpo(20))""", [{"close":1},{"close":2},{"close":3}], mode="interpret"))'
Suggested close order:
- Realtime
oncerollback (interpret sessions). - The extension-analytics list when a script needs a name.
- Leave the all-
naindicator names unwired unless a Python plot is non-na.
Failure modes
| Symptom | Cause |
|---|---|
dc.high is na on an old build | __taRecord field read is only on this working tree. |
Compile plots na, interpret matches Python | Name not in emit_call.ts (extension analytics). |
New ta.beta port is non-na while Python is na | Bar-mode one-element series. Revert the port. |
once fires again on a realtime tick in Python and once in PyneTS | No tick rollback in the TS host. |