TradingView Advanced Charts Integration into Trading Platform
TradingView Advanced Charts (formerly Charting Library) is a professional charting library for embedding into trading platforms. It's the same chart as on TradingView.com itself, but licensed for use in your own products. Requires a paid license and implementation of a data feed on the exchange side.
License Types
| License | For Whom | Cost |
|---|---|---|
| Startup | Startups up to $1M ARR | Free |
| Standard | Commercial projects | $15,000/year |
| Enterprise | Large platforms | On request |
Startup license is real and accessible — just fill out a form on tradingview.com/charting-library. Condition: TradingView attribution on the chart.
UDF Data Feed Protocol
TradingView doesn't pull data itself — your platform must implement UDF (Unified Data Format) API:
Endpoints
from fastapi import FastAPI, Query
from datetime import datetime
app = FastAPI()
@app.get("/config")
def get_config():
"""Describes data feed capabilities"""
return {
"supported_resolutions": ["1", "5", "15", "30", "60", "240", "D", "W"],
"supports_group_request": False,
"supports_marks": False,
"supports_search": True,
"supports_timescale_marks": False,
"exchanges": [{"value": "", "name": "All", "desc": "All exchanges"}],
"symbols_types": [{"name": "crypto", "value": "crypto"}]
}
@app.get("/symbols")
async def get_symbol_info(symbol: str = Query(...)):
"""Information about specific symbol"""
return {
"name": symbol,
"ticker": symbol,
"description": f"{symbol} / USDT",
"type": "crypto",
"session": "24x7",
"exchange": "YourExchange",
"listed_exchange": "YourExchange",
"timezone": "Etc/UTC",
"pricescale": 100, # 2 decimal places
"minmov": 1,
"volume_precision": 8,
"has_intraday": True,
"has_daily": True,
"has_weekly_and_monthly": True,
"supported_resolutions": ["1", "5", "15", "30", "60", "240", "D"],
"currency_code": "USDT"
}
@app.get("/search")
async def search_symbols(query: str, limit: int = 30):
"""Symbol search"""
symbols = await db.search_trading_pairs(query, limit)
return [
{
"symbol": s.symbol,
"full_name": s.symbol,
"description": s.description,
"exchange": "YourExchange",
"type": "crypto"
}
for s in symbols
]
@app.get("/history")
async def get_history(
symbol: str,
resolution: str,
from_ts: int = Query(alias="from"),
to_ts: int = Query(alias="to"),
countback: int = None
):
"""OHLCV historical data — main endpoint"""
candles = await db.get_candles(
symbol=symbol,
resolution=resolution,
from_time=datetime.fromtimestamp(from_ts),
to_time=datetime.fromtimestamp(to_ts)
)
if not candles:
return {"s": "no_data"}
return {
"s": "ok",
"t": [int(c.time.timestamp()) for c in candles],
"o": [c.open for c in candles],
"h": [c.high for c in candles],
"l": [c.low for c in candles],
"c": [c.close for c in candles],
"v": [c.volume for c in candles]
}
WebSocket Streaming
For real-time updates to the last candle and new ticks:
// datafeed.js — implementation of TradingView Datafeed Interface
const Datafeed = {
subscribeBars(symbolInfo, resolution, onRealtimeCallback, subscriberUID) {
const ws = new WebSocket('wss://api.yourexchange.com/ws');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'candle_update' && data.symbol === symbolInfo.ticker) {
onRealtimeCallback({
time: data.time * 1000, // TradingView expects milliseconds
open: data.open,
high: data.high,
low: data.low,
close: data.close,
volume: data.volume
});
}
};
ws.onopen = () => {
ws.send(JSON.stringify({
action: 'subscribe',
channel: 'kline',
symbol: symbolInfo.ticker,
interval: resolution
}));
};
this._subscribers[subscriberUID] = ws;
},
unsubscribeBars(subscriberUID) {
const ws = this._subscribers[subscriberUID];
if (ws) {
ws.close();
delete this._subscribers[subscriberUID];
}
}
};
Widget Initialization
import { widget } from '@tradingview/charting-library';
const chart = new widget({
container: 'chartContainer',
library_path: '/charting_library/',
locale: 'en',
datafeed: Datafeed,
symbol: 'BTCUSDT',
interval: '60',
fullscreen: false,
autosize: true,
timezone: 'Etc/UTC',
// Theme customization
theme: 'dark',
overrides: {
'paneProperties.background': '#0f0f0f',
'paneProperties.backgroundType': 'solid',
'scalesProperties.textColor': '#aaaaaa',
},
// Enabled features
enabled_features: [
'side_toolbar_in_fullscreen_mode',
'header_screenshot',
'pre_post_market_sessions'
],
disabled_features: [
'use_localstorage_for_settings', // use custom storage
'header_symbol_search', // if no search
],
// Load/save user configuration
save_load_adapter: MySaveLoadAdapter
});
Resolution Mapping
TradingView uses non-standard resolution values. Mapping:
TV_RESOLUTION_MAP = {
'1': '1m',
'5': '5m',
'15': '15m',
'30': '30m',
'60': '1h',
'240': '4h',
'D': '1d',
'W': '1w',
'M': '1M'
}
The most common error during integration: timestamp format mismatch. TradingView history endpoint expects UNIX seconds, callback onRealtimeCallback expects milliseconds. Easy to mix up, hard to debug.







