141 lines
7.6 KiB
Markdown
141 lines
7.6 KiB
Markdown
# 神奇九转 (TD Sequential) — 算法 + lib 抽取 + 实战参考
|
|
|
|
## 位置
|
|
|
|
**主库**: `~/.hermes/scripts/lib/td9.py` (2026-08-23 抽到公用 lib, 4 个脚本共享)
|
|
|
|
```python
|
|
from lib.td9 import td9_levels, td9_summary
|
|
|
|
td9 = td9_levels(closes, current) # dict 或 None
|
|
summary = td9_summary(td9) # 一行短字符串
|
|
```
|
|
|
|
**禁止**: 在任何脚本里复制 `td9_levels()` 本地实现。要改算法只改 `lib/td9.py`, 4 个脚本自动同步。
|
|
|
|
## 用途
|
|
|
|
`daily_t_analysis.py` v3.1 (2026-08-23 替代 v3.0 海龟) 的核心策略之一。每日持仓推送里给每只票算九转计数 + 方向 + (完成时) 入场/止损参考。**2026-08-23 抽到 `~/.hermes/scripts/lib/td9.py` 公用库, 4 个脚本接入**: `daily_t_analysis.py` / `cn_dividend_buy_timing.py` / `scan_cn.py` / `dca_scanner.py`。
|
|
|
|
## 算法 (Tom DeMark TD Sequential)
|
|
|
|
```python
|
|
def td9_levels(closes, current):
|
|
"""买入九转: 连续 9 根 close[i] < close[i-4]
|
|
卖出九转: 连续 9 根 close[i] > close[i-4]
|
|
数据要求: 至少 13 根 K 线 (1 + 4 + 8)"""
|
|
if len(closes) < 13:
|
|
return None
|
|
# 从最新一根往回数,遇不符合条件就 break
|
|
buy_count = sum(1 for i in range(len(closes)-1, 3, -1)
|
|
if closes[i] < closes[i-4]
|
|
for _ in iter(lambda: True, True)
|
|
if closes[i] < closes[i-4] else break_counting())
|
|
# 实际用 for-else 模式实现更清晰:
|
|
buy_count = 0
|
|
for i in range(len(closes) - 1, 3, -1):
|
|
if closes[i] < closes[i - 4]:
|
|
buy_count += 1
|
|
else:
|
|
break
|
|
sell_count = 0
|
|
for i in range(len(closes) - 1, 3, -1):
|
|
if closes[i] > closes[i - 4]:
|
|
sell_count += 1
|
|
else:
|
|
break
|
|
```
|
|
|
|
**完成判定**: `count >= 9` → `done=True`,方向由买/卖计数决定。
|
|
**未完成但有意义**: `count >= 5` → 显示进行中。
|
|
**入场/止损参考 (仅完成时)**:
|
|
- 入场 = 当前价 (策略风格: 完成次日 close > 完成当日 high 触发,实际推送里用 current 简化)
|
|
- 止损 = 第 9 根 K 线收盘价 (`closes[len-9]`)
|
|
|
|
## 输出行 (横向 N 列 markdown 表)
|
|
|
|
```
|
|
| 🧙 九转 | 多 九转买✓ 9/9 | 空 九转卖… 5/9 | - 九转… 0/9 |
|
|
| 🧙 九转入 | 385.50 | - | - |
|
|
| 🧙 止损 | 380.10 | - | - |
|
|
```
|
|
|
|
- `✓` = 完成 (done=True, count>=9) → 入场/止损有数字
|
|
- `…` = 进行中 (count>=5 但 <9) → 入场/止损是 `-`
|
|
- 无显示 = count<5 或横盘
|
|
|
|
## 单元测试 (2026-08-23 验证 6/6 通过)
|
|
|
|
测试脚本保存在 `/tmp/test_td9.py`,**验证算法独立于 longbridge SDK**(避免每次都拉真实行情调试):
|
|
|
|
```python
|
|
import sys; sys.path.insert(0, '/home/openclaw/.hermes/scripts')
|
|
from daily_t_analysis import td9_levels
|
|
|
|
# 1. 连续跌 14 根 → count=10, done=True, dir=多 (count 可以 >9,继续算"超耗")
|
|
assert td9_levels([100-i for i in range(14)], 86)['count'] >= 9
|
|
|
|
# 2. 连续涨 14 根 → count>=9, dir=空
|
|
assert td9_levels([80+i for i in range(14)], 93)['direction'] == '空'
|
|
|
|
# 3. <13 根 → None
|
|
assert td9_levels([100-i for i in range(12)], 89) is None
|
|
|
|
# 4. 平盘 14 根 → count=0, dir=-
|
|
assert td9_levels([100]*14, 100)['count'] == 0
|
|
|
|
# 5. 振荡 (跌3涨3跌3涨3) → count=0
|
|
assert td9_levels([100,99,98,97,98,99,100,99,98,99,100,99,98,99], 99)['count'] == 0
|
|
|
|
# 6. 部分跌 (前 5 平 + 后 10 跌) → count 在 6 左右, done=False
|
|
closes = [95]*5 + [100, 99, 98, 97, 96, 95, 94, 93, 92, 91]
|
|
assert td9_levels(closes, 91)['count'] >= 5 and not td9_levels(closes, 91)['done']
|
|
```
|
|
|
|
## 工作流教训 (2026-08-23)
|
|
|
|
1. **算法函数要先单元测试再集成测试** — `daily_t_analysis.py` 顶部 `from longport import openapi` 会拉真实 API,慢且依赖 proxychains。把纯算法函数 (`td9_levels`, `bollinger_levels`, `rsi_levels` 等) 单独 test 一次,确认逻辑对了再跑全脚本。
|
|
2. **no_agent=true cron 只需改脚本,不动 cron prompt** — cron `cb187ab5f9fc` 的 `script=daily_t_analysis.py` 直接调脚本 stdout,无需编辑 cron prompt。
|
|
3. **改完即提交 + push** — 同步 `~/.hermes/scripts/` (Hermes-Scripts 仓库) 到 git.hi6k.com,避免下次部署丢失。
|
|
4. **horizontal N 列 markdown 表 (QQ mobile 可滑动) 是用户偏好** — 1 票 1 列,不要 1 票 1 表。详见 `daily-t-analysis-cron.md`。
|
|
|
|
## 4 个使用脚本 (2026-08-23)
|
|
|
|
| 脚本 | cron job | 角色 | TD9 用法 |
|
|
|---|---|---|---|
|
|
| `daily_t_analysis.py` | `cb187ab5f9fc` BJT 21:00 | 持仓做 T 分析 | 表格 + 🧙九转(计数+方向) + 🧙九转入 + 🧙止损 三行 |
|
|
| `cn_dividend_buy_timing.py` | `8000d3cfed23` BJT 11:30 | A股每日买入时机 | **入场增强**: `recommend_entry()` 接 td9; 卖出完成 → 🔴升🟡 + 用九转止损价 |
|
|
| `scan_cn.py` | `5d62894cdaee` BJT 周四 19:30 | A股周扫描 | 阶梯入场表后 + 🧙九转 + 🧙止损 两行 |
|
|
| `dca_scanner.py` | `84c46e13db14` / `89a3e7a6e6fe` BJT 周四 20:00/21:30 | 港美股周扫描 | 同 scan_cn, 阶梯入场表后 + 🧙两行 |
|
|
|
|
## 入场时机增强 (cn_dividend_buy_timing.py 详解)
|
|
|
|
TD9 在 `recommend_entry(div_yield, current, ma50, support, atr_pct, trend, td9=None)` 里是**信号增强层**, 不替代 MA50/支撑/趋势等基础条件:
|
|
|
|
| TD9 状态 | 对原入场判别的影响 |
|
|
|---|---|
|
|
| 买入计数 ≥7 (未完成, 跌势末期) | 🟢今天买 理由加 "+ 🧙九转买 N/9 (跌势末期)" |
|
|
| 卖出计数 ≥7 (未完成, 涨势末期) | 🟢今天买 理由加 "⚠️🧙九转卖 N/9 (涨势末期,回撤将至)" |
|
|
| **卖出完成 (done=True, 涨势到顶)** | 🔴不入场 **升级为 🟡等回撤 ★★☆, 止损用九转止损价 (第9根收盘)** |
|
|
| 买入计数 <5 或 无九转信号 | 不影响原判别 |
|
|
|
|
**典型效果** (2026-08-23 实测):
|
|
- 中国神华 (601088.SH): 九转卖出完成 11/9 → 原本 🔴不入场 → 升级 🟡等回撤 + 九转止损 44.70
|
|
- 建设银行 (601939.SH): 九转卖出完成 10/9 → 同升级
|
|
- 邮储银行 (601658.SH): 九转 0/9 → 走原流程, 高息+价<MA50+贴近支撑 → 🟢今天买 ★★★
|
|
|
|
**核心价值**: 在用户"吃股息"前提下, 九转避免在涨势到顶 (td9_sell_done) 时买入, 用九转止损价作为新的入场触发参考。
|
|
|
|
## 不替代
|
|
|
|
- `strategy-management` skill 的"海龟"是复杂版(Donchian 通道 + ATR 仓位管理) — 九转只是做 T 计数指标,不是完整交易系统
|
|
- `intraday-regime-detector` 的元策略判别(R²/ADF/vol) — 九转只算单票的动量耗尽信号,不管市场状态
|
|
|
|
## Pitfalls
|
|
|
|
- **🔴 单元测试先于集成**: 改 `td9_levels` 逻辑时先在 `/tmp/test_td9.py` 跑 6 个边界 case, 再 import 到全脚本里跑。`daily_t_analysis.py` 顶部 `from longport import openapi` 会拉真实 API + proxychains, 慢且依赖重, 每次跑调试算法不划算。
|
|
- **🔴 td9_levels 抽到 lib 别再 copy-paste**: 4 个脚本都依赖 `~/.hermes/scripts/lib/td9.py` 公用库。**禁止** 在任何脚本里复制 `td9_levels()` 实现 — 修改逻辑时只改 `lib/td9.py`, 4 个脚本自动同步。
|
|
- **🔴 输出格式必须横向 N 列 (用户偏好 2026-07-29)**: 九转在表格里和其他指标一样, 1 票 1 列。`td9_summary()` 返回的短字符串是 cell 内容, 直接拼到 `| col1 | col2 | ... |` 行里。
|
|
- **🔴 长桥 30 根 K 线限**: K 线少于 13 根时 `td9_levels` 返回 None, 调用方需要保护 (`if td9:`)。`cn_dividend_buy_timing.py` 已经过滤 (`len(closes) >= 13`), 其他新脚本接入时也要保护。
|
|
- **🔴 九转只是动量耗尽计数**: 不是趋势反转确认。完成信号 (count≥9) 后价格可能继续原方向运行 1-3 根, 实战要结合 MA50 / 支撑 / 趋势等基础条件。**单独用九转做单**风险高。
|