lottery-hk: v1.2.6 — 特码脚本改中文文件名 lottery_特码.py
User 2026-07-30 反馈: - 脚本名 lottery_te_ma.py → lottery_特码.py (中文, 更直观) - 同步 SKILL.md 引用 (description + scripts 段) - version 1.2.5 → 1.2.6
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: dividend-investing
|
||||
description: "Dividend stock research, analysis, and ex-dividend alerting across A/HK/US markets. Covers: dividend history analysis (yield, growth, payout ratio), pre-ex-dividend day alerts via cron job, yield-vs-financing-cost arbitrage calculations, and record date tracking. Now includes stability scoring (years + CAGR + volatility + recent) for A-shares via AKShare. Not for short-term trading entries — this is the dividend-side analysis mindset."
|
||||
description: "Dividend stock research, analysis, and ex-dividend alerting across A/HK/US markets. Covers: dividend history analysis (yield, growth, payout ratio), pre-ex-dividend day alerts via cron job, yield-vs-financing-cost arbitrage calculations, and record date tracking. Now includes stability scoring (years + CAGR + volatility + recent) for A-shares via AKShare. Push output uses horizontal markdown tables (4-8 cols, user 2026-07-29 preference) with 次/年 + 连续(年) + vs MA50 enrichment. Not for short-term trading entries — this is the dividend-side analysis mindset."
|
||||
version: 1.2.0
|
||||
author: Hermes Agent
|
||||
license: MIT
|
||||
@@ -11,6 +11,16 @@ metadata:
|
||||
related_skills: [tonghuashun, longbridge-python-sdk, stock-analysis]
|
||||
scripts:
|
||||
- "scripts/dividend_alert.py: 'Daily dividend scan. Cron jobs (id `789a7710b1cf` A股+港股, `366934c1474c` 美股) call `scripts/dividend_alert_cn_hk.sh` and `scripts/dividend_alert_us.sh` (proxychains4 + 过滤 [proxychains] 日志). Contains score_dividend_stability() with _stability_cache per symbol per run. Edit here in skill repo to update.'"
|
||||
- "scripts/dividend_alert.py is a duplicate under ~/.hermes/scripts/ (cron path). Keep both in sync — cron uses absolute path /home/openclaw/.hermes/scripts/dividend_alert.py (rule: skill scripts under skills/, cron scripts under ~/.hermes/scripts/)."
|
||||
|
||||
references:
|
||||
- dividend-yield-rate-sort: "分红扫描按股息率% 倒序(用户偏好 2026-07-13)"
|
||||
- fill-gap-timing: "填权时间线数据 + 抓取分析"
|
||||
- dividend-yield-arbitrage: "股息率 vs 融资成本套息"
|
||||
- cron-schedule-and-push-timing: "cron schedule / Beijing-time push timing (why 11:00 BJT)"
|
||||
- dividend-stability-score: "5 维评分 (派息年数/CAGR/波动/最近/连续) 综合稳定性 0-100 + 5 星等级; 数据源 akshare stock_history_dividend_detail(indicator='分红'); 缓存避免重复查询; 2026-07-22 新增"
|
||||
- cn-dividend-buy-timing-pool: "Manual HIGH_DIVIDEND_POOL list (17 A-share blue chips) + 综合评分公式 `score = annual_yield + stability_bonus` where stability_bonus = (stability - 2) * 2.0 (stab=3 → +2%, stab=2 → 0, stab=1 → -2%). 用户 2026-07-29 反馈纯 yield 排序把 招商银行(5%)/伊利股份(4%)/长江电力(4.5%) 挤出去, 加 stability bonus 后这 3 票稳定进 top 15。脚本: ~/.hermes/scripts/cn_dividend_buy_timing.py (cron 任务待接入)。脚本里 stability 字段: 3=连续5年+稳定, 2=连续3年, 1=波动。"
|
||||
- akshare-dividend-history-and-push-enrichment: "AKShare 两套历史股息 API (A 股 stock_history_dividend_detail + 港股 stock_hk_dividend_payout_em) + push 字段扩展模式 (次/年 + 连续(年) + vs MA50) + ⚠️ ma_off double-*100 bug 教训 + 数据累积+循环外拼表模式 + 名称行单独存在。2026-07-29 实战 + 2026-07-30 加 ma_off bug fix。适用所有 dividend_alert 类推送。"
|
||||
references:
|
||||
- dividend-yield-rate-sort: "分红扫描按股息率% 倒序(用户偏好 2026-07-13)"
|
||||
- fill-gap-timing: "填权时间线数据 + 抓取分析"
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
# AKShare 股息历史 API + Push 字段扩展模式 (2026-07-29 实战)
|
||||
|
||||
## 1. AKShare 两套历史股息 API
|
||||
|
||||
A 股 和 港股 用**不同的接口**(2026-07-29 验证可用):
|
||||
|
||||
| 市场 | API | 输入 | 列 | 来源 |
|
||||
|------|------|------|------|------|
|
||||
| **A 股** (6 位) | `ak.stock_history_dividend_detail(code, indicator='分红')` | 6 位代码 | 公告日期/送股/转增/派息/进度/除权除息日/股权登记日/红股上市日 | 新浪财经 |
|
||||
| **港股** (5 位) | `ak.stock_hk_dividend_payout_em(code)` | 5 位代码 | 最新公告日期/财政年度/分红方案/分配类型/除净日/截至过户日/发放日 | 东方财富港股 |
|
||||
|
||||
**注意**: 美股 Nasdaq API (`api.nasdaq.com/api/calendar/dividends?date=YYYY-MM-DD`) **只返回当天** — 没有历史。
|
||||
要美股历史需 `stock_us_dividend_em` (akshare) 或 yfinance。
|
||||
|
||||
### 1.1 helper 实现
|
||||
|
||||
```python
|
||||
def get_dividend_history(code):
|
||||
"""返回: (annual_count_avg, continuous_years, is_recent)
|
||||
code: 6 位 A 股 OR 5 位 港股
|
||||
"""
|
||||
is_hk = code.isdigit() and len(code) == 5
|
||||
is_a = code.isdigit() and len(code) == 6
|
||||
try:
|
||||
if is_hk:
|
||||
df = ak.stock_hk_dividend_payout_em(code)
|
||||
elif is_a:
|
||||
df = ak.stock_history_dividend_detail(code)
|
||||
else:
|
||||
return (0, 0, False)
|
||||
# 过滤 + 提取年份 (用除权日 / 除净日)
|
||||
done = df.dropna(subset=['除权除息日' if is_a else '除净日']).copy()
|
||||
if is_a:
|
||||
done = done[(done['进度'] == '实施') & (done['送股'] == 0) & (done['转增'] == 0)]
|
||||
if done.empty:
|
||||
return (0, 0, False)
|
||||
date_col = '除权除息日' if is_a else '除净日'
|
||||
done['year'] = done[date_col].astype(str).str[:4].astype(int)
|
||||
# 平均年度派息次数 (近 3 年)
|
||||
last_3y = done[done['year'] >= 2024]
|
||||
annual_count = round(last_3y.groupby('year').size().mean(), 1) if not last_3y.empty else 0
|
||||
# 连续派息年数
|
||||
years_with_div = sorted(set(done['year'].tolist()))
|
||||
continuous = 0
|
||||
for y in range(2025, 2010, -1):
|
||||
if y in years_with_div:
|
||||
continuous += 1
|
||||
else:
|
||||
break
|
||||
return (annual_count, continuous, not done[done['year'] == 2026].empty)
|
||||
except Exception:
|
||||
return (0, 0, False)
|
||||
```
|
||||
|
||||
**性能**: 5 票 ~1.2s, 12 票 ~3s (cron 推送时间内可接受)。
|
||||
|
||||
## 2. Push 字段扩展: 次/年 + 连续(年) + vs MA50
|
||||
|
||||
dividend_alert.py 在 2026-07-29 加了 3 列,显著提升推送价值。
|
||||
|
||||
### 2.1 最终表结构 (8 列)
|
||||
|
||||
| 票 | 名称 | 每10股派 | 现价 | 股息率 | 次/年 | 连续(年) | vs MA50 |
|
||||
|
||||
**字段说明**:
|
||||
- **次/年**: 近 3 年平均派息次数。1.0 = 年度派, 1.5 = 半年+年度, 1.7 = 多季度(高息稳定)
|
||||
- **连续(年)**: 派息连续年数。🔥10+ = 10 年以上稳定, ⚡5-9 = 5-9 年
|
||||
- **vs MA50**: 当前价对 50 日均线的偏离 (用长桥 K 线算)
|
||||
|
||||
### 2.2 emoji 等级系统
|
||||
|
||||
| 状态 | 阈值 | emoji |
|
||||
|------|------|------|
|
||||
| 连续派息 ≥10 年 | 10+ | 🔥 |
|
||||
| 连续派息 5-9 年 | 5-9 | ⚡ |
|
||||
| 离 MA50 > +5% | 显著高估 | 🟢(但下行风险) |
|
||||
| 离 MA50 0 ~ +5% | 略高 | 🟡 |
|
||||
| 离 MA50 -10 ~ 0 | 略低 | 🔴(买入机会) |
|
||||
| 离 MA50 < -10% | 大幅低于 | ⛔(危险/可能趋势反转) |
|
||||
|
||||
⚠️ 注意: 🟢/🔴 在此场景**语义反转** — 通常用 🟢 表示"好",但 vs MA50 偏离=大代表下行风险高。需在推送头部加注释说明。
|
||||
|
||||
## 3. ⚠️ 必看 Bug: `ma_off` double *100
|
||||
|
||||
**陷阱**: 在 `cn_dividend_buy_timing.py` 中我犯了这个错:
|
||||
|
||||
```python
|
||||
# 错: 显示时再 *100
|
||||
'ma_off': (current/ma50-1)*100, # 存储为 0.05 (= 5%)
|
||||
# ...
|
||||
L.append(f"| 离均线 | {'+' if r['ma_off']>=0 else ''}{ r['ma_off']*100:.1f}% |")
|
||||
# 输出: +982.7% (应该是 +9.8%)
|
||||
```
|
||||
|
||||
**正解**: 要么存 fraction (0.05), 要么存 percent (5.0), **但只能 *100 一次**。
|
||||
|
||||
```python
|
||||
# ✅ 选 1: 存 percent, 显示直接用
|
||||
'ma_off_pct': (current/ma50-1)*100,
|
||||
# 显示: f"{'+' if r['ma_off_pct']>=0 else ''}{r['ma_off_pct']:.1f}%"
|
||||
|
||||
# ✅ 选 2: 存 fraction, 显示时 *100
|
||||
'ma_off': (current/ma50-1), # 0.05
|
||||
# 显示: f"{r['ma_off']*100:+.1f}%" # 显式 + 避免符号混乱
|
||||
```
|
||||
|
||||
## 4. 数据累积 + 循环外拼装表 模式
|
||||
|
||||
**为什么**: 在循环内 `lines.append(f"| ...")` 难维护,容易出现 **状态混乱 bug**(像上面 ma_off)。
|
||||
|
||||
**模式**:
|
||||
|
||||
```python
|
||||
# 1. 累积 (在循环内)
|
||||
row_data = []
|
||||
for c in candidates[:8]:
|
||||
feats = compute(c)
|
||||
row_data.append({
|
||||
'code': c['code'],
|
||||
'name': c['name'][:6],
|
||||
'price': c['price'],
|
||||
'ma_off_pct': (c['price']/feats['ma50']-1)*100,
|
||||
# ... 一行所有字段
|
||||
})
|
||||
|
||||
# 2. 输出 (在循环外)
|
||||
if row_data:
|
||||
cols = [r['code'] for r in row_data]
|
||||
n = len(cols)
|
||||
hdr = "| 项目 | " + " | ".join(cols) + " |"
|
||||
sep = "|:---|" + "|".join([":---"] * n) + "|"
|
||||
L.append(hdr)
|
||||
L.append(sep)
|
||||
L.append("| 现价 | " + " | ".join([f"{r['price']:.2f}" for r in row_data]) + " |")
|
||||
L.append("| 离均线 | " + " | ".join([f"{r['ma_off_pct']:+.1f}%" for r in row_data]) + " |")
|
||||
# ...
|
||||
```
|
||||
|
||||
**好处**:
|
||||
- 字段名在 dict 里出现一次
|
||||
- 显示公式跟存储值**显式对应**(可单元测试)
|
||||
- 多张表 (基本面/点位/性价比) 都是同一模式
|
||||
- bug 容易被肉眼发现
|
||||
|
||||
## 5. 名称列单独一行 (横向表 4-8 列最佳实践)
|
||||
|
||||
**问题**: 横向表列是票代码 (601288),**但 QQ 用户滑动时想看到名称**(农业银行)。
|
||||
|
||||
**方案**: 名称作为单独行,放在代码行之上:
|
||||
|
||||
```python
|
||||
L.append(name_hdr) # | 名称 | 农业银行 | 工商银行 | ...
|
||||
L.append(name_sep)
|
||||
L.append(hdr) # | 项目 | 601288 | 601398 | ...
|
||||
L.append(sep)
|
||||
L.append("| 现价 | ...")
|
||||
```
|
||||
|
||||
**效果**:
|
||||
```
|
||||
| 名称 | 农业银行 | 工商银行 | 中国神华 | ...
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 项目 | 601288 | 601398 | 601088 | ...
|
||||
|:---|:---|:---|:---|:---|
|
||||
| 现价 | 7.05 | 8.14 | 45.62 | ...
|
||||
```
|
||||
|
||||
QQ mobile 用户**滑动时同时看到名称和代码**,**不需要查文档**。
|
||||
|
||||
## 6. 不要做
|
||||
|
||||
- ❌ 把每行字段全写成一行 (无换行, QQ 滚得累)
|
||||
- ❌ 列里塞 `f"{x:.6f}"` 这种 6 位小数
|
||||
- ❌ 列名用全角字符 (渲染乱)
|
||||
- ❌ 一次性输出 20+ 列 (挤, 滑动难受)
|
||||
- ❌ 混用 emoji 前缀 (⭐600809 和 600809 ⭐ 风格不一致)
|
||||
- ❌ 在表格里用 `|` 字符 (转义难, 破表)
|
||||
- ❌ `head -c 1800` 字节截断 UTF-8 文本 (Chinese 字符 3 字节,可能切坏)
|
||||
- ❌ **每个数值单元都 *100 两次**(ma_off 教训)
|
||||
@@ -0,0 +1,125 @@
|
||||
---
|
||||
name: cn-dividend-buy-timing-pool
|
||||
description: "Manual HIGH_DIVIDEND_POOL list (17 A-share blue chips) + 综合评分公式 `score = annual_yield + stability_bonus` where stability_bonus = (stability - 2) * 2.0. 用户 2026-07-29 反馈纯 yield 排序把 招商银行/伊利股份/长江电力 挤出去, 加 stability bonus 后这 3 票稳定进 top 15. 脚本: ~/.hermes/scripts/cn_dividend_buy_timing.py (cron 任务待接入). stability 字段: 3=连续5年+稳定, 2=连续3年, 1=波动."
|
||||
version: 1.0.0
|
||||
type: reference
|
||||
---
|
||||
|
||||
# A 股高息股买入时机 — 候选池 + 综合评分
|
||||
|
||||
**用户原话** (2026-07-29):
|
||||
- 招商银行 (5% 股息率) 和 伊利股份 (4%) 没被选出来 — 因为纯按 yield 排序进不去 top 8
|
||||
- "全仓, 分红稳定" — 关注分红稳定性
|
||||
|
||||
## 设计 — 综合评分 (yield + stability bonus)
|
||||
|
||||
```python
|
||||
score = annual_yield + stability_bonus
|
||||
stability_bonus = (stability - 2) * 2.0 # stab=3 → +2%, stab=2 → 0, stab=1 → -2%
|
||||
```
|
||||
|
||||
| stability | 含义 | bonus |
|
||||
|-----------|------|-------|
|
||||
| 3 | 连续 5 年+ 稳定 (银行/公用事业/必选消费龙头) | +2.0% |
|
||||
| 2 | 连续 3 年 (通信/化工) | 0 |
|
||||
| 1 | 波动 (矿/小盘) | -2.0% |
|
||||
|
||||
## 17 票手动池 (用户 review)
|
||||
|
||||
```python
|
||||
HIGH_DIVIDEND_POOL = [
|
||||
# ---- 高息 ≥5.5% + 稳定(stability≥2) ----
|
||||
{'sym': '600188.SH', 'name': '兖矿能源', 'annual_yield': 7.0, 'stability': 2},
|
||||
{'sym': '601288.SH', 'name': '农业银行', 'annual_yield': 6.5, 'stability': 3},
|
||||
{'sym': '601398.SH', 'name': '工商银行', 'annual_yield': 6.5, 'stability': 3},
|
||||
{'sym': '601088.SH', 'name': '中国神华', 'annual_yield': 6.5, 'stability': 3},
|
||||
{'sym': '600023.SH', 'name': '浙能电力', 'annual_yield': 6.5, 'stability': 3},
|
||||
{'sym': '600585.SH', 'name': '海螺水泥', 'annual_yield': 6.5, 'stability': 3},
|
||||
{'sym': '601006.SH', 'name': '大秦铁路', 'annual_yield': 6.5, 'stability': 3},
|
||||
{'sym': '601225.SH', 'name': '陕西煤业', 'annual_yield': 6.5, 'stability': 2},
|
||||
{'sym': '601939.SH', 'name': '建设银行', 'annual_yield': 6.0, 'stability': 3},
|
||||
{'sym': '601658.SH', 'name': '邮储银行', 'annual_yield': 6.0, 'stability': 3},
|
||||
{'sym': '600015.SH', 'name': '华夏银行', 'annual_yield': 5.5, 'stability': 3},
|
||||
{'sym': '600028.SH', 'name': '中国石化', 'annual_yield': 5.5, 'stability': 3},
|
||||
# ---- 稳定大盘 (stability=3 单独加权) ----
|
||||
{'sym': '600036.SH', 'name': '招商银行', 'annual_yield': 5.0, 'stability': 3}, # 银行龙头 PB 低
|
||||
{'sym': '600887.SH', 'name': '伊利股份', 'annual_yield': 4.0, 'stability': 3}, # 消费/必选龙头
|
||||
{'sym': '600900.SH', 'name': '长江电力', 'annual_yield': 4.5, 'stability': 3},
|
||||
{'sym': '601728.SH', 'name': '中国电信', 'annual_yield': 5.0, 'stability': 2},
|
||||
{'sym': '600050.SH', 'name': '中国联通', 'annual_yield': 5.0, 'stability': 2},
|
||||
]
|
||||
```
|
||||
|
||||
## 时机判别 (3 类)
|
||||
|
||||
```python
|
||||
def recommend_entry(div_yield, current, ma50, support, atr_pct, trend):
|
||||
if div_yield >= 6.0:
|
||||
if current < ma50 and current <= support * 1.02 and "偏弱" not in trend and "📉空头" not in trend:
|
||||
return ("🟢今天买", 3, current, support * 0.97, "高息 + 价 < 均线 + 贴近支撑")
|
||||
elif current < ma50:
|
||||
return ("🟡等回撤", 2, ma50 * 0.98, current * 0.97, "高息 + 价 < 均线—等跌稳")
|
||||
elif current <= ma50 * 1.03:
|
||||
return ("🟡等回撤", 2, ma50, current * 0.97, "高息 + 价贴近均线")
|
||||
else:
|
||||
return ("🔴不入场", 1, ma50, current * 0.93, "高息但价远高于均线")
|
||||
elif div_yield >= 5.0:
|
||||
if current < ma50 * 1.05:
|
||||
return ("🟡等回撤", 2, ma50 * 0.98, current * 0.95, "中等股息率")
|
||||
else:
|
||||
return ("🔴不入场", 1, ma50, ma50 * 0.95, "中等股息率但价已偏贵")
|
||||
else:
|
||||
return ("🔴不入场", 0, current, current * 0.95, "股息率<5%不达预期")
|
||||
```
|
||||
|
||||
## 仓位 (8000 元小资金)
|
||||
|
||||
```python
|
||||
# 单票建议 4000 元(一半仓, 留 4000 备用)
|
||||
lots = int(4000 // current // 100) * 100 # A 股一手 100 股
|
||||
lots = max(lots, 100) # 至少一手
|
||||
```
|
||||
|
||||
## 实际效果 (2026-07-29 测试)
|
||||
|
||||
**综合评分倒序 top 15:**
|
||||
|
||||
| 名次 | 股票 | annual_yield | stability | score |
|
||||
|------|------|--------------|-----------|-------|
|
||||
| 1 | 农业银行 | 6.5% | 3 | 8.5 |
|
||||
| 2 | 工商银行 | 6.5% | 3 | 8.5 |
|
||||
| 3 | 中国神华 | 6.5% | 3 | 8.5 |
|
||||
| 4 | 浙能电力 | 6.5% | 3 | 8.5 |
|
||||
| 5 | 海螺水泥 | 6.5% | 3 | 8.5 |
|
||||
| 6 | 大秦铁路 | 6.5% | 3 | 8.5 |
|
||||
| 7 | 建设银行 | 6.0% | 3 | 8.0 |
|
||||
| 8 | 邮储银行 | 6.0% | 3 | 8.0 |
|
||||
| 9 | 华夏银行 | 5.5% | 3 | 7.5 |
|
||||
| 10 | 中国石化 | 5.5% | 3 | 7.5 |
|
||||
| 11 | 兖矿能源 | 7.0% | 2 | 7.0 |
|
||||
| 12 | **招商银行** | 5.0% | 3 | **7.0** (纯 yield 排序排第 13, 加上后进 #12) |
|
||||
| 13 | 陕西煤业 | 6.5% | 2 | 6.5 |
|
||||
| 14 | **长江电力** | 4.5% | 3 | **6.5** (纯 yield 排第 16, 加上后进 #14) |
|
||||
| 15 | **伊利股份** | 4.0% | 3 | **6.0** (纯 yield 排第 17, 加上后进 #15) |
|
||||
|
||||
**关键验证** (用户原话):"招商银行怎么没选出来。还有伊利股份" — 加 stability bonus 后 3 票全部稳定进 top 15。
|
||||
|
||||
## 为什么不直接用 akshare 拉高息池
|
||||
|
||||
试过 `ak.stock_dividend_yield_em` → **不存在**。`stock_history_dividend` 只能拉单只, 不能批量筛。
|
||||
|
||||
**手动维护池**的 trade-off:
|
||||
- ✅ 17 票全是用户 review 过的 (大盘蓝筹稳定)
|
||||
- ✅ 包含 招商/伊利/长江电力 这类稳定但 yield 略低的票
|
||||
- ❌ 没法自动更新 (季度 review 一次就够)
|
||||
|
||||
## cron 接入 (待用户确认)
|
||||
|
||||
建议 `0 11 * * 1-5` 每天 11:00 北京 (开盘前 30 min), 与 `789a7710b1cf` (dividend_alert) 同步。
|
||||
|
||||
## 文件位置
|
||||
|
||||
- **脚本**: `~/.hermes/scripts/cn_dividend_buy_timing.py` (cron 脚本, 不在 skill repo)
|
||||
- **wrapper**: `~/.herclaw/.hermes/scripts/cn_dividend_buy_timing_cron.sh`
|
||||
- **git 仓库**: Hermes-Scripts (commit `fdacf52`)
|
||||
- **规则**: skill 的脚本在 `skills/.../scripts/`, cron 的脚本在 `~/.hermes/scripts/` (用户原话 2026-07-29 "如果是定时任务的就放在 Scripts 仓库下")
|
||||
Reference in New Issue
Block a user