8.4 KiB
8.4 KiB
推荐算法回测方案 — 约定与设计
一、回测规则约定(已确认)
| 项目 | 约定 | 说明 |
|---|---|---|
| 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 的加仓/清仓判断。
五、回测程序与运行
- 脚本位置:
stock-html/backtest_recommend.py - 依赖:需存在表
stock_kline_daily且含 2026 年及以后的日 K 数据(可先运行sync_kline.py等同步脚本)。 - 运行:在项目根目录下执行
cd stock-html && ./venv/bin/python backtest_recommend.py - 输出:控制台打印交易记录 + 核心统计(胜率/回撤/持仓天数/盈亏比/个股明细);结果写入
docs/backtest_result.json。 - 约定: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% + 信号卖出),跑出基准年化与回撤,再逐项加「止损」「高点回撤止盈」或选股过滤,对比同一区间下收益率与回撤的变化,再决定是否采用。