Aekor

Aekor
专注于用户阅读体验的响应式博客主题
  1. 首页
  2. TradingAgents-CN
  3. 正文

TradingAgents-CN 项目优化:报告多格式导出、新增系统日志模块、数据同步进度优化,数据源优先级统一(10-29)

2025-10-30 11039点热度 0人点赞 0条评论

一、升级概览

2025 年 10 月 29 日,TradingAgents-CN 完成了一次重要的 系统功能完善 工作。

本次更新通过 21 个提交,完成了 数据源优先级统一、报告多格式导出、系统日志管理、数据同步进度优化 等多项功能,显著提升了系统的 数据一致性、功能完整性、可维护性和用户体验。

核心改进

  • 数据源优先级统一:所有 stock_basic_info 查询统一使用数据源优先级。
  • 报告多格式导出:支持 Markdown、JSON、DOCX、PDF 四种格式。
  • 系统日志模块:支持日志查看、过滤、统计、下载和批量导出。
  • 日志配置统一:日志配置迁移到 TOML 文件,支持 Docker 环境。
  • 数据同步进度优化:增加多数据源同步详细进度日志。
  • 前端体验优化:报告下载改为下拉菜单,日志管理新增可视化页面。

二、数据源优先级统一

2.1 问题背景

相关提交:

  • be56c32:所有 stock_basic_info 查询统一使用 数据源优先级。

此前系统中多个地方会查询股票基本信息,但没有统一遵循数据源优先级配置,导致不同接口返回的数据可能来自不同数据源。

主要问题

数据不一致

同一股票代码在不同接口中可能返回不同数据源的数据,用户看到的信息可能不一致。

优先级配置被忽视

用户在系统设置中配置的数据源优先级没有被完全应用,部分接口仍然使用硬编码数据源。

影响范围广

受影响的接口和模块包括:

  • 股票搜索接口。
  • 股票列表接口。
  • 股票筛选接口。
  • 自选股接口。
  • 股票行情接口。
  • MongoDB 缓存适配器。

2.2 解决方案

统一数据源查询逻辑

async def search_stocks(q: str, limit: int = 10):
    """搜索股票,使用数据源优先级"""
    configs = await UnifiedConfigManager.get_data_source_configs_async()
    sorted_configs = sorted(configs, key=lambda x: x.priority, reverse=True)

    if sorted_configs:
        primary_source = sorted_configs[0].source
        return await get_stock_list(q, source=primary_source, limit=limit)

修改所有查询接口

本次统一改造了以下模块:

  • app/routers/stock_data.py:search_stocks 接口。
  • app/routers/stocks.py:get_quote 接口。
  • app/services/stock_data_service.py:get_stock_list 方法。
  • app/services/database_screening_service.py:screen 方法。
  • app/services/favorites_service.py:get_user_favorites 方法。
  • tradingagents/dataflows/cache/mongodb_cache_adapter.py:get_stock_basic_info 方法。

兼容旧数据

对于没有 source 字段的旧数据,系统会补充默认数据源。

if not record.get('source'):
    record['source'] = primary_source

2.3 优化效果

  • 所有查询都遵循数据源优先级。
  • 用户在系统设置中的配置可以完整生效。
  • 不同接口返回的数据更加一致。
  • 数据来源更加清晰可控。

三、报告多格式导出功能

3.1 功能背景

相关提交:

  • 62126b6:添加 PDF 和 Word 格式报告导出 功能。
  • 264d7b0:增加 PDF 打包能力。
  • 6532b5a:Dockerfile 添加 wkhtmltopdf 支持 PDF 导出。
  • ee78839:使用 GitHub 直接下载 pandoc 和 wkhtmltopdf。

此前报告主要支持原始格式下载,无法满足不同场景下的分享、归档和编辑需求。

3.2 支持的导出格式

本次新增后,报告支持 4 种导出格式:

格式用途
Markdown原始文本格式,便于编辑和版本管理
JSON数据格式,适合系统集成和二次处理
DOCXWord 文档,适合编辑、归档和分享
PDF便携式文档,适合正式分发和阅读

3.3 后端实现

新增 ReportExporter 报告导出工具类。

class ReportExporter:
    """报告导出工具类"""

    @staticmethod
    async def export_markdown(report: Report) -> bytes:
        """导出为 Markdown 格式"""
        content = f"# {report.title}\n\n{report.content}"
        return content.encode('utf-8')

    @staticmethod
    async def export_json(report: Report) -> bytes:
        """导出为 JSON 格式"""
        data = {
            "title": report.title,
            "content": report.content,
            "created_at": report.created_at.isoformat(),
            "analysts": report.analysts,
            "model": report.model
        }
        return json.dumps(data, ensure_ascii=False, indent=2).encode('utf-8')

    @staticmethod
    async def export_docx(report: Report) -> bytes:
        """导出为 DOCX 格式"""
        md_content = await ReportExporter.export_markdown(report)
        docx_content = subprocess.run(
            ['pandoc', '-f', 'markdown', '-t', 'docx'],
            input=md_content,
            capture_output=True
        ).stdout
        return docx_content

    @staticmethod
    async def export_pdf(report: Report) -> bytes:
        """导出为 PDF 格式"""
        html_content = markdown.markdown(report.content)
        pdf_content = subprocess.run(
            ['wkhtmltopdf', '-', '-'],
            input=html_content.encode('utf-8'),
            capture_output=True
        ).stdout
        return pdf_content

3.4 下载接口改造

@router.get("/reports/{report_id}/download")
async def download_report(report_id: str, format: str = "markdown"):
    """下载报告,支持多种格式"""
    report = await get_report(report_id)

    exporter = ReportExporter()

    if format == "markdown":
        content = await exporter.export_markdown(report)
        media_type = "text/markdown"
        filename = f"{report.title}.md"
    elif format == "json":
        content = await exporter.export_json(report)
        media_type = "application/json"
        filename = f"{report.title}.json"
    elif format == "docx":
        content = await exporter.export_docx(report)
        media_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
        filename = f"{report.title}.docx"
    elif format == "pdf":
        content = await exporter.export_pdf(report)
        media_type = "application/pdf"
        filename = f"{report.title}.pdf"

    return StreamingResponse(
        iter([content]),
        media_type=media_type,
        headers={"Content-Disposition": f"attachment; filename={filename}"}
    )

3.5 前端下拉菜单

报告详情页将下载按钮改为下拉菜单。

<el-dropdown @command="handleDownload">
  <el-button type="primary">
    下载报告
  </el-button>
  <template #dropdown>
    <el-dropdown-menu>
      <el-dropdown-item command="markdown">Markdown</el-dropdown-item>
      <el-dropdown-item command="json">JSON</el-dropdown-item>
      <el-dropdown-item command="docx">Word (DOCX)</el-dropdown-item>
      <el-dropdown-item command="pdf">PDF</el-dropdown-item>
    </el-dropdown-menu>
  </template>
</el-dropdown>

3.6 Docker 镜像配置

Docker 后端镜像中加入导出依赖。

RUN apt-get update && apt-get install -y \
    pandoc \
    wkhtmltopdf \
    fonts-noto-cjk \
    && rm -rf /var/lib/apt/lists/*

3.7 优化效果

  • 支持 4 种报告导出格式。
  • 用户可根据场景选择适合格式。
  • Word 和 PDF 适合正式分享与归档。
  • Docker 镜像内置导出依赖,部署后即可使用。

四、系统日志导出功能

4.1 功能背景

相关提交:

  • 98d173b:添加 系统日志导出功能。
  • 7205e52:统一日志配置到 TOML,支持 Docker 环境生成 tradingagents.log。
  • c93c20c:修复 Docker 环境下日志导出服务找不到日志文件的问题。

用户反馈问题时,往往不方便查看和导出日志。为提升问题定位效率,本次新增 系统日志管理模块。

4.2 后端日志服务

新增 LogExportService,支持日志文件列表、内容读取、导出和统计。

class LogExportService:
    """日志导出服务"""

    async def get_log_files(self) -> List[Dict]:
        """获取日志文件列表"""
        log_dir = Path(self.log_directory)
        files = []

        for log_file in log_dir.glob("*.log"):
            stat = log_file.stat()
            files.append({
                "filename": log_file.name,
                "size": stat.st_size,
                "modified": stat.st_mtime,
                "lines": self._count_lines(log_file)
            })

        return files

    async def read_logs(
        self,
        filename: str,
        level: Optional[str] = None,
        keyword: Optional[str] = None,
        lines: int = 100
    ) -> str:
        """读取日志内容,支持过滤"""
        log_file = self.log_directory / filename

        with open(log_file, 'r', encoding='utf-8') as f:
            all_lines = f.readlines()

        filtered_lines = all_lines

        if level:
            filtered_lines = [l for l in filtered_lines if level in l]
        if keyword:
            filtered_lines = [l for l in filtered_lines if keyword in l]

        return ''.join(filtered_lines[-lines:])

日志统计支持:

  • 日志文件数量。
  • 日志总大小。
  • ERROR 数量。
  • WARNING 数量。
  • INFO 数量。

4.3 后端 API

新增日志相关 API:

@router.get("/api/system/logs/files")
async def get_log_files():
    """获取日志文件列表"""

@router.post("/api/system/logs/read")
async def read_logs(request: ReadLogsRequest):
    """读取日志内容"""

@router.post("/api/system/logs/export")
async def export_logs(request: ExportLogsRequest):
    """导出日志文件"""

@router.get("/api/system/logs/statistics")
async def get_statistics():
    """获取日志统计"""

4.4 前端日志管理页面

新增 LogManagement.vue 页面,提供:

  • 日志统计信息展示
  • 日志文件列表
  • 在线查看日志内容
  • 按日志级别过滤
  • 按关键词搜索
  • 按行数限制读取
  • 单个日志下载
  • 批量日志导出

前端筛选项包括:

  • 日志级别:全部、ERROR、WARNING、INFO。
  • 关键词。
  • 行数限制。
  • 刷新按钮。

4.5 日志配置统一到 TOML

日志配置迁移到 TOML 文件,方便在本地与 Docker 环境中统一管理。

[handlers.file_main]
class = "logging.handlers.RotatingFileHandler"
filename = "/app/logs/tradingagents.log"
maxBytes = 10485760
backupCount = 5
formatter = "standard"

[handlers.file_webapi]

class = "logging.handlers.RotatingFileHandler" filename = "/app/logs/webapi.log" maxBytes = 10485760 backupCount = 5 formatter = "standard"

[handlers.file_error]

class = "logging.handlers.RotatingFileHandler" filename = "/app/logs/error.log" maxBytes = 10485760 backupCount = 5 formatter = "standard"

[loggers.tradingagents]

level = "INFO" handlers = ["console", "file_main"] propagate = false

4.6 优化效果

  • 用户可以在界面查看日志。
  • 支持多种过滤条件。
  • 支持日志导出和下载。
  • 日志配置统一管理。
  • Docker 环境完整支持。
  • 问题反馈和远程排查更方便。

五、数据同步进度优化

5.1 问题背景

相关提交:

  • 49f2d39:增加 多数据源同步详细进度日志。

此前数据同步过程中缺少清晰的进度反馈:

  • 用户不知道同步进行到哪里。
  • 无法估算还需要等待多久。
  • 同步失败位置难以定位。
  • 错误统计不清楚。

5.2 BaoStock 适配器增加进度日志

def sync_stock_data(self, symbols: List[str]):
    """同步股票数据,添加进度日志"""
    total = len(symbols)
    success_count = 0
    fail_count = 0

    for i, symbol in enumerate(symbols):
        try:
            data = self._fetch_data(symbol)
            success_count += 1
        except Exception as e:
            fail_count += 1

            if fail_count % 50 == 0:
                logger.warning(f"已失败 {fail_count} 次")

        if (i + 1) % 50 == 0:
            progress = (i + 1) / total * 100
            logger.info(f"同步进度: {progress:.1f}% ({i + 1}/{total}), 最新: {symbol}")

    logger.info(f"同步完成: 成功 {success_count}, 失败 {fail_count}")

5.3 多数据源同步服务增加进度日志

async def sync_all_sources(self, symbols: List[str]):
    """同步所有数据源,添加进度日志"""
    logger.info(f"开始同步 {len(symbols)} 只股票")

    for source in self.sources:
        logger.info(f"处理数据源: {source.name}")

        for i in range(0, len(symbols), 100):
            batch = symbols[i:i+100]
            progress = (i + 100) / len(symbols) * 100
            logger.info(f"批量写入进度: {progress:.1f}%")
            await self.write_batch(batch)

        logger.info(f"{source.name} 同步完成")

5.4 前端超时调整

同步接口超时时间从 2 分钟增加到 10 分钟。

const syncRequest = axios.create({
  timeout: 10 * 60 * 1000
})

5.5 优化效果

  • 同步过程有更详细的进度反馈。
  • 用户等待体验更好。
  • 同步失败位置更容易定位。
  • 错误统计更加清晰。
  • 长时间同步任务不容易被前端误判为超时失败。

六、统计数据

6.1 提交统计

指标数量
总提交数21
修改文件数40+
新增代码2500+ 行
删除代码300+ 行
净增代码2200+ 行

6.2 功能分类

类型数量
数据源统一1 项
报告导出4 项
系统日志3 项
数据同步1 项
其他优化12 项

6.3 代码行数分布

模块新增代码量
系统日志功能约 1100 行
报告导出功能约 900 行
数据源统一约 160 行
数据同步进度约 250 行
其他优化约 400 行

七、技术亮点

7.1 数据源优先级设计

特点:

  • 统一的数据源查询接口。
  • 灵活的数据源优先级配置。
  • 向后兼容旧数据。
  • 查询结果更加一致。

7.2 多格式导出架构

特点:

  • 模块化导出工具类。
  • 支持 Markdown、JSON、DOCX、PDF 多格式转换。
  • Docker 完整集成。
  • 适配不同报告使用场景。

7.3 系统日志管理

特点:

  • 完整的日志查看和导出功能。
  • 灵活的日志过滤:级别、关键词、行数。
  • 日志统计和分析。
  • 安全的文件操作,防止路径遍历。
  • 支持大文件分页读取。
  • 支持 ZIP 压缩导出。

7.4 日志配置统一

特点:

  • 日志配置从代码迁移到 TOML 文件。
  • 支持主日志、WebAPI、Worker、错误日志等多个日志文件。
  • Docker 环境完整支持。
  • 日志级别和处理器配置更灵活。

7.5 进度反馈机制

特点:

  • 同步进度日志更详细。
  • 错误统计更清楚。
  • 用户等待体验更好。
  • 问题诊断更容易。

八、总结

本次更新通过 21 个提交,完成了 报告导出、系统日志、数据同步进度和数据源优先级统一 等多项系统功能完善。

主要成果包括:

  • 数据一致性提升:所有 stock_basic_info 查询统一使用数据源优先级,用户配置完整生效。
  • 报告导出增强:支持 Markdown、JSON、DOCX、PDF 四种格式。
  • 系统日志管理:新增日志查看、过滤、统计、下载和批量导出功能。
  • 日志配置统一:迁移到 TOML 配置,并支持 Docker 环境生成主日志文件。
  • 数据同步进度优化:增加详细同步进度日志,前端同步超时提升到 10 分钟。
  • 用户体验改善:报告下载更灵活,问题排查更方便,同步过程更透明。

这些改进显著提升了 TradingAgents-CN 的 数据一致性、功能完整性、可维护性和用户体验,也让系统在实际使用和问题诊断场景中更加顺手。

✅ 官方唯一渠道:📦 GitHub 仓库:https://github.com/hsliuping/TradingAgents-CN

Aekor AI-API 中转站,让全球顶尖 AI 大模型“触手可及”!你是否曾为这些烦恼头疼?

🔹 人在国内,却总被海外官网 API 的高延迟、掉线、甚至无法访问困扰?

🔹 想用最强的 GPT、Claude 等模型,却卡在海外信用卡、支付审核等重重阻碍?

🔹 官方 API 太贵?Aekor 为你打通“网络-支付-成本”的任督二脉!

💡 Aekor 核心价值:好用、便宜、快 💡

🚀 高速稳定,告别掉线国内专线加速,API 响应低延迟,告别「转圈圈」的焦虑,开发效率瞬间拉满!

🧠 顶尖模型,随需而调涵盖 GPT 系列、Claude 系列等全球主流大厂模型,一次接入,轻松调用!

🎁 免费白嫖,诚意拉满!

注册即送 20 美元体验额度,够你狠狠测试一轮模型质量与线路稳定性了!

🚪 入口:https://api.aekor.com

⚠️ 温馨提示:API 中转市场虽多但良莠不齐(甚至有些会偷工减料换小模型糊弄事儿)。Aekor 坚持提供正版稳定的服务,但还是建议:先用免费的 20 刀测试是否契合自身需求,满意了再小额充值上车,理性消费不盲目。

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: Docker日志 JSON导出 Markdown导出 pandoc TradingAgents-CN wkhtmltopdf 多数据源同步 数据源优先级 股票分析平台
最后更新:2026-06-28

Aekor

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

使用AI教程

  • API报错解决方案
  • API 基础知识
  • API Key 获取

分类

  • Blog
  • TradingAgents-CN
  • 使用教程

COPYRIGHT © 2026 Aekor. ALL RIGHTS RESERVED.