6.6 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
项目概述
基于 Docker + Python(tushare) + PostgreSQL 的中国期货行情分析系统,实现日线数据采集与三层加权打分模型。运行方式支持两种模式:① 宿主机 cron/launchd 定时调用 docker-compose run 执行 CLI;② 通过 FastAPI 服务以 HTTP API 触发。详细业务说明见 README.md。
常用命令
# === 启动全栈服务(PostgreSQL + tushare API + web) ===
docker-compose up -d
# === tushare CLI(不传参 = 按当月 FG 主力自动选合约,轮换规则见 contracts.py:ROLLOVER_RULES) ===
docker-compose run --rm tushare python -m src.main
# 显式指定合约(注意交易所后缀:.ZCE/.SHF/.DCE,郑商所是 .ZCE 不是 .CZC)
docker-compose run --rm tushare python -m src.main RB2510.SHF
# 用品种代号自动选当月主力(目前只配置了 FG)
docker-compose run --rm tushare python -m src.main --symbol FG
# === tushare API 服务(容器内运行 uvicorn,端口 8000) ===
# 触发单次流水线
curl -X POST http://localhost:8000/api/v1/run -H "Content-Type: application/json" \
-d '{"symbol":"FG"}'
# 查询打分列表
curl "http://localhost:8000/api/v1/scores?limit=5"
# === 修改代码后必须重建镜像 ===
docker-compose build tushare
docker-compose build web
# === 查最新打分(PostgreSQL) ===
docker-compose exec postgres psql -U trade -d futures -c \
"SELECT ts_code, trade_date, composite, signal FROM scores ORDER BY trade_date DESC LIMIT 5;"
tushare/.env 必须存在且含 TUSHARE_TOKEN=xxx(已 gitignored)。
关键架构
单进程串行流水线:src.main.main() 先按命令行参数(显式 ts_code 优先,否则 contracts.active_contract(symbol) 按当月主力自动选)定下合约,再调 run() 顺序执行 fetcher → storage(candles) → scorer → storage(scores)。无后台任务、无队列,每次 CLI 调用处理一个合约一日。
FastAPI 服务(src.api):容器默认以 uvicorn src.api:app 启动,暴露 /api/v1/run(触发流水线)、/api/v1/scores、/api/v1/scores/{id}、/api/v1/contracts、/api/v1/candles 等端点。启动时自动 storage.init_db() 建表。API 与 CLI 共用同一套 fetcher/storage/scorer 逻辑。
主力轮换规则(contracts.py):每个品种在 ROLLOVER_RULES 中维护 month -> (主力月, 年份偏移) 表。FG 当前规则:1-3/12 月→05、4-7 月→09、8-11 月→01,其中 8-11 月与 12 月跨年(year_offset=1)。新增品种(如 RB、I)只需在该 dict 里加一条,无需改 main 流程。
三层打分模型(scorer.py):综合 = 短期(7日,0.4) + 中期(15日,0.35) + 长期(30日,0.25)。score_daily() 要求 DataFrame ≥31 行,fetcher.fetch_contract 默认拉一个合约的全历史(实际 100+ 行),按 trade_date 升序排列后供打分使用。打分结果通过 dataclass ScoreResult + ScoreDetail 流转,storage.save_score 把 detail 序列化为 detail_json 文本列。
PostgreSQL 作为业务数据库:docker-compose 编排 postgres:18.3-alpine3.23,tushare 与 web 服务均通过 DATABASE_URL 连接。storage.py 使用 psycopg3 驱动,candles 与 scores 表以 ON CONFLICT (ts_code, trade_date) DO UPDATE 实现幂等,可反复重跑同一天。scores 表主键为 UUID DEFAULT uuidv7() PRIMARY KEY(见 models.py 与 storage.py)。
Docker 边界:tushare/src/ 与 web/backend/、web/frontend/ 均在 Dockerfile 的 COPY 阶段拷进镜像,没有源码挂载——改完 Python/Go/Vue 代码不重建镜像就跑等于跑旧代码。这是重要陷阱。
配置/密钥规则
.gitignore 排除范围广(见文件):data/、*.db*、.env*、CTP 流文件(*.con/*.dat/ResultInfo.xml 等)、.claude/、所有日志。新增任何账户、token、行情流文件务必先确认匹配 ignore 规则。
注意 web/backend/dist/ 在 .gitignore 中有显式例外:目录本身入库,但内部文件除 .gitkeep/index.html 外都被忽略——这是为了 go:embed all:dist 在本地能编译,真正的 SPA 产物在 Docker 构建期生成。
Web 模块(报告浏览端)
./web/ 是独立的报告浏览端,与 tushare 流水线解耦:tushare 写 PostgreSQL,web 只读访问业务数据、读写 auth.db。docker-compose 上是 web 服务,与 tushare/postgres 共存不互相依赖。
架构与边界:
- 后端 Go(
golang:1.25.8-alpine3.23构建,alpine:3.23运行),路由chi,业务数据库驱动github.com/lib/pq(PostgreSQL),鉴权数据库仍用modernc.org/sqlite(纯 Go 无 CGO)管理auth.db。前端 Vue 3 + Vite + Element Plus + ECharts。 - 单进程同源服务:Vue 产物在 Docker 构建期由
node阶段产出dist/,被go:embed all:dist嵌入二进制,运行时由 Go 同时服务/api/*与 SPA 静态文件——不引入 nginx 旁车。 - 双 DB 分离:业务数据
futures(PostgreSQL)通过DATABASE_URL只读访问;auth.db(SQLite)由 web 自己 init/写入,落在./data/auth.db(已被.gitignore覆盖),容器挂载./data:/app/auth。 - 鉴权 JWT(HS256, Bearer header),12h 过期,无 sessions 表。前端把 token 持久化到
localStorage,axios 拦截器统一注入 + 401 自动跳登录。 - 前端支持暗/浅色模式切换(
stores/theme.ts),侧边导航在暗色模式用#282828、浅色模式用#f9fafb。
禁止公开注册:登录后管理员才能在 /admin/users 维护账号。首次启动时 auth.Bootstrap 检查 users 表,若没有 admin 行 且 env 同时存在 ADMIN_USER/ADMIN_PASS,则用 bcrypt(cost=12) 写一行 admin。一旦 admin 存在,这两个 env 被静默忽略——避免轮换 env 时静默改密。忘记管理员密码的恢复方式:停服 → sqlite3 data/auth.db "DELETE FROM users WHERE role='admin'" → 重置 env → 重启。
修改即重建:沿用 tushare 服务的约定,web/backend/ 与 web/frontend/ 都通过镜像 COPY 进容器,没有源码挂载。改完 Go/Vue 代码不重建镜像就跑等于跑旧代码。重建命令 docker-compose build web。
常用命令:
# 首启需先在 web/backend/.env 写 ADMIN_USER/ADMIN_PASS/JWT_SECRET (gitignored)
docker-compose up -d web
docker-compose logs -f web # 看 [bootstrap] 日志确认 admin 是否被创建
# 仅重建 web,不影响 tushare
docker-compose build web && docker-compose up -d web
# 本地开发 (后端 + 前端分别起,api 走代理)
cd web/backend && go run ./ # 需要本地 Go 1.25.8;dist/ 目录的占位会被 embed
cd web/frontend && npm install && npm run dev # 默认 5173 端口,/api 代理到 8080