Production-quality financial chart generator — candlestick, line, area, OHLC, Heikin-Ashi, performance heatmaps, and sector group charts.
Project description
TradeChart — Library Edition v2.1.0
Python → Financial Charts
Generate production-quality candlestick, line, area, OHLC, Heikin-Ashi, and performance heatmap charts from code.
Automatic multi-provider data fetching · 7 technical indicators · 3 themes · PNG/SVG/PDF output · 14 built-in sector groups.
Installation
pip install TradeChart
Optional Extras
| Extra | Installs | Benefit |
|---|---|---|
TradeChart[tradingview] |
tvDatafeed |
TradingView as a fallback data provider |
TradeChart[mplfinance] |
mplfinance |
Higher-quality candlestick rendering |
TradeChart[xlsx] |
openpyxl |
Excel .xlsx export support |
TradeChart[all] |
All of the above | Everything |
pip install TradeChart[all]
Quick Start
import tradechart as tc
tc.chart("AAPL", "1mo", "candle", indicators=["sma", "bollinger"])
Ticker Groups — Averaged Series
tc.chart(), tc.data(), and tc.export() accept a list or tuple of ticker symbols in addition to a single string. When a group is supplied the library:
- Fetches each ticker independently (using the normal provider fallback chain).
- Aligns all series to their overlapping trading dates.
- Computes the column-wise mean of Open, High, Low, Close, and Volume across all tickers.
- Renders or returns that single averaged series, labelled
AVG(AAPL,MSFT,AMZN).
import tradechart as tc
tech = ["AAPL", "MSFT", "AMZN"]
# Chart the average of the three — produces a single line/candle series
tc.chart(tech, "3mo", "line")
# Fetch the averaged DataFrame for custom analysis
df = tc.data(tech, "6mo")
# Export the averaged data to CSV
tc.export(tech, "1y", fmt="csv", output_location="./exports")
Collision note — variable names vs ticker symbols
There is no ambiguity between a variable named after a real ticker (e.g. DNUT) and the ticker string "DNUT". Python's type system handles this automatically:
# This passes the string "DNUT" → Krispy Kreme ticker
tc.chart("DNUT", "1mo")
# This passes the list held by the variable DNUT → averaged group
DNUT = ["AAPL", "MSFT"]
tc.chart(DNUT, "1mo") # library sees a list, not the name "DNUT"
The library inspects isinstance(ticker, (list, tuple)) — it never looks at variable names. Any list or tuple is a group; any string is a single ticker.
Behaviour on partial failure
If one or more tickers in the group fail to fetch data, they are skipped with a warning and the remaining tickers are averaged. If all tickers fail, or if the surviving tickers share no common trading dates, a DataFetchError is raised with a clear explanation.
API Overview
| Function | Description |
|---|---|
tc.terminal(mode) |
Set console logging verbosity |
tc.theme(name) |
Set chart colour theme |
tc.watermark(enabled) |
Toggle the TRADELY logo watermark |
tc.config(**kwargs) |
Batch-set multiple global options at once |
tc.chart(...) |
Fetch data and render a chart image |
tc.compare(...) |
Overlay multiple tickers on one chart |
tc.heatmap(...) |
Render a performance heatmap for a ticker group |
tc.data(...) |
Fetch raw OHLCV data as a DataFrame |
tc.export(...) |
Export market data to CSV / JSON / XLSX |
tc.clear_cache() |
Flush the in-memory data cache |
tc.SECTOR_GROUPS |
Dict of 14 pre-defined ticker lists (sectors, indices, crypto, …) |
tc.chart() — Render a Chart
Fetches market data and saves a chart image to disk. Returns the pathlib.Path of the saved file.
path = tc.chart(
"AAPL",
duration="3mo",
chart_type="candle",
indicators=["sma", "ema", "rsi", "macd"],
show_volume=True,
fmt="png",
output_location="./charts",
output_name="apple_q1.png",
)
print(f"Saved → {path}")
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ticker |
str | list[str] | tuple[str, ...] |
Yes | — | Instrument symbol such as "AAPL", "BTC-USD", "EURUSD=X", "^GSPC" — or a list/tuple of symbols to average (see Ticker Groups). |
duration |
str |
No | "1mo" |
Time span of the chart. See Durations. |
chart_type |
str |
No | "candle" |
Chart style. One of: "candle", "line", "ohlc", "area", "heikin_ashi". |
output_location |
str | None |
No | Current working directory | Directory to save the file. Created automatically if it does not exist. |
output_name |
str | None |
No | {TICKER}_{duration}_{type}.{fmt} |
Custom filename. Extension is added automatically if omitted. |
fmt |
str |
No | "png" |
Output format. One of: "png", "jpg", "svg", "pdf", "webp". |
indicators |
list[str] | None |
No | None |
Technical indicators to overlay or add as sub-panels. See Indicators. |
show_volume |
bool |
No | True |
Whether to show a volume sub-panel beneath the price chart. Has no effect on "line" and "area" chart types. |
Chart Types
| Value | Description |
|---|---|
"candle" |
Candlestick chart with open/high/low/close bodies and wicks |
"heikin_ashi" |
Heikin-Ashi smoothed candles (OHLC converted before rendering; source data unchanged) |
"ohlc" |
OHLC bar chart — vertical high/low line with left (open) and right (close) ticks |
"line" |
Close price line chart |
"area" |
Close price line chart with shaded fill beneath the curve |
tc.compare() — Multi-Ticker Overlay
Plots multiple tickers on a single chart for performance comparison. Returns the pathlib.Path of the saved file.
path = tc.compare(
["AAPL", "MSFT", "GOOG", "AMZN"],
duration="6mo",
normalise=True,
fmt="png",
output_location="./charts",
output_name="big_tech_6mo.png",
)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
tickers |
list[str] |
Yes | — | 2–8 ticker symbols to overlay on the same chart. Each is fetched independently using the provider fallback chain. |
duration |
str |
No | "1mo" |
Shared time span applied to every ticker. See Durations. |
normalise |
bool |
No | True |
True — plot percentage change from the first bar of the period (recommended when tickers have different price scales). False — plot raw closing prices. |
output_location |
str | None |
No | Current working directory | Output directory. Created if missing. |
output_name |
str | None |
No | compare_{tickers}_{duration}.{fmt} |
Custom filename. |
fmt |
str |
No | "png" |
Output format: "png", "jpg", "svg", "pdf", "webp". |
tc.heatmap() — Performance Heatmap
Renders a market-cap weighted treemap — one tile per ticker — where tile size is proportional to market capitalisation and tile colour encodes percentage change over the requested duration. Red = loss, green = gain. Designed for sector snapshots and portfolio overviews, matching the style of professional tools like Finviz and Bloomberg.
import tradechart as tc
# Magnificent 7 over the last month
tc.heatmap(tc.SECTOR_GROUPS["mag7"], "1mo")
# All S&P 500 sector ETFs over 3 months
tc.heatmap(tc.SECTOR_GROUPS["sp500_etfs"], "3mo")
# Custom list
tc.heatmap(["AAPL", "MSFT", "NVDA", "GOOGL", "META"], "6mo", fmt="png")
Each tile shows:
- Ticker symbol (bold)
- ± % change over the duration
- Last closing price
Tile sizes use a squarified treemap algorithm to minimise wasted space while keeping aspect ratios close to square. Market-cap data is fetched automatically via yfinance. When market-cap data is unavailable (indices, futures, commodities), the renderer falls back to an equal-area grid automatically. The colour scale is symmetrically ranged to the largest move in the group. A colourbar legend is included.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
tickers |
list[str] |
Yes | — | 2 or more ticker symbols. Use tc.SECTOR_GROUPS["key"] or any custom list. |
duration |
str |
No | "1mo" |
Time span applied to every ticker. See Durations. |
output_location |
str | None |
No | Current working directory | Output directory. Created if missing. |
output_name |
str | None |
No | heatmap_{group}_{duration}.{fmt} |
Custom filename. |
fmt |
str |
No | "png" |
Output format: "png", "jpg", "svg", "pdf", "webp". |
Returns: pathlib.Path of the saved heatmap image.
tc.SECTOR_GROUPS — Pre-defined Ticker Lists
A dictionary of curated ticker groups ready to pass into tc.heatmap(), tc.compare(), tc.chart(), or tc.export().
import tradechart as tc
print(list(tc.SECTOR_GROUPS.keys()))
# ['mag7', 'sp500_etfs', 'tech', 'finance', 'energy', 'healthcare',
# 'consumer_disc', 'consumer_stap', 'industrials', 'realestate',
# 'utilities', 'crypto', 'indices', 'commodities']
# Use as a heatmap input
tc.heatmap(tc.SECTOR_GROUPS["crypto"], "1mo")
# Use as a compare input (max 8 tickers)
tc.compare(tc.SECTOR_GROUPS["sp500_etfs"][:8], "3mo")
# Use as an averaged chart input
tc.chart(tc.SECTOR_GROUPS["mag7"], "6mo", "line")
| Key | Tickers |
|---|---|
"mag7" |
AAPL, MSFT, NVDA, AMZN, GOOGL, META, TSLA |
"sp500_etfs" |
XLK, XLF, XLE, XLV, XLY, XLI, XLB, XLU, XLRE, XLC, XLP |
"tech" |
AAPL, MSFT, NVDA, AMD, INTC, ORCL, CRM, ADBE, QCOM, TXN |
"finance" |
JPM, BAC, GS, MS, WFC, C, BLK, AXP, V, MA |
"energy" |
XOM, CVX, COP, EOG, MPC, VLO, PSX, OXY, HES, SLB |
"healthcare" |
JNJ, LLY, UNH, ABBV, MRK, ABT, TMO, PFE, DHR, BMY |
"consumer_disc" |
AMZN, TSLA, HD, MCD, NKE, SBUX, LOW, TGT, BKNG, GM |
"consumer_stap" |
WMT, PG, KO, PEP, COST, PM, MO, CL, GIS, KHC |
"industrials" |
CAT, HON, UPS, BA, GE, MMM, RTX, LMT, DE, EMR |
"realestate" |
AMT, PLD, EQIX, SPG, CCI, PSA, DLR, O, WELL, AVB |
"utilities" |
NEE, DUK, SO, D, AEP, EXC, SRE, PCG, ED, ETR |
"crypto" |
BTC-USD, ETH-USD, BNB-USD, SOL-USD, ADA-USD, XRP-USD, DOGE-USD, AVAX-USD |
"indices" |
^GSPC, ^DJI, ^IXIC, ^RUT, ^FTSE, ^N225, ^HSI, ^GDAXI |
"commodities" |
GC=F, SI=F, CL=F, NG=F, HG=F, ZC=F, ZS=F, PL=F |
tc.data() — Fetch Raw OHLCV Data
Fetches market data and returns it as a pandas.DataFrame without rendering any chart. Useful for further analysis or custom plotting.
df = tc.data("TSLA", "3mo")
print(df.head())
# Open High Low Close Volume
# Date
# 2024-01-02 248.5 251.3 245.0 249.8 120000000
# ...
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ticker |
str | list[str] | tuple[str, ...] |
Yes | — | Instrument symbol or a group to average (see Ticker Groups). |
duration |
str |
No | "1mo" |
Time span. See Durations. |
Returns: pandas.DataFrame with a DatetimeIndex and columns Open, High, Low, Close, Volume.
Data is cleaned (NaN rows dropped, Volume NaN → 0) and downsampled to a maximum of 2,000 rows.
tc.export() — Export Data to File
Fetches market data and writes it to a file. Returns the pathlib.Path of the saved file.
# CSV
path = tc.export("AAPL", "1y", fmt="csv", output_location="./exports")
# JSON
path = tc.export("MSFT", "6mo", fmt="json", output_name="msft_6mo.json")
# Excel
path = tc.export("BTC-USD", "3mo", fmt="xlsx") # requires TradeChart[xlsx]
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
ticker |
str | list[str] | tuple[str, ...] |
Yes | — | Instrument symbol or a group to average (see Ticker Groups). |
duration |
str |
No | "1mo" |
Time span. See Durations. |
fmt |
str |
No | "csv" |
Export format: "csv", "json", or "xlsx". Excel export requires pip install TradeChart[xlsx]. |
output_location |
str | None |
No | Current working directory | Output directory. Created if missing. |
output_name |
str | None |
No | {TICKER}_{duration}.{fmt} |
Custom filename. |
tc.config() — Batch Settings
Set multiple global options in a single call. Returns a dict snapshot of all current settings.
tc.config(
terminal="full",
theme="light",
dpi=200,
overwrite=True,
fig_size=(16, 9),
cache_ttl=600,
watermark=False,
)
| Key | Type | Default | Valid values / range | Description |
|---|---|---|---|---|
terminal |
str |
"on_done" |
"full", "on_done", "none" |
Console logging verbosity. See Terminal Modes. |
theme |
str |
"dark" |
"dark", "light", "classic" |
Chart colour theme. See Themes. |
watermark |
bool |
True |
True, False |
Show or hide the TRADELY logo in the bottom-left corner of charts. |
overwrite |
bool |
False |
True, False |
False — append _1, _2, … to the filename if it already exists. True — overwrite the existing file silently. |
dpi |
int |
150 |
50–600 |
Output resolution in dots per inch. Higher values produce larger, sharper files. |
fig_size |
tuple[int, int] |
(14, 7) |
Any valid (width, height) in inches |
Matplotlib figure size. Increase for wide monitors or presentations. |
cache_ttl |
int |
300 |
Any positive integer (seconds) | How long fetched data is kept in memory. 0 effectively disables caching. |
tc.terminal() — Logging Verbosity
tc.terminal("full") # Show every step
tc.terminal("on_done") # Show summary after completion (default)
tc.terminal("none") # Complete silence — no output at all
Terminal Modes
| Mode | What prints | Best for |
|---|---|---|
"full" |
Every internal step, provider attempts, row counts, file paths | Debugging and development |
"on_done" |
One-line summary after each operation completes | Normal interactive use |
"none" |
Nothing — completely silent | Production scripts, CI pipelines, bots |
tc.theme() — Chart Colour Theme
tc.theme("dark") # Default
tc.theme("light")
tc.theme("classic")
Themes
| Name | Background | Candle colours | Spine |
|---|---|---|---|
"dark" |
#1e1e2f (dark navy) |
Green #26a69a / Red #ef5350 |
Hidden |
"light" |
#ffffff (white) |
Green #26a69a / Red #ef5350 |
Hidden |
"classic" |
#f5f5dc (parchment) |
Dark green #2e7d32 / Dark red #c62828 |
Visible |
tc.watermark() — Logo Watermark
tc.watermark(True) # Enable (default)
tc.watermark(False) # Disable
The TRADELY logo is stamped in the bottom-left corner of every chart by default. The logo is downloaded once from the CDN and cached locally at ~/.tradechart/cache/tradely_logo.png for all subsequent renders.
tc.clear_cache() — Flush Data Cache
tc.clear_cache()
Clears all in-memory cached market data, forcing the next fetch to go to the network. Useful after a TTL has not yet expired but you need fresh data (e.g. during live market hours).
Durations
| Value | Period | Bar Resolution |
|---|---|---|
"1d" |
1 day | 5-minute bars |
"5d" |
5 days | 15-minute bars |
"1mo" |
1 month | Daily bars |
"3mo" |
3 months | Daily bars |
"6mo" |
6 months | Daily bars |
"1y" |
1 year | Weekly bars |
"2y" |
2 years | Weekly bars |
"5y" |
5 years | Weekly bars |
"10y" |
10 years | Monthly bars |
"max" |
All available history | Monthly bars |
Indicators
Pass any combination as a list to tc.chart(indicators=[...]).
| Name | Panel | Default Parameters | Description |
|---|---|---|---|
"sma" |
Price overlay | Period 20 | Simple Moving Average of the close price |
"ema" |
Price overlay | Period 20 | Exponential Moving Average of the close price |
"bollinger" |
Price overlay | Period 20, 2σ | Bollinger Bands — upper, middle (SMA), and lower band plotted as dashed lines with a shaded band |
"vwap" |
Price overlay | — | Volume-Weighted Average Price — cumulative from the first bar of the dataset |
"rsi" |
Sub-panel (0–100) | Period 14 | Relative Strength Index with overbought (70) and oversold (30) reference lines |
"macd" |
Sub-panel | Fast 12, Slow 26, Signal 9 | MACD line, signal line, and histogram |
"volume" |
Sub-panel | — | Volume bars coloured by bar direction. Equivalent to show_volume=True when used as an indicator. |
Example — multiple indicators:
tc.chart(
"NVDA",
duration="6mo",
chart_type="candle",
indicators=["ema", "bollinger", "rsi", "macd"],
show_volume=True,
)
Data Providers
TradeChart tries providers in priority order and falls back automatically on failure or empty data.
| Priority | Provider | Requires | Notes |
|---|---|---|---|
| 1 | yfinance | Included by default | Primary source. Covers stocks, ETFs, indices, crypto, forex. |
| 2 | TradingView | pip install TradeChart[tradingview] |
Tried if yfinance returns empty or fails. Attempts multiple exchanges automatically (NASDAQ, NYSE, AMEX, CRYPTO, FX). |
| 3 | Stooq | Nothing — free CSV endpoint | Final fallback. No API key required. Duration mapped to a rolling date range. |
If all three providers fail, a DataFetchError is raised with a list of each provider's error message.
Notes
Caching
Fetched data is cached in-memory for cache_ttl seconds (default 300 s / 5 minutes). All subsequent calls with the same ticker and duration within that window are served from cache. Call tc.clear_cache() to force a re-fetch, or set tc.config(cache_ttl=0) to disable caching entirely.
File collision handling
By default (overwrite=False), TradeChart appends a counter to avoid overwriting existing files: chart.png → chart_1.png → chart_2.png. Set tc.config(overwrite=True) to overwrite silently.
Watermark
The logo PNG is downloaded once from the TRADELY CDN and stored at ~/.tradechart/cache/tradely_logo.png. Subsequent renders use the local file. Disable with tc.watermark(False) or tc.config(watermark=False).
Thread safety
The global settings singleton and engine initialisation are protected by locks. tc.chart() can be called concurrently from multiple threads (e.g. a Discord bot handling simultaneous requests).
Heikin-Ashi
The "heikin_ashi" chart type converts standard OHLC data to Heikin-Ashi candles during rendering only. The cached source data and any DataFrame returned by tc.data() are never modified.
mplfinance
When mplfinance is installed (pip install TradeChart[mplfinance]), candlestick and Heikin-Ashi charts use it for higher-quality rendering. Otherwise a pure-matplotlib fallback is used automatically — no configuration required.
Output resolution
Default DPI is 150, producing a ~2100 × 1050 px image at the default figure size. Increase with tc.config(dpi=300) for print-quality output.
Error Handling
All TradeChart exceptions inherit from TradeChartError.
| Exception | Raised when |
|---|---|
DataFetchError |
All configured providers fail to return data for the requested ticker/duration |
InvalidTickerError |
The ticker string fails validation (too long, invalid characters) |
RenderError |
Chart rendering fails (e.g. empty dataset after cleaning) |
OutputError |
The chart cannot be saved (e.g. permission denied) |
ConfigError |
An unknown key is passed to tc.config() |
import tradechart as tc
from tradechart import DataFetchError, RenderError
try:
tc.chart("INVALID!!!", "1mo")
except DataFetchError as e:
print(f"Data error: {e}")
except RenderError as e:
print(f"Render error: {e}")
Example Charts
Further Details
- Documentation: doc.tradely.dev
- PyPI: pypi.org/project/TradeChart
- Source: github.com/techareaone/TradeChart
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tradechart-2.1.0.tar.gz.
File metadata
- Download URL: tradechart-2.1.0.tar.gz
- Upload date:
- Size: 47.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7b4e2b5dc5c15359a7d4d45fbabb558ea7b7257581657744216367baab1b592
|
|
| MD5 |
9fcb89af1f724f1b4487902f32735556
|
|
| BLAKE2b-256 |
ec1a8bb29051dd2a022913390cad97d4039e1dfb7dee168281762144d3074096
|
Provenance
The following attestation bundles were made for tradechart-2.1.0.tar.gz:
Publisher:
publish.yml on techareaone/TradeChart
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tradechart-2.1.0.tar.gz -
Subject digest:
a7b4e2b5dc5c15359a7d4d45fbabb558ea7b7257581657744216367baab1b592 - Sigstore transparency entry: 1247157828
- Sigstore integration time:
-
Permalink:
techareaone/TradeChart@313068fc5d3cb401ac4cb95bbbc3198e7859c91b -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/techareaone
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@313068fc5d3cb401ac4cb95bbbc3198e7859c91b -
Trigger Event:
push
-
Statement type:
File details
Details for the file tradechart-2.1.0-py3-none-any.whl.
File metadata
- Download URL: tradechart-2.1.0-py3-none-any.whl
- Upload date:
- Size: 55.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2fe30714ccac2e2a4293af39c4310fdfcdfdc479df2a133969bb618d9acf429f
|
|
| MD5 |
2217c3ee8ca196d645bc5eaa92513225
|
|
| BLAKE2b-256 |
9385bc164494b12759aaefe68afc0045e466ce67b61fdf6e589a00311ec27b46
|
Provenance
The following attestation bundles were made for tradechart-2.1.0-py3-none-any.whl:
Publisher:
publish.yml on techareaone/TradeChart
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tradechart-2.1.0-py3-none-any.whl -
Subject digest:
2fe30714ccac2e2a4293af39c4310fdfcdfdc479df2a133969bb618d9acf429f - Sigstore transparency entry: 1247157833
- Sigstore integration time:
-
Permalink:
techareaone/TradeChart@313068fc5d3cb401ac4cb95bbbc3198e7859c91b -
Branch / Tag:
refs/tags/v2.1.0 - Owner: https://github.com/techareaone
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@313068fc5d3cb401ac4cb95bbbc3198e7859c91b -
Trigger Event:
push
-
Statement type: