Skip to content

Automated Report Distribution

This guide explains how to set up and use the automated report distribution system in DSTA.

Overview

The report scheduler automatically generates and distributes trading reports via:

  • Email (SMTP)
  • Telegram Bot
  • Local file storage
  • Report archiving with retention policies

Supports daily, weekly, and monthly schedules with customizable templates.

Quick Start

1. Configuration

Set up environment variables for email and Telegram:

# Email configuration
export SMTP_HOST="smtp.gmail.com"
export SMTP_PORT="587"
export SMTP_USERNAME="your-email@gmail.com"
export SMTP_PASSWORD="your-app-password"

# Telegram configuration
export TELEGRAM_BOT_TOKEN="your-bot-token"

2. Basic Usage

from src.analytics.report_scheduler import (
    ReportDistributor,
    ReportScheduler,
    ReportConfig,
)
from src.analytics.reports.daily import DailyReportGenerator

# Create distributor
distributor = ReportDistributor()

# Create scheduler
scheduler = ReportScheduler(distributor)

# Define report generator
def generate_daily_report():
    generator = DailyReportGenerator()
    # ... load your data
    report = generator.generate_report(...)
    return report

# Configure report
config = ReportConfig(
    name='Daily Trading Summary',
    report_type='daily',
    generator=generate_daily_report,
    schedule_type='daily',
    schedule_time='18:00',  # 6 PM every day
    email_enabled=True,
    email_recipients=['trader@example.com'],
    formats=['html', 'text'],
)

# Add to scheduler
scheduler.add_report(config)

# Run scheduler (blocking)
scheduler.run()

Configuration Options

ReportConfig

Complete configuration options:

config = ReportConfig(
    # Basic settings
    name='My Report',               # Report name
    report_type='daily',            # 'daily', 'monthly', 'custom'
    generator=my_generator_func,    # Callable that returns report

    # Schedule
    schedule_type='daily',          # 'daily', 'weekly', 'monthly'
    schedule_time='09:00',          # Time in HH:MM format

    # Email distribution
    email_enabled=True,
    email_recipients=[
        'trader1@example.com',
        'trader2@example.com',
    ],

    # Telegram distribution
    telegram_enabled=True,
    telegram_chat_ids=[
        '123456789',    # Get from Telegram
        '987654321',
    ],

    # File storage
    file_enabled=True,
    file_path=Path('reports/daily'),

    # Export formats
    formats=['html', 'text', 'json'],

    # Archiving
    archive_enabled=True,
    archive_path=Path('reports/archive/daily'),
    archive_retention_days=90,      # Keep for 90 days

    # Error handling
    retry_on_failure=True,
    max_retries=3,
    retry_delay_minutes=5,
)

Schedule Types

Daily Reports

config = ReportConfig(
    name='Daily Summary',
    schedule_type='daily',
    schedule_time='18:00',  # Every day at 6 PM
    ...
)

Weekly Reports

config = ReportConfig(
    name='Weekly Analysis',
    schedule_type='weekly',
    schedule_time='monday 09:00',  # Every Monday at 9 AM
    ...
)

Monthly Reports

config = ReportConfig(
    name='Monthly Performance',
    schedule_type='monthly',
    schedule_time='09:00',  # First of month at 9 AM
    ...
)

Distribution Channels

Email

Gmail Setup

  1. Enable 2-factor authentication
  2. Generate app-specific password
  3. Configure environment:
export SMTP_HOST="smtp.gmail.com"
export SMTP_PORT="587"
export SMTP_USERNAME="your-email@gmail.com"
export SMTP_PASSWORD="your-app-password"

Custom SMTP Server

distributor = ReportDistributor(
    smtp_host='mail.yourcompany.com',
    smtp_port=587,
    smtp_username='reports@yourcompany.com',
    smtp_password='password',
)

Email Content

Emails include: - HTML formatted report (primary) - Plain text version (fallback) - Attachments (optional)

Telegram

Bot Setup

  1. Create bot with @BotFather
  2. Get bot token
  3. Get your chat ID:
  4. Message @userinfobot
  5. Or check https://api.telegram.org/bot{TOKEN}/getUpdates

Configuration

config = ReportConfig(
    telegram_enabled=True,
    telegram_chat_ids=['YOUR_CHAT_ID'],
    ...
)

Telegram Message Format

Telegram messages include: - Report title and timestamp - Summary (first few lines) - Full report as attachment (optional) - HTML formatting supported

File Storage

Reports are saved locally:

config = ReportConfig(
    file_enabled=True,
    file_path=Path('reports/daily'),
    formats=['html', 'text', 'json'],
)

Files are named: {report_name}_{timestamp}.{format}

Example: Daily_Trading_Summary_20260126_180000.html

Report Generators

Daily Report

from src.analytics.reports.daily import DailyReportGenerator

def generate_daily():
    generator = DailyReportGenerator()

    # Load data for today
    portfolio = load_portfolio_data()
    trades = load_trades_data()
    positions = load_positions()

    return generator.generate_report(
        date=datetime.now().date(),
        portfolio=portfolio,
        trades=trades,
        positions=positions,
    )

Monthly Report

from src.analytics.reports.monthly import MonthlyReportGenerator

def generate_monthly():
    generator = MonthlyReportGenerator()

    # Load data for current month
    year = datetime.now().year
    month = datetime.now().month

    portfolio_values = load_monthly_portfolio()
    trades = load_monthly_trades()

    return generator.generate_report(
        year=year,
        month=month,
        portfolio_values=portfolio_values,
        trades=trades,
    )

Custom Report

def generate_custom():
    """Your custom report generator."""
    # Generate report data
    data = analyze_trading_performance()

    # Create report object with export methods
    class CustomReport:
        def export_html(self, report):
            return "<html>...</html>"

        def export_text(self, report):
            return "Text report..."

    return CustomReport()

Running the Scheduler

As a Background Service

# scheduler.py
import logging
from src.analytics.report_scheduler import ReportScheduler, ReportDistributor

logging.basicConfig(level=logging.INFO)

distributor = ReportDistributor()
scheduler = ReportScheduler(distributor)

# Add all your reports
scheduler.add_report(daily_config)
scheduler.add_report(weekly_config)
scheduler.add_report(monthly_config)

# Run forever
scheduler.run()  # Blocking

Run as daemon:

python scheduler.py &

With systemd

Create /etc/systemd/system/dsta-reports.service:

[Unit]
Description=DSTA Report Scheduler
After=network.target

[Service]
Type=simple
User=dsta
WorkingDirectory=/path/to/dsta
ExecStart=/path/to/python scheduler.py
Restart=always

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable dsta-reports
sudo systemctl start dsta-reports
sudo systemctl status dsta-reports

Manual Execution

Run report once (for testing):

# Run specific report
scheduler.run_once('Daily Trading Summary')

# Run all reports
scheduler.run_once()

Archive Management

Reports are automatically archived with configurable retention:

config = ReportConfig(
    archive_enabled=True,
    archive_path=Path('reports/archive/daily'),
    archive_retention_days=90,  # Keep for 90 days
    ...
)

Archive structure:

reports/
└── archive/
    ├── daily/
    │   ├── 20260126_180000.html
    │   ├── 20260126_180000.text
    │   └── ...
    └── monthly/
        ├── 20260101_090000.html
        └── ...

Old reports are automatically deleted after retention period.

Error Handling

Retry Configuration

config = ReportConfig(
    retry_on_failure=True,
    max_retries=3,
    retry_delay_minutes=5,
    ...
)

If report generation or distribution fails: 1. Logs error 2. Waits retry_delay_minutes 3. Retries up to max_retries times 4. Logs final failure if all attempts fail

Monitoring

Check logs for issues:

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('reports.log'),
        logging.StreamHandler(),
    ]
)

Complete Example

#!/usr/bin/env python3
"""
DSTA Report Scheduler
Automated daily and monthly reports via email and Telegram.
"""

import logging
from pathlib import Path
from datetime import datetime
from src.analytics.report_scheduler import (
    ReportDistributor,
    ReportScheduler,
    ReportConfig,
)
from src.analytics.reports.daily import DailyReportGenerator
from src.analytics.reports.monthly import MonthlyReportGenerator

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/reports.log'),
        logging.StreamHandler(),
    ]
)

# Create distributor
distributor = ReportDistributor()

# Create scheduler
scheduler = ReportScheduler(distributor)

# Daily report generator
def generate_daily():
    generator = DailyReportGenerator()
    # TODO: Load your actual data
    return generator.generate_report(...)

# Monthly report generator
def generate_monthly():
    generator = MonthlyReportGenerator()
    # TODO: Load your actual data
    return generator.generate_report(...)

# Configure daily report
daily_config = ReportConfig(
    name='Daily Trading Summary',
    report_type='daily',
    generator=generate_daily,
    schedule_type='daily',
    schedule_time='18:00',
    email_enabled=True,
    email_recipients=['trader@example.com'],
    telegram_enabled=True,
    telegram_chat_ids=['123456789'],
    formats=['html', 'text'],
    archive_retention_days=30,
)

# Configure monthly report
monthly_config = ReportConfig(
    name='Monthly Performance Report',
    report_type='monthly',
    generator=generate_monthly,
    schedule_type='monthly',
    schedule_time='09:00',
    email_enabled=True,
    email_recipients=['trader@example.com', 'manager@example.com'],
    formats=['html', 'json'],
    archive_retention_days=365,
)

# Add reports to scheduler
scheduler.add_report(daily_config)
scheduler.add_report(monthly_config)

# Run scheduler
if __name__ == '__main__':
    logging.info("Starting DSTA Report Scheduler...")
    scheduler.run()

Troubleshooting

Email not sending

  1. Check SMTP credentials
  2. Verify 2FA and app password (Gmail)
  3. Check firewall/port 587
  4. Review logs for error details

Telegram not sending

  1. Verify bot token
  2. Check chat ID
  3. Ensure bot is in group (for group chats)
  4. Test with curl:
    curl -X POST \
      "https://api.telegram.org/bot{TOKEN}/sendMessage" \
      -d "chat_id={CHAT_ID}" \
      -d "text=Test message"
    

Reports not generated

  1. Check report generator function
  2. Verify data sources are accessible
  3. Review logs for exceptions
  4. Test generator manually:
    report = generate_daily()
    print(report.export_text(report))
    

Schedule not running

  1. Verify schedule_time format
  2. Check scheduler is running
  3. Test with run_once() first
  4. Review system time zone

Best Practices

  1. Test generators before scheduling
  2. Start with file distribution then add email/Telegram
  3. Monitor logs regularly
  4. Set appropriate retention for archives
  5. Use retry logic for critical reports
  6. Keep credentials secure (use environment variables)
  7. Test email templates across devices
  8. Document custom generators for maintenance

Security

  • Never commit credentials to git
  • Use environment variables or secret managers
  • Restrict file permissions on config files
  • Use app-specific passwords (Gmail)
  • Rotate Telegram bot tokens periodically
  • Monitor for failed delivery attempts

Support

For issues with report scheduling:

  1. Check logs in logs/reports.log
  2. Verify configuration
  3. Test individual components
  4. Open GitHub issue with details