A Python wrapper around TradingView’s Advanced Charting Library with a Pythonic datafeed, widget generator, and runtime shape‑API.
BrainChart — Python × TradingView Advanced Charts
BrainChart connects your Python data (Pandas/NumPy) to TradingView’s Advanced Charting Library. It provides:
- A minimal UDF-compatible FastAPI backend (
/config,/search,/symbols,/history,/time). - A Symbol model to register local OHLCV CSV + metadata.
- A ChartWidget generator that writes a self-contained
runtime/widget/index.htmlto open in a browser. - A runtime Shapes API (REST wrappers) to create/list/delete drawings on a specific symbol.
You keep full control in Python; the library handles the ACL plumbing.
Using TradingView’s Advanced Charting Library from Python usually means writing a custom datafeed, serving files, and glueing JS <> Python. This project streamlines that:
- Register symbols from a Pandas DataFrame.
- Serve data via a ready-made UDF backend.
- Generate a working widget page.
- Inject drawings programmatically.
Objective: fast iteration for research and prototyping without switching stacks.
# clone the repo
git clone https://github.com/MostafaRoohy/BrainChart.git
cd BrainChart
# create and activate the environment
conda env create -f env/environment.yml
conda activate brainchartpip install -r env/requirements.txtNote: The project is not yet packaged. Import from the repo root (so
import brainchartworks) or add the repo toPYTHONPATH.
-
Python: 3.12
-
Packages (see
env/requirements.txtorenv/environment.yml):fastapi,uvicorn,pandas,numpy,pydantic,requests,SQLAlchemy,ipython,ipykernel
Proposed workflow: use the provided Conda env/environment.yml to ensure deterministic environments across contributors.
Below are concise, working examples.
All exampled csv files exist in playground/candle_data/.
You can see all the examples in playground/example.ipynb.
import time
import pandas as pd
from brainchart import Symbol, ChartWidget, BrainChart
# 1) Prepare OHLCV DataFrame (timestamp in ms)
df_1 = pd.read_csv("./candle_data/CardGlass.csv")
# 2) Define the symbol with the DataFrame
symbol_1 = Symbol(tohlcv_df = df_1,
ticker = "CGSS",
name = "CardGlass",
description = "CardGlass is a symbol",
exchange = "DEx")
# 3) Create the widget with the default symbol
widget = ChartWidget(symbol=symbol_1)
# 3) Create the BrainChart
brain_chart = BrainChart(symbols_list=[symbol_1], chart_widget=widget)
brain_chart.imagine()
# 4) Open browser and navigate to the generated server: http://localhost:8000import pandas as pd
from brainchart import Symbol, ChartWidget, BrainChart
# 1) Prepare OHLCV DataFrame (timestamp in ms)
df_1 = pd.read_csv("./candle_data/CardGlass.csv")
df_2 = pd.read_csv("./candle_data/RageGuy.csv")
# 2) Define the symbol with the DataFrame
symbol_1 = Symbol(tohlcv_df = df_1,
ticker = "CGSS",
name = "CardGlass",
description = "CardGlass is a symbol",
exchange = "DEx")
symbol_2 = Symbol(tohlcv_df = df_2,
ticker = "RGG",
name = "Rage Guy",
description = "Rage Guy is another symbol",
exchange = "DEx")
# 3) Create the BrainChart
brain_chart = BrainChart(symbols_list=[symbol_1, symbol_2])
brain_chart.imagine()
# 4) Open browser and navigate to the generated server: http://localhost:8000Switch symbols from the widget’s native UI.
import pandas as pd
from brainchart import Symbol, ChartWidget, BrainChart
# 1) Prepare OHLCV DataFrame (timestamp in ms). The df has extra columns 'series_1', 'series_2', 'series_3'.
df_1 = pd.read_csv("./candle_data/CryBB.csv")
# 2) Define the symbol with the DataFrame, and pass the column names you want to see in the chart
symbol_1 = Symbol(tohlcv_df = df_1,
ticker = "CBB",
name = "CryBB",
description = "Babies Cry",
exchange = "DEx",
series_column = ['series_1', 'series_3'],
series_panel = ['overlay', 'pane'])
# 3) Create the BrainChart
brain_chart = BrainChart(symbols_list=[symbol_1])
brain_chart.imagine()
# 4) Open browser and navigate to the generated server: http://localhost:8000The custom series become selectable in the UI (overlay vs. an auxiliary pane).
import pandas as pd
from brainchart import Symbol, ChartWidget, BrainChart
# 1) Prepare OHLCV DataFrame (timestamp in ms)
df_1 = pd.read_csv("./candle_data/CardGlass.csv")
df_2 = pd.read_csv("./candle_data/RageGuy.csv")
# 2) Define the symbol with the DataFrame
symbol_1 = Symbol(tohlcv_df = df_1,
ticker = "CGSS",
name = "CardGlass",
description = "CardGlass is a symbol",
exchange = "DEx")
symbol_2 = Symbol(tohlcv_df = df_2,
ticker = "RGG",
name = "Rage Guy",
description = "Rage Guy is another symbol",
exchange = "DEx")
# 3) Create the BrainChart
brain_chart = BrainChart(symbols_list=[symbol_1, symbol_2])
brain_chart.imagine()
# 4) Open browser and navigate to the generated server: http://localhost:8000
# 5) Make shapes
from brainchart.shape import Shapes, ShapeType, ShapePoint, TrendlineOverrides
shaper_1 = Shapes(symbol_1)
shape = ShapeType.trend_line
points = [ShapePoint.priced(1757332740000, 0.282), ShapePoint.priced(1757331660000, 0.294)]
ovr = TrendlineOverrides(linecolor="#10b981", linewidth=5, show_angle=True)
shaper_1.create(shape, points, ovr)import pandas as pd
from brainchart import Symbol, ChartWidget, BrainChart
# 1) Prepare OHLCV DataFrame (timestamp in ms)
df_1 = pd.read_csv("./candle_data/CardGlass.csv")
df_2 = pd.read_csv("./candle_data/RageGuy.csv")
# 2) Define the symbol with the DataFrame
symbol_1 = Symbol(tohlcv_df = df_1,
ticker = "CGSS",
name = "CardGlass",
description = "CardGlass is a symbol",
exchange = "DEx")
symbol_2 = Symbol(tohlcv_df = df_2,
ticker = "RGG",
name = "Rage Guy",
description = "Rage Guy is another symbol",
exchange = "DEx")
# 3) Create the BrainChart
brain_chart = BrainChart(symbols_list=[symbol_1, symbol_2])
brain_chart.imagine()
# 4) Open browser and navigate to the generated server: http://localhost:8000
# 5) Make shapes
from brainchart.shape import Shapes, ShapeType, ShapePoint, TrendlineOverrides
shaper_1 = Shapes(symbol_1)
shape = ShapeType.trend_line
points = [ShapePoint.priced(1757332740000, 0.282), ShapePoint.priced(1757331660000, 0.294)]
ovr = TrendlineOverrides(linecolor="#10b981", linewidth=5, show_angle=True)
shaper_1.create(shape, points, ovr)
# 6) You can remove a specific shape, or just remove them all
shaper_1.all() # Lists all the shapes
# shaper_1.remove(shape_id=5)
# shaper_1.remove_all()I only onboard collaborators after a short discussion to align expectations.
Just ping me, and we will have a friendly chat and plan for the project.
If you rely on BrainChart in production or research, sponsoring helps prioritize maintenance and new features.
Or if you would like to support this project, you can donate using the following methods:
- GitHub Sponsors: MostafaRoohy
- Monero (XMR):
85VxJ4mu4K8eRx7nsM6AdAh9RCELooXsFfy5NfSWKSvjaHF8w9heKDAaLHT2L2bWGZPayb2uiKG7cNZHt3vWHL1e5GC5gJs - Bitcoin (BTC):
bc1qpzzdzds3mj93v3gp8y943yj4gcmasyhznf27ae - USDT (BEP20):
0xb7A2695c5277d632660a8Bd93c6a0edCeBE283B7 - Solana (SOL):
B5anfZmQjBNUhR2kYJMQMfxEVQ7b5NAy1kGL9eoKeKw1 - Ton (TON):
UQD9wEyrAxrTcpFRi9xQwb1U0gDjnXjbW8xu9veBIWfR2njS - Ethereum (ETH):
0xb7A2695c5277d632660a8Bd93c6a0edCeBE283B7 - Litecoin (LTC):
ltc1qx4dz04x3ptt6mxc0q9fg3vjqt2kyvkzrcwqq4d
Thank you for your support!
- UDF‑compatible FastAPI backend:
/config,/search,/symbols,/history,/time. - Register local symbols from a Pandas DataFrame; auto‑writes
runtime/datafeed/<TICKER>.csvandregistry.json. - Widget generator writes
runtime/widget/index.htmlpointing to your local datafeed. - Shapes runtime API with typed points and per‑tool overrides.
- Multi‑series support per symbol (overlay or separate pane) via
series_column,series_color,series_panel. - Self‑contained; TradingView’s library is vendored under
charting_library/.
My roadmap for developing this project is as follows.
1️⃣ Version 1 RoadMap (Current)
-
✅ Chart Widget
- ☑️ The Main Chart Widget
-
✅ Symbol
- ☑️ Symbol Modeling
-
✔️ Symbol Model
-
✔️ SymbolExt
-
- ☑️ Symbol Modeling
-
✅ Offline Static TOHLCV Data for Symbol
- ☑️ Symbol DataFeed
-
✅ Shaping Functionalities
-
☑️ Base
-
✔️ Drawing
-
✔️ Drawings API
-
-
☑️ Advanced
-
✖️ (postponed) createexecutionshape()
-
✖️ (postponed) IExecutionLineAdapter
-
✖️ (postponed) createanchoredshape()
-
✖️ (postponed) CreateAnchoredShapeOptions
-
-
✅ Project ReDesign & BackEnd/FrontEnd Overview
- ✔️ COMPLETE ReView & ReWire
-
✅ Custom TimeSeries Data
-
☑️ Foundamentals
- ✖️ (postponed) Built-In Indicators
- ✖️ (postponed) Custom Study
-
☑️ MetaInfo
- ✖️ (postponed) MetaInfo
- ✖️ (postponed) Custom Study Inputs
- ✖️ (postponed) Custom Study Defaults
-
☑️ Custom Indicator
- ✖️ (postponed) Custom Indicator Constructor
- ✖️ (postponed) PineJS
- ✔️ Custom Study Plots
- ✔️ Custom Study OHLC Plots
-
☑️ Other
- ✖️ (postponed) Examples
- ✖️ (postponed) Extending The Time Scale
-
2️⃣ Version 2 RoadMap
-
⬜️ Advanced Chart Widget
-
⬜️ Datafeed Re-Architecture
-
⬜️ Project ReDesign & BackEnd/FrontEnd Overview (again)
- ⚪️ COMPLETE ReView & ReWire
-
⬜️ Online DataFeed Streaming
3️⃣ Version 3 RoadMap
-
⬜️ Custom Indicator/Study
-
⚪️ Foundamentals
-
⚪️ MetaInfo
-
⚪️ Custom Indicator
-
⚪️ Other
-
-
⬜️ Advanced Shaping Functionalities
MIT — see LICENSE.
-
How should my df be?
Your df must include
timestamp,open,high,low,close,volumecolumns. And thetimestampcolumn must be in milliseconds (I will flex it later). -
Does shapes API accept ms or s?
Both. Timestamps are normalized; ms are auto‑converted to seconds for drawings.
-
Where are runtime artifacts?
Under
runtime/database/andruntime/datafeed/andruntime/widget/.