Docs
Open Studio

API reference

finlab.plot

On this page7

finlab.plot draws candlestick, radar, treemap, river and strategy charts with plotly. Every plotting function returns a plotly.graph_objects.Figure: call .show() to display it, or use plotly methods to customize it. plot_candles() draws from any price series, so it works for US stocks, and plot_tw_stock_radar() compares any FinLab dataset across a portfolio. The other plot_tw_stock_* helpers read Taiwan datasets and are for the Taiwan market only.

Which function to use

You want toUse
Draw a candlestick chart with indicators from your own price seriesplot_candles()
Draw a candlestick chart for a Taiwan stockplot_tw_stock_candles() (Taiwan only)
Compare several stocks' financial metricsplot_tw_stock_radar()
Compare your cloud strategies' returns with a benchmarkStrategyReturnStats
See how your cloud strategies' holdings are spreadStrategySunburst (Taiwan only)
Show the whole market by industry, sized and colored by two metricsplot_tw_stock_treemap() (Taiwan only)
Add your own metric to that treemapcreate_treemap_data() (Taiwan only)
See where a stock's P/E or P/B sits in its rangeplot_tw_stock_river() (Taiwan only)

All of these need the plotly package (pip install plotly).

Draw candlestick charts

plot_candles()

Draws a candlestick chart with volume, overlay lines on the price panel and technical-indicator subplots, from price series you supply. Use it for US stocks or any custom data.

from finlab import data
from finlab.plot import plot_candles

data.set_market('us')
symbol = 'AAPL'

# Draw an Apple candlestick chart with the default Bollinger Bands and KD indicator
plot_candles(
    symbol,
    close=data.get('price:close')[symbol],
    open_=data.get('price:open')[symbol],
    high=data.get('price:high')[symbol],
    low=data.get('price:low')[symbol],
    volume=data.get('price:volume')[symbol],
    recent_days=200,
).show()
ParameterTypeDefaultDescription
symbolstrrequiredSymbol shown in the title; also used to pick the symbol's column when an indicator returns a DataFrame. stock_id is accepted as an alias.
close, open_, high, low, volumepd.SeriesrequiredDate-indexed price and volume series of one symbol.
recent_daysint250Number of most recent rows to plot.
resamplestr'D'Candle period: 'D' daily, 'W' weekly, 'M' monthly.
overlay_funcdict or list[dict]NoneLines drawn on the price panel, {name: indicator}. None uses Bollinger Bands from data.indicator('BBANDS').
technical_funcdict or list[dict]NoneIndicator subplots; each dict is one subplot. None uses the KD indicator from data.indicator('STOCH').

Returns a plotly.graph_objects.Figure.

An indicator can be a DataFrame (from data.indicator()), a Series, a NumPy array, a callable that receives the OHLCV DataFrame, or a TA-Lib function name such as 'RSI(timeperiod=14)'; TA-Lib function names require the ta-lib package.

To choose your own overlay lines and subplots:

from finlab import data
from finlab.data import indicator
from finlab.plot import plot_candles

data.set_market('us')
symbol = 'MSFT'
prices = {
    'close': data.get('price:close')[symbol],
    'open_': data.get('price:open')[symbol],
    'high': data.get('price:high')[symbol],
    'low': data.get('price:low')[symbol],
    'volume': data.get('price:volume')[symbol],
}

overlay_func = {
    'ema_20': indicator('EMA', timeperiod=20),
    'ema_60': indicator('EMA', timeperiod=60),
}
k, d = indicator('STOCH')
rsi = indicator('RSI')
technical_func = [{'K': k, 'D': d}, {'RSI': rsi}]

plot_candles(
    symbol,
    **prices,
    recent_days=300,
    overlay_func=overlay_func,
    technical_func=technical_func,
).show()

data.indicator() uses unadjusted prices by default, so pass the unadjusted price:close/open/high/low series to keep the overlay lines aligned with the candles.

plot_tw_stock_candles()

Draws a candlestick chart for a Taiwan stock: it loads the stock's prices and volume, then calls plot_candles(). It reads Taiwan price datasets, so for US stocks use plot_candles() with US price series.

from finlab.plot import plot_tw_stock_candles

plot_tw_stock_candles('2330', recent_days=200).show()
ParameterTypeDefaultDescription
symbolstrrequiredTaiwan stock code. stock_id is accepted as an alias.
recent_daysint400Number of most recent trading days to plot.
adjust_priceboolFalseUse adjusted prices.
resamplestr'D'Candle period: 'D' daily, 'W' weekly, 'M' monthly.
overlay_funcdict or list[dict]NoneLines on the price panel. None uses Bollinger Bands.
technical_funcdict or list[dict]NoneIndicator subplots. None uses one KD subplot.

Returns a plotly.graph_objects.Figure, the candlestick chart.

Compare financial metrics

plot_tw_stock_radar()

Compares the rank levels of several metrics across a portfolio: each metric is ranked across all symbols at the chosen row and cut into cut_bins levels; missing values show no level.

from finlab import data
from finlab.plot import plot_tw_stock_radar

data.set_market('us')

# Example 1: Compare profitability and leverage of four large caps
plot_tw_stock_radar(
    portfolio=['AAPL', 'MSFT', 'NVDA', 'AMZN'],
    feats=[
        'us_ratios:gross_profit_margin',
        'us_ratios:operating_profit_margin',
        'us_ratios:net_profit_margin',
        'us_ratios:debt_to_assets_ratio',
    ],
    mode='bar_polar',  # Bar polar chart
).show()

# Example 2: Show where one stock ranks on each metric
plot_tw_stock_radar(
    portfolio=['NVDA'],
    feats=[
        'us_ratios:gross_profit_margin',
        'us_ratios:operating_profit_margin',
        'us_ratios:net_profit_margin',
        'us_ratios:current_ratio',
        'us_ratios:debt_to_assets_ratio',
    ],
    mode='line_polar',  # Line polar chart
    line_polar_fill='toself',
    cut_bins=8,  # Split metric values into 8 levels
).show()

us_ratios:* keys hold recent daily snapshots, which suits this latest-value comparison.

ParameterTypeDefaultDescription
portfoliolist[str]requiredSymbols to compare, e.g. ['AAPL', 'MSFT'].
featslist[str]NoneFinLab dataset keys to compare. None uses 18 Taiwan financial metrics, so pass feats for other markets. Axis names are the part of each key after :.
modestr'line_polar''line_polar', 'bar_polar' or 'scatter_polar' (see plotly express).
line_polar_fillstrNoneFill for 'line_polar': None, 'toself' (close each trace into a shape) or 'tonext' (fill between consecutive traces).
periodstrNoneRow label of the datasets to compare. None uses the latest row.
cut_binsint10Number of rank levels.
titlestrNoneChart title.
custom_datapd.DataFrameNoneYour own rank levels: index of symbols, one column per metric. Replaces feats.

Returns a plotly.graph_objects.Figure, or None (with an error log) when none of the symbols has data.

Which mode to pick:

  • 'bar_polar': bar polar chart, recommended for comparing 2 to 5 stocks.
  • 'line_polar': line polar chart, suited to one stock across many metrics.
  • 'scatter_polar': scatter polar chart, suited to viewing the raw data points.

Monitor your cloud strategies

Both classes read the strategies you uploaded to FinLab cloud, so sign in with finlab.login() first.

StrategyReturnStats()

Compares the returns of your uploaded strategies with a benchmark over a period.

from finlab import data
from finlab.plot import StrategyReturnStats

sp500 = data.get('world_index:adj_close')['^GSPC']

stats = StrategyReturnStats('2025-01-01', '2025-12-31', benchmark_return=sp500)
stats.plot_strategy_last_return().show()
stats.plot_strategy_creturn().show()
ParameterTypeDefaultDescription
start_datestrrequiredStart date of the return calculation.
end_datestrrequiredEnd date of the return calculation.
strategy_nameslist[str]NoneNames of your own strategies to include. None includes all uploaded strategies.
benchmark_returnpd.SeriesNoneBenchmark price series. None uses the Taiwan weighted return index, so pass one for US strategies.

stats.get_benchmark_return()

Returns the benchmark series between start_date and end_date, as a pd.Series.

stats.get_benchmark_return()

stats.plot_strategy_last_return()

Draws a horizontal bar chart of each strategy's return over the period, with the benchmark and the strategy mean marked.

stats.plot_strategy_last_return().show()

stats.plot_strategy_creturn()

Draws the cumulative return of each strategy over the period, with the benchmark.

stats.plot_strategy_creturn().show()

StrategySunburst()

Taiwan market only: draws a sunburst chart of the holdings of your strategies uploaded to FinLab cloud, for monitoring several strategies at once. Holdings are grouped by Taiwan industry and labeled for the Taiwan site; holdings in other markets all fall under other_securities, so it is not useful for US strategies.

from finlab.plot import StrategySunburst

strategies = StrategySunburst()
strategies.plot().show()

It takes no parameters.

strategies.get_strategy_df()

Returns the combined holdings after applying strategy weights.

strategies.get_strategy_df({'US Momentum': 0.6, 'Quality Value': 0.4})
ParameterTypeDefaultDescription
select_strategydictNoneStrategy names and their capital weights, e.g. {'US Momentum': 0.6, 'Quality Value': 0.4}. None takes all strategies, equally weighted.

Returns a pd.DataFrame of holdings, or None when you have no strategies.

strategies.plot()

Draws the holdings sunburst.

# Show which strategies hold each position
strategies.plot(path=['market', 'category', 'stock_id', 's_name']).show()
ParameterTypeDefaultDescription
select_strategydictNoneStrategy names and weights, as in get_strategy_df().
pathlist[str]NoneRings from inside to outside. None uses ['s_name', 'market', 'category', 'stock_id']; ['market', 'category', 'stock_id', 's_name'] shows which strategies hold each position.
color_continuous_scalestr'RdBu_r'Name of a plotly color scale.

Returns a plotly.graph_objects.Figure, the holdings sunburst.

Taiwan market charts

These helpers read Taiwan company and valuation data, so they work for the Taiwan market only.

plot_tw_stock_treemap()

Draws a nested treemap of Taiwan stocks grouped by market and industry; block area and color show two metrics at once.

from finlab.plot import plot_tw_stock_treemap

# Block area: trading value; color: return over the period
plot_tw_stock_treemap(
    start='2024-01-02',
    end='2024-01-31',
    area_ind='turnover',
    item='return_ratio',
).show()
ParameterTypeDefaultDescription
start, endstrNoneDate range, e.g. '2024-01-02' and '2024-01-31'. Both must be trading days.
area_indstr'market_value'Metric for block area: 'market_value' or 'turnover' (trading value over the period).
itemstr'return_ratio'Metric for block color: 'return_ratio' (return between start and end) or a FinLab dataset key, which shows its latest value in the range.
cliptupleNoneClip item to (lower, upper) so extreme values do not flatten the color scale (see DataFrame.clip).
color_continuous_scalestr'Temps'Name of a plotly color scale.
treemap_datapd.DataFrameNoneCustom data in the format returned by create_treemap_data().

Returns a plotly.graph_objects.Figure, or None when the data or area_ind is unavailable. return_ratio is the return between the two days, so setting start and end to the same day makes every block 0.

Common combinations:

  • Market heat: area_ind='market_value', item='return_ratio'
  • Trading activity: area_ind='turnover', item='return_ratio'

create_treemap_data()

Builds the data behind plot_tw_stock_treemap(): one row per Taiwan stock with symbol, close, turnover, return_ratio, category, market, market_value and country, plus a column for item when it is a dataset key. Add your own columns, then pass the result as plot_tw_stock_treemap(treemap_data=...).

from finlab.plot import create_treemap_data, plot_tw_stock_treemap

treemap = create_treemap_data(start='2024-01-02', end='2024-01-31', item='return_ratio')
print(treemap.head())

plot_tw_stock_treemap(treemap_data=treemap).show()
ParameterTypeDefaultDescription
start, endstrrequiredDate range.
itemstr'return_ratio''return_ratio' or a FinLab dataset key whose latest value in the range is added.
cliptupleNoneClip item to (lower, upper).

Returns a pd.DataFrame, or None if item has no data in the range.

plot_tw_stock_river()

Draws a P/E or P/B river chart for a Taiwan stock: the bands are the price implied by evenly spaced multiples between the stock's lowest and highest P/E (or P/B) in the period, and the line is the closing price, showing where the current valuation sits.

from finlab.plot import plot_tw_stock_river

plot_tw_stock_river(
    stock_id='2330',
    start='2015-01-01',
    end='2024-01-01',
    mode='pe',
    split_range=10,
).show()
ParameterTypeDefaultDescription
symbolstr'2330'Taiwan stock code (pass the stock you want; the default is a sample code). stock_id is accepted as an alias.
start, endstrNoneDate range, e.g. '2020-01-02' and '2024-01-05'. None uses all data.
modestr'pe''pe' (price-to-earnings) or 'pb' (price-to-book).
split_rangeint8Number of bands; more bands give finer color levels.

Returns a plotly.graph_objects.Figure, or None when the mode or symbol is invalid. It needs a long enough history (at least 2 years is recommended), and because financial statements are published with a delay, the latest quarter may have no data yet.

Common questions

The snippets below reuse symbol and prices from the plot_candles() example.

Charts are not displaying, what should I do?
# Cause 1: Forgot to call .show()
fig = plot_candles(symbol, **prices)
# Not displayed

fig = plot_candles(symbol, **prices)
fig.show()  # Correct

# Cause 2: Missing plotly package
# Solution: pip install plotly

# Cause 3: Jupyter Notebook environment issue
# Add at the beginning of the notebook:
import plotly.io as pio

pio.renderers.default = 'notebook'
How do I export charts as images?
fig = plot_candles(symbol, **prices, recent_days=200)

# Export as HTML (interactive)
fig.write_html('chart.html')

For a PNG, install Kaleido (pip install kaleido, which also needs a Chrome browser) and call fig.write_image('chart.png', width=1200, height=800).

How do I customize chart styles?
fig = plot_candles(symbol, **prices, recent_days=200)

# Change title
fig.update_layout(title='Apple Price Trend')

# Change color theme
fig.update_layout(template='plotly_dark')  # Dark theme

# Adjust chart size
fig.update_layout(width=1200, height=600)

fig.show()
Which datasets can the radar chart compare?

Any dataset key whose rows hold one value per symbol works, such as the us_ratios:* and us_key_metrics:* snapshot fields:

from finlab import data

data.search('margin', market='us')  # Find US margin fields
The radar chart's metrics have very different ranges, what can I do?

Values are already converted to rank levels, so metrics with different units are comparable. Use cut_bins to change how many levels there are:

plot_tw_stock_radar(
    portfolio=['AAPL', 'MSFT'],
    feats=[
        'us_ratios:gross_profit_margin',
        'us_key_metrics:return_on_equity',
        'us_ratios:debt_to_equity_ratio',
    ],
    cut_bins=10,  # Split all metrics into 10 levels
).show()

Next steps

For advanced styling, see the Plotly documentation.

↑↓ Move Enter Open Esc Close