Tear sheets¶
A Fundcloud tear sheet is a single rendered artefact that a non-technical stakeholder can read end-to-end — stat cards, cumulative return curve, drawdown, rolling Sharpe, a return distribution, and a monthly heatmap — with the exact run parameters embedded in the footer. Three output formats share the same content and formatting layer, so an HTML sent to a partner, a PDF attached to a monthly note, and an Excel workbook used for internal review are always consistent.
Pick the format that matches the recipient
HTML is best for interactive exploration and emails (self-contained, no runtime needed). PDF is the lowest-friction archive format (matplotlib default, no system dependencies). Excel is the right choice whenever the recipient will resize charts, change the colour of a series, or pivot the numbers themselves — XlsxWriter emits native charts, not screenshots.
from fundcloud.reports import Tearsheet
ts = Tearsheet(portfolio, title="Demo", benchmark=bench_returns)
ts.render_html("demo.html") # self-contained plotly — always available
ts.render_pdf("demo.pdf") # matplotlib PdfPages — needs fundcloud[viz]
ts.render_excel("demo.xlsx") # XlsxWriter — needs fundcloud[reports]
# Opt-in CSS-styled PDF (needs WeasyPrint + Pango):
ts.render_pdf("demo.pdf", engine="weasyprint")
Each render emits a Path (except render_html which also returns the
HTML string when path=None).
What's inside¶
The HTML page is a two-column layout — charts on the left, numeric tables (including the categorised metrics sidebar) on the right:
Left column — fc-charts |
Right column — fc-sidebar |
|---|---|
| Cumulative return (%) | Categorised metrics (Return / Risk-adjusted / …) |
| Drawdown | Period performance table |
| Rolling Sharpe | EOY returns table |
| Rolling α / β (if benchmark) | Worst 10 drawdowns |
| Return distribution | Top 10 runups |
| Monthly heatmap | |
| EOY returns (paired bars) |
Every sidebar section is a collapsible <details class="fc-group"> accordion — the same styling for metric groups and for the new numeric tables. PDF and Excel render the same content laid out as separate pages / sheets (see below).
Ingredients¶
- Stat cards — CAGR, Sharpe, max drawdown, CVaR-95 (top of the page).
- Cumulative return (%) chart — starts at 0% and is percent-formatted; overlays the benchmark as a dashed reference when supplied.
- Drawdown, Rolling Sharpe (63-bar), Return distribution, Monthly heatmap (year × month, when the history spans more than 60 days).
- EOY returns paired bar chart (benchmark amber, strategy blue, dashed mean-return reference line).
- Period performance table — MTD / 3M / 6M / YTD / 1Y / 3Y (ann.) / 5Y (ann.) / 10Y (ann.) / All-time (ann.). One column per series (benchmark prepended when supplied).
- EOY returns table — Year / Benchmark / Strategy.
- Worst 10 drawdowns table — Started / Recovered / Drawdown / Days, sorted by depth.
- Top 10 runups table — Started / Peaked / Runup / Days, sorted by magnitude.
- Categorised metrics — every metric from
fundcloud.metrics.metrics()grouped by category (Return, Risk-adjusted, Risk, Drawdown, Distribution, Trade, Calendar, and Benchmark when a benchmark is given). The sidebar header readsMETRICS — {strategy} vs {benchmark}so the two value columns are self-describing. Each row has a?badge; hover it for the definition and formula. - Benchmark rows — when
benchmark=is supplied: the cumulative curve gets a dashed overlay, the metrics sidebar grows aBenchmarksection (with the benchmark's own values shown in a second column), and a rolling α/β panel joins the chart list. PDFs get a dedicated benchmark page; Excel Summary sheets mirror the categorised layout with a Strategy / Benchmark column pair, and aBenchmarksheet carries the aligned return series.
HTML output¶
- Plotly runtime is embedded inline — the single file is self-contained, fine to email or commit.
- Expect ~5 MB per report because of the inline JS; drop to PDF for smaller artefacts.
PDF output¶
Default (pure-Python): :class:matplotlib.backends.backend_pdf.PdfPages
— one stat-table page plus one chart per page. No system libraries
required; the charts are the same matplotlib figures used by every other
renderer, so the output is consistent and nothing gets cropped.
Optional WeasyPrint engine: pass engine="weasyprint" to
render_pdf when you want the HTML/CSS paged-media layout. WeasyPrint
needs Pango / GLib / cairo — on macOS that's brew install pango plus
export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib; on Debian/Ubuntu,
apt install libpango-1.0-0 libpangoft2-1.0-0. If the WeasyPrint import
fails, Fundcloud raises a clear ImportError pointing back to the
matplotlib default.
Excel output (optional extra)¶
- Uses XlsxWriter with native charts — not images — so the numbers remain editable in Excel and the charts update live.
- Sheets:
Summary,Period Returns,Yearly Returns,Drawdowns,Runups,Returns, andWeights(when a weights frame is available on the portfolio). Percentage columns and embedded cumulative charts use the workbook's shared0.00%format.
One-figure alternative — plots.summary¶
If the recipient just wants the charts — no stat cards, no table, no Jinja template — call fundcloud.plots.summary directly. It returns a single Plotly Figure with the same canonical panels (cumulative, drawdown, rolling Sharpe, distribution, monthly heatmap) plus an optional composition row, ready to write to HTML or a PNG:
from fundcloud import plots
plots.summary(portfolio.returns, weights=portfolio.weights).write_html("quick.html")
Themes apply to both surfaces. Setting the theme before rendering re-themes the Tearsheet HTML too:
See Plots → Themes for the alias map.
Custom templates¶
Drop a Jinja2 file at fundcloud/reports/templates/<name>.html.j2
(the same place the default strategy.html.j2 lives), then
Tearsheet(..., template="<name>"). The shared
fundcloud.reports.formatting helpers
(stat_cards, stats_rows, format_stat) keep HTML and PDF output
consistent.