One compiler for every Pine version
PyneComp turns Pine Script into Pyne code, the Python that PyneCore runs, and it converts older Pine scripts to v6. Since November 12, 2026, one new compiler does all of that. The API compiles and converts with it, and the PyneIDE language server is built from it.
If you use PyneComp through the API or PyneIDE, you don’t have to change anything, because the calls are the same. What comes back changed in a few places. This post covers those places and why I built a new compiler instead of fixing the old one again.
What the old one taught us
The first PyneComp compiler grew one fix at a time. Every bug report, every script that ran differently on TradingView and every corner of the language I measured went into it. That is where most of what PyneComp knows about Pine came from.
It also meant the same Pine rules ended up in several places. The compiler had them, the v6 converter had its own version of them, and the language server in PyneIDE needed them too. A fix had to land in each copy, and sometimes it landed in only one. The compiler and the editor could disagree about the same line.
The other lesson was about what to accept. The old compiler was built to translate scripts that already run on TradingView. Given a script TradingView would refuse, it often translated that too, and you found out when the result misbehaved.
The new compiler takes everything the old one learned and puts it in one place: one description of the language, for every Pine version, and every tool reads it. It is written in Rust, which mostly matters to me, because it lets the same code run inside the API and inside the editor.
It rejects what TradingView rejects
The new compiler checks the language the way TradingView does: types, qualifiers, the arguments each built-in takes, and names that only exist in a newer Pine version. Every rule comes with a pair of small probe scripts, one TradingView accepts and one it refuses, and the compiler has to give the same answer as TradingView on both.
I then ran it over about 42,000 real-world scripts of every Pine version, with one requirement: every script the new compiler refuses, TradingView must refuse too. By the end, it refused no script that TradingView accepted.
A second test came from TradingView itself. I took the v6 output of TradingView’s own converter for about 1,100 popular public v4 and v5 scripts. The new compiler refused 82 of them, and the old one had compiled all 82. I sent 7 of them back to TradingView, one for each kind of error, and TradingView refused all 7.
The error messages changed along with the rules. They point at the line in your script, even when the script is older than v6 and had to be converted first. They describe the problem in Pine terms and, when there is only one way to fix it, they say what to write:
Line 2047: The argument `offset` of `plot` is a `series int`; it takes a `simple int`.
Because PyneIDE’s language server is built from the same compiler, the editor shows you the same errors before you compile.
Pine v1 to v3, now supported
The old compiler compiled most v1, v2 and v3 scripts, but nobody checked whether the result
was right, and the old converter only handled v4 and v5. The new compiler supports all
3 versions, for compiling and for converting to v6, and they are tested against
TradingView like the newer ones. Some of what these versions did was never documented.
Where it mattered, for example which parameter a positional argument of study() ends up
in, I measured it on TradingView instead of assuming it.
Conversions keep your text
When you convert a script, the parts that need no change now come back exactly as you
wrote them. The old converter reprinted the whole script from its own model: indicator("N")
came back as indicator('N'), the spacing changed, and a diff of the conversion showed
changes on almost every line. A diff now shows only what the conversion did.
It is also faster
Compiling one script never felt slow, so you are unlikely to notice this one, except on large conversions. I timed both compilers on the same scripts, in the same Python process, the way the API calls them: 1 warm-up run, then the median of 5 runs, on an Apple M4 Max, on one thread.
| Task | Scripts | Old (median) | New (median) | Slowest, old → new |
|---|---|---|---|---|
| Compile a v6 script | 1,164 | 29.3 ms | 0.77 ms | – |
| Convert a v4 or v5 script | 1,121 | 277.7 ms | 1.13 ms | 28 s → 124 ms |
An API request also spends time on the network and in the API itself, and that part did not change. Where the difference shows is the slowest conversions: 217 of these scripts took longer than a second with the old converter, the slowest 28 seconds.
What is still missing
Conversion isn’t finished. Of the 1,121 v4 and v5 scripts above, 1,107 convert to v6 that
compiles. 12 are refused on purpose, with a message explaining why: they have no faithful
v6 form. One example is a v4 script that tests a bool for na, which a v6 bool can
never be. The remaining 2 convert to v6 that TradingView rejects, because v4 let offset
change from bar to bar and v6 does not. The old converter got those 2 wrong in exactly
the same way.