Aekor

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

TradingAgents-CN 项目优化:用户设置与财务指标优化:TTM 计算、WebSocket 、UI 改进(10-26)

2025-10-27 4867点热度 0人点赞 0条评论

一、升级概览

2025 年 10 月 26 日,TradingAgents-CN 完成了一次全面的 系统优化。

本次更新通过 36 个提交,围绕 用户偏好设置系统重构、财务指标计算优化、WebSocket 连接修复、UI 体验改进 等方向展开,显著提升了系统的 数据准确性、用户体验和稳定性。

核心改进

  • 用户偏好设置系统重构:解决设置刷新后丢失的问题。
  • 分析偏好自动应用:单股分析和批量分析优先读取用户偏好。
  • TTM 计算修复:正确处理财报累计值和基准期选择。
  • PS/PE 指标优化:市销率和动态市盈率使用 TTM 数据计算。
  • Tushare Token 配置优化:数据库配置优先于环境变量,支持 Web 后台修改生效。
  • WebSocket 连接修复:统一开发环境和生产环境连接逻辑。
  • UI 体验改进:添加数据源注册引导,修复深色主题下白色背景问题。
  • 关于页面完善:补充原项目介绍和致谢。

二、用户偏好设置系统重构

2.1 问题背景

相关提交:

  • 41ca79f:修复所有设置保存到 localStorage 的问题。
  • 6283a5c:修复所有个人设置保存问题,包括外观、分析偏好和通知设置。
  • e2fef6b:修复通用设置中邮箱地址保存后刷新恢复原值的问题。
  • e56c571:修复主题设置保存后刷新不生效的问题。

此前用户在前端修改个人设置后,刷新页面会恢复到旧值。

受影响的设置包括:

  • 主题设置:深色 / 浅色不生效。
  • 分析偏好设置:模型、分析师选择不生效。
  • 通知设置:刷新后丢失。
  • 邮箱地址:保存后刷新恢复原值。

2.2 根本原因

问题主要来自 前后端设置存储不一致。

前端和后端存储不同步

前端将设置保存到 localStorage,后端则使用 MongoDB 的 users 集合存储用户信息。

两者没有同步机制。

页面刷新时后端数据覆盖前端设置

authStore 初始化时,会从后端 /api/auth/me 获取用户信息,并覆盖本地 localStorage 中的设置。

后端没有返回用户偏好字段

/api/auth/me 接口没有返回 preferences 字段,导致前端无法拿到完整用户偏好。

2.3 解决方案

后端返回用户偏好设置

@router.get("/me")
async def get_current_user(current_user: dict = Depends(get_current_user_from_db)):
    """获取当前用户信息"""
    return {
        "id": str(user.id),
        "username": user.username,
        "email": user.email,
        "name": user.username,
        "is_admin": user.is_admin,
        "roles": ["admin"] if user.is_admin else ["user"],
        "preferences": user.preferences.model_dump() if user.preferences else {}
    }

前端同步用户偏好到 appStore

setAuthInfo(token: string, refreshToken: string, user: User) {
  this.token = token
  this.refreshToken = refreshToken
  this.user = user

  this.syncUserPreferencesToAppStore()
}

syncUserPreferencesToAppStore() {
  const appStore = useAppStore()

  if (this.user?.preferences) {
    if (this.user.preferences.theme) {
      appStore.theme = this.user.preferences.theme
      appStore.applyTheme()
    }

    if (this.user.preferences.analysis) {
      appStore.analysisPreferences = this.user.preferences.analysis
    }

    if (this.user.preferences.notifications) {
      appStore.notificationSettings = this.user.preferences.notifications
    }
  }
}

添加用户偏好迁移脚本

新增迁移脚本:

scripts/migrate_user_preferences.py

用于给旧用户补充默认 preferences 字段。

默认偏好包括:

  • theme
  • analysis.default_model
  • analysis.default_analysts
  • notifications.email_enabled
  • notifications.browser_enabled

2.4 优化效果

  • 用户设置保存到数据库。
  • 刷新页面后设置不再丢失。
  • 前后端偏好数据保持同步。
  • 支持多设备同步用户偏好。

三、分析偏好设置优化

3.1 问题背景

相关提交:

  • 767ac03:修正分析偏好默认值,与单股分析模块保持一致。
  • 25de33c:单股分析和批量分析优先读取用户偏好设置。

此前存在两个问题:

默认值不一致

个人设置页面默认模型为 gpt-4o-mini,但单股分析页面默认模型为 gpt-4o,用户容易困惑。

分析页面不读取用户偏好

每次打开分析页面时,系统都会使用硬编码默认值,用户需要重新选择模型和分析师。

3.2 解决方案

单股分析页面初始化时优先读取 appStore.analysisPreferences。

onMounted(async () => {
  const appStore = useAppStore()

  if (appStore.analysisPreferences) {
    analysisForm.model =
      appStore.analysisPreferences.default_model || 'gpt-4o-mini'

    analysisForm.analysts =
      appStore.analysisPreferences.default_analysts ||
      ['market', 'fundamentals', 'news', 'social']
  }
})

3.3 优化效果

  • 默认模型统一为 gpt-4o-mini。
  • 单股分析和批量分析自动读取用户偏好。
  • 用户不需要每次重复选择模型和分析师。
  • 分析流程更加顺手。

四、财务指标计算优化

4.1 修复 TTM 计算问题

相关提交:

  • 9c11d98:重构 TTM 计算逻辑,正确处理累计值和基准期选择。
  • 5de898e:移除 TTM 计算中不准确的简单年化降级策略。
  • b0413c6:Tushare 数据源添加 TTM 营业收入和净利润计算。
  • 5384339:修复 AKShare 数据源的 TTM 计算和估值指标。
  • 8077316:修复基本面分析实时 API 调用中的 TTM 计算问题。

TTM,也就是 Trailing Twelve Months,是计算 PE_TTM 和 PS_TTM 的关键指标。

此前 TTM 计算存在严重问题。

4.1.1 累计值处理错误

财报中的季度数据通常是累计值。

例如:

  • Q1 是第一季度累计。
  • Q2 是上半年累计。
  • Q3 是前三季度累计。

如果直接将 Q1、Q2、Q3 相加,就会重复计算。

错误示例:

Q1 + Q2 + Q3 = 前三季度数据被重复计算

4.1.2 基准期选择不合理

此前使用 Q4 作为基准期,但 Q4 年报通常发布时间较晚,导致 TTM 数据不够及时。

4.1.3 简单年化策略不准确

当没有完整四个季度数据时,旧逻辑可能使用:

Q1 × 4

这种简单年化方式会忽略季节性因素,导致估值指标失真。

4.2 正确的 TTM 公式

新的 TTM 计算公式为:

TTM = 最新年报 + (最新季报 - 去年同期季报)

例如当前最新财报为 2024Q3,则:

TTM_营业收入 = 2023年报营业收入 + (2024Q3营业收入 - 2023Q3营业收入)

TTM_净利润 = 2023年报净利润 + (2024Q3净利润 - 2023Q3净利润)

4.3 实现逻辑

def _calculate_ttm_metrics(self, reports: List[Dict]) -> Optional[Dict]:
    """计算 TTM 指标,正确处理累计值"""

    annual_reports = [
        r for r in reports if r["report_type"] == "年报"
    ]

    if not annual_reports:
        return None

    latest_annual = annual_reports[0]

    quarterly_reports = [
        r for r in reports
        if r["report_type"] in ["一季报", "中报", "三季报"]
    ]

    if not quarterly_reports:
        return {
            "revenue_ttm": latest_annual.get("revenue"),
            "net_profit_ttm": latest_annual.get("net_profit")
        }

    latest_quarterly = quarterly_reports[0]
    latest_quarter = latest_quarterly["report_type"]
    latest_year = int(latest_quarterly["end_date"][:4])
    last_year = latest_year - 1

    last_year_same_quarter = None

    for report in reports:
        if (
            report["report_type"] == latest_quarter and
            int(report["end_date"][:4]) == last_year
        ):
            last_year_same_quarter = report
            break

    if not last_year_same_quarter:
        return {
            "revenue_ttm": latest_annual.get("revenue"),
            "net_profit_ttm": latest_annual.get("net_profit")
        }

    revenue_ttm = (
        latest_annual.get("revenue", 0) +
        latest_quarterly.get("revenue", 0) -
        last_year_same_quarter.get("revenue", 0)
    )

    net_profit_ttm = (
        latest_annual.get("net_profit", 0) +
        latest_quarterly.get("net_profit", 0) -
        last_year_same_quarter.get("net_profit", 0)
    )

    return {
        "revenue_ttm": revenue_ttm if revenue_ttm > 0 else None,
        "net_profit_ttm": net_profit_ttm if net_profit_ttm != 0 else None
    }

4.4 优化效果

  • TTM 计算更准确。
  • 正确处理累计财报数据。
  • 基准期选择更合理。
  • 移除不准确的简单年化策略。
  • PE_TTM 和 PS_TTM 更可信。

五、市销率 PS 与动态市盈率 PE_TTM 修复

5.1 问题背景

相关提交:

  • f333020:修复市销率 PS 使用季度 / 半年报数据的 bug。
  • c522523:标记 Tushare 和实时行情数据源的 PS/PE 计算问题。
  • ad69c71:修复 Tushare 数据源市值计算,并删除未使用的估算函数。

此前 市销率 PS 使用季度或半年报数据计算,导致明显失真。

错误计算:

PS = 市值 / Q3营业收入

正确计算:

PS = 市值 / TTM营业收入

例如:

市值:100 亿
2024Q3 营业收入:60 亿
TTM 营业收入:80 亿

错误 PS = 100 / 60 = 1.67
正确 PS = 100 / 80 = 1.25

5.2 解决方案

基本面数据中统一先计算 TTM 指标,再用 TTM 指标计算估值。

reports = self._get_financial_reports(code)
ttm_metrics = self._calculate_ttm_metrics(reports)

quote = self.get_realtime_quote(code)
market_cap = quote.get("market_cap")

if ttm_metrics and market_cap:
    ps = (
        market_cap / ttm_metrics["revenue_ttm"]
        if ttm_metrics["revenue_ttm"]
        else None
    )

    pe_ttm = (
        market_cap / ttm_metrics["net_profit_ttm"]
        if ttm_metrics["net_profit_ttm"]
        else None
    )

5.3 优化效果

  • PS 使用 TTM 营业收入计算。
  • PE_TTM 使用 TTM 净利润计算。
  • 避免季度数据带来的季节性失真。
  • 基本面估值指标更可靠。

六、Tushare Token 配置优先级优化

6.1 问题背景

相关提交:

  • 75edbc8:修复 Tushare Token 配置优先级问题,支持 Web 后台修改立即生效。
  • da3406b:修复数据源优先级读取时的异步 / 同步冲突问题。

此前用户在 Web 后台修改 Tushare Token 后,系统仍可能使用环境变量中的旧 Token。

主要原因:

  • 环境变量优先级高于数据库配置。
  • 用户在 Web 后台修改后无法立即生效。
  • 配置读取存在异步 / 同步上下文冲突。

6.2 解决方案

调整配置优先级:数据库配置优先,环境变量作为降级方案。

async def get_data_source_config(self, source_name: str) -> Optional[Dict]:
    """获取数据源配置,数据库优先"""

    db_config = await self._get_from_database(source_name)

    if db_config and db_config.get("api_key"):
        return db_config

    env_key = f"{source_name.upper()}_TOKEN"
    env_value = os.getenv(env_key)

    if env_value:
        return {"api_key": env_value}

    return None

同时,将 Tushare 初始化拆成同步初始化和异步初始化。

class TushareAdapter:
    def __init__(self):
        self.token = os.getenv("TUSHARE_TOKEN")
        self._provider = None

    async def initialize(self):
        """异步初始化,从数据库读取配置"""
        config_service = ConfigService()
        config = await config_service.get_data_source_config("tushare")

        if config and config.get("api_key"):
            self.token = config["api_key"]

        if self.token:
            self._provider = ts.pro_api(self.token)

6.3 优化效果

  • Web 后台修改 Tushare Token 后可立即生效。
  • 数据库配置优先级高于环境变量。
  • 修复异步 / 同步冲突。
  • 数据源配置管理更符合用户预期。

七、WebSocket 连接优化

7.1 问题背景

相关提交:

  • d0512fc:修复 Docker 部署时 WebSocket 连接失败的问题。
  • f176a10:优化 WebSocket 连接逻辑,支持开发和生产环境。

Docker 部署时,前端错误地尝试连接:

ws://localhost:8000

但生产环境中应该连接服务器实际地址。

7.2 解决方案

启用 Vite WebSocket 代理

export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',
        changeOrigin: true,
        secure: false,
        ws: true
      }
    }
  }
})

前端统一使用当前访问地址

const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
const host = window.location.host
const wsUrl = `${wsProtocol}//${host}/api/ws/notifications?token=${token}`

ws = new WebSocket(wsUrl)

7.3 适配效果

环境访问地址WebSocket 连接代理方式
开发http://localhost:3000ws://localhost:3000/api/ws/...Vite 代理到后端
生产http://服务器IPws://服务器IP/api/ws/...Nginx 代理到后端
HTTPShttps://域名wss://域名/api/ws/...Nginx 代理到后端

7.4 优化效果

  • 无需为不同环境修改代码。
  • 自动适配 ws:// 和 wss://。
  • 自动使用当前访问地址。
  • Docker 部署下 WebSocket 连接更稳定。

八、UI 体验改进

8.1 添加数据源注册引导

相关提交:

  • f7e4546:添加厂家注册引导功能。
  • 0ad8489:调整注册引导提示字体大小。
  • 9a57973:为数据源添加注册引导功能。
  • d58484e:修复 TypeScript 类型错误,添加缺失类型定义。

在数据源配置页面中,如果用户尚未填写 API Key,系统会显示注册引导。

<el-alert
  v-if="!form.api_key && providerInfo.register_url"
  type="info"
  :closable="false"
>
  <template #title>
    <div>
      <span>还没有 API Key?</span>
      <el-link
        :href="providerInfo.register_url"
        target="_blank"
        type="primary"
        :underline="false"
      >
        点击注册 {{ providerInfo.display_name }}
      </el-link>
    </div>
  </template>
</el-alert>

优化效果:

  • 用户可快速跳转到数据源注册页面。
  • 新用户更容易完成 API Key 配置。
  • 减少配置错误。

8.2 修复深色主题白色背景问题

相关提交:

  • f1fe1d0:修复深色主题下分析页面的白色背景问题。

优化样式:

html.dark {
  .page-container {
    background-color: var(--el-bg-color) !important;
  }

  .el-card {
    background-color: var(--el-bg-color) !important;
    color: var(--el-text-color-primary) !important;
  }

  .el-form {
    background-color: transparent !important;
  }
}

优化效果:

  • 深色主题下背景更加统一。
  • 页面可读性提升。
  • 用户体验更一致。

8.3 关于页面添加原项目介绍和致谢

相关提交:

  • 70b1971:在关于页面添加原项目介绍和致谢。

新增内容包括:

  • 原项目链接:TradingAgents by virattt。
  • 项目来源说明。
  • 对原作者开源贡献的致谢。

优化效果:

  • 尊重原作者贡献。
  • 项目来源更透明。
  • 用户更容易理解项目背景。

九、技术亮点

9.1 正确的 TTM 计算公式

TTM = 最新年报 + (最新季报 - 去年同期季报)

这个公式能正确处理累计值,避免重复计算。

9.2 数据库优先的配置策略

db_config = await self._get_from_database(source_name)

if db_config and db_config.get("api_key"):
    return db_config

数据库配置优先于环境变量,支持 Web 后台修改立即生效。

9.3 WebSocket 自动适配

const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
const host = window.location.host
const wsUrl = `${wsProtocol}//${host}/api/ws/notifications?token=${token}`

开发和生产环境共用同一套连接逻辑。

9.4 用户偏好同步机制

syncUserPreferencesToAppStore() {
  const appStore = useAppStore()

  if (this.user?.preferences) {
    appStore.theme = this.user.preferences.theme
    appStore.analysisPreferences = this.user.preferences.analysis
    appStore.notificationSettings = this.user.preferences.notifications
  }
}

用户偏好前后端同步,并支持多设备一致体验。


十、统计数据

10.1 提交统计

指标数量
提交数36
修改文件120+
新增代码4000+ 行
删除代码1500+ 行

10.2 核心价值

方向价值
用户体验设置保存不丢失,分析页面自动应用偏好
数据准确性TTM、PS、PE_TTM 计算更准确
系统稳定性WebSocket 更稳定,配置读取冲突减少
开发体验开发和生产环境连接逻辑统一

十一、总结

本次更新通过 36 个提交,围绕 用户设置、财务指标、WebSocket 和 UI 体验 做了一次全面优化。

主要成果包括:

  • 用户偏好设置系统重构:设置保存到数据库,刷新页面不再丢失。
  • 分析偏好自动应用:单股分析和批量分析优先读取用户配置。
  • TTM 计算修复:正确处理财报累计值,使用合理公式计算近 12 个月指标。
  • PS/PE_TTM 优化:使用 TTM 营业收入和 TTM 净利润计算估值指标。
  • Tushare Token 配置优化:数据库配置优先,Web 后台修改可立即生效。
  • WebSocket 连接优化:开发、生产、HTTPS 环境自动适配。
  • UI 体验改进:数据源注册引导、深色主题修复、关于页面致谢完善。

这些改进显著提升了 TradingAgents-CN 的 用户体验、财务数据准确性、系统稳定性和配置管理能力,也让系统更适合在长期使用、多设备访问和 Docker 部署场景中运行。

✅ 官方唯一渠道:📦 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 国际许可协议 进行许可
标签: AkShare API Key配置 Docker部署 PE_TTM PS_TTM TradingAgents-CN TTM计算 Tushare WebSocket优化 数据源配置 股票分析平台
最后更新:2026-07-04

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.