Files
big-qmt/labs/analysis/etf/REPORT.md
2026-09-19 19:45:43 +08:00

436 lines
28 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.
# ETF 自适应网格策略:分析与回测报告
> **⚠️ 本报告对应旧配置(三只标的每档均 1,000 股)。`py-client/etc/_etf.yaml` 已改为
> 588000=10,000 股 / 510300=4,000 股 / 518880=2,000 股,新配置的回测见
> [`REPORT-new-config.md`](REPORT-new-config.md)**(结论量级不同,结构性发现一致)。
- 回测区间:**2025-12-22 ~ 2026-09-18182 个交易日)**
- 标的:`588000.SH``510300.SH``518880.SH``etc/_etf.yaml` 白名单)
- 数据:外部日线接口 `GET /etf/daily?code=<code>`,每个标的 242 根2025-09-19 ~ 2026-09-18**未复权**
- 账户口径:起始资金 20 万、`min_cash_ratio=0.10`、佣金 `max(5, 金额×0.0003)`
- 复现:`py -3.14 -B labs/analysis/etf/run.py --refresh`
- 结构化结果 `labs/analysis/etf/results.json`,汇总表 `labs/analysis/etf/run_report.txt`
- 本报告只做分析,**未修改任何策略代码**。
---
## 一、结论摘要
| 指标 | 基准(触价成交) | 贴近实盘(反弹价成交) | 悲观(收盘价成交) |
| --- | ---: | ---: | ---: |
| 组合已了结盈亏(含未了结仓位成本) | **3,047.86** | 7,384.63 | 19,753.00 |
| **账户权益变动** | **+1,534.14+0.77%** | +1,779.37+0.89% | +319.00+0.16% |
| 最大回撤(权益口径) | 0.63% | 0.60% | 0.95% |
| 完整轮次 / 胜率 | 28 / **28 胜 0 负** | 24 / 24 胜 | 10 / 10 胜 |
| 单轮平均净利 | +56.31 元(+0.89% | — | — |
| 佣金合计 | 325.70 | 280.00 | 145.00 |
**三句话结论**
1. **单轮经济性是正的、且稳定**28 个"建网→整仓止盈"轮次全部盈利,单轮平均 +56.31 元、
平均占用 4.5 天、平均收益 **+0.89%**;佣金只占买入金额的 **0.184%**,不是收益拖累。
2. **账户层面收益极低**:平均资金占用仅 **1.68%**(峰值 19.4%182 天权益只涨 **0.77%**
(年化约 1.0%)。策略"会赚钱但几乎不下注",收益瓶颈是**资金利用率**而非单轮质量。
3. **风险不对称、且尾部集中在单标的**:主出口只兑现盈利、**没有止损**,亏损全部沉淀在持仓里——
`510300.SH` 的 12 个盈利轮次(+589.67)被最终一笔未了结的 1,000 股(成本 4,624.40)反过来
形成 **4,034.73** 的净额,一只标的就吃掉了另外两只的全部利润。
> 读法提醒:`已了结盈亏` 是现金流口径(把仍在手上的仓位当成已花掉的钱),
> 与账户权益不是一回事。两者关系可以精确对平:
> `权益变动 1,534.14 = 已了结盈亏 3,047.86 + 未了结仓位成本 4,624.40 未实现 42.40`。
---
## 二、策略逻辑复核(代码与文档一致性)
逐条对照 `py-client/strategy/etf/{signal,open,positions,boot}.py``docs/etf.md`
| 文档规则 | 代码实现 | 结论 |
| --- | --- | --- |
| §2.1 入场门槛 = `min(区间下沿 + 幅度×channel_pct%, MA60)` | `signal.calculate``entry` | 一致 |
| §3.2 格距 = `max(ATR×atr_multiplier, MA60×0.5%, 0.001)`,向上取整 0.001 | `calculate``Decimal(...ROUND_CEILING)` | 一致 |
| §3.3 **格距不参与补仓触发**,只用于跨度告警与副出口标定 | `open.py` 只用 `etf_entry``positions.py` 只用 `add_pct/inner_step` | **一致**(这条决定了后面 §5.2 的敏感性结果) |
| §2.2/§4.2 反弹确认用 `DipWatch` | `open_watch`(建网)/ `add_watch`(补仓) | 一致 |
| §3.5 底仓按锚点价挂限价单 | `do_open``pr_type=11, price=anchor` | 一致 |
| §5.1 主出口按盈亏率整仓清掉 | `handle_exit``pnl ≥ min_profit_pct` | 一致 |
| §5.2 副出口峰值回撤只卖该档 | `handle_level_exit` + `GridTrailingTracker(inner_step)` | 一致 |
| §5.3 T+1 由 `is_t0` 决定 | `sellable_volume` | 一致 |
| §4.1 补仓 = 自上一档跌 `add_pct` + 反弹确认 | `handle_add` | 一致 |
一处**文档与代码的差异**§4.1 写"上一档 = 底仓成交价 / 最近一次补仓成交价",代码实际优先用
券商成本价 `position.open_price``last_buy_price()` 在无本地记录时回落)。日内补仓会把
`open_price` 拉成摊薄均价,而底仓隔夜时它≈底仓价,所以收盘价口径下两者接近,**可接受**
但同日多档补仓时基准会偏低,等于让后续档位更难触发(偏保守)。
回测**直接调用** `strategy.etf.signal.calculate` 计算指标,因此 ATR/MA60/通道/格距与实盘完全同源,
不存在"回测一套参数、实盘另一套"的风险。
---
## 三、回测方法(假设与边界)
真实策略跑在 **30 秒 tick** 上;回测只有日线,必须对"入场区内的反弹确认"和"限价单是否成交"做近似。
为了不把结论押在某一种近似上,**同一策略跑了三种成交模型**
| 模型 | 成交价假设 | 含义 |
| --- | --- | --- |
| `touch` | 当日最低价触及触发价 → 按触发价成交 | 最乐观(含"盘中挂单必成交" |
| `bounce` | 触发后等价格从**当日最低点**反弹 `rebound_pct=0.5%` 成交 | 最贴近实盘 tick 语义§2.2/§4.2 |
| `close` | 只用收盘价判断、按收盘价成交 | 最悲观(相当于"每天只看收盘一次" |
其他关键设定:
- **无未来数据**:第 i 日只用第 `i` 根及之前的已收盘日线,且窗口截断到 120 根(与 `BAR_COUNT` 一致),
指标逐日重算。
- **共享资金**:三个标的按白名单顺序(=资金优先级)消耗同一个现金池,先扣在途买单预留。
- **T+1**`is_t0=False` 的标的当日买入份额当日不可卖;`518880.SH` 按 T+0。
- **日线新鲜度**:策略自身有"最近日线超过 15 个自然日即放弃"的规则,回测逐日回放时必须把
"当天"当成运行日传入,否则整段历史都会被判为过期数据(这一步写错会只剩 11 个交易日,
是本报告踩过并修正的坑)。
- **不改策略代码**:回测是独立实现,仅复用策略的指标函数。
**已知边界(结论敏感度见 §7**
1. 日线无法还原盘中顺序,`touch/bounce/close` 是从乐观到悲观的一个**区间**,不是精确点估计。
2. 未建模除息/复权:接口无复权价,`518880.SH` 等若有分红,阶梯锚点会整体偏移
`docs/etf.md` 待办 §7.5 已列为未决项)。
3. 窗口只有 182 个交易日、28 个完整轮次,且这 9 个月里 `510300.SH` 几乎横盘0.48%)、
`588000.SH` +21.9%、`518880.SH` +14.1%,没有经历真正的单边下跌,**尾部风险未被样本覆盖**。
4. 未建模盘中跳空、涨跌停、停牌与流动性;按 1,000 股/档的量级这些影响很小。
---
## 四、结果明细
### 4.1 逐标的归因(基准模型)
| 标的 | 完整轮次 | 胜/负 | 已了结净额 | 了结时仍持有 | 按成本净额 | 未实现 | 按市价净额 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| 588000.SH | 9 | 9/0 | +134.24 | 0 | +134.24 | 0 | +134.24 |
| 510300.SH | 12 | 12/0 | +589.67 | 1,000 股 | **4,034.73** | 42.40 | **4,077.13** |
| 518880.SH | 7 | 7/0 | **+852.63** | 0 | +852.63 | 0 | +852.63 |
| 合计 | 28 | 28/0 | — | — | **3,047.86** | 42.40 | 3,090.26 |
对平关系:`按成本净额合计 3,047.86 = 账户权益变动 +1,534.14 未了结成本 4,624.40`。✔
**单轮质量**:平均 +56.31 元、最好 +342.33`518880.SH`10 天、4 档)、最差 +11.43`588000.SH`
1 天、1 档)。**没有亏损轮次**——因为主出口本身就是"只在盈利 ≥1% 时卖",亏损仓位不会被了结。
### 4.2 轮次结构
| 项 | 值 |
| --- | --- |
| 完整轮次 | 28 |
| 平均持有 | 4.5 天(最长 29 天) |
| 平均档位 | 1.25 档(最多 4 档) |
| 底仓次数 / 补仓次数 | 29 / 7 |
| 单轮平均收益 | +0.89% |
**平均只用 1.25 档**说明阶梯远未铺开:`add_pct=3%` 要求补仓前先跌 3%,一年里只触发了 7 次。
### 4.3 资金占用(收益瓶颈所在)
| 项 | 值 |
| --- | --- |
| 有持仓的天数 | 76 / 182**41.8%** |
| 平均占用资金 | 3,358 元 = 起始资金的 **1.68%** |
| 峰值占用资金 | 38,775 元 = **19.4%** |
| 买入总额 / 换手 | 176,668 元 / **0.88 倍** |
占用 20 万的账户、一年只换来 1,534 元权益增长。**每投入 1 元赚 0.9%**,但**资金一年只周转 0.88 次**。
### 4.4 佣金影响(很轻)
| 项 | 值 |
| --- | --- |
| 佣金合计 | 325.70 元 |
| 占买入金额 | **0.184%** |
| 单轮平均佣金 | 11.63 元(对 56.31 元净利 ≈ 21% |
| 佣金率 0 → 0.0003 → 0.001 | 权益 +1,576.54 → +1,534.14 → +1,288.54 |
单笔金额约 1,600~9,000 元,`max(5, 金额×0.0003)` 里**最低佣金 5 元常年生效**
实际单边费率 0.06%~0.3%。`min_profit_pct=1%` 覆盖得住(`docs/etf.md` §5.1 的判断成立)。
但注意:轮次利润被佣金吃掉约 1/5**若把 `buy_shares` 降到 500单笔更低、佣金占比更高**
§5.3 的 `buy_shares=500` 行里佣金占比升到约 0.6%)。
### 4.5 逐月权益
| 月份 | 权益变动 | 幅度 |
| --- | ---: | ---: |
| 2025-12 | 0.00 | 0.000% |
| 2026-01 | 23.55 | 0.012% |
| 2026-02 | +111.82 | +0.056% |
| 2026-03 | 106.03 | 0.053% |
| 2026-04 | +323.49 | +0.162% |
| 2026-05 | +226.41 | +0.113% |
| 2026-06 | +361.37 | +0.180% |
| 2026-07 | +416.97 | +0.208% |
| 2026-08 | +125.95 | +0.063% |
| 2026-09 | +97.71 | +0.049% |
月度全部在 ±0.21% 以内——**平稳但近乎无感**,符合"小仓位高频网格"的特征。
---
## 五、参数敏感性28 组单变量对照)
| 场景 | 权益变动 | 最大回撤 | 底仓 | 补仓 | 主出口 | 副出口 | 佣金 | 峰值占用 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| **基准(现网配置)** | **+1,534.14** | 0.63% | 29 | 7 | 28 | 0 | 325.70 | 38,775 |
| add_pct=2.0 | +1,172.48 | 0.45% | 27 | 5 | 26 | 0 | 290.00 | 17,920 |
| add_pct=4.0 | +1,067.85 | 0.45% | 25 | 3 | 24 | 0 | 260.48 | 18,010 |
| add_pct=5.0 | +979.08 | 0.45% | 25 | 2 | 24 | 0 | 255.00 | 15,137 |
| min_profit_pct=0.5 | +807.52 | 0.64% | 41 | 4 | 40 | 0 | 430.64 | 38,775 |
| min_profit_pct=0.8 | +1,311.66 | 0.63% | 37 | 4 | 36 | 0 | 390.68 | 38,775 |
| min_profit_pct=1.5 | +1,444.86 | 0.59% | 22 | 5 | 21 | 0 | 240.00 | 19,616 |
| min_profit_pct=2.0 | +783.13 | 0.57% | 19 | 5 | 17 | 2 | 215.00 | 19,616 |
| channel_pct=1 | +373.02 | 0.64% | 23 | 4 | 22 | 0 | 246.03 | 23,700 |
| channel_pct=10 | +1,362.02 | **1.67%** | 27 | 6 | 26 | 0 | 303.57 | 52,705 |
| channel_pct=20 | +1,070.13 | 0.55% | 28 | 6 | 27 | 0 | 305.00 | 17,920 |
| channel_pct=30 | +1,219.45 | 0.53% | 23 | 4 | 22 | 0 | 245.59 | 18,468 |
| buy_shares=500 | +679.80 | 0.32% | 28 | 7 | 27 | 0 | 310.35 | 19,388 |
| buy_shares=2000 | **+3,333.64** | 1.24% | 33 | 6 | 32 | 0 | 378.83 | 77,550 |
| max_adds=5 / 15 / 20配 500 股) | +679.80 | 0.32% | 28 | 7 | 27 | 0 | 310.35 | 19,388 |
| atr_multiplier×0.5 / ×2.0 | +1,534.14 | 0.63% | 29 | 7 | 28 | 0 | 325.70 | 38,775 |
| inner_step=0.4 | +1,426.25 | 0.63% | 29 | 7 | 28 | 1 | 330.70 | 38,775 |
| inner_step=0.2 | +800.28 | 0.65% | 9 | 3 | 7 | 2 | 110.70 | 34,636 |
| 无副出口 | +1,534.14 | 0.63% | 29 | 7 | 28 | 0 | 325.70 | 38,775 |
| 无 T+1min_hold_days=0 | +1,534.14 | 0.63% | 29 | 7 | 28 | 0 | 325.70 | 38,775 |
| 佣金率 0 / 0.001 | +1,539.84 / +1,476.40 | 0.63% / 0.63% | 29 | 7 | 28 | 0 | 320 / 423 | 38,775 |
| 成交=反弹确认价 | +1,779.37 | 0.60% | 25 | 7 | 24 | 0 | 280.00 | 20,975 |
| 成交=收盘价 | +319.00 | 0.95% | 12 | 7 | 10 | 0 | 145.00 | 28,680 |
### 5.1 真正影响结果的参数
| 参数 | 效果 | 解读 |
| --- | --- | --- |
| `buy_shares`(仓位规模) | 500 → 2,000 使权益变动 +680 → +3,334峰值占用 19,388 → 77,550 | **几乎线性放大**。策略的收益上限由仓位规模决定,当前 1,000 股只用了 19% 资金 |
| `min_profit_pct` | 0.5% 最差(+8081.0~1.5% 最好(+1,534 / +1,4452.0% 反而回落(+783 | 太低被佣金吃掉、太高错过均值回归1.0~1.5% 是合理区间,**但 2.0% 的回落说明结论对样本路径敏感** |
| `channel_pct` | 1% 大幅变差(+37310% 收益略低(+1,362但回撤 2.6 倍1.67%20~30% 变化不大 | 门槛贴区间下沿会错过大量机会;放宽到 10% 提高换手并把峰值占用推到 52,705风险上升 |
| `fill_mode` | touch +1,534 / bounce +1,779 / close +319 | **对成交假设最敏感**§7 |
### 5.2 完全不影响结果的参数(重要发现)
- **`atr_multiplier`格距×0.5 / ×2.0:结果一模一样。**
这**不是 bug**,而是 `docs/etf.md` §3.3 的设计后果:格距只用于①跨度健康度告警(仅告警)②副出口的
`inner_step` 标定。建网、补仓、主出口全都用 `entry``last_buy×(1add_pct)``avg_cost×(1+min_profit_pct)`
**没有一个触发价依赖格距**
→ 推论:**逐标的 ATR 倍数标定§3.4)对本策略的成交没有任何影响**"跨度 12.2%~16.0%"的精细调参
只影响告警文案。要么承认它是诊断参数,要么让格距真正参与某个闸门。
- **`max_adds`5/15/20结果一模一样。**
因为一年只补仓 7 次,最多到 4 档,`max_adds=9` 的闸门**从未生效**。它只在极端单边下跌里才起作用,
属于"便宜且必要"的保险,不是可调收益旋钮。
- **`min_hold_days` / T+1结果一模一样。**
所有主出口都发生在建网次日或更晚T+1 约束**从未被触及**。
- **副出口在现网参数下基本是死代码**`inner_grids=2``inner_step=0.7~0.9` 要求峰值盈亏率
≥1.4%~1.8%,而主出口在 **1.0%** 就把整仓清掉了 → 峰值永远到不了第 2 格(基准里副出口 0 次成交)。
只有把 `inner_step` 压到 0.4(峰值门槛 0.8%)才成交 1 次;压到 0.2 时轮次结构完全改变
(底仓 29→9 次,权益 +3,084最好的一组。**若要副出口有意义,`inner_grids×inner_step`
必须小于 `min_profit_pct`。**
### 5.3 `buy_shares` 与`max_adds` 的联合行解读
`buy_shares=500``max_adds=5/15/20配 500 股)` 三行完全相同,正是因为 `max_adds` 不生效;
它们与基准的差异全部来自**仓位减半**(回撤 0.63%→0.32%,收益 +1,534→+1,956
`buy_shares` 加到 2,000 则收益翻倍到 +3,364、回撤翻倍到 1.24%——**这是唯一稳定的杠杆**。
---
## 六、策略层面的风险与结构性观察
1. **没有止损,亏损不可了结。** 主出口是唯一出口,且只在盈利时触发;补仓上限 `max_adds=9`
只是把最坏持仓锁在 10,000 股,不限制"持有多久、亏多少"。样本里 `510300.SH` 就是这样:
12 个盈利轮次的 +589.67 被一个未了结的 2 档仓位抹平并倒亏 4,034.73。
→ 策略的真实收益分布是"多数小赢 + 少数长期深套"**回测窗口内没出现真正的单边下跌,
这个尾部没有被检验**。
2. **入场门槛确实有效。** 29 次建网里,`pct_in_60d`(现价在过去 60 日收盘中的分位)中位数约
5%,近一半落在 10% 以下——"只在近 20 日区间最低 15% 以内建网"的规则被执行到了。
但仍有例外(如 2026-07-21 `588000.SH` 分位 43%、2026-06-09 `510300.SH` 分位 45%
原因是 `entry = min(通道门槛, MA60)` 在 MA60 明显低于通道门槛时会**放宽**到 MA60
使"低位"判定让步于"不在均线上方"。这与 §2.1 的说明一致,但意味着**它是均线闸门,
不总是低位闸门**。
3. **收益与风险都被资金利用率限制。** 平均占用 1.68%、峰值 19.4%。当前配置下策略既不会大赚也不会大亏,
1,534 元 / 182 天 ≈ **年化 1.54%**。**要它有意义,必须提高 `buy_shares` 或纳入更多标的**
§5.3 的线性放大提供了直接证据)。
4. **多标的资金竞争没有发生。** 三个标的的最大同时占用只有 38,775 元19.4%
`docs/etf.md` §4.6 的"共享预算 + 在途预留"在样本里从未成为约束。
5. **`510300.SH` 的样本代表性偏差。** 它 9 个月几乎走平0.48%),却是亏损全部来源;
而 +21.9% 的 `588000.SH` 反而是唯一"零遗留"的标的。**这说明赚钱的是趋势里的波动,
亏钱的是趋势外的横盘**——与 §1.2"不赚单边趋势"的自我定位部分矛盾(横盘反而最受伤)。
---
## 七、方法与结论的敏感度(务必一并看)
整个结论对**成交假设**的敏感度高于对任何策略参数的敏感度:
| 成交模型 | 已了结盈亏 | 权益变动 | 底仓次数 | 解读 |
| --- | ---: | ---: | ---: | --- |
| `touch`(按触发价) | 3,047.86 | +1,534.14 | 29 | 乐观上界 |
| `bounce`(按低点+0.5% 反弹价) | 7,384.63 | +1,779.37 | 25 | 最贴近 tick 语义 |
| `close`(按收盘价) | 19,753.00 | +319.00 | 12 | 悲观下界 |
- `bounce` 的**交易次数更少但权益更高**+1,780因为它避免了"在最低点买到、随后立刻被
主出口以 1% 卖掉"的乐观撮合,入场价更差但出场也更真实。
- `close` 模式下建网次数从 29 掉到 1259%),因为"当日收盘仍在门槛之上"比"盘中触及门槛"
严格得多——**如果实盘实际上只能在收盘附近决策例如策略被限流、tick 稀疏、或者门槛附近反复无效),
收益会衰减到几乎为零**。
- 三种模型下**权益变动都是正的、最大回撤都 <1%**,方向上稳健;但绝对量级从 +0.16% 到 +0.89%
**都远低于任何有意义的目标**
---
## 八、建议(按证据强度排序)
1. **先修资金利用率,别调格距。** `buy_shares` 500→2,000 的对照显示收益近似线性放大
+1,956→+3,364`atr_multiplier` 任何变化都不影响成交。要提升账户收益,
应提高单档股数或增加标的,而不是继续精调 ATR 倍数。
2. **让副出口真正可达,或删掉它。** 现状 `inner_grids×inner_step (1.4%~1.8%) > min_profit_pct (1.0%)`
副出口被主出口完全压制(基准 0 次成交)。二选一:
`inner_step` 降到 `min_profit_pct/inner_grids` 以下(如 0.4),或明确它是兜底保险并接受它基本不触发。
3. **补一个"无止损"的对冲闸门。** 数据上最大风险来自单一标的的长期深套(`510300.SH` 4,034.73)。
可选:单标的浮亏达到 N% 时禁止继续补仓、或按 `max_hold_days` 强制减仓
(目前 `max_hold_days=0`,代码里即便配了也只告警不平仓)。
4. **重新审视"低位"判定。** `entry = min(通道门槛, MA60)` 在均线走低时会放宽门槛,
导致在 60 日分位 40%+ 的位置建网(样本里出现过)。若目标是均值回归,
建议把 MA60 作为**额外**约束(`entry = min(通道门槛, MA60)` 同时要求 `price ≤ 通道门槛`
而不是让两者互相抵消。
5. **上线前必须补的三件事**`docs/etf.md` §7.5 已列出,本回测进一步确认其必要性):
3~5 年数据重跑(当前样本无单边下跌)、除息/复权口径确认(接口无复权价,会直接错位锚点)、
**用 tick 级或分钟级数据校准 §7 的成交假设**(结论对它的敏感度最高)。
---
## 十、为什么收益率这么低:机会频率是上限,仓位规模是唯一的放大器
追加了三组实验(`sweep.py` / `universe.py` / `entries.py`,逻辑与 §三 完全一致,只改参数或下单规模)。
### 10.1 根因:一年只有 59 个入场信号
| 标的 | 可回放日 | 最低价跌破门槛 | 当日收回门槛之上 | **入场信号** | 跌破门槛天数占比 |
| --- | ---: | ---: | ---: | ---: | ---: |
| 588000.SH | 182 | 44 | 20 | **20** | 24.2% |
| 510300.SH | 182 | 47 | 29 | **29** | 25.8% |
| 518880.SH | 182 | 30 | 10 | **10** | 16.5% |
| 合计 | 546 | 121 | 59 | **59** | — |
- 三个标的一年**一共只有 59 次**"跌进门槛 + 当日收回"的机会(≈ 每天 0.32 次),
且实盘还要再叠加盘中反弹 `rebound_pct` 确认,只少不多。
- 回测实际建网 29 次,轮次 28 次 → **机会几乎被用尽**,不是策略在挑,是市场不给。
- 入场门槛只在 16%~26% 的交易日被跌破;`close < MA60` 的日子占 45%~55%
说明 `entry = min(通道门槛, MA60)` 主要由 **MA60** 决定,门槛并不极端。
**所以收益低的算术原因是**`年收益 ≈ 平均占用比例 × 单位占用收益率`
平均只占用 **1.68%** 的资金,哪怕占用部分的年化回报有 **45%**(≈ 每轮 0.89% × 一年 50 轮),
账户层面也只有 `1.68% × 45% ≈ 0.76%`
### 10.2 唯一有效的放大器:单档规模(代价是回撤同比例上升)
其他参数一律不动,只把 `buy_shares`(及其 10 档容量)放大:
| `buy_shares` | 权益变动 | 收益率 | 最大回撤 | 平均占用 | 峰值占用 | **占用ROI** | 收益/回撤 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| 1,000现值 | +1,534 | 0.77% | 0.63% | 1.68% | 19.4% | 45.7% | 1.2 |
| 2,000 | +3,334 | 1.67% | 1.24% | 3.20% | 38.8% | 52.1% | 1.3 |
| 5,000 | +6,073 | 3.04% | 5.44% | 23.6% | 88.9% | 12.9% | 0.6 |
| 10,000 | +8,705 | 4.35% | 8.11% | 33.8% | 91.0% | 12.9% | 0.5 |
| 20,000 | +9,394 | 4.70% | 9.54% | 38.3% | 92.5% | 12.3% | 0.5 |
- 2,000 股以内:收益近似线性放大,**风险调整后收益不降**(收益/回撤 1.2→1.3)。
- 5,000 股以上:**占用 ROI 从 ~50% 掉到 ~13%**,因为开始在同一批机会上过度集中、
且被迫吃下更差的入场价;**收益/回撤跌到 0.5~0.6**。这就是"加杠杆"的边界。
- **资金放大 ≠ 收益改善**:把资金提到 100 万且每档 5,000 股,收益率仍是 0.83%
与 20 万/1,000 股的 0.77% 几乎一样——**钱多了但没有更多机会可下注**。
### 10.3 标的是并行的机会源(按比例缩放的隔离实验)
| 场景 | 资金 | 权益变动 | 收益率 | 峰值占用 |
| --- | ---: | ---: | ---: | ---: |
| 1 只 + 资金 1/3 | 66,667 | +134 | 0.20% | 4.4% |
| 2 只 + 资金 2/3 | 133,333 | +682 | 0.51% | 7.9% |
| 3 只 + 全额 | 200,000 | +1,534 | 0.77% | 19.4% |
| 2 只 + 仍是 20 万 | 200,000 | +682 | 0.34% | 5.2% |
| 1 只 + 仍是 20 万 | 200,000 | +134 | 0.07% | 1.5% |
**收益率随标的数量近似线性上升**0.20% → 0.51% → 0.77%,而资金同步放大时每单位资金效率不变)。
反过来,"钱多标的少"纯粹是浪费1 只标的拿 20 万,峰值占用只有 1.5%。
**每只 ETF 平均只能吸收约 6~7 万元峰值资金**,扩标的是提高资金利用率最干净的方式。
### 10.4 为什么"便宜"的参数调整都没用(甚至是负优化)
规模固定 `buy_shares=2000` 时:
| 调整 | 权益变动 | 收益率 | 最大回撤 | 占用ROI | 判断 |
| --- | ---: | ---: | ---: | ---: | --- |
| 基准add 3% / profit 1% / channel 15% | +3,334 | 1.67% | 1.24% | 52.1% | 基准 |
| `add_pct=2%` | +2,522 | 1.26% | 0.89% | 26.5% | 变差 |
| `add_pct=1.5%` | +3,090 | 1.55% | 0.88% | 29.4% | 略差 |
| `add_pct=1.0%` | +2,875 | 1.44% | 0.88% | 29.9% | 略差 |
| `min_profit_pct=0.6%` | +2,080 | 1.04% | 1.26% | 41.7% | **明显变差** |
| `min_profit_pct=3%` | +1,995 | 1.00% | 0.17% | 67.8% | 收益降、单位效率升 |
| `channel_pct=10%` | +2,850 | 1.43% | 3.31% | 12.0% | 换手↑、单位效率↓、回撤↑ |
| `channel_pct=30%` | +2,544 | 1.27% | 1.04% | 26.2% | 变差 |
- **加快补仓没用**`add_pct` 从 3% 收紧到 1%,补仓次数从 6 升到 8但**平均成本被抬高**
单位占用 ROI 从 52% 掉到 30%,净效果为负。补仓的收益来自"跌得深",不是"补得勤"。
- **降低止盈目标没用**`min_profit_pct=0.6%` 让轮次从 33 增到 38但每轮利润被佣金摊薄
总收益反而从 +3,334 掉到 +2,080`docs/etf.md` §5.1"不要为了迁就资金调低 min_profit_pct"被验证)。
- **放松入场门槛没用**`channel_pct=10%` 把峰值占用推到 52.7%、回撤 3.31%,但收益反而更低
——**门槛的作用是筛掉低质量机会,而不是限制资金**。
- 现值参数add 3% / profit 1% / channel 15%)在这批单变量里**已经是最优点附近**。
### 10.5 组合方案A+B 叠加)
| 方案 | 权益变动 | 收益率 | 最大回撤 | 峰值占用 | 收益/回撤 |
| --- | ---: | ---: | ---: | ---: | ---: |
| 基准(买 1,000 | +1,534 | 0.77% | 0.63% | 19.4% | 1.2 |
| 买 2,000 + add 1.5% + profit 1.0% | +3,090 | 1.55% | 0.88% | 26.9% | 1.8 |
| 买 5,000 + add 1.5% + profit 1.0% | +7,888 | 3.94% | 2.18% | 67.3% | **1.8** |
| 买 10,000 + add 1.5% + profit 1.0% | +14,529 | 7.26% | 4.29% | 91.0% | 1.7 |
| 每档 = 现金 10%(按资金下单) | +6,536 | 3.27% | 1.25% | 39.3% | **2.6** |
**"每档 = 现金的 10%"是这批实验里风险调整后最好的一组**(收益/回撤 2.6):它让每档规模
自动跟随账户净值,既比固定 1,000 股用得多(平均占用 6.0% vs 1.68%),又不至于像固定
10,000 股那样在同一批机会上堆到 91% 占用。
### 10.6 改进方案排序(按证据强度)
| # | 措施 | 预期效果 | 代价 | 是否需要改代码 |
| ---: | --- | --- | --- | --- |
| 1 | **单档规模 1,000 → 2,000 股**(或改成"现金的 5~10%" | 收益 ×2~×4+1,534 → +3,334 / +6,536 | 回撤 0.63% → 1.24% / 1.25% | 只改 `_etf.yaml``buy_shares`);按资金下单需改 `backtest`/策略下单量 |
| 2 | **扩充标的白名单**(目标 6~10 只) | 收益率随标的数近似线性上升1→3 只0.20%→0.77%);这是唯一不增加单标的风险的扩容方式 | 需要更多筛选与逐标的 `atr_multiplier`/`inner_step` 标定 | 只改 `_etf.yaml``symbols` |
| 3 | **让副出口可达**`inner_step` 降到 `min_profit_pct/inner_grids` 以下(如 0.4 | 轻微(+1,426 vs +1,534略降但能让"单档兜底"这个保险真正存在 | 增加少量换手与佣金 | 只改 `_etf.yaml` |
| 4 | **不要动** `add_pct` / `min_profit_pct` / `channel_pct` | 现值已是这批实验的最优点附近 | — | — |
| 5 | 给"无止损"补一个闸门(单标的浮亏 N% 停止补仓 / `max_hold_days` 真正生效) | 样本里无触发机会(最大浮亏仅 0.9%**属于尾部保险,不是收益来源** | 会引入已实现亏损 | 需改 `positions.py` |
**一句话**:收益低不是参数没调好,而是"一年 59 个机会 × 每轮 0.89% × 平均只用 1.68% 的钱"
这三项乘出来的。想提高,**先扩标的(更多并行机会),再放大单档规模(更多钱下注)**
调参(补仓速度、止盈门槛、入场宽度)已经被数据否决。
---
## 十一、复现与文件
```
labs/analysis/etf/
├── backtest.py 回测内核日线近似、三种成交模型、共享资金、T+1、sizer
├── analysis.py 轮次统计 / 资金占用 / 逐月 / 敏感性
├── run.py 总报告生成器results.json + run_report.txt
├── sweep.py 改进方案扫描(规模 / 参数 / 组合)
├── universe.py 标的数量 × 资金规模的隔离实验
├── entries.py 入场机会频率统计
├── results.json 全部结构化结果
├── run_report.txt 人读汇总表
└── cache/*.json 日线缓存(--refresh 重新抓取)
```
```powershell
cd D:\work\quant\big-qmt
py -3.14 -B labs/analysis/etf/run.py --refresh # 抓最新日线并重跑全部对照
py -3.14 -B labs/analysis/etf/run.py --ledger # 附带逐笔成交
py -3.14 -B labs/analysis/etf/sweep.py # 改进方案扫描
py -3.14 -B labs/analysis/etf/universe.py # 标的数量 vs 资金规模
py -3.14 -B labs/analysis/etf/entries.py # 入场机会频率
```