- USAGE 新增 §6.3.1「归档的日常操作」:查看 / 筛选(回写 URL)/ 导出完整 JSON / 以此参数再跑 / 删除(写明「删除即失去结果,结果只存归档一份」)/ 历史归档用 restore_experiment_from_job 按原 id 重建;并说明归档完整度如何标注 - USAGE/README 更正技术栈与图表基座:TradingView Lightweight Charts 4.2.3 为唯一 图表基座(ECharts 已从 package.json、pnpm-lock.yaml、node_modules、文档与 架构图标注中全部清除),并记录实测证据(个股页图表根节点为 div.tv-lightweight-charts,页面 canvas 无一来自其它图表库) - ARCHITECTURE 更正「当前数据库」(原写 SQLite/未来 MySQL):现为本机 MariaDB 10.11, §6 补目标库硬约束;USAGE 补服务器身份与实测连接证据 - AGENT.md 新增 §0.1:数据库目标只允许本机 MariaDB,禁止 192.168.1.10, 由 config.py::assert_db_target_allowed 硬拦截(命中直接抛错,不静默降级) - DEV_PLAN_DIVIDEND_BACKTEST 记录三轮实施与验证、归档恢复边界(§12.5)、已知限制 - DEV_PLAN v2/v3 标注为历史记录(避免把当时的远端库地址当现状照抄); ROADMAP 更正 M3 图表选型
15 KiB
AGENT.md
AI Agent 开发约束
本文件是本项目所有 AI Coding Agent(Claude Code、DSH、REASONIX等)的开发约束。
在修改代码前必须阅读本文件和 ARCHITECTURE.md。
AI 回答必须使用中文
0. 网络下载与代理规则
当网络下载(git clone、pip / uv 安装、wget、数据下载、Docker pull 等)出现困难或超时时, 统一使用本机局域网 HTTP 代理:
192.168.1.160:3128
示例(仅在下载失败 / 超时时启用,不把代理写入代码或 Git):
# git clone(仅对 GitHub 等外网 https 目标使用)
git -c http.proxy=http://192.168.1.160:3128 -c https.proxy=http://192.168.1.160:3128 clone <url>
# pip / uv 安装
export http_proxy=http://192.168.1.160:3128
export https_proxy=http://192.168.1.160:3128
uv pip install <pkg>
# wget / curl
wget -e use_proxy=yes -e http_proxy=http://192.168.1.160:3128 <url>
注意事项:
- 代理只用于外网下载;内网资源(如 ssh git@192.168.1.10、局域网服务)不要走代理。
- 代理 IP 属于局域网配置,不写入
.env/config.yaml/ 任何提交进 Git 的文件。 - 直接下载成功时不要多此一举走代理。
0.1 数据库目标:只允许本机 MariaDB(硬约束)
- 数据库一律指向本机 MariaDB 10.11(
127.0.0.1:3306/qlib)。 - 禁止把
192.168.1.10作为数据库目标(该地址在本文档中仅作外网代理白名单/SSH 提及, 不是数据库目标)。远端旧库只作为历史数据来源,已不再写入。 - 该约束不是「靠自觉」:
app/core/config.py::assert_db_target_allowed在get_settings()解析出 URL 后立刻校验,命中禁用主机直接抛错(应用起不来),不允许「起得来但连错库」。 禁用列表默认192.168.1.10,可用环境变量QLIB_FORBIDDEN_DB_HOSTS覆盖(空串=不限制)。 - 理由:连错库属于最危险的静默错误 —— 不报错、界面正常,回测/归档/策略却写到了另一台机器上。
- 新增脚本/文档/示例配置时,DB 主机一律写
127.0.0.1,禁止出现远端库地址作为默认值。
1. 项目定位
这是一个:
- A股量化研究平台
- 个人开发项目
- 以选股、因子研究、回测为核心
- 以低频/中低频交易研究为目标
- Qlib 为量化研究引擎
- Tushare 为首选数据源
- 新浪财经为备用数据源
- SQLite 为当前数据库
- MySQL 为未来数据库
- React / Next.js 为前端
- FastAPI 为后端
- AI Agent 为后期研究助手
不要把项目开发成高频交易系统。
2. 总体开发原则
必须遵守:
简单优先
模块解耦
接口稳定
数据可追溯
实验可复现
禁止未来函数
AI 可调用
SQLite → MySQL 可迁移
API KEY, 账号密码等敏感信息写入根目录.env文件
可配置项统一写入根目录config.yaml 文件
禁止为了“看起来专业”而过度微服务化。
3. 修改代码前
AI Agent 必须先:
- 阅读
ARCHITECTURE.md - 阅读相关模块代码
- 找到现有接口
- 判断是否可以复用
- 最小范围修改
- 修改后运行测试
禁止看到需求就直接大量重构。
4. 架构边界
严格遵守:
Frontend
↓
API
↓
Application Service
↓
Domain
↓
Repository / DAO
↓
Infrastructure
量化:
Application Service
↓
Quant Service
↓
Qlib Adapter
↓
Qlib
禁止:
Frontend → Qlib
Frontend → Database
Agent → Database
Agent → Qlib internal API
Service → sqlite3
5. 数据源约束
5.1 Tushare 是第一数据源
所有已有 Tushare 能提供的数据,默认必须优先使用 Tushare。
禁止无理由改成新浪。
5.2 新浪是备用数据源
新浪财经只能作为:
- Tushare 缺失数据
- Tushare 暂时不可用
- 数据交叉验证
- 特定行情数据补充
必须通过:
SinaAdapter
接入。
业务代码不得直接 import 新浪 API 实现。
6. Data Provider 接口
业务层只能依赖抽象接口:
class MarketDataProvider(Protocol):
...
例如:
provider.get_daily(...)
provider.get_stock_basic(...)
provider.get_financial(...)
不能:
from tushare import ...
散落在业务代码中。
正确:
MarketDataProvider
│
├── TushareProvider
└── SinaProvider
7. 数据源 Failover
推荐:
Tushare
│
├── success → use
│
└── failure / missing
↓
Sina
但必须记录:
source
request_time
success
failure_reason
row_count
data_date
不能静默切换导致数据来源不可追踪。
8. 数据一致性
任何行情数据必须至少考虑:
symbol
trade_date
open
high
low
close
volume
amount
需要复权时必须使用明确的复权因子。
禁止在代码中偷偷改变:
前复权
后复权
不复权
必须在 API / Research Specification 中明确。
9. 未来函数是最高优先级风险
严禁:
回测日期 T
使用 T 之后才公布的数据
财务数据必须区分:
report_date
announce_date
研究查询必须支持:
as_of_date
任何新增财务数据功能,都必须回答:
在回测当天,这条数据是否已经公开?
如果无法回答,不得用于回测。
10. DAO / Repository 约束
业务层禁止直接操作:
sqlite3
SQLAlchemy Session
SQL
业务层只能调用:
Repository Interface
例如:
stock_repo.get_by_symbol(...)
factor_repo.list(...)
experiment_repo.save(...)
11. SQLite → MySQL 兼容
当前使用 SQLite。
但是:
任何业务代码都不能假设数据库是 SQLite。
禁止:
SELECT * FROM sqlite_master
禁止 SQLite 专有 SQL。
禁止:
sqlite3.connect()
出现在 Service / Domain 层。
数据库访问统一:
SQLAlchemy
Repository
Alembic
未来切换 MySQL 时,业务层不应该修改。
12. Migration
数据库结构必须使用:
Alembic
禁止手工修改生产数据库结构作为正式方案。
新增字段必须:
Model
↓
Migration
↓
Test
13. Parquet 使用原则
大量历史时序数据优先:
Parquet
SQLite 主要存:
- metadata
- configuration
- experiment
- job
- factor definition
- strategy
- 索引/小规模业务数据
不要把几十年、全市场、高频明细全部塞入 SQLite。
14. Qlib 使用原则
Qlib 必须被 Adapter 封装。
例如:
QlibDatasetAdapter
QlibModelAdapter
QlibBacktestAdapter
业务层不要直接依赖 Qlib 内部实现。
禁止项目代码到处出现:
import qlib
尽量集中在:
quant/qlib_adapter/
15. 不要修改 Qlib 源码
默认禁止:
修改 site-packages/qlib
如果 Qlib 功能不满足要求:
优先:
Adapter
Wrapper
Extension
只有确实无法实现时,才考虑 fork,并必须记录原因。
16. Research Specification
前端、Agent、后端统一通过:
Research Specification
描述研究任务。
不要让前端直接构造 Qlib YAML。
不要让 Agent 直接生成任意 Qlib 配置。
正确流程:
User / Agent
↓
Research Specification
↓
Schema Validation
↓
Strategy Builder
↓
Qlib Adapter
17. API 设计
API 必须面向业务对象:
/api/stocks
/api/universes
/api/factors
/api/factor-tests
/api/strategies
/api/backtests
/api/experiments
/api/jobs
/api/agent
不要设计成:
/api/qlib/xxx
除非是内部 Adapter API。
18. API 输入输出
API 输入必须使用:
Pydantic Schema
不要直接把 SQLAlchemy Model 暴露给前端。
例如:
Request DTO
↓
Application Service
↓
Domain
↓
Repository
输出:
Domain
↓
Response DTO
↓
Frontend
19. 异步任务
以下任务必须考虑异步执行:
- 大量数据下载
- 因子计算
- 模型训练
- 回测
- 大规模参数搜索
- AI Research
API 不应该长时间阻塞 HTTP 请求。
返回:
{
"job_id": "BT-001",
"status": "queued"
}
前端通过 SSE / WebSocket 获取进度。
20. Job 状态
统一状态:
queued
running
success
failed
cancelled
可选阶段:
data_loading
feature_calculation
model_training
prediction
backtesting
analysis
saving_result
21. Experiment 必须可复现
每次研究必须保存:
experiment_id
data_version
code_version
strategy_version
universe
factors
model
parameters
backtest_config
start_date
end_date
result
最好记录:
git commit
目标:
任何一个历史实验,都应该尽可能可以重新运行。
22. 因子开发约束
每个因子必须明确:
name
description
formula
input data
frequency
lookback
direction
normalization
neutralization
例如:
momentum_60
定义:
过去60个交易日收益率
频率:
daily
方向:
higher_is_better
禁止创建只有:
factor1()
factor2()
而没有定义和文档的因子。
23. 因子研究不能只看收益率
新增因子测试至少考虑:
IC
RankIC
ICIR
分层收益
换手率
稳定性
行业暴露
市值暴露
不同市场阶段
不能因为:
Sharpe > 2
就直接认为因子有效。
24. 回测约束
回测必须考虑:
手续费
印花税
滑点
涨跌停
停牌
成交约束
调仓频率
如果某项没有实现,必须在 UI 和结果中明确显示。
禁止默认假设:
永远可以买入
永远可以卖出
没有交易成本
25. 选股策略
核心目标是:
低频
选股
组合
回测
默认优先:
daily data
weekly rebalance
monthly rebalance
不要默认引入:
tick
order book
HFT
除非用户明确要求。
26. 前端约束
前端必须:
业务导向
参数清晰
结果可视化
不要直接暴露:
Qlib internal config
Python object
SQL
用户看到:
股票池
因子
模型
策略
回测
而不是:
DatasetH
HandlerLP
SignalRecord
27. 前端结果统一
回测结果必须标准化。
推荐:
summary
equity_curve
drawdown
monthly_returns
yearly_returns
positions
trades
risk_metrics
factor_exposure
前端组件只依赖这个结构。
28. AI Agent 约束
Agent 是:
Research Assistant
不是:
System Administrator
Agent 默认只能通过 Tool:
search_stock
get_market_data
test_factor
create_strategy
run_backtest
get_experiment
compare_experiments
Agent 不得:
直接删除数据库
直接修改数据库
直接执行 shell
修改生产配置
修改数据源凭证
修改系统安全配置
29. AI Agent 的研究行为
Agent 应优先:
提出假设
↓
建立实验
↓
运行测试
↓
分析结果
↓
提出下一步
而不是:
看到高收益
↓
宣布策略成功
必须主动考虑:
overfitting
look-ahead bias
survivorship bias
data leakage
transaction cost
parameter sensitivity
out-of-sample
30. 禁止数据泄露
股票池也必须防止:
未来成分股
未来行业分类
未来财务数据
未来退市信息
例如不能用“2026年的沪深300成分股”回测2015年。
必须使用历史时点对应的成分数据。
31. 测试要求
每次修改至少运行相关测试。
重点测试:
Data Adapter
DAO
Repository
Research Specification
Future-data protection
Factor
Backtest
API
关键金融逻辑必须有单元测试。
32. 类型与代码质量
Python:
Python 3.11+
推荐:
ruff
pytest
mypy / pyright
pydantic
SQLAlchemy 2.x
Alembic
代码必须尽量:
typed
small
testable
documented
33. 配置管理
禁止把:
Tushare Token
数据库密码
LLM API Key
写进 Git。
使用:
.env
.env.example
.env.example 只提供变量名,不提供真实密钥。
34. Git 约束
每个功能尽量:
一个清晰 commit
Commit message 要表达实际修改:
feat: add tushare daily data provider
fix: prevent future financial data leakage
feat: add backtest job API
禁止提交:
数据库
缓存
大规模行情文件
模型权重
.env
secret
35. 修改现有代码的原则
优先:
最小修改
而不是:
顺手重构整个项目
如果确实需要架构调整:
- 说明原因
- 明确影响范围
- 分阶段修改
- 保证每阶段可运行
36. 新功能开发流程
AI Agent 应按照:
1. 阅读 ARCHITECTURE.md
2. 理解需求
3. 定义 Domain
4. 定义 DTO
5. 定义 Repository Interface
6. 实现 Infrastructure
7. 实现 Application Service
8. 实现 API
9. 实现前端
10. 编写测试
11. 运行测试
12. 更新文档
不要倒过来从 UI 开始堆代码。
37. 数据迁移原则
未来 SQLite → MySQL 时:
Domain 不变
Application 不变
API 不变
Frontend 不变
只调整:
Infrastructure / Database Configuration
这是 DAO / Repository 抽象必须保证的目标。
38. 第一阶段禁止事项
MVP 阶段不要主动增加:
Kubernetes
微服务集群
Kafka
复杂消息队列
实时交易
高频交易
复杂权限系统
多租户
GPU 集群
除非用户明确提出。
39. 推荐 MVP 技术栈
Frontend
React / Next.js
TypeScript
ECharts
Backend
FastAPI
Pydantic
SQLAlchemy
Alembic
Data
Tushare
Sina fallback
Parquet
DuckDB
Quant
Qlib
LightGBM
Database
SQLite
Testing
pytest
ruff
Deployment
Docker Compose
40. 最重要的开发原则
如果一个实现:
更简单
更容易测试
更容易替换
更容易解释
优先选择它。
如果一个实现:
把 Qlib
数据库
前端
Agent
强耦合在一起:
默认拒绝。
最终系统必须保持:
Data
↓
Domain
↓
Research
↓
Qlib
↓
Experiment
↓
API
↓
Frontend
↓
Agent
每一层职责明确、接口稳定、可测试、可替换。
41. Agent 每次任务结束前必须检查
□ 是否违反 ARCHITECTURE.md?
□ 是否绕过 DAO?
□ 是否把 SQLite 写死?
□ 是否直接依赖 Qlib 内部实现?
□ 是否可能引入未来函数?
□ 是否引入数据泄露?
□ 是否有测试?
□ 是否修改了 API 契约?
□ 是否需要更新文档?
□ 是否把 secret 提交进 Git?
□ 是否进行了不必要的大规模重构?
如果任一项为“是”,必须先处理或明确向用户报告。
42. 最终架构目标
本项目最终应该能够做到:
用户
↓
Web UI / AI Agent
↓
Research Specification
↓
Application Service
↓
Data / Factor / Strategy / Backtest
↓
Qlib
↓
Experiment
↓
可视化结果
并且:
Tushare → Sina
SQLite → MySQL
Qlib → 其他量化引擎
普通研究 → AI Agent
都不应该要求推翻整个系统。
这比单纯快速把功能写出来更重要。