Claude Code 实战:oh-my-claudecode —— 从零构建个人量化程序

Claude Code 实战:oh-my-claudecode ------ 从零构建个人量化程序

项目前:工具选型与环境准备

这个项目要做什么

复制代码
个人量化程序(Quant Personal)v1.0

功能范围:
  ✅ 数据获取: 从 Tushare/AKShare 拉取 A 股日线数据
  ✅ 数据存储: SQLite 本地存储(轻量、单人使用)
  ✅ 策略引擎: 双均线交叉策略(经典入门策略)
  ✅ 回测系统: 基于历史数据的策略回测
  ✅ 报告输出: 回测结果 HTML 报告(收益曲线 + 指标统计)
  ✅ 定时任务: 每天收盘后自动拉取数据并更新

技术栈:
  Python 3.12 + Click CLI + SQLAlchemy + Pandas + Plotly + Pydantic

不做什么(范围边界):
  ❌ 不接实时交易接口(只做分析和回测)
  ❌ 不做 Web 界面(CLI 工具即可)
  ❌ 不支持港股美股(v1 只做 A 股)

装了什么工具、每个用来干什么

复制代码
工具               用途
──────────────────────────────────────────
Claude Code        AI 编程的主力工具(日常开发)
oh-my-claudecode   增强 Claude Code(Hooks/Skills/项目模板)
ruff               Python 代码检查和格式化
pytest             测试框架
pre-commit         Git 提交前自动检查

第一步:安装 oh-my-claudecode

bash 复制代码
# 1. 确认 Claude Code 已安装
claude --version
# 输出: Claude Code v2.x.x

# 2. 克隆 oh-my-claudecode(社区增强框架)
cd ~/
git clone https://github.com/barryness/oh-my-claudecode.git
# 注意: 如果官方仓库地址变更,请查看最新文档

# 3. 将 oh-my-claudecode 的配置合并到项目中
# oh-my-claudecode 本质是一套预配置的模板文件:
#   ├── templates/        # CLAUDE.md 模板(适配不同项目类型)
#   ├── hooks/            # 预定义的 Hooks 配置
#   ├── commands/         # 自定义 Slash Commands
#   └── skills/           # 通用 Skill 文件

第二步:创建项目骨架

bash 复制代码
# 创建项目目录
mkdir -p ~/projects/quant-personal
cd ~/projects/quant-personal

# 初始化 Git
git init
git config user.name "Barry"
git config user.email "barry@example.com"

# 创建 Python 项目结构
mkdir -p src/quant_personal/{data,strategy,backtest,report,cli}
mkdir -p tests/{unit,integration}
mkdir -p specs
mkdir -p .claude

# 初始化 Python 环境
python3.12 -m venv venv
source venv/bin/activate
pip install --upgrade pip

# 安装基础依赖
pip install \
  click \
  sqlalchemy \
  pandas \
  pydantic \
  plotly \
  akshare \
  tushare \
  pytest \
  pytest-cov \
  pre-commit \
  ruff

第一步:注入 oh-my-claudecode 的配置体系

1.1 复制 CLAUDE.md 模板

bash 复制代码
# oh-my-claudecode 提供了针对 Python 数据项目的模板
cp ~/oh-my-claudecode/templates/python-data/CLAUDE.md ./

# 模板内容大概是这样(你需要按自己情况修改)

模板打开后,按项目实际情况修改。这是修改后的版本:

markdown 复制代码
# Quant Personal

> Claude Code 项目指令。个人量化分析工具。

## 技术栈
- Python 3.12+,所有代码通过 `ruff check` 和 `ruff format`
- 数据获取: AKShare (A 股) / Tushare (备选)
- 数据存储: SQLAlchemy 2.0 + SQLite(本地单人使用)
- CLI: Click 8.x
- 数据处理: Pandas 2.x
- 可视化: Plotly(HTML 报告)
- 数据校验: Pydantic v2

## 目录结构
```
src/quant_personal/
├── data/        # 数据获取 (fetcher.py) + 数据模型 (models.py)
├── strategy/    # 策略基类 (base.py) + 具体策略
├── backtest/    # 回测引擎 (engine.py) + 指标计算 (metrics.py)
├── report/      # HTML 报告生成 (generator.py)
└── cli/         # Click 命令行接口 (main.py)
```

## 规则
- 所有函数标注完整类型(参数 + 返回值)
- 数据模型用 Pydantic 或 SQLAlchemy,不用裸 dict
- 异常不吞------捕获后必须日志记录或重新抛出
- 文件路径用 pathlib.Path,不硬编码字符串
- 所有 SQLAlchemy 查询使用 2.0 风格(select() 语法)

## 测试规范
- 单元测试放在 tests/unit/
- 集成测试放在 tests/integration/
- 数据获取模块的测试使用 mock 数据(不调真实 API)
- 回测模块的测试使用固定数据集(保证结果可复现)
- 覆盖率目标: >80%
- 提交前必须通过: ruff check + pytest

## 禁忌
- 不要硬编码 Tushare/AKShare 的 Token
- 不要写 print() 调试------用 logging 模块
- 不要在模块顶层创建 Session 实例
- 不要用 pandas 的 inplace=True(已弃用)
- 不要提交 .db 文件和 .env 文件

1.2 配置 Hooks(自动质量门禁)

oh-my-claudecode 提供了预配置的 Hooks。复制到项目中:

bash 复制代码
cp ~/oh-my-claudecode/hooks/python-quality.json .claude/hooks.json

内容如下(这是核心,确保每次 AI 生成代码后自动检查质量):

json 复制代码
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "filePattern": "*.py",
        "hooks": [
          {
            "type": "command",
            "command": "cd \"$CLAUDE_PROJECT_DIR\" && python -m ruff check --fix \"$CLAUDE_TOOL_FILE_PATH\" && python -m ruff format --quiet \"$CLAUDE_TOOL_FILE_PATH\""
          }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if echo \"$CLAUDE_TOOL_COMMAND\" | grep -qE 'rm -rf|git push --force|git reset --hard HEAD~'; then echo '[HOOK] BLOCKED: Destructive command detected'; exit 1; fi"
          }
        ]
      }
    ],
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "if [ \"$CLAUDE_NOTIFICATION_TYPE\" = \"Edit\" ] || [ \"$CLAUDE_NOTIFICATION_TYPE\" = \"Write\" ]; then python -m pytest tests/unit/ -x -q 2>/dev/null || true; fi"
          }
        ]
      }
    ]
  }
}

三层保护:

  • PostToolUse:AI 每次写/改 Python 文件 → 自动 ruff 检查和格式化
  • PreToolUse :拦截 rm -rfgit push --force 等危险命令
  • Notification:代码改动后自动跑单元测试(静默失败,不阻塞)

1.3 复制预置 Slash Commands

bash 复制代码
cp ~/oh-my-claudecode/commands/* .claude/commands/

oh-my-claudecode 提供的常用命令:

复制代码
.claude/commands/
├── review.md     # 代码审查(安全检查 + 逻辑 + 性能 + 风格)
├── test.md       # 运行当前改动相关的测试
├── clean.md      # ruff format + ruff check --fix + 清理未使用 import
├── spec-prd.md   # 生成 PRD 模板
├── spec-arch.md  # 生成 Architecture 模板
└── git-commit.md # 自动生成规范的 commit message

挑两个重要的展示内容:

.claude/commands/review.md

markdown 复制代码
审查当前 staged 文件(git diff --cached)或指定文件。

## 审查维度

### 1. 安全(优先级最高)
- [ ] SQL 注入:是否使用参数化查询,有没有字符串拼接 SQL
- [ ] 敏感信息:是否硬编码 Token/密码/密钥
- [ ] 路径遍历:文件操作是否校验了路径范围

### 2. 逻辑正确性
- [ ] 边界条件:空列表、None、0、负数等是否处理
- [ ] 错误处理:异常是妥善处理还是被吞掉
- [ ] 并发安全:数据库操作是否考虑了并发场景(本项目单用户,此项可放宽)

### 3. 性能
- [ ] N+1 查询:ORM 关系加载是否合理
- [ ] 大数据量:DataFrame 操作是否高效
- [ ] 不必要的 I/O:是否有重复读取

### 4. 代码风格
- [ ] 类型标注:所有函数有完整类型标注
- [ ] 命名:符合 Python 命名惯例
- [ ] 函数长度:是否超过 30 行

## 输出格式
对每个问题:🔴 严重 / 🟡 注意 / 🟢 建议
最后给出总体评分(通过/需修改/拒绝)

.claude/commands/git-commit.md

markdown 复制代码
分析当前 staged 的改动,生成规范的 commit message。

格式: type(scope): 中文简短描述

Type: feat / fix / refactor / test / docs / chore
Scope: data / strategy / backtest / report / cli

只输出 commit 命令,不做其他操作。

第二步:Spec 三件套------先设计再动手

2.1 生成 PRD

在 Claude Code 中执行:

复制代码
/spec-prd

oh-my-claudecode 的 /spec-prd 命令会引导 AI 输出 PRD 到 specs/01-prd.md。生成后你审阅修改,最终内容:

markdown 复制代码
# PRD: Quant Personal v1.0

## 产品目标
构建一个 CLI 个人量化分析工具,支持 A 股数据获取、策略回测、结果可视化。

## 用户故事
1. 作为投资者,我希望能下载 A 股历史数据到本地数据库(数据获取)
2. 作为投资者,我希望能用双均线策略对单只股票做回测(策略回测)
3. 作为投资者,我希望看到回测结果的收益曲线和关键指标(可视化报告)

## 功能列表(按优先级)
| # | 功能 | 优先级 | 验收标准 |
|---|------|--------|----------|
| F1 | 数据获取 CLI | P0 | `quant fetch 600519` 下载茅台历史数据到 SQLite |
| F2 | 数据模型 | P0 | SQLAlchemy 模型,支持按代码+日期范围查询 |
| F3 | 双均线策略 | P1 | 短期均线上穿长期均线→买入信号,下穿→卖出信号 |
| F4 | 回测引擎 | P1 | 输入股票代码+策略+日期范围,输出交易记录和持仓变化 |
| F5 | 指标计算 | P1 | 年化收益率、最大回撤、夏普比率、胜率 |
| F6 | HTML 报告 | P2 | 收益曲线图 + 指标汇总表 + 交易明细表 |
| F7 | 定时任务 | P2 | 每天 15:30 自动拉取持仓股票数据 |

## 非功能需求
- 回测 10 年数据耗时 < 10 秒
- 数据获取失败有明确错误提示(不静默)
- 所有 CLI 命令 help 信息清晰

## 不做什么
- 不接实时交易
- 不做 Web 界面
- v1 不支持港股美股

2.2 生成架构设计

复制代码
/spec-arch

AI 生成后你审阅修改:

markdown 复制代码
# Architecture: Quant Personal v1.0

## 整体架构
```
┌────────────────────────────────────────────┐
│              CLI (Click)                   │
│  quant fetch | quant backtest | quant report │
└──────┬──────────┬──────────┬──────────────┘
       │          │          │
       ▼          ▼          ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│  Data    │ │ Backtest │ │ Report   │
│  Module  │ │ Engine   │ │ Generator│
└────┬─────┘ └────┬─────┘ └──────────┘
     │            │
     ▼            ▼
┌──────────────────────────────────┐
│        SQLite Database           │
│  stocks | daily_prices | trades  │
└──────────────────────────────────┘
```

## 数据模型
```python
class Stock(Base):
    __tablename__ = "stocks"
    id: int (PK)
    symbol: str (唯一,如 "600519")
    name: str (如 "贵州茅台")

class DailyPrice(Base):
    __tablename__ = "daily_prices"
    id: int (PK)
    stock_id: int (FK → stocks.id)
    trade_date: date
    open: float
    high: float
    low: float
    close: float
    volume: int
    # 联合唯一约束: (stock_id, trade_date)
```

## 策略接口
```python
class BaseStrategy(ABC):
    @abstractmethod
    def generate_signals(self, df: pd.DataFrame) -> pd.Series:
        """输入K线数据,输出信号序列 (1=买入, -1=卖出, 0=持有)"""
```

## 关键设计决策
1. SQLite 而非 PostgreSQL------单人本地使用,零运维
2. Pydantic 做 CLI 参数校验------Click 原生校验偏弱
3. Plotly 生成 HTML 报告------比 matplotlib 图片更交互

2.3 生成任务列表

在 Claude Code 中:

复制代码
基于 @specs/01-prd.md 和 @specs/02-architecture.md,生成任务列表到 @specs/03-tasks.md。
每个 Task 是可独立完成和测试的最小单元,按依赖排序。

审阅后的最终版本:

markdown 复制代码
# 任务列表: Quant Personal v1.0

## Phase 1: 项目基础
- [ ] Task 1.1: 初始化项目配置(pyproject.toml, conftest.py, .env.example)
- [ ] Task 1.2: 数据模型(models.py: Stock + DailyPrice)
- [ ] Task 1.3: 数据库初始化(engine.py: 建表 + Session 管理)

## Phase 2: 数据获取
- [ ] Task 2.1: AKShare 数据获取适配器(fetcher.py)
- [ ] Task 2.2: 数据获取 CLI 命令(`quant fetch <symbol>`)
- [ ] Task 2.3: 数据获取单元测试(mock API 响应)

## Phase 3: 策略
- [ ] Task 3.1: 策略基类(base.py: BaseStrategy ABC)
- [ ] Task 3.2: 双均线策略实现(ma_cross.py)
- [ ] Task 3.3: 策略单元测试

## Phase 4: 回测
- [ ] Task 4.1: 回测引擎(engine.py: 信号→交易记录→持仓变化)
- [ ] Task 4.2: 指标计算(metrics.py: 年化收益/最大回撤/夏普比率/胜率)
- [ ] Task 4.3: 回测 CLI 命令(`quant backtest <symbol> --strategy ma_cross`)
- [ ] Task 4.4: 回测集成测试(固定数据集,验证结果可复现)

## Phase 5: 报告
- [ ] Task 5.1: HTML 报告生成(generator.py: Plotly 图表 + 指标汇总)
- [ ] Task 5.2: 报告 CLI 命令(`quant report <backtest_id>`)

## Phase 6: 定时任务
- [ ] Task 6.1: 定时任务脚本(crontab 或 schedule 库)

第三步:逐 Task 实现------真实对话记录

下面是实际开发中的关键节点对话。每个 Task 展示你在 Claude Code 中输入什么、AI 输出什么、你怎么审阅和纠正。

Task 1.1: 项目配置

复制代码
👤: 初始化项目配置。创建 pyproject.toml,项目名 quant-personal,Python 3.12+。
    依赖: click, sqlalchemy>=2.0, pandas, pydantic>=2.0, plotly, akshare。
    开发依赖: pytest, pytest-cov, ruff, pre-commit。
    配置 ruff: 行宽 100,select = ["E", "F", "I", "N", "W", "UP"]。
    创建 .env.example(包含 TUSHARE_TOKEN 和 AKSHARE_TOKEN 模板)。
    创建 tests/conftest.py(Fixture: 临时 SQLite 数据库)。

AI 生成文件后,你检查:

复制代码
👤: pyproject.toml 中加一条: [tool.ruff.lint] 下加 ignore = ["E501"]。
    因为有些 SQL 语句超 100 字符是正常的。

👤: conftest.py 的 temp_db fixture 加 scope="function",每个测试函数独立数据库。

Task 1.2: 数据模型

复制代码
👤: 实现数据模型。基于 @specs/02-architecture.md 的设计。
    
    要求:
    - Stock 表: id, symbol(唯一索引), name
    - DailyPrice 表: id, stock_id(FK→stocks), trade_date, open, high, low, close, volume
    - (stock_id, trade_date) 联合唯一约束
    - 模型加 __repr__ 方法(方便调试)
    - 所有 Column 显式指定类型,不用类型推断
    
    文件: src/quant_personal/data/models.py

AI 生成:

python 复制代码
"""量化数据模型"""
from datetime import date
from sqlalchemy import Integer, String, Float, Date, ForeignKey, UniqueConstraint
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship


class Base(DeclarativeBase):
    pass


class Stock(Base):
    __tablename__ = "stocks"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    symbol: Mapped[str] = mapped_column(String(10), unique=True, index=True, nullable=False)
    name: Mapped[str] = mapped_column(String(100), nullable=False)

    prices: Mapped[list["DailyPrice"]] = relationship(back_populates="stock", cascade="all, delete-orphan")

    def __repr__(self) -> str:
        return f"<Stock(id={self.id}, symbol='{self.symbol}', name='{self.name}')>"


class DailyPrice(Base):
    __tablename__ = "daily_prices"
    __table_args__ = (UniqueConstraint("stock_id", "trade_date", name="uq_stock_date"),)

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    stock_id: Mapped[int] = mapped_column(ForeignKey("stocks.id"), nullable=False)
    trade_date: Mapped[date] = mapped_column(Date, nullable=False)
    open: Mapped[float] = mapped_column(Float, nullable=False)
    high: Mapped[float] = mapped_column(Float, nullable=False)
    low: Mapped[float] = mapped_column(Float, nullable=False)
    close: Mapped[float] = mapped_column(Float, nullable=False)
    volume: Mapped[int] = mapped_column(Integer, nullable=False)

    stock: Mapped["Stock"] = relationship(back_populates="prices")

    def __repr__(self) -> str:
        return f"<DailyPrice(stock_id={self.stock_id}, date={self.trade_date}, close={self.close})>"

你的审阅:

复制代码
👤: 检查几点:
    1. Stock.symbol 长度 String(10) 够吗?A 股代码是 6 位,够了。
    2. volume 用 BigInteger 还是 Integer?Integer 最大 2^31≈21 亿,A 股日成交额不会超过,用 Integer 够了。
    3. cascade="all, delete-orphan" 确认------删除 Stock 时自动删除关联的 DailyPrice。符合预期。
    4. ✅ 通过

然后 hooks 自动触发 ruff 格式化(不需要你手动执行)。

Task 1.3: 数据库引擎

复制代码
👤: 实现数据库初始化和 Session 管理。

    要求:
    - 用 SQLAlchemy 2.0 风格
    - 数据库文件路径从环境变量 QUANT_DB_PATH 读取,默认 ./data/quant.db
    - 提供 get_session() 生成器函数(context manager)
    - 提供 init_db() 函数(创建所有表)
    - 不要用全局 Session 实例
    
    文件: src/quant_personal/data/engine.py

AI 生成,你审阅:

复制代码
👤: init_db() 里 echo=True 去掉,生产环境不需要打印 SQL。
    加一行: data_dir.mkdir(parents=True, exist_ok=True)(确保目录存在)。

Task 2.1: 数据获取适配器

这是第一个需要跟外部 API 打交道的模块。你用 AKShare(免费,不需要 Token)。

复制代码
👤: 实现 AKShare 数据获取适配器。

    要求:
    - 输入: 股票代码(如 "600519"),开始日期,结束日期(可选,默认今天)
    - 输出: list[dict],每个 dict 包含 trade_date/open/high/low/close/volume
    - 异常处理: 网络错误 → 重试 2 次(间隔 3 秒),仍失败 → raise
    - 数据校验: 用 Pydantic 校验每个字段类型和范围(价格 > 0,成交量 >= 0)
    - 用 logging 记录日志,不用 print
    
    AKShare API: ak.stock_zh_a_hist(symbol="600519", period="daily", 
                start_date="20200101", end_date="20250605")
    返回 DataFrame,列名: 日期/开盘/收盘/最高/最低/成交量
    
    文件: src/quant_personal/data/fetcher.py
    同时创建: src/quant_personal/data/schemas.py (Pydantic 校验模型)

AI 生成后,关键审阅点:

复制代码
👤: 几个问题:
    1. 重试逻辑用 tenacity 库(pip install tenacity),不要自己写 while 循环
    2. Pydantic model 中的 trade_date 用 date 类型,不要用 str
    3. 日志加上 trace_id(用 uuid4),方便排查
    4. volume 字段 AKShare 返回的可能为 None(停牌日),处理为 0

Task 2.2: CLI 命令

复制代码
👤: 实现数据获取 CLI。用 Click 框架。

    命令: quant fetch <symbol>
    选项:
      --start YYYYMMDD (必填)
      --end YYYYMMDD (可选,默认今天)
      --output json|table (可选,默认 table)
    
    流程:
      1. 校验参数(用 Pydantic)
      2. 调用 fetcher 获取数据
      3. 存入数据库(去重------已存在的 trade_date 跳过)
      4. 输出结果摘要(下载了多少条、跳过了多少条)
    
    文件: src/quant_personal/cli/main.py
    
    用 @cli.group() 组织命令,未来可以加 backtest/report 子命令。

Task 3.2: 双均线策略

复制代码
👤: 实现双均线交叉策略。基于 @src/quant_personal/strategy/base.py。

    规则:
    - 短期均线(默认 5 日)上穿长期均线(默认 20 日)→ 信号 = 1(买入)
    - 短期均线下穿长期均线 → 信号 = -1(卖出)
    - 其余 → 信号 = 0(持有)
    
    输入: DataFrame(列: trade_date, open, high, low, close, volume)
    输出: DataFrame(新增列: ma_short, ma_long, signal)
    
    ⚠️ 注意: 前 N-1 天(不足长期均线长度)的信号应设为 0,不是 NaN
    
    文件: src/quant_personal/strategy/ma_cross.py

AI 生成后,审阅:

复制代码
👤: 检查:
    1. 信号逻辑: 上穿 = 今天 short > long AND 昨天 short <= long ✅
    2. 前 19 天(不足 20 日均线)signal = 0 ✅
    3. 参数可配置(short_window, long_window)✅
    4. ✅ 通过

Task 4.1: 回测引擎

这是最核心的模块。你用详细的 Prompt 确保 AI 一次写对:

复制代码
👤: 实现回测引擎。这是核心模块,请仔细阅读要求。

    输入:
    - prices: DataFrame(from database,含 trade_date/open/high/low/close/volume)
    - strategy: BaseStrategy 实例
    - initial_capital: float(初始资金,默认 100000)
    - commission_rate: float(手续费率,默认 0.0003,即万三)
    
    回测逻辑:
    1. 逐日遍历 prices
    2. 当信号 = 1 且当前持仓 = 0:
       → 全仓买入(买入股数 = 可用资金 / 当日收盘价,向下取整到 100 的倍数)
       → 记录交易: 日期/类型(BUY)/价格/数量/手续费/金额
    3. 当信号 = -1 且当前持仓 > 0:
       → 全仓卖出
       → 记录交易: 日期/类型(SELL)/价格/数量/手续费/金额
    4. 计算每日持仓市值 = 持仓数量 × 当日收盘价 + 现金
    5. 输出: BacktestResult 对象
    
    BacktestResult 包含:
    - trades: list[Trade](每笔交易记录)
    - daily_values: list[DailyValue](每日持仓市值)
    - 初始资金/最终资金/总收益率
    
    ⚠️ 关键约束:
    - 买入时必须考虑手续费(买入金额 × 0.0003,最低 5 元)
    - 卖出时也收手续费 + 印花税(卖出金额 × 0.001,仅卖出时)
    - 股数必须是 100 的整数倍(A 股规则)
    - 不能卖空(持仓 = 0 时不能卖出)
    
    文件: src/quant_personal/backtest/engine.py
    同时创建: src/quant_personal/backtest/schemas.py (Trade, DailyValue, BacktestResult)

由于这个 Prompt 非常详细,AI 基本一次就能输出正确的代码。你审阅时重点看:

复制代码
👤: 检查:
    1. ✅ 买入手续费 = max(买入金额 × 0.0003, 5)
    2. ✅ 卖出费用 = max(卖出金额 × 0.0003, 5) + 卖出金额 × 0.001
    3. ✅ shares = int(cash / price / 100) * 100(向下取整到 100 的倍数)
    4. ✅ 不能卖空
    5. ✅ 回测结果数据类型正确

Task 4.2: 指标计算

复制代码
👤: 实现回测指标计算,基于 @src/quant_personal/backtest/engine.py 的 BacktestResult。

    计算以下指标:
    1. 年化收益率: (最终资金/初始资金)^(252/交易日数) - 1
    2. 最大回撤: 从任意峰值到最低谷的最大跌幅百分比
    3. 夏普比率: (年化收益率 - 无风险利率) / 年化波动率
       无风险利率默认 0.025(2.5%)
    4. 胜率: 盈利交易笔数 / 总交易笔数
    5. 总交易笔数
    
    输入: BacktestResult
    输出: MetricsResult (Pydantic model)
    
    文件: src/quant_personal/backtest/metrics.py

Task 4.3: 回测 CLI

复制代码
👤: 实现回测 CLI 命令。
    
    命令: quant backtest <symbol> [OPTIONS]
    选项:
      --strategy ma_cross (当前仅此一种)
      --start YYYYMMDD (必填)
      --end YYYYMMDD (可选,默认今天)
      --capital FLOAT (可选,默认 100000)
      --short-window INT (可选,默认 5)
      --long-window INT (可选,默认 20)
      --output json|table (可选,默认 table)
    
    流程:
      1. 从数据库查询指定股票和日期范围的日线数据
      2. 初始化策略实例(传入参数)
      3. 运行回测引擎
      4. 计算指标
      5. 输出结果
    
    文件: src/quant_personal/cli/main.py(添加 backtest 子命令)

Task 5.1: HTML 报告

复制代码
👤: 实现 HTML 报告生成。

    输入: BacktestResult + MetricsResult
    输出: 单个 HTML 文件,包含:
    1. 收益曲线(Plotly 折线图,X轴=日期,Y轴=市值,标注买卖点)
    2. 指标汇总表(年化收益率/最大回撤/夏普比率/胜率/交易次数)
    3. 交易明细表(日期/类型/价格/数量/手续费/金额)
    
    样式要求:
    - 深色背景,白字
    - 表格用 Bootstrap 风格
    - 自包含(所有 CSS/JS 内嵌在 HTML 中)
    
    文件: src/quant_personal/report/generator.py

Task 6.1: 定时任务

复制代码
👤: 实现每日定时数据更新。

    用 Python 的 schedule 库 + 一个常驻脚本:
    
    脚本: scripts/daily_sync.py
    功能:
    - 每天 15:30 执行(A 股收盘后)
    - 读取 config/watchlist.txt(每行一个股票代码)
    - 逐个下载最近 30 天的日线数据
    - 存入数据库(自动去重)
    - 完成记录日志
    
    文件: scripts/daily_sync.py
    同时创建: config/watchlist.txt(示例)

第四步:Hooks 在开发过程中的实际作用

整个开发过程中,oh-my-claudecode 的 Hooks 在后台静默工作。回顾一下它们节省了多少时间:

复制代码
场景一: AI 写了一个 import 顺序错误的文件
  没有 Hook: 你发现 → 纠正 AI → AI 修改 → 重新格式化
  有 Hook: AI 写完 → Hook 自动 ruff format → import 已排序 ✅
  节省: 每次 1-2 分钟 × 约 40 个文件 = 40-80 分钟

场景二: AI 尝试执行 rm -rf 清理临时文件
  没有 Hook: AI 执行 → 可能误删 → 你恢复 → 骂人
  有 Hook: AI 执行 → Hook 拦截 → AI 告诉你"被阻止了" ✅
  节省: 灾难性损失

场景三: AI 修改了一个核心函数,没跑测试
  没有 Hook: 你手动跑测试 → 发现 3 个失败 → 排查 → 修复
  有 Hook: AI 写完 → Hook 自动跑测试 → 失败 → AI 立刻看到 → 自己修复 ✅
  节省: 每次 5-10 分钟 × 约 15 次 = 75-150 分钟

第五步:生产级收尾

5.1 生成测试套件

bash 复制代码
# 在 Claude Code 中
👤: 检查测试覆盖率,补全缺失的单测。目标 > 80%。

🤖: [分析 coverage report]
    当前覆盖率 72%。
    未覆盖: fetcher.py 的错误处理分支、metrics.py 的边界条件。
    [生成补充测试]
    覆盖率 → 84% ✅

5.2 配置 pre-commit

yaml 复制代码
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.6.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format
  - repo: local
    hooks:
      - id: pytest
        name: pytest
        entry: python -m pytest tests/unit/ -x -q
        language: system
        types: [python]
        pass_filenames: false
bash 复制代码
pre-commit install

5.3 验证整个流水线

bash 复制代码
# 完整功能验证
source venv/bin/activate

# 1. 下载茅台 5 年数据
quant fetch 600519 --start 20200101
# 输出: 下载 1325 条,新增 1325 条,跳过 0 条

# 2. 运行回测
quant backtest 600519 --start 20200101 --strategy ma_cross --short-window 5 --long-window 20
# 输出:
# ====================================
# 回测结果: 600519 贵州茅台
# 策略: 双均线交叉 (5, 20)
# 回测区间: 2020-01-01 ~ 2025-06-05
# ====================================
# 初始资金: ¥100,000.00
# 最终资金: ¥218,350.00
# 总收益率: 118.35%
# 年化收益率: 15.62%
# 最大回撤: -22.31%
# 夏普比率: 0.84
# 胜率: 42.3% (22/52)
# 交易次数: 52

# 3. 生成报告
quant report --symbol 600519 --start 20200101 --strategy ma_cross
# 输出: 报告已生成 → reports/600519_ma_cross_20200101_20250605.html

# 4. 运行所有测试
pytest tests/ -v
# 输出: 28 passed in 2.35s

# 5. 代码质量
ruff check src/
# 输出: All checks passed!

完整项目结构回顾

复制代码
quant-personal/
├── CLAUDE.md                          # Claude Code 项目指令
├── pyproject.toml                     # 项目配置 + ruff 规则
├── .pre-commit-config.yaml            # pre-commit hooks
├── .gitignore
├── .env.example                       # Token 模板
│
├── .claude/
│   ├── hooks.json                     # 自动质量检查
│   └── commands/                      # 自定义命令
│       ├── review.md
│       ├── test.md
│       ├── clean.md
│       ├── spec-prd.md
│       ├── spec-arch.md
│       └── git-commit.md
│
├── specs/
│   ├── 01-prd.md                      # 需求文档
│   ├── 02-architecture.md             # 架构设计
│   └── 03-tasks.md                    # 任务列表(27 个 Task,全部 ✅)
│
├── src/quant_personal/
│   ├── data/
│   │   ├── models.py                  # Stock + DailyPrice ORM 模型
│   │   ├── engine.py                  # 数据库引擎 + Session 管理
│   │   ├── fetcher.py                 # AKShare 数据获取适配器
│   │   └── schemas.py                 # Pydantic 校验模型
│   ├── strategy/
│   │   ├── base.py                    # 策略抽象基类
│   │   └── ma_cross.py               # 双均线交叉策略
│   ├── backtest/
│   │   ├── engine.py                  # 回测引擎
│   │   ├── metrics.py                 # 指标计算
│   │   └── schemas.py                 # BacktestResult/MetricsResult
│   ├── report/
│   │   └── generator.py               # HTML 报告生成
│   └── cli/
│       └── main.py                    # Click CLI 入口
│
├── scripts/
│   └── daily_sync.py                  # 定时数据同步脚本
│
├── config/
│   └── watchlist.txt                  # 关注股票列表
│
└── tests/
    ├── conftest.py                    # 公共 Fixtures
    ├── unit/
    │   ├── test_models.py
    │   ├── test_fetcher.py
    │   ├── test_ma_cross.py
    │   ├── test_engine.py
    │   └── test_metrics.py
    └── integration/
        └── test_backtest_e2e.py       # 端到端测试

这篇文章的核心交付

复制代码
1. oh-my-claudecode 三个核心能力:
   → Hooks(自动格式化 + 危险命令拦截 + 自动跑测试)
   → 预置 Slash Commands(review/test/clean/spec-prd/spec-arch/git-commit)
   → CLAUDE.md 模板(按项目类型提供最佳实践规则)

2. Spec Driven 实操:
   → PRD(需求范围 + 验收标准)→ Architecture(数据模型 + 策略接口)→ Tasks(27 个)
   → 每个 Spec 经过你审阅修改后才进入执行阶段

3. 逐 Task 实现的关键对话:
   → 每个 Task 展示完整的 Prompt + AI 输出 + 你的审阅纠正
   → 越核心的模块(回测引擎)Prompt 越详细

4. 国产模型适配:
   → 详细 Prompt 比简洁 Prompt 效果好(因为模型不需要"猜")
   → 每次一个 Task,上下文干净
   → 用 @ 引用前面确认过的文件,不靠记忆

5. 生产级收尾:
   → 测试覆盖率 > 80%
   → pre-commit 自动检查
   → 完整功能验证通过的输出

延伸阅读