- 删除 11 个残留文件: continuation.md, init_plan.md, reasonix.toml, djapi/continuation.md, djapi/.serena/, djapi/.claude/, djapi/.mcp.json, .claude/skills/, docs/usage.html, docs/db_schema.md, docs/report_db_design.md - 7 个 CLAUDE-*.md 移入 docs/ 并重命名去 CLAUDE- 前缀 - 新增 4 个文档: architecture.md, development.md, api.md, deployment.md - 重写 usage.md, README.md - 修复所有过时引用和交叉链接
586 lines
15 KiB
Markdown
586 lines
15 KiB
Markdown
# cc-cursor 使用指南
|
||
|
||
Mac Mini 单机量化研究平台,覆盖数据获取 → 因子计算 → 回测 → 参数优化 → ML 模型 → 情绪因子 → Agent 系统全链路。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [环境准备](#1-环境准备)
|
||
2. [数据库连接](#2-数据库连接)
|
||
3. [数据层 — DataManager](#3-数据层--datamanager)
|
||
4. [因子引擎 — FactorEngine](#4-因子引擎--factorengine)
|
||
5. [回测引擎 — VectorBTEngine](#5-回测引擎--vectorbtengine)
|
||
6. [参数优化 — OptunaEngine](#6-参数优化--optunaengine)
|
||
7. [ML 模型 — LightGBM / CatBoost](#7-ml-模型--lightgbm--catboost)
|
||
8. [情绪因子 — SentimentEngine](#8-情绪因子--sentimentengine)
|
||
9. [Agent 系统 — 命令行入口](#9-agent-系统--命令行入口)
|
||
10. [配置说明](#10-配置说明)
|
||
11. [完整示例](#11-完整示例)
|
||
12. [常见问题](#12-常见问题)
|
||
|
||
---
|
||
|
||
## 1. 环境准备
|
||
|
||
### 硬件要求
|
||
|
||
- macOS / Linux(本系统开发于 Mac Mini)
|
||
- 内存 ≥ 16GB(ML 模型训练推荐)
|
||
- 网络:可访问东方财富 / 同花顺 API
|
||
|
||
### Python 环境
|
||
|
||
```bash
|
||
conda activate quant # Python 3.11.13
|
||
python --version # → 3.11.13
|
||
```
|
||
|
||
### 核心依赖
|
||
|
||
| 包 | 版本 | 用途 |
|
||
|---|------|------|
|
||
| pandas | 3.0 | 数据处理 |
|
||
| numpy | 2.4 | 数值计算 |
|
||
| akshare | 1.18 | A 股数据获取 |
|
||
| vectorbt | 1.0 | 回测引擎 |
|
||
| optuna | 4.9 | 参数优化 |
|
||
| lightgbm | 4.6 | 梯度提升模型 |
|
||
| catboost | 1.2 | 梯度提升模型 |
|
||
| scikit-learn | 1.9 | 特征工程 |
|
||
| sqlalchemy | 2.0 | 数据库 ORM |
|
||
| pymysql | 1.2 | MySQL 连接 |
|
||
|
||
### 项目路径设置
|
||
|
||
从 `finance/` 目录运行代码。脚本开头加入:
|
||
|
||
```python
|
||
import sys
|
||
sys.path.insert(0, "/path/to/cc-cursor/finance")
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 数据库连接
|
||
|
||
### 建立 SSH 隧道
|
||
|
||
```bash
|
||
bash shared/script/autossh.sh
|
||
```
|
||
|
||
验证隧道:
|
||
|
||
```bash
|
||
lsof -i :13306 | grep LISTEN
|
||
```
|
||
|
||
### 连接信息
|
||
|
||
```
|
||
Host: 127.0.0.1
|
||
Port: 13306
|
||
User: myquant
|
||
Password: <your-db-password>
|
||
Database: myquant
|
||
```
|
||
|
||
### 数据库表
|
||
|
||
所有表使用 `mac_` 前缀:
|
||
|
||
| 表名 | 内容 | 说明 |
|
||
|------|------|------|
|
||
| `mac_stock_basic` | A 股列表 | 5,524 只股票 |
|
||
| `mac_stock_daily` | 日线行情 | 按需同步 |
|
||
| `mac_stock_financial` | 财务指标 | 同花顺核心指标 |
|
||
| `mac_report` | 报告持久化 | 日报归档 |
|
||
|
||
---
|
||
|
||
## 3. 数据层 — DataManager
|
||
|
||
### 初始化
|
||
|
||
```python
|
||
from data.data_manager import DataManager
|
||
|
||
dm = DataManager()
|
||
dm.init_db() # 首次使用创建表(幂等操作)
|
||
```
|
||
|
||
### 获取股票列表
|
||
|
||
```python
|
||
stocks = dm.get_stock_list() # → 5,524 只 A 股
|
||
stocks = dm.get_stock_list(force_refresh=True) # 强制刷新
|
||
```
|
||
|
||
### 获取日线数据
|
||
|
||
```python
|
||
daily = dm.get_daily("000001.SZ") # 全量日线
|
||
daily = dm.get_daily("000001.SZ", start="20240101", end="20241231")
|
||
```
|
||
|
||
### 获取财务数据
|
||
|
||
```python
|
||
fina = dm.get_financial("000001.SZ")
|
||
# → DataFrame: end_date, eps, bvps, roe, net_profit_margin, debt_to_assets
|
||
```
|
||
|
||
### 数据同步
|
||
|
||
```python
|
||
n = dm.sync_daily("000001.SZ") # 增量同步到最新
|
||
```
|
||
|
||
> 数据源优先级:Tushare(优先)→ AkShare(fallback)。DB 缓存优先。
|
||
|
||
---
|
||
|
||
## 4. 因子引擎 — FactorEngine
|
||
|
||
### 因子注册表
|
||
|
||
```python
|
||
from factors.registry import get_factor, list_factors, list_categories
|
||
|
||
print(list_categories()) # → 12 个分类
|
||
print(list_factors("RSI")) # → ['rsi_7', 'rsi_14']
|
||
print(len(list_factors())) # → 34 个因子
|
||
```
|
||
|
||
### 创建因子实例
|
||
|
||
```python
|
||
factor = get_factor("momentum_20") # 20 日动量
|
||
factor = get_factor("rsi_14") # 14 日 RSI
|
||
factor = get_factor("roe") # ROE 基本面因子
|
||
factor = get_factor("news_sent_5") # 5 日新闻情绪因子
|
||
```
|
||
|
||
### 计算因子
|
||
|
||
```python
|
||
from factors.engine import FactorEngine
|
||
|
||
engine_fe = FactorEngine(dm)
|
||
factors = [
|
||
get_factor("momentum_20"),
|
||
get_factor("rsi_14"),
|
||
get_factor("volatility_20"),
|
||
]
|
||
factor_df = engine_fe.compute("000001.SZ", factors)
|
||
# → DataFrame: index=trade_date, columns=[momentum_20, rsi_14, volatility_20]
|
||
```
|
||
|
||
### 截面因子
|
||
|
||
```python
|
||
cross = engine_fe.compute_universe(
|
||
factors=[get_factor("momentum_20"), get_factor("rsi_14")],
|
||
date="20250630",
|
||
ts_codes=["000001.SZ", "600519.SH", "300750.SZ"],
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 回测引擎 — VectorBTEngine
|
||
|
||
- 初始资金:100,000 元 | 手续费:0.03%(万三) | 方向:只做多
|
||
|
||
### 创建引擎
|
||
|
||
```python
|
||
from backtest.vectorbt.engine import VectorBTEngine
|
||
|
||
engine_bt = VectorBTEngine(initial_capital=100_000, commission=0.0003)
|
||
```
|
||
|
||
### 使用内置策略
|
||
|
||
```python
|
||
from backtest.strategies.rsi_mean_revert import RSIMeanRevertStrategy
|
||
|
||
strategy = RSIMeanRevertStrategy(oversold=30, overbought=70)
|
||
report = engine_bt.run(strategy, price_df, factor_df)
|
||
print(report.summary())
|
||
# → 收益=29.4% 年化=4.3% 回撤=-19.1% 夏普=0.37 胜率=77.1%
|
||
```
|
||
|
||
### 内置策略清单
|
||
|
||
| 策略 | 类名 | 适用场景 |
|
||
|------|------|----------|
|
||
| 均线交叉 | `SMACrossStrategy(fast=5, slow=20)` | 趋势跟踪 |
|
||
| RSI 反转 | `RSIMeanRevertStrategy(oversold=30, overbought=70)` | 均值回归 |
|
||
| 动量突破 | `MomentumBreakoutStrategy(lookback=20, exit_period=10)` | 动量策略 |
|
||
| 因子阈值 | `FactorCrossStrategy(factor_column, buy_threshold, sell_threshold)` | 通用因子 |
|
||
| 因子轮动 | `FactorRotationStrategy(factor_name, top_n=5)` | 截面选股 |
|
||
|
||
### 自定义策略
|
||
|
||
```python
|
||
from backtest.base import BaseStrategy
|
||
|
||
class MyStrategy(BaseStrategy):
|
||
name = "my_strategy"
|
||
category = "custom"
|
||
|
||
def __init__(self, param_a=10):
|
||
self.param_a = param_a
|
||
|
||
def generate_signals(self, factor_df):
|
||
signals = pd.Series(-1, index=factor_df.index)
|
||
signals[factor_df["rsi_14"] < 30] = 1 # 超卖买入
|
||
signals[factor_df["rsi_14"] > 70] = 0 # 超买卖出
|
||
return signals
|
||
```
|
||
|
||
### 回测报告字段
|
||
|
||
`total_return`, `cagr`, `max_drawdown`, `sharpe_ratio`, `calmar_ratio`, `annual_volatility`, `win_rate`, `profit_factor`, `total_trades`, `avg_hold_days`, `equity_curve`, `drawdown_curve`, `monthly_returns`, `trades_df`
|
||
|
||
---
|
||
|
||
## 6. 参数优化 — OptunaEngine
|
||
|
||
### 使用预置搜索空间
|
||
|
||
```python
|
||
from optimizer.engine import OptunaEngine
|
||
from optimizer.space import rsi_revert_space
|
||
|
||
opt_engine = OptunaEngine(engine_bt)
|
||
|
||
result = opt_engine.optimize(
|
||
strategy_class=RSIMeanRevertStrategy,
|
||
search_space=rsi_revert_space,
|
||
price_df=price_df,
|
||
factor_df=factor_df,
|
||
metric="sharpe", # sharpe/cagr/calmar/total_return
|
||
n_trials=200,
|
||
)
|
||
print(result.summary())
|
||
# → 最优参数: oversold=13, overbought=66
|
||
# → 最优目标 (sharpe): 0.5985
|
||
```
|
||
|
||
### Walk-Forward 验证
|
||
|
||
```python
|
||
wf_result = opt_engine.optimize_walk_forward(
|
||
strategy_class=RSIMeanRevertStrategy,
|
||
search_space=rsi_revert_space,
|
||
price_df=price_df, factor_df=factor_df,
|
||
metric="sharpe", n_trials=80,
|
||
train_window=756, test_window=252,
|
||
)
|
||
```
|
||
|
||
### 自定义搜索空间
|
||
|
||
```python
|
||
from optimizer.space import SearchSpace
|
||
|
||
my_space = SearchSpace(params=[
|
||
{"name": "fast", "type": "int", "low": 2, "high": 30, "step": 1},
|
||
{"name": "slow", "type": "int", "low": 15, "high": 120, "step": 5},
|
||
])
|
||
```
|
||
|
||
---
|
||
|
||
## 7. ML 模型 — LightGBM / CatBoost
|
||
|
||
### 特征工程
|
||
|
||
```python
|
||
from models.features import FeatureEngine
|
||
|
||
fe = FeatureEngine(lookahead=5, label_type="regression")
|
||
X, y = fe.build(factor_df, price_df, fit=True)
|
||
# → Winsorize(1%/99%) → ffill → median fill → RobustScaler → 标签计算
|
||
```
|
||
|
||
### LightGBM 训练
|
||
|
||
```python
|
||
from models.lightgbm.model import LightGBMModel
|
||
|
||
model = LightGBMModel(
|
||
params={"n_estimators": 200, "learning_rate": 0.03, "num_leaves": 15},
|
||
eval_ratio=0.2,
|
||
)
|
||
model.fit(X_train, y_train)
|
||
pred = model.predict(X_test)
|
||
ic = pred.corr(y_test)
|
||
```
|
||
|
||
### CatBoost 训练
|
||
|
||
```python
|
||
from models.catboost.model import CatBoostModel
|
||
|
||
model = CatBoostModel(
|
||
params={"iterations": 200, "learning_rate": 0.03, "depth": 5},
|
||
eval_ratio=0.2,
|
||
)
|
||
model.fit(X_train, y_train)
|
||
```
|
||
|
||
### ML 策略回测
|
||
|
||
```python
|
||
from models.backtest_integration import MLStrategy, MLBenchmark
|
||
|
||
strategy = MLStrategy(model, fe, buy_quantile=0.7, sell_quantile=0.3, rebalance_freq=5)
|
||
report = engine_bt.run(strategy, price_df, factor_df)
|
||
|
||
# 多模型对比
|
||
benchmark = MLBenchmark([lgb_model, cb_model], fe, price_df, factor_df)
|
||
df = benchmark.run() # → model × (IC, return, sharpe, win_rate, trades)
|
||
```
|
||
|
||
### 重要约束
|
||
|
||
- lookahead 固定,不输入模型(防目标泄露)
|
||
- 交叉验证用 TimeSeriesSplit(不 shuffle)
|
||
- 特征工程严禁使用未来数据
|
||
|
||
---
|
||
|
||
## 8. 情绪因子 — SentimentEngine
|
||
|
||
### 配置 API Key
|
||
|
||
编辑 `finance/.env`:
|
||
|
||
```bash
|
||
QWEN_API_KEY=sk-your-key-here
|
||
QWEN_MODEL=qwen-turbo
|
||
```
|
||
|
||
### 使用情绪引擎
|
||
|
||
```python
|
||
from factors.sentiment.sentiment_engine import SentimentEngine
|
||
|
||
sent = SentimentEngine(dm)
|
||
sent_df = sent.compute("000001.SZ", max_news=20)
|
||
# → DataFrame: (trade_date, news_sent_5, news_conf_5, sent_delta_5)
|
||
```
|
||
|
||
### 新闻数据源
|
||
|
||
| 数据源 | 说明 |
|
||
|--------|------|
|
||
| AkShare `stock_news_em` | 东方财富个股新闻 |
|
||
| MariaDB `xwlb_daily_ext` | 新闻联播分割数据 |
|
||
| MCP `trendradar-news` | 外部新闻聚合服务 |
|
||
|
||
### 日期对齐机制
|
||
|
||
- 新闻联播:`news_date + 1 day`(晚间播出 → 次日市场影响)
|
||
- 非交易日 → 对齐到最近交易日
|
||
|
||
---
|
||
|
||
## 9. Agent 系统 — 命令行入口
|
||
|
||
### CLI 命令
|
||
|
||
```bash
|
||
python finance/cli/agent_cli.py daily # 5 步完整流程
|
||
python finance/cli/agent_cli.py picks 15 # 选股 Top 15
|
||
python finance/cli/agent_cli.py risk # 风险评估
|
||
python finance/cli/agent_cli.py research # 因子研究(IC 评估)
|
||
python finance/cli/agent_cli.py report 20260603 # 生成日报
|
||
python finance/cli/agent_cli.py warmup 50 # 首次预热缓存
|
||
```
|
||
|
||
### 每日流程
|
||
|
||
```
|
||
[Step 1/5] 增量同步 → 只更新已缓存股票
|
||
[Step 2/5] 风险评估 → RiskAgent: high/medium/low + 仓位
|
||
[Step 3/5] 股票打分 → SelectionAgent: 多因子等权打分
|
||
[Step 4/5] 情绪因子 → SentimentEngine.compute()
|
||
[Step 5/5] 生成日报 → ReportAgent: .md + .html + 解读
|
||
```
|
||
|
||
### 4 个 Agent
|
||
|
||
| Agent | 职责 |
|
||
|-------|------|
|
||
| ResearchAgent | 因子 IC/IC_IR 评估 |
|
||
| SelectionAgent | 多因子股票打分(等权) |
|
||
| RiskAgent | 波动率+回撤→仓位建议 |
|
||
| ReportAgent | 市场+选股+情绪+风险→日报 |
|
||
|
||
### Demo 验证脚本
|
||
|
||
```bash
|
||
python finance/cli/demo_data_manager.py --ts_code 600519.SH
|
||
python finance/cli/demo_factor_engine.py --ts_code 300750.SZ
|
||
python finance/cli/demo_backtest.py --ts_code 000001.SZ
|
||
python finance/cli/demo_optimizer.py --ts_code 000001.SZ --trials 100
|
||
python finance/cli/demo_ml.py --ts_code 000001.SZ --lookahead 5
|
||
python finance/cli/demo_sentiment.py --ts_code 600519.SH
|
||
python finance/cli/demo_sentiment_detail.py --ts_code 600519.SH --date 20260603
|
||
```
|
||
|
||
---
|
||
|
||
## 10. 配置说明
|
||
|
||
### 环境变量(`finance/.env`)
|
||
|
||
```bash
|
||
# ── Qwen API ──────────────────────
|
||
QWEN_API_KEY=sk-xxx # DashScope API Key
|
||
QWEN_MODEL=qwen-turbo # qwen-turbo/plus/max
|
||
|
||
# ── 数据库 ───────────────────────
|
||
MAC_DB_HOST=127.0.0.1
|
||
MAC_DB_PORT=13306
|
||
MAC_DB_USER=myquant
|
||
MAC_DB_PASSWORD=<your-db-password>
|
||
MAC_DB_NAME=myquant
|
||
|
||
# ── Tushare ──────────────────────
|
||
TUSHARE_TOKEN=your_token_here
|
||
|
||
# ── 情绪分析范围 ─────────────────
|
||
SENTIMENT_SCOPE_TYPE=index
|
||
SENTIMENT_SCOPE_INDEXES=000300,000905
|
||
SENTIMENT_MAX_NEWS_PER_STOCK=20
|
||
```
|
||
|
||
---
|
||
|
||
## 11. 完整示例
|
||
|
||
### 示例 1:快速回测
|
||
|
||
```python
|
||
import sys; sys.path.insert(0, "finance")
|
||
|
||
from data.data_manager import DataManager
|
||
from factors.registry import get_factor
|
||
from factors.engine import FactorEngine
|
||
from backtest.vectorbt.engine import VectorBTEngine
|
||
from backtest.strategies.rsi_mean_revert import RSIMeanRevertStrategy
|
||
|
||
dm = DataManager(); dm.init_db()
|
||
price = dm.get_daily("000001.SZ").set_index("trade_date")
|
||
|
||
engine_fe = FactorEngine(dm)
|
||
factor_df = engine_fe.compute("000001.SZ", [get_factor("rsi_14")])
|
||
|
||
engine_bt = VectorBTEngine()
|
||
report = engine_bt.run(RSIMeanRevertStrategy(30, 70), price, factor_df)
|
||
print(report.summary())
|
||
```
|
||
|
||
### 示例 2:策略寻优 + Walk-Forward
|
||
|
||
```python
|
||
from optimizer.engine import OptunaEngine
|
||
from optimizer.space import rsi_revert_space
|
||
|
||
opt_engine = OptunaEngine(engine_bt)
|
||
result = opt_engine.optimize(
|
||
RSIMeanRevertStrategy, rsi_revert_space,
|
||
price, factor_df, metric="sharpe", n_trials=200,
|
||
)
|
||
print(result.summary())
|
||
|
||
wf = opt_engine.optimize_walk_forward(
|
||
RSIMeanRevertStrategy, rsi_revert_space,
|
||
price, factor_df, n_trials=80,
|
||
train_window=756, test_window=252,
|
||
)
|
||
```
|
||
|
||
### 示例 3:ML 训练 + 回测
|
||
|
||
```python
|
||
from models.features import FeatureEngine
|
||
from models.lightgbm.model import LightGBMModel
|
||
from models.backtest_integration import MLStrategy
|
||
|
||
fe = FeatureEngine(lookahead=5)
|
||
X, y = fe.build(factor_df, price, fit=True)
|
||
split = int(len(X) * 0.7)
|
||
|
||
model = LightGBMModel(params={"n_estimators": 200, "learning_rate": 0.03})
|
||
model.fit(X.iloc[:split], y.iloc[:split])
|
||
|
||
strategy = MLStrategy(model, fe)
|
||
report = engine_bt.run(strategy, price, factor_df)
|
||
```
|
||
|
||
---
|
||
|
||
## 12. 常见问题
|
||
|
||
### Q: SSH 隧道连接失败?
|
||
|
||
```bash
|
||
lsof -i :13306 | grep LISTEN
|
||
bash shared/script/autossh.sh
|
||
```
|
||
|
||
### Q: AkShare 返回 RemoteDisconnected?
|
||
|
||
系统已内置 3 次递增间隔重试 + fallback 机制。如果持续失败:等待 30 秒后重试,或检查网络。
|
||
|
||
### Q: 因子计算结果全是 NaN?
|
||
|
||
- 技术因子:前 N 个周期内 NaN 是正常的(如 20 日动量前 19 天为 NaN)
|
||
- 基本面因子:检查财务数据是否已同步
|
||
- 情绪因子:检查是否配置了 `QWEN_API_KEY`
|
||
|
||
### Q: 回测结果为 0 笔交易?
|
||
|
||
- 检查策略参数是否过于严格
|
||
- 使用 `OptunaEngine.optimize()` 寻找更优参数
|
||
|
||
### Q: 模型训练只有 2 棵树?
|
||
|
||
单股票预测噪声比低,建议:
|
||
- 设置 `eval_ratio=0.0` 禁用早停
|
||
- 降低 `learning_rate` 到 0.01
|
||
- 增加 `min_data_in_leaf` 防止过拟合
|
||
|
||
### Q: 日报中选股为空?
|
||
|
||
需要先同步目标股票池的数据:
|
||
|
||
```bash
|
||
python finance/cli/agent_cli.py warmup 50
|
||
```
|
||
|
||
---
|
||
|
||
## 13. 文档索引
|
||
|
||
| 文档 | 内容 |
|
||
|------|------|
|
||
| [架构说明](architecture.md) | 项目架构、数据流、设计原则 |
|
||
| [开发指南](development.md) | 环境搭建、开发约定、模块说明 |
|
||
| [部署说明](deployment.md) | 本地环境、服务器、uWSGI、rsync 部署 |
|
||
| [因子与表结构速查](reference.md) | 34 因子注册表、DB 表结构、数据源接口 |
|
||
| [数据层详解](data-layer.md) | DataManager、数据库、缓存策略、已知 Bug |
|
||
| [因子引擎详解](factors.md) | 因子计算、情绪引擎、新闻源 |
|
||
| [回测引擎详解](backtest.md) | VectorBT、策略、信号工具、Optuna |
|
||
| [ML 模型详解](ml-models.md) | 特征工程、LightGBM/CatBoost、ML 策略 |
|
||
| [Agent 系统详解](agents.md) | Agent 架构、CLI、日报 |
|
||
| [DJAPI 接口](api.md) | Django API 端点参考 |
|
||
| [日报查询 API](news_report_api.md) | news/reports + news/events 接口 |
|
||
| [日报数据库](db_schema_v1.1.md) | news_report / news_event 表结构 | |