• Markets & Machines
  • Posts
  • Say Hello to Quantmod Charting: Built for Quants Who Miss Cufflinks

Say Hello to Quantmod Charting: Built for Quants Who Miss Cufflinks

I’ve always loved Cufflinks.

It’s been my go-to for quick, interactive charts — super clean, super smooth, and just worked. One-liner plots and boom: good-looking visual. But lately? It's been… breaking all over the place. Many functions are deprecated, and the last major update? That was like five years ago.

So I thought, “Okay, let me just fork it and patch it up.”

Spoiler: That rabbit hole goes deep.

I tried switching to lightweight wrappers around Plotly Express. That kind of worked… but it didn’t feel the same. You know that feeling when you go from something buttery to something kinda dry? Yeah.

So, I scrapped all that and started fresh — using raw Plotly graph objects, rebuilt some of my fav Cufflinks tricks, and wrapped it all up under the hood of my quantmod workflow.

I didn’t try to rebuild Cufflinks piece by piece — just wanted to bring back that smooth, effortless charting vibe. And honestly? It delivers.

What You Get with Quantmod Charting

This new quantmod charting module gives you:

  • One-liner interactive charts using .iplot()

  • Candlesticks, bars, treemaps, line plots — ready to go

  • Auto-normalization for comparing stocks

  • Support for subplots

  • Sensible defaults (no wrestling with Plotly’s layout config)

Real Examples From My Notebook

Here’s a taste of what it looks like:

import pandas as pd
import quantmod.charts 
from quantmod.timeseries.performance import dailyReturn, volatility

# Load multiple stocks  
df = pd.read_csv('data.csv', index_col=0, parse_dates=True)
df.head(2)


         ASIANPAINT	ICICIBANK	ITC	RELIANCE	TCS
Date					
2019-01-01	1371.55	363.75	282.70	1024.97	1902.80
2019-01-02	1383.30	364.60	280.60	1011.62	1923.30


# Calculate daily returns
daily_returns = dailyReturn(df)
daily_returns.head(2)


         ASIANPAINT	ICICIBANK	ITC	RELIANCE	TCS
Date					
2019-01-01	NaN	NaN	NaN	NaN	NaN
2019-01-02	0.008530	0.002334	-0.007456	-0.013110	0.010716


# Load single stock data
df1 = pd.read_csv('titan.csv', index_col=0, parse_dates=True)
df1.head(2)

           open	high	low	close	volume	returns
date						
2024-05-23	3371.966416	3449.113880	3366.733539	3440.791260	977789	NaN
2024-05-24	3440.841223	3443.781553	3393.097300	3401.270508	878625	-1.155242



# Calculate Statistics
ret = daily_returns.mean() * 252 * 100
vol = volatility(daily_returns) * 100
stats = pd.DataFrame({"AnnRet": ret, "AnnVol": vol})


            AnnRet	    AnnVol
ASIANPAINT	18.553645	26.389029
ICICIBANK	20.582369	33.036501
ITC	        10.034972	26.492389
RELIANCE	18.890664	30.309543
TCS	        14.089459	24.841592

1. Line Chart

df.iplot(kind="line", y="ITC", color='cornflowerblue', title="Line Chart")
Line Chart

2. Scatter Plot

daily_returns.iplot(kind="scatter", x="ICICIBANK", y="ITC", color="green", title="Scatter Plot")
Scatter Plot

3. OHLC Chart

df1.iplot(kind="ohlc", title="OHLC Chart")
OHLC Cart

4. Candlestick Chart

df1.iplot(kind="candlestick", title="Candle Chart")
Candlestick Chart

5. Overlay Chart

df[["ICICIBANK", "ITC"]].iplot(kind="overlay", secondary_y="ICICIBANK", title="ICICIBANK & ITC Overlay Chart")
Overlay Chart

6. Subplots

df[['ITC', 'ICICIBANK']].iplot(kind="subplots", showlegend=True, title=" ITC & ICICBank Subplots")
Subplots

7. Iterative Subplots

daily_returns.iloc[:,:4].iplot(kind="subplots", showlegend=True, title="Stock Returns")
Iterative Subplots

8. Normalised Plot

df.iplot(kind="normalized", title="Normalized Prices")
Normalised Plot

9. Histogram

daily_returns.iplot(kind="histogram")
Histogram

10. Histogram without overlap

daily_returns.iloc[:,:4].iplot(kind="histogram", overlap=False, showlegend=True)
Histogram without overlap

11. Boxplot

daily_returns.iplot(kind="box", showlegend=True, title="Box Plot Analysis")
Boxplot

12. Bar Chart

stats.iplot(kind="bar", showlegend=True, title="Annualised Return & Volatility")
Bar Chart

13. Pie Chart

ret.to_frame("Annual Return").iplot(kind="pie", showlegend=True, title="Annual Return Share by Stock")

14. Pie Chart

corrmatrix = daily_returns.corr()
corrmatrix.iplot(kind="heatmap", colorscale="Jet", title="Correlation Plot")
Heatmap

15. Treemap

stats.iplot(
    kind="treemap",
    labels=stats.index,
    parents=[""] * len(stats),
    values="AnnRet",
    title="Treemap of Annualised Returns",
)
Treemap

Why I Built This

Like I said — I didn’t set out to build a new charting tool. I just wanted Cufflinks to work again. When it didn’t, I rebuilt the parts I missed, cleaned them up, and plugged it into my quantmod workflow.

It’s now something I use daily — lightweight, flexible, and feels just right for how I like to explore data. If you’ve ever loved the feel of Cufflinks, or just want a clean, frictionless way to plot financial data interactively, this might be your thing.

Try it. Break it. Tell me what’s missing. I’d love to improve it based on how you work.

You can find docs and updates here 👉 kannansingaravelu.com/quantmod

Catch you in the next chart.
— Kannan