Skip to content

Real-time Streaming

The streaming system provides continuous real-time data from TradingView Desktop as JSONL (newline-delimited JSON) output. It uses a poll-and-diff pattern -- polling TradingView at a configurable interval and emitting a line only when the data changes.


Architecture

TradingView Desktop  <--CDP-->  pollLoop()  --JSONL-->  stdout
                                    |
                              dedup check
                          (skip if unchanged)

All streams share the same core pollLoop() function:

  1. Call a fetcher function that evaluates JavaScript in TradingView's page context via CDP
  2. JSON-stringify the result and compare to the previous hash
  3. If the data changed (or dedup is disabled), write a JSON line to stdout
  4. Sleep for the configured interval
  5. Repeat until SIGINT or SIGTERM

Each emitted line includes metadata fields:

Field Description
_ts Unix timestamp in milliseconds when the data was emitted
_stream Stream label (e.g., quote, bars, values, lines)

Connection errors (CDP/ECONNREFUSED) are silently retried with a 2-second backoff. Other errors are logged to stderr.


Available Streams

Quote Stream

Emits the latest bar's OHLCV data for the active chart symbol.

tv stream quote [-i 300]

Output fields: symbol, time, open, high, low, close, volume

Default interval: 300ms

{"symbol":"ES1!","time":1710000000,"open":5200.25,"high":5201.50,"low":5199.75,"close":5201.00,"volume":1234,"_ts":1710000300,"_stream":"quote"}

Bars Stream

Emits the last bar with resolution metadata. Useful for detecting new bar formation.

tv stream bars [-i 500]

Output fields: symbol, resolution, bar_time, open, high, low, close, volume, bar_index

Default interval: 500ms

Values Stream

Emits current numeric values from all visible indicators (RSI, MACD, Bollinger Bands, EMAs, etc.).

tv stream values [-i 500]

Output fields: symbol, study_count, studies[] (each with name and values object)

Default interval: 500ms

{"symbol":"ES1!","study_count":3,"studies":[{"name":"RSI","values":{"plot_0":65.4}},{"name":"MACD","values":{"plot_0":12.5,"plot_1":10.2,"plot_2":2.3}}],"_ts":1710000500,"_stream":"values"}

Lines Stream

Emits horizontal price levels drawn by Pine Script indicators via line.new(). Levels are deduplicated and sorted high-to-low.

tv stream lines [-i 1000] [-f "Session Hunt"]

Output fields: symbol, study_count, studies[] (each with study name and levels array)

Default interval: 1000ms

Filter option: -f, --filter narrows to indicators whose name contains the given substring (case-insensitive).

Labels Stream

Emits text annotations drawn by Pine Script indicators via label.new(). Capped at 50 labels per study.

tv stream labels [-i 1000] [-f "Bias AI"]

Output fields: symbol, study_count, studies[] (each with study name and labels array of {text, price})

Default interval: 1000ms

Tables Stream

Emits structured table data drawn by Pine Script indicators via table.new().

tv stream tables [-i 2000] [-f "Profiler"]

Output fields: symbol, study_count, studies[] (each with study name and tables array of {rows})

Default interval: 2000ms

All Panes Stream

Emits data from all panes simultaneously in a multi-chart layout. Each pane reports its symbol, resolution, and latest bar data.

tv stream all [-i 500]

Output fields: layout, pane_count, panes[] (each with index, symbol, resolution, OHLCV fields)

Default interval: 500ms


JSONL Output Format

Each line is a self-contained JSON object. Lines are written to stdout with \n separators. This is compatible with standard JSONL/NDJSON tooling.

# Pretty-print each line
tv stream quote | jq .

# Extract just the close price
tv stream quote | jq -r '.close'

# Filter for a specific indicator
tv stream values | jq '.studies[] | select(.name | contains("RSI"))'

# Log to file
tv stream quote >> quote_log.jsonl

Startup Banner

When a stream starts, a compliance notice and status line are written to stderr (not stdout), so they do not interfere with JSONL parsing:

[stream:quote] started, interval=300ms, Ctrl+C to stop

When stopped:

[stream:quote] stopped after 45.2s

Use Cases

Price Monitoring

Continuously log price data for later analysis:

tv stream quote -i 1000 >> es_prices.jsonl

Indicator-Driven Automation

Watch for RSI crossing a threshold:

tv stream values | jq --unbuffered 'select(.studies[] | .name == "RSI" and .values.plot_0 > 70)' | head -1
echo "RSI overbought detected"

Multi-Symbol Dashboard

Monitor all panes in a split layout simultaneously:

tv stream all | jq -c '{(.panes[].symbol): .panes[].close}'

Level Change Detection

Track when Pine Script indicators update their drawn levels:

tv stream lines -f "ICT" -i 2000 | jq '.studies[].levels'

Data Logging for Backtesting

Record bars to build a local dataset:

tv stream bars -i 5000 >> bar_data.jsonl

Configuration

Option Flag Description
Poll interval -i, --interval Milliseconds between polls (stream-specific defaults shown above)
Study filter -f, --filter Filter by indicator name (lines, labels, tables streams only)

Lower intervals increase responsiveness but also increase CDP traffic. For most use cases, the defaults are well-tuned. Avoid intervals below 100ms as they may cause excessive CPU usage.