# How to Generate Reports from the Daily Stock Analysis: Complete Implementation Guide

> Easily generate daily stock analysis reports with the NotificationService in ZhuLinsen/daily_stock_analysis. Convert analysis results into markdown, WeChat, or text formats.

- Repository: [mumu/daily_stock_analysis](https://github.com/ZhuLinsen/daily_stock_analysis)
- Tags: how-to-guide
- Published: 2026-04-30

---

**Use the `NotificationService` class in [`src/notification.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/notification.py) to convert `AnalysisResult` objects into markdown, WeChat, or brief text reports using methods like `generate_aggregate_report()` or `generate_daily_report()`.**

The `daily_stock_analysis` repository provides a flexible reporting pipeline that transforms stock analysis data into multiple output formats. By leveraging the `NotificationService` class and the underlying Jinja2-based `ReportRenderer`, you can programmatically generate everything from detailed decision dashboards to compact one-line summaries optimized for chat bots and SMS notifications.

## Prerequisites: Preparing Analysis Results

Before generating reports, you need a list of `AnalysisResult` objects. These are typically produced by the `Analyzer` class defined in **[`src/analyzer.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/analyzer.py)**.

```python
from typing import List
from src.analyzer import Analyzer
from src.schemas import AnalysisResult

# Example: Run analysis for multiple stock codes

codes = ["600519", "AAPL", "hk00700"]
results: List[AnalysisResult] = Analyzer().run(codes)

```

Each `AnalysisResult` contains fields such as `code`, `name`, `sentiment_score`, `operation_advice`, `trend_prediction`, and `dashboard` data that the reporting engine will format.

## Understanding Report Types

The system uses the `ReportType` enum defined in **[`src/enums.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/enums.py)** (lines 20-23) to determine output formatting. The available options are:

- **`SIMPLE`**: Generates brief one-line summaries per stock, ideal for chat bots or SMS limitations.
- **`FULL`** / **`DETAILED`**: Produces rich markdown dashboards suitable for email or web interfaces.
- **`BRIEF`**: Equivalent to `SIMPLE`, providing quick overviews without detailed metrics.

```python
from src.enums import ReportType

# Select based on your delivery channel

report_type = ReportType.FULL  # Options: SIMPLE, FULL, DETAILED, BRIEF

```

## Generating Reports with NotificationService

The `NotificationService` class in **[`src/notification.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/notification.py)** serves as the primary entry point for all report generation. It reads global configuration from [`src/config.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/config.py) and automatically detects available notification channels.

### Initialize the Service

```python
from src.notification import NotificationService

# Construction loads configuration but makes no network calls

notifier = NotificationService()

```

### Direct Report Methods

For specific formatting requirements, call the dedicated rendering methods directly:

**`generate_daily_report(results)`** (lines 525-635): Creates a comprehensive markdown report with full analysis details.

**`generate_dashboard_report(results)`** (lines 669-846): Generates a decision-dashboard format in rich markdown.

**`generate_wechat_dashboard(results)`** (lines 869-1055): Produces compact WeChat-compatible output with a ≤4000 character limit.

**`generate_brief_report(results)`** (lines 1066-1104): Outputs one-line summaries for quick scanning.

```python

# Full markdown report

markdown = notifier.generate_daily_report(results)

# WeChat-compatible compact version

wechat_msg = notifier.generate_wechat_dashboard(results)

# Brief one-liners for bots

brief = notifier.generate_brief_report(results)

```

### Convenience Wrapper Method

When you want the system to automatically select the appropriate format based on `ReportType`, use **`generate_aggregate_report()`** (lines 239-250). This method chooses between brief and dashboard formats automatically.

```python
from src.enums import ReportType

# Automatically selects dashboard for FULL/DETAILED, brief for SIMPLE/BRIEF

content = notifier.generate_aggregate_report(results, ReportType.SIMPLE)

```

## Template Customization with Jinja2

When `config.report_renderer_enabled` is `True`, the system delegates rendering to **[`src/services/report_renderer.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/services/report_renderer.py)**, which uses Jinja2 templates. If templates are missing, it falls back to native Python formatters.

The renderer loads templates from the directory specified by `config.report_templates_dir`, typically:

- **`templates/report_markdown.j2`**: For full markdown and dashboard reports.
- **`templates/report_wechat.j2`**: For WeChat-compatible output.

Custom templates receive a rich `context` dictionary containing:
- `results`: The analysis data
- `enriched`: Pre-computed localization data
- `labels`: Language-specific UI strings
- `report_language`, `summary_only`, `history_by_code`

## Complete Working Example

This end-to-end script demonstrates generating reports from the command line:

```python
#!/usr/bin/env python

# generate_report.py

import sys
import argparse
from typing import List

from src.analyzer import Analyzer
from src.notification import NotificationService
from src.enums import ReportType

def main(codes: List[str], typ: str = "full"):
    # Step 1: Analyze the stocks

    results = Analyzer().run(codes)
    
    # Step 2: Initialize the notification service

    notifier = NotificationService()
    
    # Step 3: Map string to ReportType enum

    try:
        report_type = ReportType.from_str(typ)
    except ValueError:
        print(f"Unsupported type '{typ}'. Choose from: simple, full, detailed, brief")
        sys.exit(1)
    
    # Step 4: Generate the report

    report = notifier.generate_aggregate_report(results, report_type)
    
    # Step 5: Output

    print(report)

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Generate stock analysis reports")
    parser.add_argument("codes", nargs="+", help="Stock codes to analyze")
    parser.add_argument("--type", default="full", 
                       help="Report type (simple|full|detailed|brief)")
    args = parser.parse_args()
    main(args.codes, args.type)

```

Execute with: `python generate_report.py 600519 AAPL --type full`

## Summary

- **`NotificationService`** in [`src/notification.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/notification.py) is the primary entry point for generating reports from `daily_stock_analysis`.
- **ReportType enum** controls output format: use `SIMPLE` or `BRIEF` for compact summaries, `FULL` or `DETAILED` for rich markdown dashboards.
- **Specific methods** like `generate_wechat_dashboard()` and `generate_daily_report()` provide direct access to specific formats.
- **`generate_aggregate_report()`** automatically selects the appropriate formatter based on the requested `ReportType`.
- **Jinja2 templates** in the `templates/` directory allow full customization of markdown and WeChat outputs, with fallback to native Python formatting if templates are unavailable.

## Frequently Asked Questions

### What is the difference between `generate_daily_report` and `generate_dashboard_report`?

`generate_daily_report()` (lines 525-635) produces a comprehensive markdown document containing all analysis fields and historical context, suitable for detailed review. `generate_dashboard_report()` (lines 669-846) generates a decision-focused dashboard format that emphasizes actionable insights and trend predictions in a structured layout.

### How do I customize the report templates?

Create custom Jinja2 templates in the directory specified by your `config.report_templates_dir` setting (default: `templates/`). Name them `report_markdown.j2` for standard reports or `report_wechat.j2` for WeChat output. The `ReportRenderer` in [`src/services/report_renderer.py`](https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/src/services/report_renderer.py) will automatically load your templates and inject the analysis context dictionary.

### What happens if the Jinja2 template is missing?

The `ReportRenderer` implements graceful fallback behavior. If the configured template file cannot be found or if `config.report_renderer_enabled` is `False`, the system automatically falls back to the internal Python formatter methods defined in `NotificationService`, ensuring reports are always generated even without custom templates.

### How do I generate a report for specific notification channels?

Use `generate_wechat_dashboard()` for WeChat messages (automatically handles the 4000-character limit), `generate_brief_report()` for SMS or bot integrations, or `generate_daily_report()` for email attachments. Alternatively, pass a `ReportType` value to `generate_aggregate_report()` to let the service automatically select the appropriate format for your target channel.