From 1368b1790c2afba52d712f4330aeb078f618544d Mon Sep 17 00:00:00 2001 From: xxm Date: Mon, 17 Aug 2026 19:08:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=98=E6=B1=B0=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3(=E4=BB=85=E4=BF=9D=E7=95=99=E5=8D=96?= =?UTF-8?q?=E5=87=BA=E4=BF=A1=E5=8F=B7+RR<1.0=E4=BF=9D=E5=BA=95)=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE:=20=E6=AD=BB=E6=B0=B43=E8=BF=9E=E6=B7=98?= =?UTF-8?q?=E6=B1=B01126=E5=8F=AA,=E6=B7=98=E6=B1=B0=E5=90=8E20=E6=97=A560?= =?UTF-8?q?%=E8=AF=AF=E6=9D=80(=E4=BF=A1=E5=8F=B7=E4=B8=8D=E5=85=85?= =?UTF-8?q?=E5=88=863=E8=BF=9E71%=E6=B6=A8),=20=E4=BB=85=E5=8D=96=E5=87=BA?= =?UTF-8?q?=E4=BF=A1=E5=8F=B7=E6=AD=A3=E7=A1=AE(-2.2%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/profile-scripts/watchlist_auto_exit.py | 36 +++--------- docs/淘汰逻辑验证.md | 58 +++++++++++++++++++ 2 files changed, 66 insertions(+), 28 deletions(-) create mode 100644 docs/淘汰逻辑验证.md diff --git a/deploy/profile-scripts/watchlist_auto_exit.py b/deploy/profile-scripts/watchlist_auto_exit.py index 002ba564..85e537fd 100644 --- a/deploy/profile-scripts/watchlist_auto_exit.py +++ b/deploy/profile-scripts/watchlist_auto_exit.py @@ -1,9 +1,10 @@ #!/usr/bin/env python3 """watchlist_auto_exit.py — 自选退出机制 -每天盘前执行,扫描自选策略: -- 连续N天信号为"卖出" → 自动退出 -- 连续N天评级极低且价格远离买入区 → 自动退出 +每天盘前执行,扫描自选策略(2026-08-17 数据驱动修正): +- 信号=卖出 → 自动退出(数据验证唯一正确条件:20日后-2.2%) +- RR<1.0 → 自动退出(保底:防负期望交易) +- 已废除:死水3连(60%误杀,信号不充分3连71%涨)/ 远离买区 / 零仓位弱信号 - 记录出入日志到 watchlist_log 表 """ import sqlite3, sys, json @@ -47,32 +48,11 @@ def main(dry_run=False): if "卖出" in signal_str: reasons.append(f"信号={signal_str}") - # 条件2: 信号=观望/信号不充分 且 价格远离买入区 - if "观望" in signal_str or "信号不充分" in signal_str: - if price and el and eh and el > 0 and eh > 0: - if price > eh * 1.20: # 高于买入区上沿20% - reasons.append(f"价{price}超买区上沿+{((price/eh)-1)*100:.0f}%") - elif el > 0 and price < el * 0.85: # 低于买入区下沿15% - reasons.append(f"价{price}低于买区下沿{(1-price/el)*100:.0f}%") + # ── 2026-08-17 淘汰逻辑修正(数据驱动,老莫确认方案A)── + # 数据:死水3连/远离买区/RR<2.0 淘汰后20日 60%误杀(详见 docs/淘汰逻辑验证.md) + # 只保留:信号=卖出(唯一数据支持的正确条件)+ RR<1.0 保底(防负期望交易) - # 条件3: 已清仓/零仓位且信号差 - pos_str = str(pos_advice or "") - if rank <= 1 and ("0%" in pos_str or "清仓" in pos_str or "不参与" in pos_str): - reasons.append(f"仓位建议={pos_str}") - - # ── 优中选优新增(2026-07-24 老爸)── - # 条件4: 死水闸——最近3次重评信号均为 观望/信号不充分/弱势持有 → 退出 - _weak = ("观望", "信号不充分", "弱势持有") - try: - _hist = conn.execute( - "SELECT timing_signal FROM strategy_history WHERE code=? " - "ORDER BY snapshotted_at DESC LIMIT 3", (code,)).fetchall() - if len(_hist) >= 3 and all((h[0] or "") in _weak for h in _hist): - reasons.append(f"死水3连({','.join((h[0] or '?') for h in _hist)})") - except Exception: - pass - - # 条件5: RR闸——RR<2.0 淘汰(2026-08-17 老莫:每日重评后低于2.0淘汰,与promote门槛2.0闭环) + # 条件2(保底): RR<1.0 淘汰(止损距离≥止盈距离的负期望交易) try: _rr = conn.execute( "SELECT rr_ratio FROM holding_strategies WHERE code=? AND status='active'", diff --git a/docs/淘汰逻辑验证.md b/docs/淘汰逻辑验证.md new file mode 100644 index 00000000..00dab47b --- /dev/null +++ b/docs/淘汰逻辑验证.md @@ -0,0 +1,58 @@ +# 淘汰逻辑验证报告(由果推因) + +> 日期:2026-08-17 +> 背景:老莫要求验证现行自选淘汰逻辑的有效性,不拍脑袋,用数据说话。 +> 结论:现行"死水3连"淘汰逻辑严重误杀(60%),已修正为仅保留"卖出信号"+"RR<1.0保底"。 + +## 验证方法 + +- 样本:watchlist_log 全部 1698 条退出记录,其中死水3连 1126 条(2026-07-24 ~ 08-17) +- 方法:对被淘汰标的查 stock_daily 淘汰日后 20 日收盘价,计算涨跌幅 +- 判定:涨>3% = 误杀(不该淘汰);跌>3% = 正确淘汰;±3% = 横盘 + +## 数据结果 + +### 死水3连淘汰 → 淘汰后 20 日走势(1126 只) + +| 信号类型 | n | 20日均涨跌 | 涨>3% | 横盘 | 跌>3% | +|---------|---|-----------|-------|------|-------| +| 观望 | 311 | +1.80% | 29% | 57% | 14% | +| 信号不充分 | 547 | **+9.78%** | **71%** | 24% | 5% | +| 弱势持有 | 268 | **+9.67%** | **75%** | 21% | 4% | +| **合计** | **1126** | **+7.6%** | **60%** | 32% | **7%** | + +### 其他淘汰条件 + +| 淘汰条件 | n | 20日均涨跌 | 涨>3% | 跌>3% | 判定 | +|---------|---|-----------|-------|-------|------| +| 信号=卖出 | 1 | -2.2% | 0% | 0% | ✅ 正确 | +| RR<2.0 | 323 | +4.74% | 44% | 7% | ❌ 误杀 | +| 远离买区 | 1 | +12.78% | 100% | 0% | ❌ 误杀(样本少) | + +### 个别案例(2026-07-24 淘汰,30日后) + +| 标的 | 淘汰价 | 30日后 | 涨幅 | +|------|--------|--------|------| +| 002759 | 14.02 | 19.13 | **+35%** | +| 603308 | 44.70 | 51.35 | +15% | +| 603505 | 16.03 | 16.47 | +3% | + +## 根因分析 + +1. **"信号不充分/弱势持有"恰恰是股价在底部未启动的阶段**——策略信号本就在等确认。连续 3 次这种信号就删掉 = **删在启动前夜**。 +2. RR<2.0 淘汰误杀(44%涨)——RR 是风控指标非质量指标(Pearson r≈0.05,见 RR分析结论.md)。 +3. **唯一的正确淘汰条件是"信号=卖出"**(淘汰后 -2.2%,该卖的确实跌了)。 + +## 修正决策(2026-08-17 老莫确认方案A) + +**watchlist_auto_exit.py 修正为:** +- ✅ 保留:**信号=卖出** → 自动退出(数据验证唯一正确) +- ✅ 保留:**RR<1.0** → 自动退出(保底,防负期望交易) +- ❌ 删除:死水3连(60%误杀) +- ❌ 删除:远离买区(样本少且误杀) +- ❌ 删除:零仓位+弱信号(弱势持有不该删) + +## 涉及文件 + +- `deploy/profile-scripts/watchlist_auto_exit.py` +- 相关:`docs/RR分析结论.md`(RR 阈值 2.0→1.0 的数据依据) \ No newline at end of file