Skip to content

Dashboards

ProgridPy includes a Streamlit-based interactive dashboard and an HTML export feature for sharing metrics reports. Both are built on the MetricsPlots visualization layer which produces Plotly figures.

Streamlit Dashboard

Launching the Dashboard

from progridpy.metrics import MetricsEngine, StreamlitDashboard

engine = MetricsEngine(iso_name="MISO", df_iso=trade_df)
dashboard = StreamlitDashboard(engine=engine)
dashboard.render()

Run the script with Streamlit:

streamlit run your_dashboard_script.py

Dashboard Layout

The render() method produces a full-page Streamlit application with the following sections:

Section Content
Title ISO name and date range
KPI Cards Cumulative PnL, Last Day Gain, Estimated Risk, Max Drawdown
Performance Chart 3-pane interactive chart: cumulative gains, drawdowns, daily gains
Supply/Demand Toggle Checkboxes to show total, supply, and demand curves independently
Histograms Tabbed view: Daily, 30d, and 365d gain distributions
Performance Summary Table comparing YTD vs. Historical metrics
Detailed Metrics Full metrics table with Amount and Ratio columns
Calendar Year Gains Annual cumulative gains overlay chart
Heatmaps GitHub-style daily gains heatmap across all years

Custom Time Frames

By default, the dashboard shows three columns: Overall, YTD, and Historical. You can override this with custom TimeFrameRange objects:

from datetime import date
from progridpy.metrics import MetricsEngine, StreamlitDashboard, TimeFrameRange

engine = MetricsEngine(iso_name="SPP", df_iso=trade_df)

dashboard = StreamlitDashboard(
    engine=engine,
    time_frames=[
        TimeFrameRange(label="H1 2025", start_date=date(2025, 1, 1), end_date=date(2025, 6, 30)),
        TimeFrameRange(label="H2 2025", start_date=date(2025, 7, 1), end_date=date(2025, 12, 31)),
        TimeFrameRange(label="Q1 2026", start_date=date(2026, 1, 1), end_date=date(2026, 3, 31)),
    ],
)
dashboard.render()

Time frame limits

You can provide between 1 and 3 TimeFrameRange objects. The constructor raises ValueError if the count is outside this range.

Adding a Description

Pass a description string to display explanatory text at the top of the dashboard:

dashboard = StreamlitDashboard(
    engine=engine,
    description="MISO Day-Ahead Virtual Trading Backtest -- Full Node Universe",
)
dashboard.render()

HTML Export

Export the dashboard to a standalone HTML file that can be opened in any browser. All Plotly charts remain fully interactive (hover, zoom, pan) with Plotly.js embedded in the file.

from progridpy.metrics import MetricsEngine, StreamlitDashboard

engine = MetricsEngine(iso_name="MISO", df_iso=trade_df)
dashboard = StreamlitDashboard(engine=engine)
dashboard.export_html("trading_report.html")

The exported HTML includes:

  • Title with ISO name and date range
  • KPI summary cards
  • Performance chart (cumulative gains, drawdowns, daily gains)
  • Gain distribution histograms
  • Detailed metrics table
  • Calendar year gains chart
  • Daily gains heatmap

Command-Line Export

Use the provided scripts for command-line export:

# MISO dashboard
python scripts/miso/dashboard.py -t ./trades -p ./processed --export report.html

# Or launch interactively
streamlit run scripts/miso/dashboard.py -- -t ./trades -p ./processed

MetricsPlots

For programmatic access to individual charts, use the MetricsPlots class directly through the engine's plots property:

from progridpy.metrics import MetricsEngine

engine = MetricsEngine(iso_name="MISO", df_iso=trade_df)
engine.compute()

plots = engine.plots

Available Charts

Performance Chart

A 3-pane chart with shared x-axis showing cumulative gains, drawdowns, and daily gains:

fig = plots.performance_chart(
    show_total=True,     # Total cumulative gains line
    show_supply=True,    # Supply-only cumulative gains
    show_demand=True,    # Demand-only cumulative gains
)
fig.show()

When a single series is selected (e.g., supply only), the drawdown and daily gains panes update to reflect that specific series.

Gains Histogram

Distribution histogram with KDE overlay, per-year breakdown, mean/median lines, and percentile markers (P1, P5, P10, P25, P75, P90, P95, P99):

fig = plots.gains_histogram("daily")    # Daily gains distribution
fig = plots.gains_histogram("7d")       # 7-day rolling gains
fig = plots.gains_histogram("30d")      # 30-day rolling gains
fig = plots.gains_histogram("90d")      # 90-day rolling gains
fig = plots.gains_histogram("365d")     # 365-day rolling gains

Overlay actual trading data for comparison:

fig = plots.gains_histogram("30d", actual_series=actual_daily_gains)

Cumulative Gains by Year

Annual cumulative gains overlay -- each year is a separate colored line normalized to start at 0 on day 1:

fig = plots.cumulative_gains_by_year()

Daily Gains Bar Chart

Recent daily gains as green/red bars:

fig = plots.daily_gains_bar_chart(30)             # Last 30 days
fig = plots.daily_gains_bar_chart(90)             # Last 90 days
fig = plots.daily_gains_bar_chart("latest_year")  # All days in the latest year

Daily Gains Heatmap

GitHub-style heatmap showing daily gains for a single year (weeks x days of week):

fig = plots.daily_gains_heatmap(2026)

Or a combined heatmap across all years:

fig = plots.daily_gains_heatmap_combined()

Quantile Box Plots

Box plots showing gain distributions across daily, weekly, monthly, quarterly, and yearly periods:

fig = plots.quantile_box_plots()

Saving Individual Figures

All chart methods return standard Plotly Figure objects:

import plotly.io as pio

fig = plots.performance_chart()
pio.write_html(fig, "performance.html")
pio.write_image(fig, "performance.png", width=1200, height=800)