HTML Report Generation

SkillFiles & storage

Generate 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.

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

  1. Read the template: .pi/skills/html-report/template.html
  2. Replace placeholders:
    • {{TITLE}} → Report title (appears in browser tab)
    • {{BODY}} → Your report content HTML
  3. 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

ClassUsage
.containerAuto-applied, max-width 1400px
.headerReport header with flex layout
.grid-2Two-column grid (2fr 1fr)
.grid-3Three equal columns
.grid-4Four equal columns
.dividerHorizontal rule with margin

Panels & Cards

ClassUsage
.panelContainer with border
.panel-headerSection title bar
.panel-bodyPadded content area
.panel-accentHighlighted border
.cardStandalone card
.card-accentHighlighted card

Metrics

ClassUsage
.metricsAuto-fit grid container
.metricSingle metric block
.metric-labelSmall uppercase label
.metric-valueLarge value display
.metric-value.large32px value
.metric-value.small18px value
.metric-changeSecondary info with top border

Tables

ClassUsage
tableFull-width, collapsed borders
thSticky header, uppercase
tr:hoverRow highlight on hover
tr.highlightPermanently highlighted row

Text

ClassUsage
.text-rightRight align
.text-centerCenter align
.text-mutedMeta / supporting text (#475569 dark)
.text-positiveGreen
.text-negativeRed
.text-warningOrange
.text-small11px
.text-uppercaseUppercase + letter-spacing
.text-monoIBM Plex Mono (numeric/telemetry)
.text-sansInter (UI/titles)

Pills / Badges

ClassUsage
.pillDefault bordered badge
.pill-accentInverted (white/black)
.pill-positiveGreen background
.pill-negativeRed background
.pill-warningOrange 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

ClassUsage
.btnDefault button
.btn-accentInverted button
.theme-toggleTheme 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:

TokenDarkLightUsage
--bg-base#0a0f14#FFFFFFPage background
--bg-panel#0f1519#FFFFFFPanel background
--bg-hover#151c22#f1f5f9Hover state
--border-dim#1e293b#BBBFBFDefault borders
--border-focus#05AD98#05AD98Active borders
--text-primary#e2e8f0#000000Main text
--text-secondary#94a3b8#636363Secondary text
--text-muted#475569#878787Meta / supporting text
--accent-bg#05AD98#05AD98Inverted bg
--accent-text#0a0f14#FFFFFFInverted text
--positive#05AD98#048A7APositive / green
--negative#E85D6C#D4183DNegative / red
--warning#F5A623#D4910ACaution / orange
--signal-core#05AD98#05AD98Core Radon accent
--signal-strong#0FCFB5#048A7AHigh-confidence signal
--signal-deep#048A7A#037066Deep data / selected
--dislocation#D946A8#C026A0Structural dislocation
--extreme#8B5CF6#7C3AEDExtreme / rare state
--fault#E85D6C#D4183DFeed fault / integrity
--neutral#94a3b8#878787Neutral 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

  • portfolio command (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:

  1. Connects to IB → fetches all positions + live prices
  2. Groups legs into logical structures (spreads, risk reversals, etc.)
  3. Fetches 5-day dark pool flow for every ticker including today (parallel, 8 workers)
  4. Loads trade log for thesis comparisons
  5. 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):

#SectionTemplate PlaceholderData Source
1Header{{STATUS_CLASS}}, {{STATUS_TEXT}}, {{TIMESTAMP}}Computed from attention counts
2Data Freshness Banner{{FRESHNESS_CLASS}}, {{FRESHNESS_TEXT}}Market hours check
3Summary Metrics (6 cards){{METRICS_HTML}}IB account values
4Quick-Stat Badges{{QUICK_STATS_HTML}}Position analysis
5Attention Callouts{{ATTENTION_HTML}}Expiring, stops, winners, undefined risk
6Thesis Check{{THESIS_SECTION_HTML}}Trade log + dark pool flow
7All Positions Table{{POSITION_ROWS_HTML}}IB positions + live prices
8Dark 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

VariableDescriptionExample
{{DATE}}Report date2026-03-06
{{TIMESTAMP}}Full timestamp2026-03-06 09:20 PST
{{STATUS_CLASS}}Header dot colorpositive / negative / warning
{{STATUS_TEXT}}Header status3 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 cardsNet Liq, P&L, Deployed, Margin, Positions, Kelly
{{QUICK_STATS_HTML}}3 badge panelsExpiring, At Stop, Winners
{{ATTENTION_HTML}}Callout blocks🔴 Expiring, 🟡 Stop, 🟢 Winners, ⛔ Undefined
{{THESIS_SECTION_HTML}}Full thesis tableEntry flow vs current flow with sparklines
{{POSITION_ROWS_HTML}}<tr> rowsAll positions sorted by DTE
{{FLOW_ROWS_HTML}}<tr> rowsAll tickers with sparkline + today cell
{{FOOTER_SUMMARY}}Summary line27 positions · $1.2M net liq · 134% deployed

Portfolio-Specific CSS Components

These are defined in the template (not in the base template.html):

ComponentCSS ClassPurpose
Freshness banner.freshness-bannerData recency indicator at top
Sparkline.spark + .spark-barMini bar chart for daily flow
Today highlight.spark-bar.todayWhite outline ring on today's bar
Today label.spark-today-label"today →" text under sparkline
Flow direction.flow-dir.accumulation/.distribution/.neutralColored direction text
Today tag.today-tagBlack/white "LIVE" inline badge
Progress bar.progress-container + .progress-fillFor free-trade % (extensible)
Count badge.count-badge + .alert/.successQuick-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:

  1. Header — Ticker, company, price, gate status
  2. Summary Metrics — 6 key metrics (signal score, buy ratio, flow strength, convexity, position size, max gain)
  3. Milestone Summary — All 7 milestones with pass/fail status
  4. Dark Pool Flow Section — Daily breakdown + aggregate analysis
  5. Options Flow Section — Chain bias, institutional flow, combined signal
  6. Context Section — Seasonality + analyst ratings
  7. Structure & Kelly — Position structure and Kelly sizing
  8. Trade Specification — Exact order details ready for execution
  9. Thesis & Risk Factors — Callouts with reasoning
  10. Four Gates Summary — Final gate check table

Template Variables

Replace these placeholders with actual values:

VariableDescriptionExample
{{TICKER}}Stock symbolGOOG
{{COMPANY_NAME}}Full company nameAlphabet Inc. (Class C)
{{SECTOR}}Industry sectorCommunication Services
{{CURRENT_PRICE}}Current stock price302.38
{{DATE}}Evaluation date2026-03-04
{{TIMESTAMP}}Full timestamp2026-03-04 06:43 PST
{{STATUS_TEXT}}Gate statusALL GATES PASSED
{{STATUS_CLASS}}CSS classpositive / negative / warning
{{SIGNAL_SCORE}}Combined signal score129.7
{{BUY_RATIO}}Dark pool buy ratio %94.87
{{FLOW_STRENGTH}}Flow strength 0-10089.7
{{RR_RATIO}}Risk:reward ratio3.0
{{POSITION_SIZE}}Total position cost27,544
{{POSITION_PCT}}% of bankroll2.46
{{MAX_GAIN}}Maximum profit82,456
{{NUM_CONTRACTS}}Number of contracts44
{{DTE}}Days to expiration43
{{NET_DEBIT}}Net debit per spread6.26
{{THESIS}}Trade thesisExtraordinary institutional...

Milestone Variables

For each milestone (M1, M1B, M1C, M1D, M2, M3, M3B, M4, M5, M6):

Variable PatternValues
{{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

VariableDescription
{{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:

  1. Set {{STATUS_TEXT}} to failing gate (e.g., "EDGE FAILED")
  2. Set {{STATUS_CLASS}} to negative
  3. Mark failed milestone with failed class
  4. Omit Structure & Kelly sections (not reached)
  5. Omit Trade Specification section
  6. 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:

  1. Fetches dark pool flow and options flow for context (via subprocess to fetch_flow.py / fetch_options.py)
  2. Connects to IB → fetches spot price, option chains, live greeks (25-50Δ puts and calls)
  3. Builds the full risk reversal matrix across 2-5 expirations (14-60 DTE)
  4. Computes IV skew per delta bucket per expiry
  5. Selects 3 recommendations: Primary (costless), Alternative (different expiry), Aggressive (credit)
  6. 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