Files
stock/stock-html/docs/推荐回测方案-约定与设计.md
T
freedakgmail 9c7d7abdd4 Initial commit
2026-07-17 18:49:35 +08:00

132 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 推荐算法回测方案 — 约定与设计
## 一、回测规则约定(已确认)
| 项目 | 约定 | 说明 |
|------|------|------|
| **10:00 买入依据** | 用**前一交易日收盘后**的全景扫描推荐 | 与当前应用一致,无未来数据 |
| **15:00 加仓/清仓依据** | 用**当天中午**的全景扫描数据 | 即当日 11:50 左右的扫描结果(与现有定时任务一致) |
| **成交价格** | 用**当时的实时价格** | 10:00 买入用 10:00 附近价,15:00 操作用 15:00 附近价;若无分钟数据则需约定近似方式 |
| **选股** | **每天最多买 2 只** | 全市场从「买入」中按推荐分取前 2 只,每只 1000 股(可配置 `MAX_BUYS_PER_DAY` |
## 二、时间线小结
- **T 日 10:00**:根据 **T-1 日收盘后** 的扫描结果,若出现「买入」则按约定选**最多 2 只**(推荐分从高到低),每只以 **10:00 实时价** 买入 1000 股。
- **T 日 15:00**:根据 **T 日中午**(约 11:50)的扫描结果,对当前持仓做 `compute_recommend(..., is_holding=True)`,若为「加仓」则以 **15:00 实时价** 加仓 1000 股,若为「卖出」则以 **15:00 实时价** 清仓。
- 价格:优先使用「当时实时价格」;回测若无分钟/实时数据,需在实现中明确近似规则(见下)。
## 三、实现要点与数据需求
### 3.1 10:00 推荐与价格
- **推荐**:对每个交易日 T,用 **T-1 收盘** 的日 K 跑 `detect_all_signals`,再 `compute_recommend(..., is_holding=False)`,筛出「买入」,按约定选单只(如推荐分最高或信号数最多)。
- **价格**:理想为 T 日 10:00 实时价;若无分钟数据,可用 **T 日开盘价** 作为近似,并在文档/结果中注明。
### 3.2 15:00 推荐与价格(当天中午扫描)
- **推荐**:使用 **T 日中午全景扫描** 结果。
- 若回测期内有**历史中午扫描落库**(如 `stock_signal_scan` 带 scan_time 或 scan_date=当日且标记为午扫),可直接用。
- 若没有,则需在回测中**模拟「当日中午」的扫描**:用 T 日 11:50 前可得的数据(例如 T-1 日 K + T 日 open,或若有分钟数据则用 T 日 11:30 前数据)跑一次 `detect_all_signals` + `compute_recommend`,作为当日 15:00 决策依据,且不引入 T 日 15:00 之后的数据。
- **价格**:理想为 T 日 15:00 实时价;若无分钟数据,可用 **T 日收盘价** 作为近似,并注明。
### 3.3 实时价格的回测实现
- **有实时/分钟数据**:按 10:00 / 15:00 时刻取价。
- **仅日 K**:在方案中明确写「回测采用:10:00 用当日 open15:00 用当日 close」,并视为对「当时实时价格」的近似,在结果与文档中统一说明。
## 四、选股规则(每天最多买 2 只)
- 在「买入」列表中按推荐分从高到低排序,**最多选 2 只**(`MAX_BUYS_PER_DAY=2`):
-`recommend_rate` 从高到低,同分再按 `triggered_count` 或信号强度排序;
- 每只买入 1000 股(开盘价)。
- 若当日无「买入」,则不新开仓;仅对已有持仓做 15:00 的加仓/清仓判断。
## 五、回测程序与运行
1. **脚本位置**`stock-html/backtest_recommend.py`
2. **依赖**:需存在表 **`stock_kline_daily`** 且含 2026 年及以后的日 K 数据(可先运行 `sync_kline.py` 等同步脚本)。
3. **运行**:在项目根目录下执行
```bash
cd stock-html && ./venv/bin/python backtest_recommend.py
```
4. **输出**:控制台打印交易记录 + 核心统计(胜率/回撤/持仓天数/盈亏比/个股明细);结果写入 `docs/backtest_result.json`。
5. **约定**10:00 用 T-1 扫描 + 开盘价,15:00 用当日中午扫描(T-1 + T 日 open 模拟)+ 收盘价,每天最多买 2 只(推荐分从高到低取前 2)。
### v2 优化(2026-02-25
| 优化项 | 说明 |
|--------|------|
| **股价区间过滤** | 仅扫描 2~100 元股票,避免仙股和高价股导致金额失衡 |
| **单只最大投入** | ¥30,000 上限(含加仓),防止单只占比过高 |
| **最大同时持仓** | 8 只,分散风险 |
| **卖出冷却期** | 卖出后 3 天内不再买入同只,防止反复买卖 |
| **批量 K 线加载** | 用窗口函数一次查全市场 K 线,减少 DB 往返约 10 倍 |
| **丰富统计指标** | 胜率、最大回撤、平均持仓天数、盈亏比、个股盈亏明细 |
| **对比表增强** | 15 场景对比增加胜率/回撤/盈亏比列,标注最优场景 |
### v3 优化(2026-02-25
| 优化项 | 说明 |
|--------|------|
| **基于预扫描表** | 直接从 `stock_scan_history` 读取扫描结果,无需现场计算,秒级完成回测 |
| **修复最大回撤计算** | 改为基于每日组合权益(持仓市值 + 累计现金流)的回撤,修复之前用现金流计算导致数值虚高的问题 |
| **新增回撤百分比** | 输出 `max_drawdown_pct`(最大回撤 / 总投入资金 × 100%) |
| **运算符优先级修复** | 修复 `action_taken` 判断条件的括号缺失问题 |
以上约定已写入本文档,作为实现推荐回测的统一依据。
---
## 六、清仓与止盈推荐(目的:挣钱而非单纯持有)
当前回测里**清仓**只做一件事:**推荐为「卖出」时按收盘价清仓**(即 MACD 死叉且无主升浪)。
目的是「按信号纪律出场」,但**没有**针对「高点落袋」的规则,可能拿很久才等到卖出信号,回吐利润。
### 6.1 建议增加的清仓/止盈方式
在保留「信号卖出」的前提下,可增加**以挣钱为导向**的止盈类规则,例如:
| 类型 | 说明 | 目的 |
|------|------|------|
| **固定止盈** | 持仓浮盈 ≥ X%(如 10%、15%)时,当日 15:00 清仓 | 到点落袋,不贪最后一笔 |
| **高点回撤止盈** | 从持仓期间最高价回撤 ≥ Y%(如 8%)时清仓 | 近似「高点跑」,锁定大部分利润 |
| **信号卖出(现有)** | 推荐为「卖出」时清仓 | 趋势走弱时离场 |
可只选一种,或**组合**:先看是否触发止盈,若未触发再看是否触发「卖出」;若都未触发则继续持有或按原规则加仓。
### 6.2 推荐用法(兼顾挣钱与纪律)
- **优先**:在回测中增加 **固定止盈**(如 10%):
- 每个交易日 15:00 前,若 **持仓收益率 ≥ 10%**,则当日 15:00 按收盘价清仓,视为「高点跑」一次。
- **可选**:再增加 **高点回撤止盈**(如 8%):
- 若持仓期间最高价到当前价的回撤 ≥ 8%,则当日 15:00 清仓。
- **保留**:若未触发上述止盈,仍按当前逻辑:推荐「卖出」则清仓,「加仓」则加仓,「持有」则不动。
这样既保留「按推荐买卖」的纪律,又明确加入「高点跑 / 落袋为安」的推荐,更贴近「目的是挣钱」。
---
## 七、如何提供/提升收益率
### 7.1 当前收益率指标
回测脚本已输出并写入 `backtest_result.json`
- **收益率** = (总收回 - 总投入) / 总投入 × 100%,即整段回测的累计收益。
- **年化收益率** = (1 + 收益率)^(365/回测天数) − 1,折算为「若按同样节奏跑满一年」的大致水平,便于和理财/指数对比。
v2 已内置更多指标:胜率、最大回撤、平均持仓天数、盈亏比、个股盈亏明细,均在控制台和 JSON 中输出。
### 7.2 可操作的提升方向
| 方向 | 做法 | 说明 |
|------|------|------|
| **止盈** | 使用 `--take-profit 10` 等 | 浮盈到点即走,减少回吐;可多试 8%、12% 等找合适区间。 |
| **止损** | 在回测中增加「浮亏达 X% 清仓」 | 控制单笔最大亏损,避免深套。 |
| **高点回撤止盈** | 从持仓最高价回撤 Y% 时清仓 | 贴近「高点跑」,锁住大部分利润。 |
| **选股过滤** | 在「买入」列表中提高门槛 | 如仅选 recommend_rate≥90 或 triggered_count≥2,减少弱信号。 |
| **仓位/频率** | 每日买一只 vs 仅无仓时买 | 当前为每日买一只;若改为仅无仓时买,收益曲线会不同,可对比。 |
| **参数扫描** | 对止盈比例、止损比例等做网格 | 批量回测不同参数,看哪组年化/回撤更优。 |
建议先固定一套规则(如 止盈 10% + 信号卖出),跑出基准年化与回撤,再逐项加「止损」「高点回撤止盈」或选股过滤,对比同一区间下收益率与回撤的变化,再决定是否采用。