本次提交引入了一系列重要功能,核心是实现了财务分析模块的动态配置,并对配置和报告页面的用户界面进行了改进。 主要变更: - **动态配置:** - 后端实现了 `ConfigManager` 服务,用于动态管理 `analysis-config.json` 和 `config.json`。 - 添加了用于读取和更新配置的 API 端点。 - 开发了前端 `/config` 页面,允许用户实时查看和修改分析配置。 - **后端增强:** - 更新了 `AnalysisClient` 和 `CompanyProfileClient` 以使用新的配置系统。 - 重构了财务数据相关的路由。 - **前端改进:** - 新增了可复用的 `Checkbox` UI 组件。 - 使用更直观和用户友好的界面重新设计了配置页面。 - 改进了财务报告页面的布局和数据展示。 - **文档与杂务:** - 更新了设计和需求文档以反映新功能。 - 更新了前后端依赖。 - 修改了开发脚本 `dev.sh`。
15 KiB
设计文档 - 基本面选股系统 MVP
1. 引言
1.1. 文档目的
本文档旨在根据《需求文档 - MVP版本》的要求,提供一个全面的系统设计方案。它将详细阐述系统架构、模块划分、技术选型、数据库设计和API接口,作为开发团队进行系统实现的核心技术指导文件。
1.2. 项目概述
基本面选股系统是一个Web应用,旨在为投资者提供自动化、多维度的股票基本面分析报告。用户通过输入股票代码和市场,可以获取或生成一份包含财务数据、AI业务分析、市场情绪、风险评估等多个模块的综合报告,以辅助投资决策。
1.3. 范围
本设计涵盖了从用户界面到后端服务、再到数据库的全栈技术方案。主要包括:
- 前端:用户交互界面,包括报告查询、展示、进度追踪和系统配置。
- 后端:核心业务逻辑,包括报告生成、数据获取、AI分析、任务管理和配置服务。
- 数据库:报告数据、分析模块内容、进度信息和系统配置的持久化存储。
2. 系统架构
2.1. 架构概述
系统采用前后端分离的现代化Web架构,并通过前端API代理到后端:
- 前端 (Frontend):基于 React (Next.js App Router) 的应用,负责用户界面与交互。前端通过 Next.js 内置的 API 路由作为代理,转发请求到后端(
NEXT_PUBLIC_BACKEND_URL可配置,默认http://127.0.0.1:8000/api)。 - 前端 API 代理:
/frontend/src/app/api/**下的路由将前端请求转发至后端对应路径,统一处理Content-Type与状态码。 - 后端 (Backend):基于 Python FastAPI 的异步 API 服务,负责财务数据聚合、AI生成、配置管理与分析配置管理。
- 数据库 (Database):使用 PostgreSQL(已具备模型与迁移脚手架)。当前 MVP 未落地“报告持久化”,主要以即时查询/生成返回为主;后续迭代将启用。
- 异步任务:当前 MVP 版本以“同步请求-响应”为主,不使用流式SSE或队列;后续可评估以 SSE/队列增强体验。
2.2. 技术选型
| 层次 | 技术 | 理由 |
|---|---|---|
| 前端 | React (Next.js App Router), TypeScript, Shadcn/UI, SWR | App Router 简化路由与服务能力,SWR 负责数据获取与缓存。 |
| 后端 | Python, FastAPI, SQLAlchemy (Async) | 异步框架带来高并发性能,Python拥有强大的数据处理和AI生态,SQLAlchemy提供强大的ORM能力。 |
| 数据库 | PostgreSQL | 功能强大、稳定可靠的开源关系型数据库,支持JSONB等高级数据类型,适合存储结构化报告数据。 |
| 数据源 | Tushare API, Yahoo Finance | Tushare提供全面的中国市场数据,Yahoo Finance作为其他市场的补充,易于集成。 |
| AI模型 | Google Gemini | 强大的大语言模型,能够根据指令生成高质量的业务分析内容。 |
注:当前实现通过 config/financial-tushare.json 配置需要拉取的 Tushare 指标分组,通过 config/analysis-config.json 配置各分析模块名称、模型与 Prompt 模板。
3. 后端设计 (Backend Design)
3.1. 核心服务设计
后端逻辑将围绕以下几个核心服务展开:
- ReportGenerator (报告生成器): 核心服务,负责编排整个报告生成流程。它接收报告请求,并按顺序调用各个分析模块。
- AnalysisModule (分析模块): 定义一个基础接口或抽象类,每个具体的分析(如基本面、看涨/看跌分析等)都将实现此接口。这使得系统易于扩展新的分析维度。
- DataSourceManager (数据源管理器): 封装对Tushare、Yahoo等外部数据API的调用,提供统一的数据获取接口,并处理认证、重试和缓存逻辑。
- AIService (AI服务): 封装对Gemini API的调用,负责发送Prompt、处理响应和管理Token消耗的记录。
- ConfigManager (配置管理器): 负责从
config.json或数据库中加载、更新和验证系统配置(如API密钥、数据库URL)。 - ProgressTracker (进度追踪器): 负责在报告生成的每个阶段更新状态、耗时和Token使用情况,并提供给前端查询。
3.2. 任务执行模型(MVP)
当前 MVP 以“按需生成/查询”的同步调用为主:
- 财务数据:请求到达后端即刻聚合最新数据并返回,包含元信息(耗时、步骤、API 调用统计)。
- 公司简介与各分析模块:到达后端实时调用 Gemini 生成,返回内容与 Token/耗时指标。
- 前端在同一页面内顺序执行“公司简介 → 各分析模块”,并以本地状态记录执行轨迹,不依赖 SSE/队列。
3.3. API 端点设计(当前实现)
后端 FastAPI 实现的主要端点(被前端 Next.js API 代理转发):
| Method | Endpoint | 描述 | 请求体/参数 | 响应体 |
|---|---|---|---|---|
GET |
/api/financials/config |
获取财务指标分组配置 | - | FinancialConfigResponse |
GET |
/api/financials/china/{ts_code} |
聚合中国市场财务数据(按年汇总,含元信息与步骤) | years |
BatchFinancialDataResponse |
GET |
/api/financials/china/{ts_code}/company-profile |
生成公司简介(Gemini,同步) | company_name? |
CompanyProfileResponse |
GET |
/api/financials/analysis-config |
获取分析模块配置 | - | AnalysisConfigResponse |
PUT |
/api/financials/analysis-config |
更新分析模块配置 | AnalysisConfigResponse |
AnalysisConfigResponse |
POST |
/api/financials/china/{ts_code}/analysis |
生成完整的分析报告(根据依赖关系编排) | company_name? |
List[AnalysisResponse] |
GET |
/api/config |
获取系统配置 | - | ConfigResponse |
PUT |
/api/config |
更新系统配置 | ConfigUpdateRequest |
ConfigResponse |
POST |
/api/config/test |
测试配置有效性(数据库/Gemini/Tushare 等) | ConfigTestRequest |
ConfigTestResponse |
说明:前端对应的代理路径如下(示例):
- 前端请求
/api/financials/china/...→ 代理到后端${BACKEND_BASE}/financials/china/... - 前端请求
/api/config、/api/config/test→ 代理到后端${BACKEND_BASE}/config、${BACKEND_BASE}/config/test
4. 数据库设计
4.1. 数据模型 (Schema)
【规划中】以下表结构为后续“报告持久化与历史管理”功能的设计草案,当前 MVP 未启用:
1. reports (报告表)
用于存储报告的元数据。
| 字段名 | 类型 | 描述 | 示例 |
|---|---|---|---|
id |
UUID (Primary Key) | 报告的唯一标识符 | uuid.uuid4() |
symbol |
VARCHAR | 股票代码 | "600519" |
market |
VARCHAR | 交易市场 | "china" |
status |
VARCHAR | 生成状态 (generating, completed, failed) | "completed" |
created_at |
TIMESTAMPTZ | 创建时间 | datetime.utcnow() |
updated_at |
TIMESTAMPTZ | 最后更新时间 | datetime.utcnow() |
2. analysis_modules (分析模块表)
存储每个报告的具体分析模块内容。
| 字段名 | 类型 | 描述 | 示例 |
|---|---|---|---|
id |
UUID (Primary Key) | 模块的唯一标识符 | uuid.uuid4() |
report_id |
UUID (Foreign Key) | 关联的报告ID | reports.id |
module_type |
VARCHAR | 模块类型 (e.g., "business_info", "bull_case") | "bull_case" |
content |
JSONB | 模块的分析结果,结构化数据 | {"title": "看涨分析", "data": [...]} |
status |
VARCHAR | 模块生成状态 (pending, running, completed, failed) | "completed" |
error_message |
TEXT | 失败时的错误信息 | "API call failed" |
3. progress_tracking (进度追踪表)
记录报告生成过程中每个步骤的状态和性能指标。
| 字段名 | 类型 | 描述 | 示例 |
|---|---|---|---|
id |
UUID (Primary Key) | 进度记录的唯一标识符 | uuid.uuid4() |
report_id |
UUID (Foreign Key) | 关联的报告ID | reports.id |
step_name |
VARCHAR | 步骤名称 | "获取财务数据" |
status |
VARCHAR | 步骤状态 (pending, running, completed, failed) | "completed" |
started_at |
TIMESTAMPTZ | 步骤开始时间 | datetime.utcnow() |
completed_at |
TIMESTAMPTZ | 步骤完成时间 | datetime.utcnow() |
duration_ms |
INTEGER | 步骤耗时(毫秒) | 1500 |
token_usage |
INTEGER | AI步骤的Token消耗量 | 2500 |
error_message |
TEXT | 失败时的错误信息 | "Data source timeout" |
4. system_config (系统配置表)
以键值对形式存储可动态修改的系统配置。
| 字段名 | 类型 | 描述 | 示例 |
|---|---|---|---|
config_key |
VARCHAR (Primary Key) | 配置项的键 | "gemini_api_key" |
config_value |
JSONB | 配置项的值 | {"api_key": "..."} |
4.2. 关系
reports与analysis_modules是一对多关系。reports与progress_tracking是一对多关系。
5. 前端设计 (Frontend Design)
5.1. 组件设计(当前实现)
ReportPage(frontend/src/app/report/[symbol]/page.tsx):报告主页面,基于 Tabs 展示:股价图表、财务数据表格、公司简介、各分析模块、执行详情。- 中国市场
ts_code规范化:支持纯6位数字自动推断交易所(0/3→SZ,6→SH)。 - “公司简介 → 各分析模块”按顺序串行执行,带状态、耗时与 Token 统计,可单项重试。
- 财务数据表按年列展示,包含主要指标、费用率、资产占比、周转能力、人均效率、市场表现等分组;含多项计算型指标与高亮规则(如 ROE/ROIC>12%)。
- 中国市场
TradingViewWidget:嵌入式股价图表,展示传入symbol的行情。ConfigPage(frontend/src/app/config/page.tsx):配置中心,支持数据库/Gemini/Tushare/Finnhub 配置查看、保存与测试;支持分析模块名称、模型、Prompt 模板的在线编辑与保存。- 前端 API 代理:
/frontend/src/app/api/**路由用于转发到后端,解耦部署与本地开发。
5.2. 页面与路由(当前实现)
/: 入口页。/report/[symbol]?market=china|cn|...: 报告页面(当前主要支持中国市场)。/config: 配置中心。/docs,/logs,/reports,/query: 辅助页面(如存在)。
5.3. 状态管理(当前实现)
- 数据获取:使用 SWR(
useSWR)封装于frontend/src/hooks/useApi.ts中,提供useChinaFinancials、useFinancialConfig、useAnalysisConfig、useConfig等。 - 全局配置:使用 Zustand
useConfigStore存放系统配置与加载状态。 - 页面局部状态:
ReportPage使用useState/useMemo/useRef管理任务队列、当前任务、计时器、执行记录与各模块的内容/错误/耗时/Token。
注:当前无 SSE;进度条和“执行详情”来自本地状态与后端返回的元信息(财务数据接口含步骤与耗时统计)。
5.4. 指标与显示规范(要点)
- 百分比字段支持 0–1 与百分数两种输入,自动规范化显示为
%。 - 金额类(损益/资产负债/现金流)按“亿元/亿股”等进行缩放显示,市值按“亿元”整数化展示。
- 计算项示例:自由现金流 = 经营现金流 − 资本开支;费用率=费用/收入;其他费用率=毛利率−净利率−销售−管理−研发。
- 高亮规则:例如 ROE/ROIC>12% 标绿色背景,增长率为负标红等。
5.5. 分析模块编排
系统的核心能力之一是允许分析模块之间传递信息,即一个模块可以利用前序模块的分析结果作为上下文。这通过模块间的**依赖关系(Dependencies)**实现。
-
编排方式:
- 前端不再独立、依次请求每个分析模块,而是通过调用一个统一的编排端点
POST /api/financials/china/{ts_code}/analysis来发起一次完整的报告生成任务。 - 后端编排器会读取
config/analysis-config.json中定义的模块依赖关系,通过拓扑排序算法智能地计算出最优执行顺序,确保被依赖的模块总是先于依赖它的模块执行。
- 前端不再独立、依次请求每个分析模块,而是通过调用一个统一的编排端点
-
依赖配置与上下文注入:
- 如何配置:在前端的“配置中心”页面,可以为每个分析模块通过复选框勾选其需要依赖的其他模块。保存后,这将在
analysis-config.json对应模块下生成一个dependencies数组,例如:"bull_case": { "name": "看涨分析", "dependencies": ["fundamental_analysis"], "prompt_template": "基于以下基本面分析:\n{fundamental_analysis}\n\n请生成看涨分析报告。" } - 如何工作:当后端执行时,它会先运行
fundamental_analysis模块,然后将其生成的全部文本结果,完整地替换掉bull_case模块提示词模板中的{fundamental_analysis}占位符。这样,AI在执行看涨分析时,就已经获得了充分的上下文。
- 如何配置:在前端的“配置中心”页面,可以为每个分析模块通过复选框勾选其需要依赖的其他模块。保存后,这将在
-
重要:未配置依赖但使用占位符的后果
- 如果您没有在配置中为一个模块(如
bull_case)勾选其对另一个模块(如fundamental_analysis)的依赖,但依然在其提示词模板中使用了对应的占位符({fundamental_analysis}),系统不会报错,但会发生以下情况:- 执行顺序不保证:编排器认为这两个模块独立,
fundamental_analysis不一定会在bull_case之前运行。 - 上下文不会被注入:即使前序模块先运行完,由于
dependencies列表为空,系统也不会进行占位符替换。
- 执行顺序不保证:编排器认为这两个模块独立,
- 最终结果:该占位符将作为纯文本(例如字符串
"{fundamental_analysis}")被原封不动地包含在提示词中并发送给大语言模型。这通常会导致分析质量下降,因为模型会收到一个它无法理解的指令片段,但得益于后端的安全机制(SafeFormatter),整个流程不会因缺少数据而崩溃。 - 结论:必须通过配置页面的复选框明确声明依赖关系,才能激活模块间的上下文传递。
- 如果您没有在配置中为一个模块(如
-
失败处理:
- 当前的编排流程中,如果一个模块执行失败,依赖于它的后续模块在生成提示词时,会收到一段表示错误的文本(例如
"Error: Analysis for a_module_failed.")作为上下文,而不是空字符串。这可以防止后续模块因缺少信息而生成质量过低的内容,同时也为调试提供了线索。 - 原有的单项重试功能已由全局的“重新运行完整分析”按钮取代,以适应新的编排模式。
- 当前的编排流程中,如果一个模块执行失败,依赖于它的后续模块在生成提示词时,会收到一段表示错误的文本(例如
5.6. 股票代码规范化(中国市场)
- 输入为 6 位数字时自动添加交易所后缀:首位
6→.SH,0/3→.SZ;已有后缀将转为大写保留。
6. 与最初规划的差异与后续计划
- 报告持久化/历史列表/再生成功能:目前未实现,仍按需生成并即时展示;后续将启用数据库表
reports、analysis_modules与progress_tracking完成闭环。 - SSE/队列化执行:当前为前端串行请求 + 本地状态记录;后续可引入 SSE 或任务队列以提供更丝滑的进度与并发控制。
- 多市场支持:当前聚焦中国市场(Tushare);后续将补充美股等数据源与规则。
- 权限与用户体系:MVP 暂无;后续纳入登录、权限与审计。
本设计文档已对“当前实现”与“后续规划”进行了清晰标注,便于开发与验收。
