Files
Hermes-Skills/dividend-investing/SKILL.md
T
mike 657dc41c46 Initial commit: Trading skills collection
- OKX交易自动化 (okx-auto-position, okx-crypto, okx-exchange)
- 交易信号处理 (signal-confirmation-templates, trading-signal-aggregator)
- 量化因子挖掘 (quant-factor-mining)
- 长桥集成 (longbridge-cli, longbridge-python-sdk)
- 六合彩分析 (lottery-hk)
- 股息投资 (dividend-investing, dividend-scanner)
- 日内交易 (intraday-trading)
- 同花顺 (tonghuashun)
2026-07-05 02:39:41 -04:00

12 KiB
Raw Blame History

name, description, version, author, license, platforms, metadata, scripts, requires
name description version author license platforms metadata scripts requires
dividend-investing 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. Not for short-term trading entries — this is the dividend-side analysis mindset. 1.0.0 Hermes Agent MIT
linux
macos
hermes
tags related_skills
trading
dividends
stocks
a-shares
hk-stocks
us-stocks
cron
tonghuashun
longbridge-python-sdk
stock-analysis
dividend_alert.py
python3 ~/.hermes/scripts/dividend_alert.py — daily cron job; runs via cronjob no_agent=true (script output delivered verbatim)
python3 + akshare (pip install akshare)
python3 + requests (stdlib)
For US stocks
internet access to api.nasdaq.com (no API key needed)
Cron job management (cronjob tool)

股息投资 Skill — Dividend Investing

Dividend-focused stock analysis and pre-ex-dividend alerting. Mindset is fundamentally different from trading: focus on yield stability, growth trajectory, payout ratio, cash coverage, and tax implications — not technical entry points.

Data Sources

Market Data Source API Key? Speed
🇨🇳 A股 akshare.news_trade_notify_dividend_baidu(date) Free ~3s
🇭🇰 港股 Same Baidu function (HK stocks included) Free ~3s
🇺🇸 美股 https://api.nasdaq.com/api/calendar/dividends?date=YYYY-MM-DD Free ~2s

Cross-Market Alerting Cron Job

The script ~/.hermes/scripts/dividend_alert.py runs daily and outputs a formatted dividend alert. Key design decisions:

Core Logic

# 1. Find next trading day (skip weekends)
def next_trading_day(d):
    while d.weekday() >= 5:
        d += timedelta(days=1)
    return d

# 2. A/HK: AKShare Baidu dividend calendar
df = ak.news_trade_notify_dividend_baidu(date=target_date_str)
# Returns: 股票代码, 除权日, 分红, 送股, 转增, 交易所, 股票简称, 报告期

# 3. US: Nasdaq API
url = f'https://api.nasdaq.com/api/calendar/dividends?date={date_str}'
# Returns: symbol, dividend_Rate (per-share), indicated_Annual_Dividend, record_Date, dividend_Ex_Date

Format Parsing

A-share dividend from Baidu is in 元/10股 format (e.g., "38.00元" = 3.80元/股). HK dividend from Baidu is in 港元/10股 format (e.g., "0.62港元"). US dividend from Nasdaq is in 美元/股 format (e.g., 0.56).

Cron Setup

# Create the job (EDT server time, 20:30 = Beijing 08:30 next day)
# Use no_agent=true for reliable script-only delivery
cronjob action=create \
  name='股息登记日前一天提醒' \
  schedule='30 20 * * 1-5' \
  script='dividend_alert.py' \
  no_agent=true

The no_agent=true mode delivers the script's stdout verbatim — no LLM token waste, no risk of the agent reformatting or truncating the message.

Proxy Pitfall

AKShare AND the Nasdaq API BOTH break when system proxy env vars are set:

import os
for k in ['http_proxy','https_proxy','HTTP_PROXY','HTTPS_PROXY']:
    os.environ.pop(k, None)
# Now import akshare and requests — they'll connect directly

Always put this at the top of your dividend scripts. The proxy env vars are typically set by Hermes gateway or system-level VPN wrappers, and they prevent direct HTTPS connections to Chinese financial data API endpoints (ProxyError).

Dividend Investor Mindset (vs Trader)

When the user says they want dividends (not trading), shift analysis completely:

Dimension Trader Dividend Investor
Focus Entry/exit price, momentum, MACD Yield %, payout ratio, dividend growth CAGR
Key metric Buy point, stop loss, R:R 股息率 vs 资金成本(如银行分期3%)
Timescale Days to weeks Quarters to years
Data K-line, volume, ADR, MACD Dividend history, cash flow, FCF, payout ratio
When to buy Technical breakout / support Before ex-div date (登记日前一天 = last buy day)
Tax Short-term capital gains Holding period tax rules (A股: 1月内20%, 1年以上免税)

Analysis Template

股息率 = 全年每股分红 / 当前股价
净息差 = 股息率 - 融资成本

分红增长率(5年CAGR) = (当年分红 / 5年前分红)^(1/5) - 1
分红覆盖率 = 经营现金流 / 分红总额

Dividend Capture Analysis (Buy Before Ex-div, Sell After)

When the user asks about "收息后卖" (dividend capture), the math is NOT free money:

The Core Equation

Net P&L = Dividend_Net - (Buy_Price - Sell_Price) × Shares
        = Dividend × (1 - Tax_Rate) × Shares - Price_Drop × Shares

Why Dividend Capture Fails for Retail

Scenario Tax Price Action Net Result
Sell at exact ex-div price 20% (<1mo) -div amount LOSE (tax eaten)
Sell at exact ex-div price 10% (1mo-1yr) -div amount LOSE (tax eaten)
Sell at exact ex-div price 0% (>1yr) -div amount BREAKEVEN
Stock recovers +2% (填权) 20% -div +2% SLIGHT GAIN
Stock fully fills gap Any -div +div GAIN = Dividend net

Rule of thumb: The stock MUST recover (填权) by at least the tax rate × dividend/price to break even. For A-shares with 20% tax, that's ~0.4% on a 2元 dividend on a 28元 stock.

填权 (Gap Fill) Timeline Analysis

Historical data for 华特达因 (000915):

2025年: 除权日6/11收29.49 → 第10天31.15(+5.6%) → 第15天33.22(+12.6%) ✅ 填权
2024年: 除权日5/16收33.48 → 第2天33.95(+1.4%) → 60天跌到26.89(-19.7%) ❌ 未填权(大盘差)

填权 probability depends primarily on:

  1. Stock's position in its range — near 52-week low = higher fill probability (safety margin)
  2. Broader market direction — bull market = fast fill, bear market = may never fill
  3. Stock quality — strong fundamentals (growing dividends, cash-rich) = faster fill

Dividend Capture Decision Matrix

Q: "Can I buy today for the dividend and sell right after?"
→ Show the math above. The answer is almost always NO unless the user can wait for 填权.

Q: "How long does it usually take to fill the gap?"
→ Check historical 填权 data. For quality dividend stocks at low prices, typically 2-4 weeks.

Push Notification Formatting

For dividend alerts delivered to QQ/Telegram, use this card-style layout:

📢 明日除权·红利提醒
━━━━━━━━━━━━━━━━━━━━
📅 今日 {date} 推送
⏰ 明天 {next_date} ({weekday}) 除权除息
💡 明天是登记日,今天买入仍享分红

────────────────────
🇨🇳 A股 明日除权 TOP

  ⭐{code} {name}
    💰每10股派{d:.2f}元

  💎{code} {name}
    💰每10股派{d:.2f}元

────────────────────
🇭🇰 港股 明日除权 TOP
  {code} {name}
    💰每10股派{d:.2f}港元

────────────────────
🇺🇸 美股 明日除权 TOP
  {code}
    💰${d:.2f}/股 | 年化${ann:.2f} | 年付{n}次
    📅登记日{rec_date}

━━━━━━━━━━━━━━━━━━━━
📌 操作提示
• 今天买入 → 明天登记 → 拿分红
• A股持仓1年以上免税,1月内20%税
━━━━━━━━━━━━━━━━━━━━
🤖 Hermes 每日红利雷达

Visual hierarchy rules:

  • for very high dividend (≥10元/10股)
  • 💎 for good dividend (5-10元/10股)
  • No prefix for lower dividends
  • for header/footer separators, for section dividers
  • 2-space indent per card, newline between cards
  • Empty market sections are simply omitted (no "0 results" noise)

Dividend Calendar Key Dates

A股:

  • 股权登记日 (Record date) = T day — buy on this day, still get dividend
  • 除权除息日 (Ex-div date) = T+1 trading day
  • 登记日前一天通知 → 用户登记日当天买入仍可拿分红

港股:

  • Generally same system as A-shares

美股:

  • 除权日 (Ex-div date) = cut-off. Buy on or after ex-div → no dividend
  • 登记日 (Record date) = often same day as ex-div
  • Notification should say "明天除权,今天是最后买入日"

Current Price Fetching in dividend_alert.py

The dividend_alert.py script enriches each alert card with real-time prices via LongPort SDK. Unlike the old approach (AKShare for A, Sina for HK, LongPort for US), the current unified approach uses LongPort for ALL three markets in a single batch:

Market Symbol Mapping LongPort Format
🇨🇳 A股 603733 → 603733.SH, 000858 → 000858.SZ .SH, .SZ, .BJ
🇭🇰 港股 01088 → 01088.HK, 5 → 00005.HK .HK (5-digit padded)
🇺🇸 美股 AAPL → AAPL.US .US suffix

Batch all symbols in one LongPort call:

# One ctx.quote() call for all three markets
all_syms = a_syms + hk_syms + us_syms
for i in range(0, len(all_syms), 15):
    for q in ctx.quote(all_syms[i:i+15]):
        prices[q.symbol] = float(q.last_done)

⚠️ LongPort connection can be intermittent — the SDK prints a permission table on first init and may timeout on high-load days. If LongPort fails, prices show as N/A but dividend data still outputs. The script retries on each run (cron runs daily), so a single failure self-recovers.

Dividend yield formula: Yield = (dividend_per_10shares / 10) / current_price * 100. The Baidu API returns dividend in 元/10股 format, so divide by 10 before calculating yield.

Script Reference

See scripts/dividend_alert.py for the production alerting script. See references/dividend-yield-arbitrage.md for yield vs financing cost analysis. See references/fill-gap-timing.md for historical 填权 timing data and dividend capture analysis.

Pitfalls

  1. Proxy environment variables — always unset proxy vars before calling AKShare or Nasdaq API
  2. Baidu dividend data is per-10-shares for A/HK. Don't multiply by 10 again when displaying.
  3. Nasdaq API rate limits — fine for 1 query/day in a cron job, but don't query multiple times rapidly
  4. Weekend/holiday handlingnext_trading_day() only skips Sat/Sun. For CN/HK holidays, you'd need a full trading calendar.
  5. No backward-looking price fetching for yield — current market price is available from stock_zh_a_hist() (1-2s per stock), but fetching for all alert stocks is slow (~15s for 8-10 stocks). Tradeoff: speed vs completeness.
  6. Timezone confusion — Server is usually EDT (UTC-4). Beijing is UTC+8. Cron schedule must account for this: 20:30 EDT = 08:30 BJT next day.
  7. stock_zh_a_spot_em() downloads the full A-share market (~5000 stocks) — Takes ~3-5s for a single call. This is fine for one-shot batch price lookups (as done in dividend_alert.py) but avoid calling it repeatedly in loops. For single-stock lookups, prefer stock_zh_a_hist(code, period='daily', start_date=today, end_date=today, adjust='qfq') instead (1-2s each).
  8. AKShare Baidu dividend API is intermittentak.news_trade_notify_dividend_baidu() may return 0 results on some runs despite having data on others. This is a server-side issue, not rate limiting. Mitigation: Added time.sleep(0.5) before the call to avoid cache issues. The cron job reruns daily, so a single failure self-recovers.
  9. Yield formula: divide-by-10 trap — The Baidu API returns dividend in 元/10股 format. When calculating dividend yield in percent, use (dividend_per_10shares / 10) / current_price * 100. A common bug is forgetting to divide by 10 (the "per 10 shares" unit). Verified correct formula: d/10/p*100 where d is the Baidu dividend value and p is the stock price.
  10. Variable name collisions in patch replacements — When patching Python code that uses short variable names (p, d, c, n), find-and-replace patterns can accidentally match unrelated code. Always use 3+ lines of surrounding context for unique matching.