EVO第三周内测|K 线形态变成可回测策略:双底(W 底)形态实战全记录
一、形态理解:从「看图说话」到可计算规则
任务输入的 K 线形态示意图如下——股价先后两次探底(底 1、底 2),中间反弹高点构成颈线,向上突破颈线确认形态成立:

双底形态的本质是下降趋势衰竭后的两次探底确认。把「看图说话」翻译成机器可执行的判定条件:
| 肉眼描述 | 量化规则 |
|---|---|
| 「走出了 W 形状」 | 滚动 60 日窗口内,找到两个局部最低点,两低点间隔 10–60 个交易日 |
| 「两次底部差不多低」 | 两低点价格差 / 较高低点 ≤ 3% |
| 「中间有个反弹高点」 | 颈线 = 两低点之间的区间最高价 |
| 「颈线要高于底部,否则不是标准 W」 | 颈线 ≥ 双底均值 × 1.05 |
| 「突破颈线才确认」 | 收盘价 > 颈线(V1 无其他条件) |
| 「跌破了就认错」 | 收盘价 < 双底最低点 × 0.97 止损 |
| 「涨够了就落袋」 | 收盘价 ≥ 买入价 × 1.15 止盈 |
| 「不能无限等」 | 持仓满 30 个交易日强制退出 |
防未来函数处理:形态识别在每一根 bar 上只用截至该时点的历史数据(识别窗口截至倒数第二根,避免用到未收盘的当日数据),MA200 计算只用上一根及更早的收盘价——保证逐 bar 回测无前视偏差。

二、策略实现
策略在平台策略画板中以 Python 代码落盘(策略实体 double_bottom,草稿1),核心结构:
def find_double_bottom(lows, highs, closes, *, min_distance=10, max_distance=60, price_diff_pct=0.03, neckline_premium=0.05): """滚动窗口找两个局部低点 + 颈线;不满足规则返回 None。""" # 1) 取最近 max_distance 根(截至倒数第二根,防未收盘数据) # 2) 找到窗口内最小的两个局部极小 i1, i2 # 3) 校验间隔 10-60 日、价差 <=3% # 4) 颈线 = 两低点之间区间最高价;校验 >= 双底均值 * 1.05 ...
class DoubleBottomStrategy: TARGET_WEIGHT = 0.80 # 目标仓位 80% STOP_LOSS_PCT = 0.03 # 跌破双底低点 3% 止损 TAKE_PROFIT_PCT = 0.15 # 盈利 15% 止盈 HOLD_DAYS = 30 # 最长持有 30 个交易日
def on_bar(self, bar, ctx): # 持仓中:止损 / 止盈 / 持有期三条件任一触发即清仓 # 空仓:形态识别 + 收盘价突破颈线 → 买入 80% 仓位(A 股整百手) ...

三、回测设置
| 项目 | 设置 |
|---|---|
| 标的 | 600519 贵州茅台(单标的) |
| 频率 | 日线 1d |
| 区间 | 2023-01-01 \~ 2025-12-31(实际交易起点 2023-01-03) |
| 初始资金 | 100 万元 |
| 费用 | A 股真实费率:双边佣金 2.5bp + 卖出印花税 5bp,滑点 0 |
| 基准 | 沪深300 |
| 引擎 | 平台内置事件驱动日线回测(逐 bar 撮合,目标仓位制,整百手成交) |
四、回测结果与解读
4.1 业绩(第一关)

| 指标 | 策略 | 沪深300(同期) | 解读 |
|---|---|---|---|
| 总收益 | -16.01% | +19.09% | 三年累计亏损 16 万(初始 100 万),而基准上涨近 20%,跑输基准 35.1 个百分点 |
| 年化收益 | -5.88% | +6.24% | 复合年化为负,平均每年亏约 6% |
| 最大回撤 | -19.46% | -24.80% | 回撤比基准浅(大部分时间空仓),但绝对水平仍不低 |
| 夏普比率 | -1.16 | 0.44 | 每承担一份波动换来的都是亏损 |
| 卡玛比率 | -0.30 | 0.25 | 年化收益/最大回撤为负,风险调整后收益不合格 |
| 索提诺比率 | -0.42 | — | 下行风险完全没有被正收益覆盖 |
| 月度胜率 | 5.7% | — | 35 个可统计月份里只有 2 个月盈利 |

净值曲线形态非常典型:三次往返对应三段阶梯式下跌(2023-09\~10、2024-04\~06、2024-07\~08),其余时间一条水平线(空仓)。2024 年 9 月底那波大盘暴涨启动前,策略已在 8 月 30 日止损离场——这轮 +20% 级别的基准脉冲一分未取,随后一直空仓到区间结束。
4.2 交易明细:亏损从哪里来
全区间共 6 笔成交、3 次完整往返(买+卖),每一次出场都是止损:
| # | 买入 | 卖出 | 价差盈亏 | 毛亏损 | 费用 |
|---|---|---|---|---|---|
| 1 | 2023-09-08 400 股 @1818.50 | 2023-10-19 @1630.00 | -10.37% | -75,400 元 | 671 元 |
| 2 | 2024-04-24 400 股 @1693.60 | 2024-06-11 @1569.00 | -7.36% | -49,840 元 | 640 元 |
| 3 | 2024-07-19 400 股 @1525.62 | 2024-08-30 @1443.19 | -5.40% | -32,972 元 | 586 元 |
三次往返毛亏损合计 -158,212 元、费用合计 1,897 元(约占本金 0.19%),与期末净值 839,891.57 精确对账(-158,212 - 1,897 ≈ -160,108)。亏损主体是价差,不是交易成本。
值得注意:名义 3% 止损,实际单次亏损却是 -5.4% \~ -10.4%。 原因有二:①止损线 3% 是从双底低点起算的,而买入点在颈线(高于双底低点 5% 以上),买入瞬间距离止损线就有约 8% 的空间;②止损按收盘价判定,触发当日以收盘价成交——跌势中收盘往往已远跌破线(跳空/阴跌),无法在阈值价位离场。这是形态类策略最常见的「止损名不副实」陷阱:止损半径必须从入场价反推,且要考虑收盘触发 + 隔夜跳空的滑移。
结论:在 2023-2025 茅台单边阴跌的行情里,双底作为左侧反转形态反复给出假突破信号,三次入场全部止损离场,累积成整体亏损;2025 年全年未触发形态,策略空仓躲过了继续下跌,但也没能参与反弹。
4.3 风险(第二关)

| 指标 | 数值 | 解读 |
|---|---|---|
| Beta(对沪深300) | 0.05 | 接近 0,与大盘基本不相关——空仓时间太长,暴露极低 |
| 年化波动率 | 5.09% | 远低于股票资产正常水平(20-30%),同样是低暴露的结果 |
| 前 10 集中度 | 71.3% | 单一标策略,持有期仓位全部压在一只股票上 |
| 行业暴露 | 白酒 -16.0% / 现金 116.0% | 平均行业敞口为负(多数时间空仓),行业风险即标的风险 |
| 日均换手 / 年化 | 0.59% / 1.5x | 低换手,交易磨损小(3 笔往返费用合计不足千元) |
4.4 适应性(第三关)

| 市场状态 | 天数 | 区间收益 | 夏普 |
|---|---|---|---|
| 牛市 | 262 | -2.32% | -0.64 |
| 熊市 | 307 | -12.11% | -1.47 |
| 震荡 | 158 | -2.16% | -1.81 |
亏损集中在熊市(-12.11%):印证了「左侧反转形态在下跌行情中反复止损」的判断。牛市里竟然也小幅亏损(逆势抄底形态在牛市初期频繁假信号)。
Walk-forward 样本外检验:样本外平均夏普 -1.42,样本外通过率 0%,最差窗口收益 -9.10%——样本外完全不赚钱,说明 V1 规则在这个单标的上没有稳定的预测力,不是过拟合能解释的差,而是压根不行。
4.5 归因(第四关)
收益拆解:市场 Beta +0.08% ≈ 0(几乎不暴露市场);特质 Alpha -16.09%——亏损全部来自策略自身的择时决策(形态判断),与市场涨跌无关。单标的样本不足以做风格/行业回归,平台诚实标注为空,并给出「扩大股票池即可恢复完整归因」的说明。
五、调优迭代:V2 = MA200 上升趋势前置过滤
调优逻辑:V1 的病根是「在下跌趋势里逆势抄底」。经典解法是加趋势过滤——只在大周期趋势向上时才允许开仓。V2 只改一处:收盘价必须站上 200 日均线(MA200)才允许双底突破买入,其余形态识别、仓位、止损止盈规则与 V1 完全一致。

V2 回测结果

| 指标 | V1(无趋势过滤) | V2(MA200 过滤) | 变化 |
|---|---|---|---|
| 总收益 | -16.01% | 0.00% | 全程空仓,避免全部亏损 |
| 年化收益 | -5.88% | 0.00% | — |
| 最大回撤 | -19.46% | 0.00% | 无持仓即无回撤 |
| 夏普比率 | -1.16 | —(无波动) | — |
| 月度胜率 | 5.7% | 0.0%(无交易月) | — |
| 交易笔数 | 6 | 0 | 过滤把所有信号全部拦掉 |
调优结论(重要)
V2 在本地是**「过度过滤」**:2023-2025 茅台绝大多数时间运行在 MA200 下方,站上 MA200 的窗口内又极少同时出现「双底 + 突破颈线」,结果三年零成交,策略退化成一张货币基金。从结果看它"赢"了 V1(0% > -16%),但这是用「什么都不做」赢的,不构成有效策略——真正的结论是:
- MA200 这类慢趋势过滤在单标的上不是「风控」,而是「开关」:要么全放行、要么全拦掉;
- 该标的 2023-2025 区间几乎不存在「长期趋势向上 + 双底突破」的共振时点,说明双底策略的问题不是缺过滤器,而是不适合这个样本;
- 正确方向是把它放到全市场多标的池:先 MA200 筛出趋势向上的股票篮子,再在其中找双底形态,靠分散稀释单票风险。
六、总结
- 完成了「形态图 → 量化规则 → 代码 → 回测 → 解读 → 调优」的完整闭环,每一环都有平台功能承接:识图(研究助手多模态)、策略画板(代码落盘 + 静态检查)、跑回测(8 阶段控制台)、四关报告(业绩/风险/适应性/归因)、版本管理(草稿1 → 草稿2 调优对比)。
- 双底是左侧形态,胜率天然低,且「名义止损」≠「实际止损」:本例 3 次往返全部止损,单次实际亏损 -5.4% \~ -10.4%(止损线从双底低点起算 + 收盘价触发),远大于名义的 3%——形态策略设计止损时必须从入场价反推半径并预留跳空滑移。
- 单标的 + 单一形态 = 没有统计意义:727 个交易日只有 3 次样本,无论赚亏都说明不了策略有效性;量化形态策略必须上多标的池。
- 调优不是加条件就一定更好:MA200 过滤把策略变成空仓,「跑赢 V1」是伪命题——评价调优要看单位风险收益和样本外,而不是单看收益数字。


评论