- 删除 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 - 修复所有过时引用和交叉链接
15 KiB
15 KiB
cc-cursor 使用指南
Mac Mini 单机量化研究平台,覆盖数据获取 → 因子计算 → 回测 → 参数优化 → ML 模型 → 情绪因子 → Agent 系统全链路。
目录
- 环境准备
- 数据库连接
- 数据层 — DataManager
- 因子引擎 — FactorEngine
- 回测引擎 — VectorBTEngine
- 参数优化 — OptunaEngine
- ML 模型 — LightGBM / CatBoost
- 情绪因子 — SentimentEngine
- Agent 系统 — 命令行入口
- 配置说明
- 完整示例
- 常见问题
1. 环境准备
硬件要求
- macOS / Linux(本系统开发于 Mac Mini)
- 内存 ≥ 16GB(ML 模型训练推荐)
- 网络:可访问东方财富 / 同花顺 API
Python 环境
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/ 目录运行代码。脚本开头加入:
import sys
sys.path.insert(0, "/path/to/cc-cursor/finance")
2. 数据库连接
建立 SSH 隧道
bash shared/script/autossh.sh
验证隧道:
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
初始化
from data.data_manager import DataManager
dm = DataManager()
dm.init_db() # 首次使用创建表(幂等操作)
获取股票列表
stocks = dm.get_stock_list() # → 5,524 只 A 股
stocks = dm.get_stock_list(force_refresh=True) # 强制刷新
获取日线数据
daily = dm.get_daily("000001.SZ") # 全量日线
daily = dm.get_daily("000001.SZ", start="20240101", end="20241231")
获取财务数据
fina = dm.get_financial("000001.SZ")
# → DataFrame: end_date, eps, bvps, roe, net_profit_margin, debt_to_assets
数据同步
n = dm.sync_daily("000001.SZ") # 增量同步到最新
数据源优先级:Tushare(优先)→ AkShare(fallback)。DB 缓存优先。
4. 因子引擎 — FactorEngine
因子注册表
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 个因子
创建因子实例
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 日新闻情绪因子
计算因子
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]
截面因子
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%(万三) | 方向:只做多
创建引擎
from backtest.vectorbt.engine import VectorBTEngine
engine_bt = VectorBTEngine(initial_capital=100_000, commission=0.0003)
使用内置策略
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) |
截面选股 |
自定义策略
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
使用预置搜索空间
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 验证
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,
)
自定义搜索空间
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
特征工程
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 训练
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 训练
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 策略回测
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:
QWEN_API_KEY=sk-your-key-here
QWEN_MODEL=qwen-turbo
使用情绪引擎
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 命令
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 验证脚本
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)
# ── 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:快速回测
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
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 训练 + 回测
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 隧道连接失败?
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: 日报中选股为空?
需要先同步目标股票池的数据:
python finance/cli/agent_cli.py warmup 50
13. 文档索引
| 文档 | 内容 |
|---|---|
| 架构说明 | 项目架构、数据流、设计原则 |
| 开发指南 | 环境搭建、开发约定、模块说明 |
| 部署说明 | 本地环境、服务器、uWSGI、rsync 部署 |
| 因子与表结构速查 | 34 因子注册表、DB 表结构、数据源接口 |
| 数据层详解 | DataManager、数据库、缓存策略、已知 Bug |
| 因子引擎详解 | 因子计算、情绪引擎、新闻源 |
| 回测引擎详解 | VectorBT、策略、信号工具、Optuna |
| ML 模型详解 | 特征工程、LightGBM/CatBoost、ML 策略 |
| Agent 系统详解 | Agent 架构、CLI、日报 |
| DJAPI 接口 | Django API 端点参考 |
| 日报查询 API | news/reports + news/events 接口 |
| 日报数据库 | news_report / news_event 表结构 |