How to Generate Reports from the Daily Stock Analysis: Complete Implementation Guide
Use the NotificationService class in 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.
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 (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 toSIMPLE, providing quick overviews without detailed metrics.
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 serves as the primary entry point for all report generation. It reads global configuration from src/config.py and automatically detects available notification channels.
Initialize the Service
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.
# 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.
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, 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 dataenriched: Pre-computed localization datalabels: Language-specific UI stringsreport_language,summary_only,history_by_code
Complete Working Example
This end-to-end script demonstrates generating reports from the command line:
#!/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
NotificationServiceinsrc/notification.pyis the primary entry point for generating reports fromdaily_stock_analysis.- ReportType enum controls output format: use
SIMPLEorBRIEFfor compact summaries,FULLorDETAILEDfor rich markdown dashboards. - Specific methods like
generate_wechat_dashboard()andgenerate_daily_report()provide direct access to specific formats. generate_aggregate_report()automatically selects the appropriate formatter based on the requestedReportType.- 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →