# 推荐算法回测方案 — 约定与设计 ## 一、回测规则约定(已确认) | 项目 | 约定 | 说明 | |------|------|------| | **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 用当日 open,15: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% + 信号卖出),跑出基准年化与回撤,再逐项加「止损」「高点回撤止盈」或选股过滤,对比同一区间下收益率与回撤的变化,再决定是否采用。