We’re excited to announce a new tool in the QuantForge ecosystem: pinets-cli — a command-line interface that lets you run TradingView Pine Script indicators directly from your terminal. No JavaScript project to set up, no code to write. Just point it at a .pine file and go.
pinets run rsi.pine --symbol BTCUSDT --timeframe 60
Why a CLI?
PineTS is powerful as a library, but using it requires setting up a Node.js project, writing JavaScript, and managing imports. That’s great for building applications, but sometimes you just want to:
- Quickly test an indicator against live data
- Automate indicator calculations in a cron job or CI pipeline
- Pipe results into Python,
jq, or a database - Scan multiple symbols with a simple shell loop
- Debug your Pine Script transpilation without touching JavaScript
pinets-cli makes all of this a one-liner.
Installation
npm install -g pinets-cli
Or run without installing:
npx pinets-cli run my_indicator.pine --symbol BTCUSDT --timeframe 60
Requires Node.js 20+. The package is self-contained, it bundles the entire PineTS runtime into a single file with no additional dependencies.
Getting Started
1. Create a Pine Script file
Create sma_cross.pine:
//@version=5
indicator("SMA Cross", overlay=true)
fast = ta.sma(close, 9)
slow = ta.sma(close, 21)
plot(fast, "Fast SMA", color=color.blue)
plot(slow, "Slow SMA", color=color.red)
2. Run it
pinets run sma_cross.pine --symbol BTCUSDT --timeframe 60
That’s it. You get structured JSON output with the calculated SMA values for the last 500 hourly candles:
{
"indicator": {
"title": "SMA Cross",
"overlay": true
},
"plots": {
"Fast SMA": {
"title": "Fast SMA",
"options": { "color": "#2196F3" },
"data": [
{ "time": 1704067200000, "value": 42150.33 },
{ "time": 1704070800000, "value": 42180.67 }
]
},
"Slow SMA": { ... }
}
}
Key Features
Live Binance Data
Fetch real-time market data from Binance — spot or perpetual futures — with no API key required:
# Spot market
pinets run rsi.pine --symbol BTCUSDT --timeframe 1D
# Perpetual futures (append .P)
pinets run rsi.pine --symbol ETHUSDT.P --timeframe 60
Supports all standard timeframes: 1, 5, 15, 30, 60, 240, 1D, 1W, 1M.
Custom JSON Data
Bring your own data from any source — other exchanges, CSV conversions, or historical datasets:
pinets run my_indicator.pine --data ./candles.json
The JSON file is a simple array of OHLCV candle objects:
[
{
"openTime": 1704067200000,
"open": 42000.50,
"high": 42500.00,
"low": 41800.00,
"close": 42300.00,
"volume": 1234.56
}
]
This makes pinets-cli exchange-agnostic — use data from Coinbase, Kraken, Yahoo Finance, or any source you can format as JSON.
Indicator Warmup
Long-period indicators need historical data to initialize. The --warmup flag fetches extra candles that are processed but excluded from the output:
# 200-period EMA needs warmup. Fetch 700 candles, output only the last 500.
pinets run ema200.pine --symbol BTCUSDT --timeframe 60 --candles 500 --warmup 200
No more NaN values at the start of your output.
Piping and Scripting
pinets-cli outputs clean JSON to stdout, making it a first-class citizen in shell pipelines:
# Extract the latest RSI value with jq
pinets run rsi.pine -s BTCUSDT -t 60 -q | jq '.plots.RSI.data[-1].value'
# Get all plot names from a complex indicator
pinets run macd.pine -s BTCUSDT -q | jq '.plots | keys'
Signal Filtering
Indicators that generate signals (crossovers, plotshapes) produce mostly false/null values. Use --clean to filter them out, and --plots to select only the plots you care about:
<em># Get only actual Buy and Sell signals -- no false values, no extra plots</em>
pinets run signals.pine -s BTCUSDT --plots "Buy,Sell" --clean -q | jq '.plots'
Stdin Support
Pipe indicator code directly — useful for dynamic generation or inline testing:
echo '//@version=5
indicator("Quick RSI")
plot(ta.rsi(close, 14), "RSI")' | pinets run -s BTCUSDT -t 60 -n 10 -q --pretty
Real-World Workflows
Multi-Symbol Scanning
Scan the same indicator across multiple assets with a simple loop:
for symbol in BTCUSDT ETHUSDT SOLUSDT BNBUSDT; do
echo "=== $symbol ==="
pinets run rsi.pine -s $symbol -t 1D -n 1 -q | jq '.plots.RSI.data[0].value'
done
Multi-Timeframe Analysis
Run the same indicator at different timeframes:
for tf in 15 60 240 1D; do
echo "--- Timeframe: $tf ---"
pinets run rsi.pine -s BTCUSDT -t $tf -n 1 -q | jq '.plots.RSI.data[0].value'
done
Python Integration
Feed indicator data directly into pandas for further analysis:
import subprocess
import json
import pandas as pd
result = subprocess.run(
['pinets', 'run', 'sma.pine', '-s', 'BTCUSDT', '-t', '1D', '-f', 'full', '-q'],
capture_output=True, text=True
)
data = json.loads(result.stdout)
df = pd.DataFrame(data['marketData'])
df['time'] = pd.to_datetime(df['openTime'], unit='ms')
for plot_name, plot_data in data['plots'].items():
values = [p['value'] for p in plot_data['data']]
df[plot_name] = values
print(df[['time', 'close', 'Fast SMA', 'Slow SMA']].tail(10))
Scheduled Automation
Set up a cron job to log RSI values every hour:
# crontab -e
0 * * * * pinets run /path/to/rsi.pine -s BTCUSDT -t 60 -n 1 -q | \
jq -r '.plots.RSI.data[0] | "\(.time),\(.value)"' >> /var/log/btc_rsi.csv
Debug Transpilation
See exactly what PineTS generates from your Pine Script:
pinets run my_indicator.pine -s BTCUSDT --debug
The transpiled code is printed to stderr, so it doesn’t interfere with the JSON output.
Complete Option Reference
Data Source
| Option | Short | Description | Default |
|---|---|---|---|
--symbol <ticker> | -s | Symbol to query (e.g., BTCUSDT, ETHUSDT.P) | — |
--timeframe <tf> | -t | Timeframe: 1, 5, 15, 60, 240, 1D, etc. | 60 |
--data <path> | -d | Path to a JSON data file | — |
Output
| Option | Short | Description | Default |
|---|---|---|---|
--output <path> | -o | Write output to a file | stdout |
--format <type> | -f | default (plots) or full (plots + market data) | default |
--pretty | — | Force pretty-printed JSON | auto |
--clean | — | Filter out null, false, and empty values | — |
--plots <names> | — | Comma-separated list of plot names | all |
Candle Control
| Option | Short | Description | Default |
|---|---|---|---|
--candles <count> | -n | Number of candles in output | 500 |
--warmup <count> | -w | Extra warmup candles (not in output) | 0 |
Other
| Option | Short | Description |
|---|---|---|
--debug | — | Show transpiled code |
--quiet | -q | Suppress informational messages |
--version | -v | Show version number |
--help | -h | Show help |
The QuantForge Ecosystem
pinets-cli joins the growing QuantForge family of open-source tools for quantitative trading:
- PineTS — The core transpiler and runtime. Use it as a library in Node.js or the browser to execute Pine Script indicators programmatically.
- QFChart — A charting library optimized for PineTS visualization. Render indicators with TradingView-like visual fidelity.
- pinets-cli — Run Pine Script from the command line. Designed for automation, scripting, and quick analysis.
Together, these tools let you take any Pine Script indicator from TradingView and run it on your own infrastructure — whether that’s a Node.js server, a browser dashboard, or a shell script.
Get Started
npm install -g pinets-cli
pinets run my_indicator.pine --symbol BTCUSDT --timeframe 60
Full documentation is available in the docs folder, including:
Get Involved
pinets-cli is open-source (AGPL-3.0) and we welcome contributions.
PineTS and pinets-cli are independent open-source projects and are not affiliated with, endorsed by, or associated with TradingView or Pine Script(tm). All trademarks belong to their respective owners.


Leave a Reply