Fundamental_Analysis/docs/design.md
xucheng b5a4d2212c feat: 实现动态分析配置并优化前端UI
本次提交引入了一系列重要功能,核心是实现了财务分析模块的动态配置,并对配置和报告页面的用户界面进行了改进。

主要变更:

- **动态配置:**
  - 后端实现了 `ConfigManager` 服务,用于动态管理 `analysis-config.json` 和 `config.json`。
  - 添加了用于读取和更新配置的 API 端点。
  - 开发了前端 `/config` 页面,允许用户实时查看和修改分析配置。

- **后端增强:**
  - 更新了 `AnalysisClient` 和 `CompanyProfileClient` 以使用新的配置系统。
  - 重构了财务数据相关的路由。

- **前端改进:**
  - 新增了可复用的 `Checkbox` UI 组件。
  - 使用更直观和用户友好的界面重新设计了配置页面。
  - 改进了财务报告页面的布局和数据展示。

- **文档与杂务:**
  - 更新了设计和需求文档以反映新功能。
  - 更新了前后端依赖。
  - 修改了开发脚本 `dev.sh`。
2025-10-30 14:50:36 +08:00

226 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 设计文档 - 基本面选股系统 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/队列增强体验。
![System Architecture Diagram](https://i.imgur.com/example.png) <!-- Placeholder for a real diagram -->
### 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→SZ6→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. 指标与显示规范(要点)
- 百分比字段支持 01 与百分数两种输入,自动规范化显示为 `%`
- 金额类(损益/资产负债/现金流)按“亿元/亿股”等进行缩放显示,市值按“亿元”整数化展示。
- 计算项示例:自由现金流 = 经营现金流 资本开支;费用率=费用/收入;其他费用率=毛利率−净利率−销售−管理−研发。
- 高亮规则:例如 ROE/ROIC>12% 标绿色背景,增长率为负标红等。
### 5.5. 分析模块编排
系统的核心能力之一是允许分析模块之间传递信息,即一个模块可以利用前序模块的分析结果作为上下文。这通过模块间的**依赖关系Dependencies**实现。
- **编排方式**
- 前端不再独立、依次请求每个分析模块,而是通过调用一个统一的编排端点 `POST /api/financials/china/{ts_code}/analysis` 来发起一次完整的报告生成任务。
- 后端编排器会读取 `config/analysis-config.json` 中定义的模块依赖关系,通过**拓扑排序**算法智能地计算出最优执行顺序,确保被依赖的模块总是先于依赖它的模块执行。
- **依赖配置与上下文注入**
- **如何配置**:在前端的“配置中心”页面,可以为每个分析模块通过复选框勾选其需要依赖的其他模块。保存后,这将在 `analysis-config.json` 对应模块下生成一个 `dependencies` 数组,例如:
```json
"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}`),系统**不会报错**,但会发生以下情况:
1. **执行顺序不保证**:编排器认为这两个模块独立,`fundamental_analysis` 不一定会在 `bull_case` 之前运行。
2. **上下文不会被注入**:即使前序模块先运行完,由于 `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 暂无;后续纳入登录、权限与审计。
本设计文档已对“当前实现”与“后续规划”进行了清晰标注,便于开发与验收。