HTML Report Generation
SkillFiles & storageGenerate styled HTML reports using the Terminal Dashboard theme. Use when the user needs to create an HTML report, dashboard, data visualization, or styled output document. Triggers include requests to "generate a report", "create an HTML file", "make a dashboard", "visualize data", "export to HTML", or any task requiring formatted HTML output with the project's visual identity.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the HTML Report Generation skill
What this skill tells your AI
The instructions your AI receives, as published by joemccann/radon in .pi/skills/html-report/SKILL.md and read by ahel’s review.
Generate professional HTML reports using the Terminal Dashboard theme — a precision-focused, monochromatic, high-density design supporting both dark and light modes.
Quick Start
- Read the template:
.pi/skills/html-report/template.html - Replace placeholders:
{{TITLE}}→ Report title (appears in browser tab){{BODY}}→ Your report content HTML
- Write to:
reports/[report-name].html
# Example generation pattern
template = read("/.pi/skills/html-report/template.html")
html = template.replace("{{TITLE}}", "LEAP IV Scan | 2026-03-03")
html = html.replace("{{BODY}}", body_content)
write("reports/leap-iv-scan.html", html)
Template Features
The template (template.html) includes:
- ✅ Full CSS with dark/light mode support
- ✅ System preference detection (
prefers-color-scheme) - ✅ Theme toggle button (just add the button HTML in your body)
- ✅ Inter (UI/titles) + IBM Plex Mono (numeric/telemetry) fonts loaded
- ✅ All component styles pre-defined
- ✅ Print-friendly styles
- ✅ Responsive grid utilities
You only write the <body> content — no <head> needed!
Body Structure Template
<!-- HEADER (always include) -->
<header class="header">
<div>
<h1 class="title">Report Title</h1>
<p class="subtitle">Optional subtitle or description</p>
</div>
<div class="header-actions">
<span class="timestamp">Generated: 2026-03-03 11:30 PST</span>
<button class="theme-toggle" onclick="toggleTheme()">◐ THEME</button>
</div>
</header>
<!-- METRICS (optional) -->
<div class="metrics">
<div class="metric">
<div class="metric-label">Label</div>
<div class="metric-value">Value</div>
<div class="metric-change">Change note</div>
</div>
<!-- more metrics... -->
</div>
<!-- CONTENT PANELS -->
<div class="panel">
<div class="panel-header">Section Title</div>
<div class="panel-body">
Content here
</div>
</div>
<!-- OR TABLES -->
<div class="panel">
<div class="panel-header">Data Table</div>
<table>
<thead>
<tr>
<th>Column</th>
<th class="text-right">Number</th>
</tr>
</thead>
<tbody>
<tr>
<td>Value</td>
<td class="text-right">123.45</td>
</tr>
</tbody>
</table>
</div>
<!-- FOOTER (optional) -->
<div class="footer">
<p>Footer text · Additional info</p>
</div>
Available CSS Classes
Layout
| Class | Usage |
|---|---|
.container | Auto-applied, max-width 1400px |
.header | Report header with flex layout |
.grid-2 | Two-column grid (2fr 1fr) |
.grid-3 | Three equal columns |
.grid-4 | Four equal columns |
.divider | Horizontal rule with margin |
Panels & Cards
| Class | Usage |
|---|---|
.panel | Container with border |
.panel-header | Section title bar |
.panel-body | Padded content area |
.panel-accent | Highlighted border |
.card | Standalone card |
.card-accent | Highlighted card |
Metrics
| Class | Usage |
|---|---|
.metrics | Auto-fit grid container |
.metric | Single metric block |
.metric-label | Small uppercase label |
.metric-value | Large value display |
.metric-value.large | 32px value |
.metric-value.small | 18px value |
.metric-change | Secondary info with top border |
Tables
| Class | Usage |
|---|---|
table | Full-width, collapsed borders |
th | Sticky header, uppercase |
tr:hover | Row highlight on hover |
tr.highlight | Permanently highlighted row |
Text
| Class | Usage |
|---|---|
.text-right | Right align |
.text-center | Center align |
.text-muted | Meta / supporting text (#475569 dark) |
.text-positive | Green |
.text-negative | Red |
.text-warning | Orange |
.text-small | 11px |
.text-uppercase | Uppercase + letter-spacing |
.text-mono | IBM Plex Mono (numeric/telemetry) |
.text-sans | Inter (UI/titles) |
Pills / Badges
| Class | Usage |
|---|---|
.pill | Default bordered badge |
.pill-accent | Inverted (white/black) |
.pill-positive | Green background |
.pill-negative | Red background |
.pill-warning | Orange background |
Status Indicators
<span class="status">
<span class="status-dot"></span>
LIVE
</span>
<!-- Variants -->
<span class="status-dot positive"></span>
<span class="status-dot negative"></span>
<span class="status-dot warning"></span>
<span class="status-dot static"></span> <!-- No animation -->
Buttons
| Class | Usage |
|---|---|
.btn | Default button |
.btn-accent | Inverted button |
.theme-toggle | Theme switch button |
Special Components
<!-- Callout box -->
<div class="callout">
<div class="callout-title">Note</div>
<p>Content here</p>
</div>
<div class="callout positive">...</div>
<div class="callout negative">...</div>
<div class="callout warning">...</div>
<!-- Section header -->
<div class="section-header">Section Name</div>
<!-- Progress bar -->
<div class="bar-container">
<div class="bar-fill" style="width: 75%"></div>
</div>
<div class="bar-container">
<div class="bar-fill positive" style="width: 60%"></div>
</div>
Color Tokens
Use CSS variables for theme compatibility:
| Token | Dark | Light | Usage |
|---|---|---|---|
--bg-base | #0a0f14 | #FFFFFF | Page background |
--bg-panel | #0f1519 | #FFFFFF | Panel background |
--bg-hover | #151c22 | #f1f5f9 | Hover state |
--border-dim | #1e293b | #BBBFBF | Default borders |
--border-focus | #05AD98 | #05AD98 | Active borders |
--text-primary | #e2e8f0 | #000000 | Main text |
--text-secondary | #94a3b8 | #636363 | Secondary text |
--text-muted | #475569 | #878787 | Meta / supporting text |
--accent-bg | #05AD98 | #05AD98 | Inverted bg |
--accent-text | #0a0f14 | #FFFFFF | Inverted text |
--positive | #05AD98 | #048A7A | Positive / green |
--negative | #E85D6C | #D4183D | Negative / red |
--warning | #F5A623 | #D4910A | Caution / orange |
--signal-core | #05AD98 | #05AD98 | Core Radon accent |
--signal-strong | #0FCFB5 | #048A7A | High-confidence signal |
--signal-deep | #048A7A | #037066 | Deep data / selected |
--dislocation | #D946A8 | #C026A0 | Structural dislocation |
--extreme | #8B5CF6 | #7C3AED | Extreme / rare state |
--fault | #E85D6C | #D4183D | Feed fault / integrity |
--neutral | #94a3b8 | #878787 | Neutral state |
Example: Minimal Report
{{BODY}} content:
<header class="header">
<div>
<h1 class="title">Daily Summary</h1>
</div>
<div class="header-actions">
<span class="timestamp">2026-03-03</span>
<button class="theme-toggle" onclick="toggleTheme()">◐ THEME</button>
</div>
</header>
<div class="metrics">
<div class="metric">
<div class="metric-label">Positions</div>
<div class="metric-value">12</div>
</div>
<div class="metric">
<div class="metric-label">P&L</div>
<div class="metric-value text-positive">+$4,500</div>
</div>
</div>
<div class="panel">
<div class="panel-header">Open Positions</div>
<table>
<thead>
<tr>
<th>Ticker</th>
<th class="text-right">Value</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAPL</td>
<td class="text-right">$15,000</td>
<td><span class="pill pill-positive">PROFIT</span></td>
</tr>
</tbody>
</table>
</div>
File Naming Convention
reports/
├── portfolio-2026-03-03.html
├── leap-iv-scan-2026-03-03.html
├── flow-scan-AAPL.html
├── trade-journal-2026-03.html
└── pnl-EWY-2026-03-03.html
Portfolio Report Template ⭐
For the portfolio command, ALWAYS use the dedicated portfolio template.
Template: .pi/skills/html-report/portfolio-template.html
Script: scripts/portfolio_report.py
Output: reports/portfolio-{date}.html
When to Use
portfoliocommand (auto-generates and opens in browser)- Any request for portfolio status, P&L overview, position review
- Startup portfolio health check
How It Works
The script (portfolio_report.py) is self-contained:
- Connects to IB → fetches all positions + live prices
- Groups legs into logical structures (spreads, risk reversals, etc.)
- Fetches 5-day dark pool flow for every ticker including today (parallel, 8 workers)
- Loads trade log for thesis comparisons
- Fills the template placeholders → writes HTML → opens browser
You do NOT need to fetch data separately. Just run:
python3.13 scripts/portfolio_report.py
8 Required Sections
Every portfolio report MUST include these sections (in order):
| # | Section | Template Placeholder | Data Source |
|---|---|---|---|
| 1 | Header | {{STATUS_CLASS}}, {{STATUS_TEXT}}, {{TIMESTAMP}} | Computed from attention counts |
| 2 | Data Freshness Banner | {{FRESHNESS_CLASS}}, {{FRESHNESS_TEXT}} | Market hours check |
| 3 | Summary Metrics (6 cards) | {{METRICS_HTML}} | IB account values |
| 4 | Quick-Stat Badges | {{QUICK_STATS_HTML}} | Position analysis |
| 5 | Attention Callouts | {{ATTENTION_HTML}} | Expiring, stops, winners, undefined risk |
| 6 | Thesis Check | {{THESIS_SECTION_HTML}} | Trade log + dark pool flow |
| 7 | All Positions Table | {{POSITION_ROWS_HTML}} | IB positions + live prices |
| 8 | Dark Pool Flow | {{FLOW_ROWS_HTML}} | UW dark pool API |
| — | Footer | {{FOOTER_SUMMARY}} | Computed summary |
⚠️ Today-Highlighting (MANDATORY for Sections 6, 7, 8)
Any section that displays time-series flow data MUST visually highlight today's data point:
Sparkline bars use the .spark-bar.today CSS class:
- Adds a white outline ring around today's bar
- The
today →label appears below the sparkline - Bars are colored: green (accumulation ≥70%), red (distribution ≤30%), grey (neutral)
Today column in the flow table shows the LIVE tag:
<span class="flow-dir accumulation">72%</span><span class="today-tag">LIVE</span>
Data freshness banner at the top of the report shows market status:
- Market OPEN: green pulsing dot + "All prices and flow data include today (YYYY-MM-DD)"
- Market CLOSED: amber static dot + "Using closing prices from last session"
Why this matters: A scan from yesterday may show ACCUMULATION but today's flow could be DISTRIBUTION. The today-highlight forces the reader to check whether the current day confirms or breaks the pattern.
Template Variables
| Variable | Description | Example |
|---|---|---|
{{DATE}} | Report date | 2026-03-06 |
{{TIMESTAMP}} | Full timestamp | 2026-03-06 09:20 PST |
{{STATUS_CLASS}} | Header dot color | positive / negative / warning |
{{STATUS_TEXT}} | Header status | 3 ACTIONS NEEDED / ALL POSITIONS ACTIVE |
{{FRESHNESS_CLASS}} | Banner class | `` (live) or stale (closed) |
{{FRESHNESS_TEXT}} | Banner content | 📊 ... Market OPEN ... include today |
{{METRICS_HTML}} | 6 metric cards | Net Liq, P&L, Deployed, Margin, Positions, Kelly |
{{QUICK_STATS_HTML}} | 3 badge panels | Expiring, At Stop, Winners |
{{ATTENTION_HTML}} | Callout blocks | 🔴 Expiring, 🟡 Stop, 🟢 Winners, ⛔ Undefined |
{{THESIS_SECTION_HTML}} | Full thesis table | Entry flow vs current flow with sparklines |
{{POSITION_ROWS_HTML}} | <tr> rows | All positions sorted by DTE |
{{FLOW_ROWS_HTML}} | <tr> rows | All tickers with sparkline + today cell |
{{FOOTER_SUMMARY}} | Summary line | 27 positions · $1.2M net liq · 134% deployed |
Portfolio-Specific CSS Components
These are defined in the template (not in the base template.html):
| Component | CSS Class | Purpose |
|---|---|---|
| Freshness banner | .freshness-banner | Data recency indicator at top |
| Sparkline | .spark + .spark-bar | Mini bar chart for daily flow |
| Today highlight | .spark-bar.today | White outline ring on today's bar |
| Today label | .spark-today-label | "today →" text under sparkline |
| Flow direction | .flow-dir.accumulation/.distribution/.neutral | Colored direction text |
| Today tag | .today-tag | Black/white "LIVE" inline badge |
| Progress bar | .progress-container + .progress-fill | For free-trade % (extensible) |
| Count badge | .count-badge + .alert/.success | Quick-stat numbers |
Room for Innovation
The 8 sections above are the required minimum. You can add additional sections between Section 7 (Flow) and Section 8 (Footer) for ad-hoc analysis. Ideas:
- Free Trade Progress — Progress bars for multi-leg positions approaching free status
- Sector Heatmap — Group positions by sector, show aggregate flow
- Expiry Calendar — Visual timeline of upcoming expirations
- Kelly Capacity — Detailed breakdown of capital allocation vs. Kelly optimal
- Flow Divergence Alerts — Positions where flow reversed since entry
- Correlation Matrix — Which positions move together
Add these by inserting HTML before the {{FOOTER_SUMMARY}} replacement, or by adding new placeholder variables to the template.
Reference Implementation
See: reports/portfolio-2026-03-06.html
P&L Report Template
For any trade P&L or reconciliation report, use the dedicated P&L template.
Template: .pi/skills/html-report/pnl-template.html
When to Use
- Trade closed → generate P&L report
- P&L reconciliation requested
- Historical trade analysis
- Spread P&L breakdown
P&L Template Features
Everything in the base template PLUS:
- Timeline component for trade history
- Subtotal/total row styles for tables
- Panel accent variants (positive/negative border)
- Optimized metric sizing (28px default, fits 6-digit amounts)
Required Sections
Every P&L report MUST include:
1. Header with Status Pill
<header class="header">
<div>
<h1 class="title">{{TICKER}} {{STRATEGY}} — P&L Reconciliation</h1>
<p class="subtitle">{{DESCRIPTION}} · {{EXPIRY}}</p>
</div>
<div class="header-actions">
<span class="pill pill-positive">CLOSED</span> <!-- or pill-negative for loss -->
<button class="theme-toggle" onclick="toggleTheme()">◐ THEME</button>
</div>
</header>
2. Summary Metrics (4 required)
<div class="metrics">
<div class="metric">
<div class="metric-label">Realized P&L</div>
<div class="metric-value text-positive">+$17,651</div> <!-- or text-negative -->
<div class="metric-change">Net of all commissions</div>
</div>
<div class="metric">
<div class="metric-label">Total Commissions</div>
<div class="metric-value">$168.60</div>
<div class="metric-change">{{NUM_ROUNDTRIPS}} round-trips</div>
</div>
<div class="metric">
<div class="metric-label">Hold Period</div>
<div class="metric-value">{{DAYS}} days</div>
<div class="metric-change">{{OPEN_DATE}} → {{CLOSE_DATE}}</div>
</div>
<div class="metric">
<div class="metric-label">Return on Risk</div>
<div class="metric-value text-positive">+106.8%</div> <!-- P&L / Capital at Risk -->
<div class="metric-change">On ${{CAPITAL_AT_RISK}} {{DEBIT_OR_CREDIT}}</div>
</div>
</div>
3. Trade Summary Callout
<div class="callout positive"> <!-- or "callout negative" for losses -->
<div class="callout-title">Trade Summary</div>
<p><strong>Strategy:</strong> {{STRATEGY_DESCRIPTION}}</p>
<p><strong>Thesis:</strong> {{THESIS}}</p>
<p><strong>Outcome:</strong> {{OUTCOME_DESCRIPTION}}</p>
</div>
4. Execution Table (per leg for spreads)
<div class="panel">
<div class="panel-header">{{LEG_DESCRIPTION}}</div>
<table>
<thead>
<tr>
<th>Date</th>
<th>Action</th>
<th class="text-right">Qty</th>
<th class="text-right">Price</th>
<th class="text-right">Cash Flow</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{DATE}}</td>
<td><span class="text-positive">● BUY TO OPEN</span></td>
<td class="text-right">{{QTY}}</td>
<td class="text-right">${{PRICE}}</td>
<td class="text-right text-negative">-${{AMOUNT}}</td>
</tr>
<!-- More rows... -->
<tr class="subtotal">
<td colspan="3"><strong>{{LEG}} Subtotal</strong></td>
<td class="text-right"><strong>CLOSED</strong></td>
<td class="text-right text-positive"><strong>+${{LEG_PNL}}</strong></td>
</tr>
</tbody>
</table>
</div>
5. Combined P&L Panel (for spreads)
<div class="panel panel-accent"> <!-- or panel-accent negative -->
<div class="panel-header">Combined Spread P&L</div>
<table>
<tbody>
<tr>
<td>{{LEG_1}} P&L</td>
<td class="text-right text-positive">+${{LEG_1_PNL}}</td>
</tr>
<tr>
<td>{{LEG_2}} P&L</td>
<td class="text-right text-negative">-${{LEG_2_PNL}}</td>
</tr>
<tr>
<td>Total Commissions</td>
<td class="text-right text-muted">(${{TOTAL_COMM}})</td>
</tr>
<tr class="total">
<td><strong>NET REALIZED P&L</strong></td>
<td class="text-right text-positive"><strong>+${{NET_PNL}}</strong></td>
</tr>
</tbody>
</table>
</div>
6. Trade Timeline
<div class="panel">
<div class="panel-header">Trade Timeline</div>
<div class="panel-body">
<div class="timeline">
<div class="timeline-item buy">
<div class="timeline-date">{{OPEN_DATE_FORMATTED}}</div>
<div class="timeline-action">OPENED {{STRATEGY}}</div>
<div class="timeline-detail">
{{OPEN_DETAILS}}<br>
<strong>Net {{DEBIT_OR_CREDIT}}: ${{OPEN_AMOUNT}}</strong>
</div>
</div>
<div class="timeline-item sell">
<div class="timeline-date">{{CLOSE_DATE_FORMATTED}}</div>
<div class="timeline-action">CLOSED {{STRATEGY}}</div>
<div class="timeline-detail">
{{CLOSE_DETAILS}}<br>
<strong>Net {{CREDIT_OR_DEBIT}}: ${{CLOSE_AMOUNT}}</strong>
</div>
</div>
</div>
</div>
</div>
7. Footer
<div class="footer">
<p>Generated by Trade Blotter · Data from IB Flex Query + Real-time API · {{DATE}}</p>
</div>
Return on Risk Calculation
Always calculate Return on Risk as:
Return on Risk = Realized P&L / Capital at Risk
Where Capital at Risk =
- For DEBIT spreads: Net debit paid to open
- For CREDIT spreads: Max loss (spread width - credit received)
- For long options: Premium paid
- For stock: Total cost basis
Example P&L Report Reference
See: reports/ewy-pnl-reconciliation-2026-03-03.html
Trade Specification Template ⭐ PRIMARY
For ANY trade recommendation, ALWAYS use this template.
Template: .pi/skills/html-report/trade-specification-template.html
When to Use
- ALWAYS when recommending a trade after evaluation
- ALWAYS when presenting a trade for execution confirmation
- Ticker evaluation results (whether TRADE or NO_TRADE)
- Full milestone-based evaluation output
Template Structure
The trade specification template includes ALL sections needed for a complete evaluation:
- Header — Ticker, company, price, gate status
- Summary Metrics — 6 key metrics (signal score, buy ratio, flow strength, convexity, position size, max gain)
- Milestone Summary — All 7 milestones with pass/fail status
- Dark Pool Flow Section — Daily breakdown + aggregate analysis
- Options Flow Section — Chain bias, institutional flow, combined signal
- Context Section — Seasonality + analyst ratings
- Structure & Kelly — Position structure and Kelly sizing
- Trade Specification — Exact order details ready for execution
- Thesis & Risk Factors — Callouts with reasoning
- Four Gates Summary — Final gate check table
Template Variables
Replace these placeholders with actual values:
| Variable | Description | Example |
|---|---|---|
{{TICKER}} | Stock symbol | GOOG |
{{COMPANY_NAME}} | Full company name | Alphabet Inc. (Class C) |
{{SECTOR}} | Industry sector | Communication Services |
{{CURRENT_PRICE}} | Current stock price | 302.38 |
{{DATE}} | Evaluation date | 2026-03-04 |
{{TIMESTAMP}} | Full timestamp | 2026-03-04 06:43 PST |
{{STATUS_TEXT}} | Gate status | ALL GATES PASSED |
{{STATUS_CLASS}} | CSS class | positive / negative / warning |
{{SIGNAL_SCORE}} | Combined signal score | 129.7 |
{{BUY_RATIO}} | Dark pool buy ratio % | 94.87 |
{{FLOW_STRENGTH}} | Flow strength 0-100 | 89.7 |
{{RR_RATIO}} | Risk:reward ratio | 3.0 |
{{POSITION_SIZE}} | Total position cost | 27,544 |
{{POSITION_PCT}} | % of bankroll | 2.46 |
{{MAX_GAIN}} | Maximum profit | 82,456 |
{{NUM_CONTRACTS}} | Number of contracts | 44 |
{{DTE}} | Days to expiration | 43 |
{{NET_DEBIT}} | Net debit per spread | 6.26 |
{{THESIS}} | Trade thesis | Extraordinary institutional... |
Milestone Variables
For each milestone (M1, M1B, M1C, M1D, M2, M3, M3B, M4, M5, M6):
| Variable Pattern | Values |
|---|---|
{{MX_CLASS}} | complete or failed or empty |
{{MX_DESCRIPTION}} | Description text |
{{MX_GATE_CLASS}} | gate-pass or gate-fail |
{{MX_RESULT}} | ✓ PASS or ✗ FAIL or result text |
Gate Summary Variables
| Variable | Description |
|---|---|
{{GATE1_ACTUAL}} | e.g., "3.0:1" |
{{GATE1_PILL}} | pill-positive or pill-negative |
{{GATE1_STATUS}} | PASS or FAIL |
{{GATE2_ACTUAL}} | e.g., "89.7, 5 days" |
{{GATE3_ACTUAL}} | e.g., "2.46%" |
NO_TRADE Reports
When evaluation fails a gate, still generate the report but:
- Set
{{STATUS_TEXT}}to failing gate (e.g., "EDGE FAILED") - Set
{{STATUS_CLASS}}tonegative - Mark failed milestone with
failedclass - Omit Structure & Kelly sections (not reached)
- Omit Trade Specification section
- Include callout explaining why trade was rejected
Output Location
reports/{ticker}-evaluation-{date}.html
Examples:
reports/goog-evaluation-2026-03-04.html
reports/amd-evaluation-2026-03-04.html
Reference Implementation
See: reports/goog-evaluation-2026-03-04.html
Risk Reversal Report Template ⭐
For the risk-reversal command, ALWAYS use the dedicated risk reversal template.
Template: .pi/skills/html-report/risk-reversal-template.html
Script: scripts/risk_reversal.py
Output: reports/{ticker}-risk-reversal-{date}.html
When to Use
risk-reversal [TICKER]command (auto-generates and opens in browser)- Any request involving selling puts + buying calls (or inverse) as a directional bet
- IV skew analysis for a specific ticker's options chain
How It Works
The script (risk_reversal.py) is self-contained:
- Fetches dark pool flow and options flow for context (via subprocess to fetch_flow.py / fetch_options.py)
- Connects to IB → fetches spot price, option chains, live greeks (25-50Δ puts and calls)
- Builds the full risk reversal matrix across 2-5 expirations (14-60 DTE)
- Computes IV skew per delta bucket per expiry
- Selects 3 recommendations: Primary (costless), Alternative (different expiry), Aggressive (credit)
- Fills the template → writes HTML → opens browser
You do NOT need to fetch data separately. Just run:
python3.13 scripts/risk_reversal.py IWM
8 Required Sections
Every risk reversal report MUST include these sections (in order):
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 30
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
html-report-joemccann- Source
- github.com/joemccann/radon