We’re excited to announce PineTS v0.8.9! This release cycle (v0.8.1 through v0.8.9) focused on transpiler robustness, Pine Script language coverage, and critical bug fixes – many driven by our first community contributions. Nine patch releases later, PineTS is significantly more reliable for real-world Pine Script indicators and strategies.
What’s New from v0.8.0 to v0.8.9
Full Switch Statement Support
One of the most requested Pine Script features — switch statements — is now fully supported, including complex multiline cases, TA function calls inside cases, and both expression-based and condition-based variants.
Expression-Based Switch
Use switch to select between different calculation modes at runtime:
//@version=6
indicator("Dynamic Moving Average", overlay=true)
maType = input.string("EMA", "MA Type", options=["EMA", "SMA", "RMA", "WMA"])
maLength = input.int(14, "MA Length", minval=2)
dynamicMA(src, len, maType) =>
switch maType
"EMA" => ta.ema(src, len)
"SMA" => ta.sma(src, len)
"RMA" => ta.rma(src, len)
"WMA" => ta.wma(src, len)
=> ta.sma(src, len)
result = dynamicMA(close, maLength, maType)
plot(result, "MA", color=color.blue)
Condition-Based Switch (No Expression)
Pine Script’s switch without an expression acts like an if/else if chain — PineTS now correctly transpiles this pattern:
//@version=6
indicator("RSI Signal")
rsi = ta.rsi(close, 14)
oversold = rsi < 30
overbought = rsi > 70
var signal = 0
var strength = 0.0
switch
oversold =>
signal := 1
strength := (30 - rsi) / 30
overbought =>
signal := -1
strength := (rsi - 70) / 30
=>
signal := 0
strength := 0.0
plot(signal, "Signal")
plot(strength, "Strength")
Multiline Case Blocks
Switch cases can now contain multiple statements, local variable declarations, nested conditionals, and TA function calls:
//@version=6
indicator("TA in Multiline Switch")
indicator_type = "trend"
result = switch indicator_type
"trend" =>
fast = ta.ema(close, 9)
slow = ta.ema(close, 21)
fast - slow
"momentum" =>
rsi = ta.rsi(close, 14)
rsi
plot(result, "Result")
Plot Fill Between Lines
The new fill() function lets you shade the area between two plot lines — essential for indicators like Bollinger Bands, Keltner Channels, and Ichimoku clouds:
//@version=6
indicator("Bollinger Bands", overlay=true)
length = input.int(20, "Length")
mult = input.float(2.0, "Multiplier")
[middle, upper, lower] = ta.bb(close, length, mult)
plot(middle, "Basis", color=color.blue)
p1 = plot(upper, "Upper", color=color.red)
p2 = plot(lower, "Lower", color=color.green)
fill(p1, p2, title="BB Fill", color=color.new(color.blue, 90))
The fill() function accepts the plot objects returned by plot(), along with optional color, title, and display parameters. When paired with a charting library like QFChart, the fill area renders as a semi-transparent overlay between the two lines.
Critical Transpiler Fix: User Function Variable Isolation
v0.8.4 fixed a critical issue where local variables inside user-defined functions were sharing state across different calls. Before this fix, calling the same function multiple times could produce incorrect results because variables like sum, result, or temp would bleed between calls.
The fix introduced dynamic scoping with local contexts ($$), ensuring each function invocation gets completely isolated variable storage:
//@version=6
indicator("Multi-MA Dashboard")
ma(float source, int length, simple string maType) =>
switch maType
"EMA" => ta.ema(source, length)
"SMA" => ta.sma(source, length)
"RMA" => ta.rma(source, length)
=> ta.sma(source, length)
// Each call gets isolated state - no variable collisions
fast = ma(close, 9, "EMA")
medium = ma(close, 21, "SMA")
slow = ma(close, 50, "EMA")
plot(fast, "Fast MA")
plot(medium, "Medium MA")
plot(slow, "Slow MA")
This fix is transparent to users — the same Pine Script code just works correctly now. Under the hood, each function call is wrapped with $.call(fn, callId, ...args) and gets its own scoped context.
Enhanced For Loop Support
v0.8.7 added support for tuple destructuring in for...in loops, a commonly used pattern in Pine Script for iterating over arrays with indices:
//@version=5
indicator("Array Iteration")
processMatrix(X) =>
for [idx, value] in X
// idx is the array index, value is the element
j = 0
0
plot(close)
Additional fixes ensure that for...in and for...of loops work correctly with Pine Script arrays, including proper destructuring support and resolution of function/variable name collisions in loop contexts.
Method Call Syntax
v0.8.7 introduced proper handling of user-defined method calls. When you define a function and call it with method syntax (e.g., obj.method()), PineTS now correctly transforms it into a function call with the object as the first argument:
//@version=6
indicator("Method Syntax")
arr = array.new_float(0)
arr.push(close)
size = arr.size()
plot(size)
This also works for user-defined functions used as methods, where obj.myFunc(args) is correctly transpiled to myFunc(obj, args).
Math Namespace Additions
v0.8.4 added two new math functions:
math.todegrees(radians)— Converts radians to degreesmath.toradians(degrees)— Converts degrees to radians
These are useful for indicators involving angular calculations, cycle analysis, or trigonometric patterns.
Transpiler Reliability Improvements
This release cycle brought a wave of transpiler hardening. Here are the most impactful fixes:
| Version | Fix | Impact |
|---|---|---|
| v0.8.1 | Operator precedence: (a + b) * c was losing parentheses | Arithmetic expression correctness |
| v0.8.2 | Variable name collisions in transpiler | Prevented incorrect variable renaming |
| v0.8.2 | Logical expressions (&&, ||) in function arguments | Proper evaluation in nested calls |
| v0.8.3 | Scientific notation (10e10, 1.2e-5) parsing | Lexer correctly tokenizes literals |
| v0.8.3 | Double parentheses in return statements (math.max()()) | Namespace calls in returns work |
| v0.8.4 | Array access in ternary expressions | Correct scope keys in expressions |
| v0.8.4 | SMA NaN contamination in rolling window | Falls back to recalculation |
| v0.8.5 | Multiline Pine Script condition parsing | Indentation errors resolved |
| v0.8.7 | Unary operators with function calls (!func()) | Proper AST transformation |
| v0.8.7 | Method chains (func(arg).method()) | Arguments transformed correctly |
| v0.8.8 | ta.bb return order [middle, upper, lower] | Matches Pine Script behavior |
| v0.8.8 | color.new() RGBA conversion | Correct color string output |
| v0.8.9 | Typed variable declarations | Pine Script v5 compatibility |
Bollinger Bands Return Order Fix
A notable fix in v0.8.8: ta.bb() now returns [middle, upper, lower] to match Pine Script’s actual return order. Previously, the order was incorrect, which could cause subtle bugs in indicators that destructure the result:
// Now correctly matches Pine Script behavior
[middle, upper, lower] = ta.bb(close, 20, 2.0)
Community Contributions
We’re thrilled to highlight our first community contributions! PineTS is growing beyond a solo project:
@dcaoyuan contributed:
- Fixed
color.new()RGBA string generation (v0.8.8) - Fixed
ta.bbreturn order to match Pine Script (v0.8.8) - Fixed
ta.highest/ta.lowestto accept length as first argument (v0.8.9) - Removed non-standard colors from the color palette (v0.8.9)
- Fixed unary operator handling in transpiler (v0.8.7)
@C9Bad contributed:
- Fixed parser to allow comments between
ifblock andelse(v0.8.8) - Fixed parser to allow inline comments after type fields (v0.8.8)
Thank you both for making PineTS better! Community contributions are what drive open-source projects forward.
Installation & Upgrade
Install or upgrade to the latest version:
npm install pinets@latest
Bug Fixes Summary
Across nine patch releases, here’s the full list of fixes:
- v0.8.1: Operator precedence in complex arithmetic expressions
- v0.8.2: Variable name collisions, logical expressions in function arguments
- v0.8.3: Scientific notation parsing, double-parentheses in return statements
- v0.8.4: User function variable scope isolation, SMA NaN handling,
math.roundprecision, array access in expressions - v0.8.5: Multiline conditions parsing, switch syntax conversion, deprecation warning false positives
- v0.8.6: Binance provider stream data handling
- v0.8.7: For loop destructuring, method calls, switch IIFEs, unary operators, matrix operations
- v0.8.8: Color conversion, comment handling, Bollinger Bands return order
- v0.8.9: Typed variable declarations,
ta.highest/ta.lowestargument handling, standard color list
What’s Next
The next release cycle will focus on:
- Drawing primitives:
label.*,line.*,box.*,table.*,linefill.*, andpolyline.*for full TradingView drawing parity - Strategy namespace: Expanding strategy support for backtesting workflows
- Performance: Continued optimization for large datasets and live streaming scenarios
Get Involved
PineTS is open-source (AGPL-3.0) and community-driven. We welcome contributions, bug reports, and feature requests.


Leave a Reply