- 移除 storage.py 集中式建表逻辑,改为各 API 文件自管理 - base_sync.py 新增 ensure_table_exists() 和表探测机制 - api_daily/api_pro_bar/api_bak_basic 添加 TABLE_SCHEMA 定义 - api_financial_sync 添加完整利润表字段定义 - sync.py 更新职责文档,明确仅同步每日更新数据 - AGENTS.md 添加 v2.1 架构变更历史和 AI 行为准则
387 lines
12 KiB
Markdown
387 lines
12 KiB
Markdown
# ProStock 代理指南
|
||
|
||
A股量化投资框架 - Python 项目,用于量化股票投资分析。
|
||
|
||
## 交流语言要求
|
||
|
||
**⚠️ 强制要求:所有沟通和思考过程必须使用中文。**
|
||
|
||
所有与 AI Agent 的交流必须使用中文
|
||
代码中的注释和文档字符串使用中文
|
||
禁止使用英文进行思考或沟通
|
||
|
||
|
||
## 构建/检查/测试命令
|
||
|
||
**⚠️ 重要:本项目强制使用 uv 作为 Python 包管理器和运行工具。禁止直接使用 `python` 或 `pip` 命令。**
|
||
|
||
```bash
|
||
# 安装依赖(必须使用 uv)
|
||
uv pip install -e .
|
||
|
||
# 运行所有测试
|
||
uv run pytest
|
||
|
||
# 运行单个测试文件
|
||
uv run pytest tests/test_sync.py
|
||
|
||
# 运行单个测试类
|
||
uv run pytest tests/test_sync.py::TestDataSync
|
||
|
||
# 运行单个测试方法
|
||
uv run pytest tests/test_sync.py::TestDataSync::test_get_all_stock_codes_from_daily
|
||
|
||
# 使用详细输出运行
|
||
uv run pytest -v
|
||
|
||
# 运行覆盖率测试(如果安装了 pytest-cov)
|
||
uv run pytest --cov=src --cov-report=term-missing
|
||
```
|
||
|
||
### 禁止的命令 ❌
|
||
|
||
以下命令在本项目中**严格禁止**:
|
||
|
||
```bash
|
||
# 禁止直接使用 python
|
||
python -c "..." # 禁止!
|
||
python script.py # 禁止!
|
||
python -m pytest # 禁止!
|
||
python -m pip install # 禁止!
|
||
|
||
# 禁止直接使用 pip
|
||
pip install -e . # 禁止!
|
||
pip install package # 禁止!
|
||
pip list # 禁止!
|
||
```
|
||
|
||
### 正确的 uv 用法 ✅
|
||
|
||
```bash
|
||
# 运行 Python 代码
|
||
uv run python -c "..." # ✅ 正确
|
||
uv run python script.py # ✅ 正确
|
||
|
||
# 安装依赖
|
||
uv pip install -e . # ✅ 正确
|
||
uv pip install package # ✅ 正确
|
||
|
||
# 运行测试
|
||
uv run pytest # ✅ 正确
|
||
uv run pytest tests/test_sync.py # ✅ 正确
|
||
```
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
ProStock/
|
||
├── src/ # 源代码
|
||
│ ├── config/ # 配置管理
|
||
│ │ ├── __init__.py
|
||
│ │ └── settings.py # pydantic-settings 配置
|
||
│ │
|
||
│ ├── data/ # 数据获取与存储
|
||
│ │ ├── api_wrappers/ # Tushare API 封装
|
||
│ │ │ ├── API_INTERFACE_SPEC.md # 接口规范文档
|
||
│ │ │ ├── api.md # API 接口定义
|
||
│ │ │ ├── api_daily.py # 日线数据接口
|
||
│ │ │ ├── api_stock_basic.py # 股票基础信息接口
|
||
│ │ │ ├── api_trade_cal.py # 交易日历接口
|
||
│ │ │ └── __init__.py
|
||
│ │ ├── __init__.py
|
||
│ │ ├── client.py # Tushare API 客户端(带速率限制)
|
||
│ │ ├── config.py # 数据模块配置
|
||
│ │ ├── db_inspector.py # 数据库信息查看工具
|
||
│ │ ├── db_manager.py # DuckDB 表管理和同步
|
||
│ │ ├── rate_limiter.py # 令牌桶速率限制器
|
||
│ │ ├── storage.py # 数据存储核心
|
||
│ │ └── sync.py # 数据同步主逻辑
|
||
│ │
|
||
│ ├── factors/ # 因子计算框架
|
||
│ │ ├── __init__.py
|
||
│ │ ├── base.py # 因子基类(截面/时序)
|
||
│ │ ├── composite.py # 组合因子和标量运算
|
||
│ │ ├── data_loader.py # 数据加载器
|
||
│ │ ├── data_spec.py # 数据规格定义
|
||
│ │ ├── engine.py # 因子执行引擎
|
||
│ │ ├── momentum/ # 动量因子
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── ma.py # 移动平均线
|
||
│ │ │ └── return_rank.py # 收益排名
|
||
│ │ └── financial/ # 财务因子
|
||
│ │ └── __init__.py
|
||
│ │
|
||
│ ├── pipeline/ # 模型训练管道
|
||
│ │ ├── __init__.py
|
||
│ │ ├── pipeline.py # 处理流水线
|
||
│ │ ├── registry.py # 插件注册中心
|
||
│ │ ├── core/ # 核心抽象
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ ├── base.py # 基类定义
|
||
│ │ │ └── splitter.py # 时间序列划分策略
|
||
│ │ ├── models/ # 模型实现
|
||
│ │ │ ├── __init__.py
|
||
│ │ │ └── models.py # LightGBM、CatBoost 等
|
||
│ │ └── processors/ # 数据处理器
|
||
│ │ ├── __init__.py
|
||
│ │ └── processors.py # 标准化、缩尾、中性化等
|
||
│ │
|
||
│ └── training/ # 训练入口
|
||
│ ├── __init__.py
|
||
│ ├── main.py # 训练主程序
|
||
│ ├── pipeline.py # 训练流程配置
|
||
│ └── output/ # 训练输出
|
||
│ └── top_stocks.tsv # 推荐股票结果
|
||
│
|
||
├── tests/ # 测试文件
|
||
│ ├── test_sync.py
|
||
│ └── test_daily.py
|
||
├── config/ # 配置文件
|
||
│ └── .env.local # 环境变量(不在 git 中)
|
||
├── data/ # 数据存储(DuckDB)
|
||
├── docs/ # 文档
|
||
├── pyproject.toml # 项目配置
|
||
└── README.md
|
||
```
|
||
|
||
## 代码风格指南
|
||
|
||
### Python 版本
|
||
- **需要 Python 3.10+**
|
||
- 使用现代 Python 特性(match/case、海象运算符、类型提示)
|
||
|
||
### 导入
|
||
```python
|
||
# 标准库优先
|
||
import os
|
||
import time
|
||
from datetime import datetime, timedelta
|
||
from pathlib import Path
|
||
from typing import Optional, Dict, Callable
|
||
from concurrent.futures import ThreadPoolExecutor
|
||
import threading
|
||
|
||
# 第三方包
|
||
import pandas as pd
|
||
import numpy as np
|
||
from tqdm import tqdm
|
||
from pydantic_settings import BaseSettings
|
||
|
||
# 本地模块(使用来自 src 的绝对导入)
|
||
from src.data.client import TushareClient
|
||
from src.data.storage import Storage
|
||
from src.config.settings import get_settings
|
||
```
|
||
|
||
### 类型提示
|
||
- **始终使用类型提示** 用于函数参数和返回值
|
||
- 对可空类型使用 `Optional[X]`
|
||
- 当可用时使用现代联合语法 `X | Y`(Python 3.10+)
|
||
- 从 `typing` 导入类型:`Optional`、`Dict`、`Callable` 等
|
||
|
||
```python
|
||
def sync_single_stock(
|
||
self,
|
||
ts_code: str,
|
||
start_date: str,
|
||
end_date: str,
|
||
) -> pd.DataFrame:
|
||
...
|
||
```
|
||
|
||
### 文档字符串
|
||
- 使用 **Google 风格文档字符串**
|
||
- 包含 Args、Returns 部分
|
||
- 第一行保持简短摘要
|
||
|
||
```python
|
||
def get_next_date(date_str: str) -> str:
|
||
"""获取给定日期之后的下一天。
|
||
|
||
Args:
|
||
date_str: YYYYMMDD 格式的日期
|
||
|
||
Returns:
|
||
YYYYMMDD 格式的下一天日期
|
||
"""
|
||
...
|
||
```
|
||
|
||
### 命名约定
|
||
- 变量、函数、方法使用 `snake_case`
|
||
- 类使用 `PascalCase`
|
||
- 常量使用 `UPPER_CASE`
|
||
- 私有方法:`_leading_underscore`
|
||
- 受保护属性:`_single_underscore`
|
||
|
||
### 错误处理
|
||
- 使用特定的异常,不要使用裸 `except:`
|
||
- 使用上下文记录错误:`print(f"[ERROR] 上下文: {e}")`
|
||
- 对 API 调用使用指数退避重试逻辑
|
||
- 在关键错误时立即停止(设置停止标志)
|
||
|
||
```python
|
||
try:
|
||
data = api.query(...)
|
||
except Exception as e:
|
||
print(f"[ERROR] 获取 {ts_code} 失败: {e}")
|
||
raise # 记录后重新抛出
|
||
```
|
||
|
||
### 配置
|
||
- 对所有配置使用 **pydantic-settings**
|
||
- 从 `config/.env.local` 文件加载
|
||
- 环境变量自动转换:`tushare_token` → `TUSHARE_TOKEN`
|
||
- 对配置单例使用 `@lru_cache()`
|
||
|
||
### 数据存储
|
||
- 使用 **DuckDB** 嵌入式 OLAP 数据库进行持久化
|
||
- 存储在 `data/` 目录中(通过 `DATA_PATH` 环境变量配置)
|
||
- 使用 UPSERT 模式(`INSERT OR REPLACE`)处理重复数据
|
||
- 多线程场景使用 `ThreadSafeStorage.queue_save()` + `flush()` 模式
|
||
|
||
### 线程与并发
|
||
- 对 I/O 密集型任务(API 调用)使用 `ThreadPoolExecutor`
|
||
- 实现停止标志以实现优雅关闭:`threading.Event()`
|
||
- 数据同步默认工作线程数:10
|
||
- 出错时始终使用 `executor.shutdown(wait=False, cancel_futures=True)`
|
||
|
||
### 日志记录
|
||
- 使用带前缀的 print 语句:`[模块名] 消息`
|
||
- 错误格式:`[ERROR] 上下文: 异常`
|
||
- 进度:循环中使用 `tqdm`
|
||
|
||
### 测试
|
||
- 使用 **pytest** 框架
|
||
- 模拟外部依赖(Tushare API)
|
||
- 使用 `@pytest.fixture` 进行测试设置
|
||
- 在导入位置打补丁:`patch('src.data.sync.Storage')`
|
||
- 测试成功和错误两种情况
|
||
|
||
### 日期格式
|
||
- 使用 `YYYYMMDD` 字符串格式表示日期
|
||
- 辅助函数:`get_today_date()`、`get_next_date()`
|
||
- 完全同步的默认开始日期:`20180101`
|
||
|
||
### 依赖项
|
||
关键包:
|
||
- `pandas>=2.0.0` - 数据处理
|
||
- `numpy>=1.24.0` - 数值计算
|
||
- `tushare>=2.0.0` - A股数据 API
|
||
- `pydantic>=2.0.0`、`pydantic-settings>=2.0.0` - 配置
|
||
- `tqdm>=4.65.0` - 进度条
|
||
- `pytest` - 测试(开发)
|
||
|
||
### 环境变量
|
||
创建 `config/.env.local`:
|
||
```bash
|
||
TUSHARE_TOKEN=your_token_here
|
||
DATA_PATH=data
|
||
RATE_LIMIT=100
|
||
THREADS=10
|
||
```
|
||
|
||
## 常见任务
|
||
|
||
```bash
|
||
# 同步所有股票(增量)
|
||
uv run python -c "from src.data.sync import sync_all; sync_all()"
|
||
|
||
# 强制完全同步
|
||
uv run python -c "from src.data.sync import sync_all; sync_all(force_full=True)"
|
||
|
||
# 自定义线程数
|
||
uv run python -c "from src.data.sync import sync_all; sync_all(max_workers=20)"
|
||
```
|
||
|
||
## 架构变更历史
|
||
|
||
### v2.1 (2026-02-28) - 同步模块规范更新
|
||
|
||
#### sync.py 职责划分
|
||
**变更**: 明确 `sync.py` 只包含每日更新的数据同步
|
||
**原因**: 区分高频(每日)和低频(季度/年度)数据,避免不必要的 API 调用
|
||
**规范**:
|
||
- `sync.py` / `sync_all_data()`: **仅包含每日更新的数据**
|
||
- 日线数据 (`api_daily`)
|
||
- Pro Bar 数据 (`api_pro_bar`)
|
||
- 交易日历 (`api_trade_cal`)
|
||
- 股票基本信息 (`api_stock_basic`)
|
||
- 历史股票列表 (`api_bak_basic`)
|
||
|
||
- **不应放入 `sync.py` 的季度/低频数据**:
|
||
- 财务数据 (`financial_data/` 目录): 利润表、资产负债表、现金流量表等
|
||
- 名称变更 (`api_namechange`): 已移除自动同步,建议手动定期同步
|
||
|
||
- **季度数据同步方式**:
|
||
```python
|
||
# 财务数据单独同步(不在 sync_all_data 中)
|
||
from src.data.api_wrappers.financial_data.api_financial_sync import sync_financial
|
||
sync_financial() # 增量同步利润表
|
||
|
||
# 名称变更手动同步
|
||
from src.data.api_wrappers import sync_namechange
|
||
sync_namechange(force=True)
|
||
```
|
||
|
||
### v2.0 (2026-02-23) - 重要更新
|
||
|
||
#### 存储层重构
|
||
**变更**: 从 HDF5 迁移到 DuckDB
|
||
**原因**: DuckDB 提供更好的查询性能、SQL 下推能力、并发支持
|
||
**影响**: 所有数据表现在使用 DuckDB 存储,旧 HDF5 文件可手动迁移
|
||
|
||
#### Sync 类迁移
|
||
**变更**: `DataSync` 类从 `sync.py` 迁移到 `api_daily.py`
|
||
**原因**: 实现代码职责分离,每个 API 文件包含自己的同步逻辑
|
||
**影响**:
|
||
- `sync.py` 保留为调度中心
|
||
- `api_daily.py` 包含 `DailySync` 类和 `sync_daily` 函数
|
||
|
||
#### 新增模块
|
||
**pipeline 模块**: 机器学习流水线组件(处理器、模型、划分策略)
|
||
**training 模块**: 训练入口程序
|
||
**factors/momentum**: 动量因子(MA、收益率排名)
|
||
**factors/financial**: 财务因子框架
|
||
**data/utils.py**: 日期工具函数集中管理
|
||
|
||
#### 新增 API 接口
|
||
`api_namechange.py`: 股票曾用名接口(手动同步)
|
||
`api_bak_basic.py`: 历史股票列表接口
|
||
|
||
#### 工具函数统一
|
||
`get_today_date()`、`get_next_date()`、`DEFAULT_START_DATE` 等函数统一在 `src/data/utils.py` 中管理
|
||
其他模块应从 `utils.py` 导入这些函数,避免重复定义
|
||
|
||
|
||
## AI 行为准则
|
||
|
||
### LSP 检测报错处理
|
||
|
||
**⚠️ 强制要求:当进行 LSP 检测时报错,必定是代码格式问题。**
|
||
|
||
如果 LSP 检测报错,必须按照以下流程处理:
|
||
|
||
1. **问题定位**
|
||
- 报错必定是由基础格式错误引起:缩进错误、引号括号不匹配、代码格式错误等
|
||
- 必须读取对应的代码行,精确定位错误
|
||
|
||
2. **修复方式**
|
||
- ✅ **必须**:读取报错文件,检查具体代码行
|
||
- ✅ **必须**:修复格式错误(缩进、括号匹配、引号闭合等)
|
||
- ❌ **禁止**:删除文件重新修改
|
||
- ❌ **禁止**:自行 rollback 文件
|
||
- ❌ **禁止**:新建文件重新修改
|
||
- ❌ **禁止**:忽略错误继续执行
|
||
|
||
3. **验证要求**
|
||
- 修复后必须重新运行 LSP 检测确认无错误
|
||
- 确保修改仅针对格式问题,不改变代码逻辑
|
||
|
||
**示例场景**:
|
||
```
|
||
LSP 报错:Syntax error on line 45
|
||
✅ 正确做法:读取文件第 45 行,发现少了一个右括号,添加后重新检测
|
||
❌ 错误做法:删除文件重新写、或者忽略错误继续
|
||
```
|