> ## Documentation Index
> Fetch the complete documentation index at: https://condor.hummingbot.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Reports

> Generate HTML reports with interactive charts from routines

Routines can generate HTML reports with interactive Plotly charts and markdown content. Reports are viewable in the Condor web dashboard, providing a richer experience than Telegram messages for data visualization.

## Why Reports?

| Channel      | Best For                                                 |
| ------------ | -------------------------------------------------------- |
| **Telegram** | Quick notifications, mobile alerts, simple text          |
| **Reports**  | Interactive charts, detailed analysis, scheduled outputs |

When you schedule a routine to run every hour, you may not want 24 Telegram messages per day. Instead, generate reports and check them in the dashboard when convenient.

## Viewing Reports

Reports appear in the Condor web dashboard under **Routines** → **Reports**. Open one in the full-screen viewer and use the **left/right arrow keys** to step through a routine's report history.

Each report includes:

* Title and creation time
* Source routine name and tags
* Interactive HTML content (zoomable charts, expandable sections)

<Note>
  Condor keeps a rolling buffer of the most recent reports (default 100, set by the `CONDOR_MAX_REPORTS` environment variable). Older reports are cleaned up automatically.
</Note>

## Creating Reports

### 1. Import ReportBuilder

```python theme={null}
from condor.reports import ReportBuilder
```

### 2. Generate Your Data

Create figures and tables as you normally would:

```python theme={null}
import plotly.graph_objects as go

fig = go.Figure()
fig.add_trace(go.Scatter(x=dates, y=prices, name="Price"))
fig.update_layout(title="Market Analysis")
```

### 3. Build the Report

`ReportBuilder` takes a title, and its methods are chainable. Tag the report with its source, add sections, then `await save()`:

```python theme={null}
builder = ReportBuilder("Analysis Summary")
builder.source("routine", "my_routine").tags(["analysis"])
builder.markdown("## Analysis Summary\n\nKey findings from today's scan.")
builder.plotly(fig)
builder.table([{"symbol": "SOL", "change": "+4.2%"}])
await builder.save()
```

## Complete Example

```python theme={null}
# routines/price_snapshot.py
from pydantic import BaseModel, Field
from telegram.ext import ContextTypes
import plotly.graph_objects as go

from config_manager import get_client
from condor.reports import ReportBuilder


class Config(BaseModel):
    """Snapshot prices for a set of pairs and save a report."""

    exchange: str = Field(default="binance_perpetual", description="Exchange to query")
    pairs: list[str] = Field(
        default=["BTC-USDT", "ETH-USDT", "SOL-USDT"],
        description="Trading pairs to snapshot",
    )


async def run(config: Config, context: ContextTypes.DEFAULT_TYPE) -> str:
    chat_id = context._chat_id if hasattr(context, "_chat_id") else None
    client = await get_client(chat_id, context=context)

    if not client:
        return "No server available"

    prices = await client.market_data.get_prices(config.exchange, config.pairs)
    rows = [{"pair": pair, "price": price} for pair, price in prices.items()]

    fig = go.Figure(go.Bar(x=[r["pair"] for r in rows], y=[r["price"] for r in rows]))
    fig.update_layout(title=f"Prices on {config.exchange}")

    builder = ReportBuilder(f"Price Snapshot — {config.exchange}")
    builder.source("routine", "price_snapshot").tags(["prices"])
    builder.markdown(f"## Prices on {config.exchange}")
    builder.plotly(fig)
    builder.table(rows)
    await builder.save()

    # Return text for Telegram
    return f"Saved price snapshot for {len(rows)} pairs"
```

## ReportBuilder Methods

All methods return the builder, so they can be chained.

| Method                                           | Description                                                         |
| ------------------------------------------------ | ------------------------------------------------------------------- |
| `source(source_type, source_name)`               | Tag where the report came from (e.g. `"routine", "price_snapshot"`) |
| `tags(tags)`                                     | Attach a list of string tags                                        |
| `kpi(label, value, delta=None, trend="neutral")` | Add a KPI tile                                                      |
| `markdown(text)`                                 | Add markdown-formatted text                                         |
| `plotly(fig)`                                    | Add a Plotly figure (interactive in HTML)                           |
| `table(rows, columns=None)`                      | Add a table from a list of dicts                                    |
| `await save(report_id=None)`                     | Write the report to disk; pass an existing id to update in place    |

## Use Cases

### Scheduled Market Analysis

Run a routine every hour to analyze market conditions:

```
/routines → technical_analysis → Schedule → Every 1 hour
```

Instead of 24 Telegram messages, check the reports dashboard for the latest analysis with interactive charts.

### Agent Decision Logging

When an agent runs a routine for analysis, the report captures what the agent "saw" when making decisions:

```python theme={null}
builder = ReportBuilder("Agent Analysis")
builder.source("routine", "bb_trader_analysis").tags(["agent"])
builder.markdown(f"## Agent Analysis\n\nCurrent price: ${price}\n\nSignal: {signal}")
builder.plotly(indicator_chart)
await builder.save()
```

This helps you understand and debug agent behavior by reviewing the data it analyzed.

### Comparing Tokens

Build research routines that compare multiple assets:

```python theme={null}
builder = ReportBuilder("Solana DEX Token Comparison")
builder.source("routine", "dex_comparison").tags(["solana", "dex"])
builder.markdown("## Solana DEX Token Comparison")
builder.plotly(market_cap_chart)
builder.plotly(fee_revenue_chart)
builder.table(comparison_rows)
await builder.save()
```

## Report Storage

Reports are written as HTML files to the `reports/` directory in your Condor install (`~/condor/reports/`), with an index in `reports_index.json`. The web dashboard reads from this directory.

```bash theme={null}
ls ~/condor/reports/
# 20260115_143000_price-snapshot_a1b2c3.html
# 20260115_150000_market-scanner_d4e5f6.html
```

To clean up reports manually:

```bash theme={null}
rm ~/condor/reports/*.html
```

Or use the dashboard's cleanup function under **Routines** → **Reports** → **Clean**.
