PineTS
Run Pine Script anywhere. PineTS is an open-source transpiler and runtime that brings Pine Script logic to Node.js and the browser with 1:1 syntax compatibility. Reliably write, port, and run indicators or strategies on your own infrastructure.
Install / Use
/learn @QuantForgeOrg/PineTSREADME
<p align="center"> <b>Sponsors</b><br /> <a href="https://luxalgo.com" target="_blank" rel="noopener noreferrer"><img src="./.github/images/luxalgo.png" alt="LuxAlgo" height="80px" /></a> <a href="https://github.com/sponsors/QuantForgeOrg" target="_blank" rel="noopener noreferrer"><img src="./.github/images/sponsor.png" alt="Sponsor" height="80px" /></a> </p>
What is PineTS?
PineTS is an open-source transpiler and runtime that seamlessly bridges Pine Script and the JavaScript ecosystem. Develop your indicators once and deploy them everywhere : on your servers, in the browser, or fully integrated into your trading platforms.
import { PineTS, Provider } from 'pinets';
const pineTS = new PineTS(Provider.Binance, 'BTCUSDT', '1h', 100);
// Run native Pine Script directly
const { plots } = await pineTS.run(`
//@version=5
indicator("EMA Cross")
plot(ta.ema(close, 9), "Fast", color.blue)
plot(ta.ema(close, 21), "Slow", color.red)
`);
About Pine Script™?
Pine Script™ is a domain-specific programming language created by TradingView for writing custom technical analysis indicators and strategies.
Disclaimer : PineTS is an independent project and is not affiliated with, endorsed by, or associated with TradingView or Pine Script™. All trademarks and registered trademarks mentioned belong to their respective owners.
Why PineTS?
| Challenge | PineTS Solution | | ------------------------------------------- | ---------------------------------------------------- | | Pine Script only runs on TradingView | Run indicators on your own infrastructure | | Can't integrate indicators with custom apps | Full JavaScript/TypeScript integration | | Limited to TradingView's data sources | Use any data source (Binance, custom APIs, CSV) | | No programmatic access to indicator values | Get raw values for backtesting, alerts, ML pipelines | | Can't run indicators server-side | Works in Node.js, Deno, Bun, browsers |
Quick Start
Installation
npm install pinets
Hello World
import { PineTS, Provider } from 'pinets';
// Initialize with Binance data
const pineTS = new PineTS(Provider.Binance, 'BTCUSDT', '1h', 100);
// Calculate a simple moving average
const { plots } = await pineTS.run(`
//@version=5
indicator("My First Indicator")
sma20 = ta.sma(close, 20)
plot(sma20, "SMA 20")
`);
console.log('SMA values:', plots['SMA 20'].data);
That's it! You're running Pine Script in JavaScript.
Features
Core Capabilities
- Native Pine Script v5/v6 : Run original TradingView code directly (experimental)
- 60+ Technical Indicators : SMA, EMA, RSI, MACD, Bollinger Bands, and more
- Time-Series Processing : Full Pine Script semantics with lookback support
- Real-time Streaming : Live data processing with event-based updates
- Multi-Timeframe Analysis :
request.security()for MTF indicators - High Precision : Matches TradingView's calculation precision
Two Ways to Write Indicators
<table width="100%"> <tr> <th>Native Pine Script</th> <th>PineTS Syntax (JavaScript)</th> </tr> <tr> <td>//@version=5
indicator("RSI Strategy")
rsi = ta.rsi(close, 14)
sma = ta.sma(rsi, 10)
plot(rsi, "RSI")
plot(sma, "Signal")
</td>
<td>
//@PineTS
indicator('RSI Strategy');
const rsi = ta.rsi(close, 14);
const sma = ta.sma(rsi, 10);
plot(rsi, 'RSI');
plot(sma, 'Signal');
</td>
</tr>
</table>
Live Demos
See PineTS in action with these browser-based examples:
- Williams Vix Fix : Volatility-based indicator
- Squeeze Momentum : Momentum oscillator
- Playground : Test your own Pine Script code
Demos are Built with PineTS + QFChart
Usage
Running Native Pine Script
import { PineTS, Provider } from 'pinets';
const pineTS = new PineTS(Provider.Binance, 'BTCUSDT', 'D', 200);
const { plots } = await pineTS.run(`
//@version=5
indicator("MACD", overlay=false)
[macdLine, signalLine, hist] = ta.macd(close, 12, 26, 9)
plot(macdLine, "MACD", color.blue)
plot(signalLine, "Signal", color.orange)
plot(hist, "Histogram", color.gray, style=plot.style_histogram)
`);
// Access the calculated values
console.log('MACD Line:', plots['MACD'].data);
console.log('Signal Line:', plots['Signal'].data);
Using PineTS Syntax
import { PineTS, Provider } from 'pinets';
const pineTS = new PineTS(Provider.Binance, 'ETHUSDT', '4h', 100);
const { plots } = await pineTS.run(($) => {
const { close, high, low } = $.data;
const { ta, plot, plotchar } = $.pine;
// Calculate indicators
const ema9 = ta.ema(close, 9);
const ema21 = ta.ema(close, 21);
const atr = ta.atr(14);
// Detect crossovers
const bullish = ta.crossover(ema9, ema21);
const bearish = ta.crossunder(ema9, ema21);
// Plot results
plot(ema9, 'Fast EMA');
plot(ema21, 'Slow EMA');
plotchar(bullish, 'Buy Signal');
plotchar(bearish, 'Sell Signal');
return { ema9, ema21, atr, bullish, bearish };
});
Real-time Streaming
import { PineTS, Provider } from 'pinets';
const pineTS = new PineTS(Provider.Binance, 'BTCUSDT', '1m');
const stream = pineTS.stream(
`
//@version=5
indicator("Live RSI")
plot(ta.rsi(close, 14), "RSI")
`,
{ live: true, interval: 1000 },
);
stream.on('data', (ctx) => {
const rsi = ctx.plots['RSI'].data.slice(-1)[0].value;
console.log(`RSI: ${rsi.toFixed(2)}`);
if (rsi < 30) console.log('Oversold!');
if (rsi > 70) console.log('Overbought!');
});
stream.on('error', (err) => console.error('Stream error:', err));
Custom Data Source
import { PineTS } from 'pinets';
// Your own OHLCV data
const candles = [
{ open: 100, high: 105, low: 99, close: 103, volume: 1000, openTime: 1704067200000 },
{ open: 103, high: 108, low: 102, close: 107, volume: 1200, openTime: 1704153600000 },
// ... more candles
];
const pineTS = new PineTS(candles);
const { plots } = await pineTS.run(`
//@version=5
indicator("Custom Data")
plot(ta.sma(close, 10))
`);
API Coverage
PineTS aims for complete Pine Script API compatibility. Current status:
