Python Data Visualisation for Treasury and Risk Teams: Matplotlib, Seaborn, and Plotly Compared
If you work in treasury or risk without a Tableau or Power BI seat, you already know the problem. The data is in Python or pandas, the insight is clear in your head, and the chart is stuck behind a licence request that takes three weeks to approve. Open source Python libraries close that gap immediately, and they cost nothing.
This post compares the three libraries that actually matter for finance work: Matplotlib, Seaborn, and Plotly. Not in the abstract, but judged on the outputs treasury and risk teams actually need: yield curves, correlation heatmaps, LCR outflow visuals, and cash flow waterfalls. By the end you will know which tool to reach for and when to switch.
The Three Libraries Worth Your Time
All three libraries are free, open source, and install via pip. All three integrate directly with pandas DataFrames, which means your typical workflow looks like this: pull data, clean it in pandas, pass it straight to a chart. No export, no copy and paste, no format conversion.
The differences are in what they optimise for:
- Matplotlib gives you the most control. It is the foundation everything else is built on.
- Seaborn is built on top of Matplotlib and makes statistical chart types much easier to produce.
- Plotly produces interactive charts by default and outputs clean HTML that works in a browser or a notebook without any extra setup.
Each one suits a different moment in the finance workflow. The skill is knowing which moment is which.
Matplotlib: Full Control, Higher Effort
Matplotlib has been around since 2003. It is stable, exhaustively documented, and capable of producing publication quality static charts. It is also verbose. Doing something that sounds simple, like adding a secondary axis to a yield curve chart, requires more lines of code than you might expect.
That verbosity is not a flaw exactly. It is the cost of the control you get. Every element of the chart is accessible and adjustable: tick spacing, axis label rotation, font sizes, grid line weight. For a regulatory reporting output where the chart must match a specific house style or fit a defined template, that control matters.
When to Use It in Treasury and Finance
Matplotlib is the right choice when:
- The output is a static image for a Word or PDF document, such as an ILAAP or ICAAP pack
- You need precise layout control for a chart with multiple panels, for example showing parallel HQLA composition and LCR ratios side by side
- You are building a reusable chart function that other team members will call without needing to understand the library
It is probably not the right first choice when you want something interactive, or when the statistical chart type you need (a heatmap, a distribution plot) is something Seaborn already handles in two lines.
A Worked Example: Plotting a Stylised Yield Curve
import matplotlib.pyplot as plt
import numpy as np
# Illustrative tenor points in years
tenors = [0.25, 0.5, 1, 2, 3, 5, 7, 10, 15, 20, 30]
# Stylised yield values in percent, for illustration only
yields = [4.80, 4.75, 4.60, 4.30, 4.15, 4.05, 4.10, 4.20, 4.35, 4.40, 4.38]
fig, ax = plt.subplots(figsize=(9, 4))
ax.plot(tenors, yields, marker="o", linewidth=2, color="#003865", markersize=5)
ax.set_xlabel("Tenor (years)")
ax.set_ylabel("Yield (%)")
ax.set_title("Stylised Government Yield Curve")
ax.set_xticks(tenors)
ax.grid(axis="y", linestyle="--", alpha=0.5)
plt.tight_layout()
plt.savefig("yield_curve.png", dpi=150)
plt.show()
When you embed this chart, give it descriptive alt text such as: "Stylised government yield curve plotted in Matplotlib showing illustrative tenor points from 3 months to 30 years."
The ax object is the key concept in Matplotlib. Once you understand that a figure can contain multiple axes objects, the library becomes much more manageable. Every property you want to change lives on either fig or ax.
Seaborn: Statistical Clarity With Less Code
Seaborn sits on top of Matplotlib and handles the chart types that involve distributions and relationships between variables. It accepts pandas DataFrames directly and applies sensible defaults that look clean without manual styling.
For finance teams, the killer use case is the correlation heatmap. Producing one in Matplotlib from scratch is doable but fiddly. In Seaborn it is three lines.
When to Use It in Treasury and Finance
Seaborn earns its place when:
- You are exploring relationships between variables in a model, such as correlations between liquidity buffer components or between funding sources
- You want distribution plots for a VaR or stress scenario output
- You are building something for a model review or internal audit pack where the chart needs to look professional but does not need to be interactive
It is not the right tool for a cash flow waterfall, an interactive output, or anything that needs custom layout control.
A Worked Example: Correlation Heatmap for a Liquidity Buffer Portfolio
A weekly note on treasury, liquidity and practical Python. No spam, unsubscribe any time.
import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Illustrative daily return data for five asset categories
# These categories are for illustration only and do not map directly
# to the UK regulatory HQLA classification under the LCR Delegated Regulation
np.random.seed(42)
n = 120 # roughly six months of daily observations
data = pd.DataFrame({
"Gilts": np.random.normal(0, 0.002, n),
"T-Bills": np.random.normal(0, 0.001, n),
"Supranational Bonds": np.random.normal(0, 0.003, n),
"Level 2A Bonds": np.random.normal(0, 0.004, n),
"Cash": np.zeros(n), # cash has no return variance
})
# Add some correlation structure to make it realistic
data["Supranational Bonds"] = data["Supranational Bonds"] + data["Gilts"] * 0.6
data["Level 2A Bonds"] = data["Level 2A Bonds"] + data["Gilts"] * 0.4
corr = data.corr()
fig, ax = plt.subplots(figsize=(6, 5))
sns.heatmap(
corr,
annot=True,
fmt=".2f",
cmap="coolwarm",
center=0,
ax=ax,
linewidths=0.5,
)
ax.set_title("Illustrative HQLA Asset Correlation Matrix")
plt.tight_layout()
plt.savefig("hqla_correlation.png", dpi=150)
plt.show()
When you embed this chart, use alt text such as: "Illustrative HQLA asset correlation matrix showing relationships between gilts, T-bills, supranational bonds, Level 2A bonds, and cash."
The annot=True argument puts the correlation coefficient inside each cell, which is exactly what a model reviewer or a risk committee wants to see without having to read a separate table.
For background on the five types of liquidity risk and why correlations inside the HQLA buffer matter, see this post on liquidity risk management.
Plotly: Interactivity Without a BI Licence
Plotly produces interactive charts by default. Hover tooltips, zoom, pan, legend toggling: all included, no extra configuration needed. The output is an HTML file or an inline notebook widget. You can email the HTML file to a colleague and they can interact with it in any browser without Python installed.
Most modern Jupyter environments render Plotly charts without extra steps, though some corporate setups require a renderer to be specified explicitly. If charts are not appearing inline, setting import plotly.io as pio; pio.renderers.default = "notebook" usually resolves it.
For a management information pack where someone will want to hover over a bar to see the exact number, or zoom into a specific time window on a liquidity chart, this is genuinely useful. It is the closest you will get to a BI tool without paying for one.
When to Use It in Treasury and Finance
Plotly is the right choice when:
- The audience will view the chart in a browser or a Jupyter notebook and expects to interact with it
- You are presenting a cash flow waterfall or a chart showing multiple periods of LCR projection to a management committee
- You want to share a chart that is fully contained in a single file with someone who does not run Python
It is overkill for a static PDF pack, and the syntax for some chart types, particularly the waterfall, is less intuitive than Matplotlib at first.
A Worked Example: Interactive Cash Flow Waterfall
import plotly.graph_objects as go
# Illustrative 12-month cash flow waterfall (GBP millions)
labels = [
"Opening Balance",
"Loan Repayments",
"Deposit Outflows",
"Wholesale Funding",
"Bond Coupon Payments",
"FX Swap Maturities",
"Net Derivatives",
"Closing Balance",
]
# Measure tells Plotly whether each bar is relative or a total
measure = ["absolute", "relative", "relative", "relative", "relative", "relative", "relative", "total"]
values = [500, 120, -280, 150, -45, -60, 20, 0]
fig = go.Figure(go.Waterfall(
name="Cash Flow",
orientation="v",
measure=measure,
x=labels,
y=values,
textposition="outside",
text=[f"{v:+d}" if m == "relative" else str(abs(v)) for v, m in zip(values, measure)],
connector={"line": {"color": "rgb(63, 63, 63)"}},
increasing={"marker": {"color": "#2ecc71"}},
decreasing={"marker": {"color": "#e74c3c"}},
totals={"marker": {"color": "#003865"}},
))
fig.update_layout(
title="Illustrative 12-Month Cash Flow Waterfall (GBPm)",
yaxis_title="GBP Millions",
showlegend=False,
)
fig.write_html("cashflow_waterfall.html")
fig.show()
The measure list is the key concept here. Setting a bar to "total" tells Plotly to draw it from zero rather than continuing from the previous bar, which is what you need for the opening and closing balance positions.
For more on working with variables and data structures in Python before you get to charting, see this introduction to variables for finance practitioners.
Going Further: Plotly Dash for Internal Dashboards
If Plotly interactive charts are useful, Plotly Dash is the natural next step. Dash is a Python framework for building dashboards that run in a browser, with dropdowns, sliders, and data tables, all driven by Python with no JavaScript required.
A small treasury team could build an internal LCR monitoring dashboard in Dash and host it on an internal server, giving the team an interactive tool without a Tableau or Power BI subscription. The learning curve is real. Dash introduces a callback pattern for interactivity that takes some getting used to. But for a team already comfortable with Plotly charts and basic Python, it is achievable.
Dash is free and open source. The enterprise version with additional features is commercial, but the open source version is capable enough for most internal finance use cases.
How to Choose: A Decision Framework for Finance Practitioners
The honest answer is that most teams end up using all three, but for different purposes. Here is a simple decision path:
Is the output static (PDF, Word, printed)? Reach for Matplotlib or Seaborn. Seaborn if the chart type is inherently statistical (correlation, distribution). Matplotlib if you need custom layout or the chart will be embedded in a larger automated report.
Does the audience need to interact with the chart (hover, zoom, filter)? Reach for Plotly. This includes management packs shared as HTML, internal notebook dashboards, and any chart where drilling into a specific period or category is part of the point.
Are you exploring data for yourself? Either Seaborn or Plotly works well. Seaborn is faster for statistical insight. Plotly is faster for spotting outliers because you can hover over individual points without writing extra label logic.
Is this going to a regulator (PRA110 submission, stress test output)? Static, reproducible, and precisely formatted. Matplotlib is usually the right answer here because you have full control and the output is deterministic given the same data.
The Practical Takeaway
Start with Plotly if you need interactivity, Seaborn if you need statistical chart types quickly, and Matplotlib when precise static output is the requirement. All three work directly with pandas, so there is no reason to leave your existing data workflow.
The decision is not permanent. A chart you prototype in Plotly for a management presentation can be rebuilt in Matplotlib when it needs to go into a regulatory document. The skills transfer across all three libraries because the underlying logic (figure, axes, data series, labels) is consistent.
If you want to build this skill systematically alongside finance and treasury knowledge, browse the Academy course catalogue or look at the learning paths for a guided route from Python basics through to finance applications. The Pro membership also gives you access to downloadable resources and member only content if you want to go further without starting from scratch each time.
If you are evaluating commercial BI platforms at the enterprise level, we have a separate comparison of Tableau vs Qlik Sense and Alteryx vs KNIME worth reading alongside this one.

Liquidity Management
The core building blocks of treasury: cash, liquidity, funding and the ratios regulators care about.
Take the courseGet the next one in your inbox
A weekly note across Finance & Treasury, Innovation & Automation and Career Development. No spam, unsubscribe any time.
Notes across finance and treasury, innovation and automation, and career development, written by practitioners who do the work.
