Pine Script Compatibility

PyneCore runs Pyne code: Python whose API and bar-by-bar semantics follow TradingView’s Pine Script v6, with results that match TradingView. This page lists how completely the Pine Script v6 API is covered, how closely the results match, and where PyneCore differs on purpose.

Running existing Pine Script: PyneCore does not read Pine Script source itself. Existing scripts are converted to Pyne code by PyneComp, the PyneSys compiler for Pine Script v4, v5 and v6 (v1–v3 sources are converted too, on a best-effort basis). PyneComp is a separate service that needs a PyneSys API key; with the key configured, pyne compile script.pine converts a script, and pyne run script.pine converts it before running — see Compiling Pine Scripts.

The match with TradingView is measured, not assumed: published TradingView scripts are converted with PyneComp, run by PyneCore, and every comparable output is compared with TradingView’s own.

Validation status — snapshot 2026-10-01, Pyne in the Wild

  • 920 published open-source TradingView scripts (462 indicators, 458 strategies; Pine Script v4: 320, v5: 341, v6: 259), all converted and run
  • 1,241 / 1,241 outputs comparable with TradingView verified (812 plot outputs, 429 strategy trade lists)
  • 99.768% of 117,659,091 plotted values identical to TradingView to the bit; the largest relative gap anywhere is 1.2 × 10⁻¹⁰ (about 9 significant figures)
  • 318,982 strategy trades in 429 strategies: entry and exit timing and trade counts match
  • Chart: BINANCE:BTCUSDT, 30-minute bars; per-script results and methodology are public

Status Legend

StatusMeaning
fullImplemented; results match TradingView
no-lookaheadImplemented; differs only where TradingView would leak future data — see No lookahead, ever
no data feedAPI present, but the data has no offline source: the call returns na or raises — see notes
no rendererFull API and state; exported with pyne run --viz, but PyneCore draws no chart
—Not applicable to offline execution

Technical Analysis (ta)

FeatureStatusNotes
Moving averagesfullSMA, EMA, WMA, HMA, ALMA, RMA, VWMA, SWMA
Momentum indicatorsfullRSI, MACD, CCI, CMO, MFI, ROC, TSI, etc.
Volatility indicatorsfullATR, BB, KC, STDev, Supertrend, etc.
Volume indicatorsfullOBV, ACCDIST, PVT, WAD, WVAD, NVI, PVI, etc.
Pivot pointsfullAll 6 pivot types
Statistical functionsfullCorrelation, percentile, variance, etc.
Pattern detectionfullCrossover, crossunder, rising, falling, etc.
Total: 67 functionsfullEvery ta.* function of Pine Script v6

Strategy Simulator

FeatureStatusNotes
Entry/exit ordersfullMarket, limit, stop orders
Position managementfullLong, short, pyramiding
Take-profit / stop-lossfullPrice, ticks, percent-based
Trailing stopsfullOffset-based trailing
OCA groupsfullOne-Cancels-All order groups
Commission modelsfullFixed, percent, per-contract
Margin callsfullTradingView-exact 10-step algorithm
SlippagefullConfigurable tick-based slippage
Equity trackingfullEquity curve, drawdown, P&L
Trade loggingfullCSV export with all trade fields
strategy.close_all()full
strategy.cancel_all()full
Risk managementfullstrategy.risk.* functions
calc_on_order_fillsfullRe-execution after fills, var rollback / varip persist
calc_on_every_tickfullLive mode only — no effect on historical bars
calc_on_every_history_tickno-lookaheadFour passes per bar (per sub-bar with the magnifier); each pass sees the bar as built so far — see No lookahead, ever

Request Module

FeatureStatusNotes
request.security()fullMultiprocessing with shared memory
request.security_lower_tf()fullReturns arrays of intrabar values
request.currency_rate()fullTOML-based currency pair auto-detection
request.dividends()no data feedna with ignore_invalid_symbol=True or for a crypto chart’s own ticker; raises otherwise
request.splits()no data feedna with ignore_invalid_symbol=True or for a crypto chart’s own ticker; raises otherwise
request.earnings()no data feedna with ignore_invalid_symbol=True or for a crypto chart’s own ticker; raises otherwise
request.financial()no data feedFactSet fundamentals; na with ignore_invalid_symbol=True, raises otherwise
request.economic()no data feedMacro data; raises NotImplementedError
request.quandl()no data feedNasdaq Data Link; raises NotImplementedError
request.seed()no data feedGitHub repository data; returns na (a tuple of na for tuple expressions)
request.footprint()no data feedReturns na — no tick order-flow source

request.security() Details

FeatureStatusNotes
Higher timeframefull1D, 1W, 1M, etc. from lower TF chart
Different symbolfullAny symbol with OHLCV data
Lower timeframe (LTF)fullVia request.security_lower_tf()
Multiple callsfullEach gets its own OS process
Conditional callsfullInside if/for/while blocks
Nested callsfullsecurity(… security(…) …)
barmerge.gaps_offfullForward-fills last value (default)
barmerge.gaps_onfullReturns na between periods
lookahead_offfullConfirmed previous period (default)
ignore_invalid_symbolfullReturns na for missing symbols
lookahead_onno-lookaheadSteps into the containing period, so the close[1] idiom matches TV; a bare close reads the period as built so far instead of its final value — see No lookahead, ever
currency parameterfullAuto-converts via CurrencyRateProvider

Drawing Objects

Every drawing API is implemented: objects are created, updated, deleted and read back exactly as in Pine Script, and their state rolls back with the bar on intra-bar re-execution. pyne run --viz exports plots and drawings as NDJSON (--viz-journal adds a per-bar create/update/delete event log) for any charting front end — see Visual Output. PyneCore itself draws no chart.

FeatureStatusNotes
label.*no rendererFull API and state; exported with --viz
line.*no rendererFull API and state; exported with --viz
box.*no rendererFull API and state; exported with --viz
table.*no rendererFull API and state; exported with --viz
polyline.*no rendererFull API and state; exported with --viz
linefill.*no rendererFull API and state; exported with --viz

Core Modules

ModuleStatusFunctionsNotes
mathfull24+ constants (e, pi, phi, rphi)
arrayfull57Wraps Python list
mapfull11Wraps Python dict
matrixfull51Full 2D array operations
stringfull21Named string (not str)
colorfull50+ colorsRGB creation, constants
timeframefull19Conversion, validation
sessionfull8Market session handling
barstatefull5isfirst, islast, isnew, etc.
syminfofull20+ propsFrom TOML metadata
chartfullChart type flags, colors
logfull3info, warning, error
alertfull1 + 3Alert with frequency constants
runtimefull1error() for script termination
inputfullAll input types via function params
plot / hline / fillfullOutput to CSV

Type System

TypeStatusNotes
int, float, bool, strfullNative Python types; an int travels as an integral float, as on TradingView
Series[T]fullCircular buffer, historical access
Persistent[T]fullCross-bar state via AST transformation
na / NA[T]fullFull NA propagation
ColorfullRGBA with transparency
label, line, boxfullDataclass-based drawing objects
table, polylinefull
chart.pointfullChartPoint in PyneCore
array / matrix / mapfullPython list / custom / dict
footprint / volume_rowno data feedTypes defined, no order-flow source

Enum Constants

All Pine Script v6 enum constants are implemented:

ModuleConstants
currency21 currency codes (USD, EUR, BTC, etc.)
barmergegaps_on/off, lookahead_on/off
displaynone, all, data_window, pane, price_scale, status_line
color50+ named colors
extendnone, left, right, both
formatinherit, price, volume, percent, mintick
locationabovebar, belowbar, top, bottom, absolute
position9 table positions (top/middle/bottom x left/center/right)
shape10+ marker shapes
sizeauto, tiny, small, normal, large, huge
xloc / ylocbar_index/bar_time, price/abovebar/belowbar
dayofweekmonday through sunday
dividendsgross, net
earningsactual, estimate, standardized
adjustmentnone, dividends, splits
scaleright, left, none

Pine Script Syntax Features

FeatureStatusNotes
FunctionsfullIncluding nested/inline functions
if/else/switchfullVia PyneComp compilation
for/while loopsfull
var (persistent)fullPersistent[T] annotation
varip (intrabar persist)fullPersists across re-executions (COOF and live mode)
Methods on typesfull.get(), .set(), .size(), etc.
User-defined types (UDT)fullVia PyneComp compilation
EnumsfullVia PyneComp compilation
LibrariesfullImport and use Pine libraries
Operator overloadingfull+, -, *, /, %, comparisons
Ternary operatorfullPython conditional expression
Type castingfullint(), float(), str(), bool()
na propagationfullArithmetic, comparison, logical
Multi-return (tuples)full
Default parametersfull
export (libraries)fullVia PyneComp compilation

Not Applicable to PyneCore

These Pine Script features exist only in TradingView’s live charting environment and have no equivalent in PyneCore:

FeatureReason
Chart renderingNo built-in chart — output is CSV, and NDJSON with --viz
input() UI widgetsInputs are function parameters or TOML config

No lookahead, ever

PyneCore is a backtest and live-trading runtime, not a chart-analysis tool. Where TradingView hands a script data the bar could not have known yet, PyneCore diverges from TradingView on purpose and returns what was actually knowable at that moment.

The reasoning is asymmetric. On a chart, repaint is visible and recoverable — you watch it happen and re-read the chart. In a backtest it silently inflates results, and in a live bot it produces decisions the market never supported. A loud, safe divergence beats a quiet, dangerous match, so this rule outranks TV parity everywhere it applies.

SituationTradingViewPyneCore
lookahead_on, bare close, inside an open HTF periodthe period’s FINAL close and highthe period as built up to the current chart bar
lookahead_on with the close[1] idiomthe just-closed prior periodidentical — no divergence
lookahead_off / lookahead_last_closedthe last CLOSED periodidentical — no divergence
Cross-symbol HTF lookahead_on inside an open periodthe developing barna (nothing can be aggregated from the wrong instrument)
An intra-bar pass (calc_on_order_fills, calc_on_every_history_tick)the bar’s COMPLETED open/high/low/close/volumethe bar as built up to that pass’s point in it

Note what is not affected: the canonical daily-pivot idiom request.security(sym, "D", close[1], lookahead_on) lives entirely in close[1], reads a period that has genuinely closed, and matches TradingView exactly. Only the bare form — which is future data on every chart bar except a period’s last — differs.

barmerge.lookahead_last_closed is a PyneSys-native mode for stating “last closed” intent explicitly, without relying on the TV close[1] idiom at all.

The same rule governs every body execution that stands mid-bar. calc_on_order_fills re-runs the body when an order fills, and calc_on_every_history_tick runs it at every point of the bar the broker emulator walks: without the magnifier the four assumed nodes — open, the extreme nearest the open, the other extreme, close — and with it, the end of every sub-bar. TradingView hands all of those passes the bar’s finished OHLCV, so a pass standing at the open can already read the high that only happens later; PyneCore gives each pass the bar truncated to its own point, with volume accrued to match and hl2 / hlc3 / ohlc4 / hlcc4 recomputed from the truncated values. Only the bar’s last, definitive execution sees the completed bar — which is also the only execution a strategy without these flags ever gets, so default strategies are unaffected.

Known TradingView quirks not reproduced

Behaviour that looks like a TradingView defect rather than a rule is documented here instead of being copied. Each entry says where to look if a script ever turns out to depend on it.

Session mask on the day before a fall DST change

On the day BEFORE a timezone’s fall clock change — where no offset shifts at all — TradingView appends one extra hour to the intraday close of every session run that has an endpoint on the changing wall-clock hour (02:00 in America/New_York and Europe/London, 03:00 in Australia/Sydney). On the first chart bar of that extra hour time(tf, session, tz) returns na while time_close(tf, session, tz) returns a value, so the same bar is out of and in the session at once. PyneCore returns na from both.

Measured on a 60-minute chart, 2024-01 to 2026-09, identically on BINANCE:BTCUSDT, COINBASE:BTCUSD, BITSTAMP:BTCUSD, KRAKEN:XBTUSD and CAPITALCOM:BTCUSD, so it does not depend on the data source:

Session, timezoneBars where time() is na and time_close() is not (UTC)
"1700-0200" America/New_York2024-11-02 06:00, 2025-11-01 06:00
"0200-1000" America/New_York2024-11-02 14:00, 2025-11-01 14:00
"0900-1600" America/New_Yorknone — no endpoint on the changing hour
"1700-0200" Europe/London2024-10-26 01:00, 2025-10-25 01:00
"0200-1000" Europe/London2024-10-26 09:00, 2025-10-25 09:00
"1700-0300" Australia/Sydney2024-04-05 16:00, 2025-04-04 16:00, 2026-04-03 16:00

It can only show on an instrument that trades on that day (the day before the change is a Saturday, or a Friday evening UTC for Sydney), which rules out exchange-traded and FX symbols, and only in a script that reads time_close() with such a session: the usual na(time(tf, session, tz)) test agrees with TradingView on that bar. It is one bar per affected session per year.

Where to look: _session_occurrences_opening_on and _intraday_session_bounds in pynecore/lib/__init__.py. Both functions read one session occurrence per bar, so reproducing the quirk needs a rule of its own for time_close() on that single bar.

Precision

What “matches TradingView” means, measured on the validation corpus (snapshot

2026-10-01):
  • Plotted values: 99.768% of 117,659,091 values are identical to TradingView to the bit. In 794 of the 811 compared plot outputs every single value is bit-identical. The largest relative gap anywhere is 1.2 × 10⁻¹⁰ (about 9 significant figures).
  • Strategy trades: 318,982 trades in 429 strategies; entry and exit timing and trade counts match TradingView in every one of them.
  • OHLCV data: the v2 .ohlcv format stores int64 millisecond timestamps, float64 open and volume, and high/low/close as float32 deltas from the open — promoted to float64 whenever a delta cannot hold the symbol’s tick grid exactly — and snaps prices back to the tick grid on read.

Where the non-identical values come from

IEEE-754 leaves implementations free to differ on operation ordering and internal precision, so two correct implementations of the same formula can produce results that differ by a few ULPs. The values that are not bit-identical differ far below any price tick: the largest relative gap in the whole corpus is 1.2 × 10⁻¹⁰, and typical disagreements are 1e-15 to 1e-12 absolute, adding up to at most a fraction of a percent equity drift over thousands of trades.

The disagreement is invisible in arithmetic but matters at exact-equality comparisons, where one side may see a == b while the other sees a slightly above or below b. At those sub-tick scales the difference is numerical noise, not a real trading signal. The functions most exposed to it are ta.crossover and ta.crossunder, which follow Pine’s strict-comparison spec (> / <=) and therefore inherit any boundary disagreement TradingView and PyneCore have on the same bar. Any user code that compares two computed series with ==, !=, >, < etc. without an explicit tolerance is subject to the same kind of ULP-level disagreement; if the result matters, round the operands to a meaningful number of decimal places or use math.isclose.

Resolved limitations

Limitations that older pages, issues and articles may still mention, with the release that closed them:

  • v6.4.1 — bar magnifier and calc_on_order_fills.
  • v6.5.1 — multi-period D/W/M aggregation (2D, 3W, …) is trading-day and holiday aware (#65).
  • v6.5.2 — multi-day request.security exposes the last confirmed period, not the developing one (#70).
  • v6.5.3 — nD/nW/nM aggregation follows exchange holidays and session schedules, e.g. on CME futures (#71).
  • v6.6.0 — live data (pyne run --live), broker trading (pyne run --broker) and realtime barstate flags; plot and drawing export (pyne run --viz).
  • v6.10.3 — extended trading hours: SymInfo keeps the symbol’s pre-market and post-market template, time(tf, "extended") / time(tf, "regular") read it, and on bars of the extended hours session.ispremarket, session.ispostmarket, session.ismarket, session.isfirstbar / session.islastbar and syminfo.session behave as on TradingView (see Extended Trading Hours). CFD feeds without an exchange calendar (Capital.com) count every weekday on the nD/nW/nM grid, as TradingView does.