Pine Script v6 compiler and runtime for Go — compile indicators to bytecode, execute against any market data provider

Pinescription
A high-performance Pine Script v6 compiler and runtime for Go.
Pinescription compiles Pine Script code into optimized bytecode and executes it against market data providers, enabling you to run TradingView indicators and strategies in production Go applications without webhooks or external dependencies.
Why Pinescription
- No webhooks, no lock-in. Run Pine Script indicators directly in your Go backend. Connect to any broker API through a simple provider interface.
- Native Go performance. The compiler generates optimized bytecode with streaming evaluation. Benchmarks show 164x speedup over full recomputation.
- Pine Script v6 compatible. Supports language core, arrays, matrices, tuples, 30+ indicators, and the
ta.*namespace. - Single dependency. Built on gonum for linear algebra. No other external dependencies.
Quick Start
Step 1: Install
go get github.com/woodstock-tokyo/pinescription
Step 2: Write your first indicator
package main
import ( "fmt" pinego "github.com/woodstock-tokyo/pinescription" )
func main() { engine := pinego.NewEngine() engine.RegisterMarketDataProvider(&yourProvider{}) engine.SetDefaultSymbol("AAPL")
script := var ma = sma(close, 20) var ex = ema(close, 20) ma + ex
bytecode, err := engine.Compile(script) if err != nil { panic(err) } result, err := engine.Execute(bytecode) if err != nil { panic(err) } fmt.Println("Result:", result) }
Step 3: Explore more examples
See examples/basic/main.go for a working demo with sample market data, or examples/volumeprofilepivot_anchored/ for a complex Pine Script v6 execution.
Performance
Benchmarked on Apple M3:
| Benchmark | Result | Notes | |-----------|--------|-------| | Bollinger Bands (streaming) | 634 ns/op | 164x faster than full recompute | | 5000-bar indicators | ~5.8 ms/op | Optimized sliding window | | Fisher Transform (5000 bars) | ~10.9 ms/op | Complex multi-step indicator |
The streaming execution model updates only the active bar state, avoiding full recalculation on each iteration.
Features
- Language Core:
var/constdeclarations,if/else/for/while/switch, functions, arrays, tuples, matrices - 30+ Built-in Indicators: SMA, EMA, RSI, ATR, Bollinger Bands, crossover, crossunder, stdev, correlation...
- Full
ta.*Namespace:ta.sma,ta.ema,ta.rsi,ta.atr,ta.bb... math.*Namespace:math.abs,math.pow,math.sqrt,math.log,math.sin...- Array Operations: 25+ methods including
push,pop,sort,sum,avg... - Matrix Operations: Linear algebra helpers, eigenvalues, determinant, transpose...
- String Operations:
str.format,str.split,str.replace,str.contains... - Market Data: Multi-symbol queries (
closeof,smaof...), history indexing (close[1]) - Alerts:
alert()andalertcondition()with custom sinks
Documentation
| Document | Description | |----------|-------------| | API Reference | Complete API surface: Engine, Runtime, Provider, Alerts | | Architecture and Design | Compilation pipeline, execution flow, streaming evaluation model | | Feature Reference | Exhaustive list of supported Pine Script v6 features |
Architecture
Pinescription compiles Pine Script source to intermediate representation, then encodes it as bytecode. At runtime, the VM evaluates the bytecode bar-by-bar against market data from your provider. See docs/architecture.md for detailed flow diagrams.
Provider Interface
Your market data provider implements the Provider interface:
type Provider interface {
GetSeries(seriesKey string) (SeriesExtended, error) // seriesKey = "symbol|value_type"
GetSymbols() ([]string, error)
GetValuesTypes() ([]string, error)
SetTimeframe(timeframe string) error
GetTimeframe() string
SetSession(session string) error
GetSession() string
}
Common series keys include AAPL|close, AAPL|volume, etc.
Unsupported in Open Source Version - Need Custom Function Hooks
- Strategy APIs (
strategy.entry,strategy.exit...) - Request APIs (
request.security,request.financial...) - Plot APIs (
plot,plotshape...)
RegisterFunction("strategy.order", fn) for positional-only hooks, or RegisterFunctionWithParamNames(...) when the Pine call may use named arguments, for example RegisterFunctionWithParamNames("plot", []string{"series", "title", "color"}, fn) or RegisterFunctionWithParamNames("request.security", []string{"symbol", "timeframe", "expression"}, fn). Validation still rejects parser-reserved names, non-hookable implemented built-ins, and Pine type keywords such as int, float, color, and table.
Host applications may also register selected drawing-object hook points such as polyline.new, box.new, label.new, chart.point.from_index, table.cell, and table.clear. Pinescription provides compatibility stubs for those APIs, but a host hook can capture the calls and render the resulting objects outside the runtime.
License
Pinescription is dual-licensed under AGPL-3.0-only and a commercial license.
- AGPL-3.0-only: See
LICENSES/AGPL-3.0-only.txt - Commercial: See
LICENSES/LICENSE-COMMERCIAL.md
Security
See SECURITY.md for vulnerability reporting.
Built by
Built by Woodstock K.K.
Pine Script™ is a trademark of TradingView. Pinescription is an independent project and is not affiliated with, endorsed by, or associated with TradingView.