Skill: gykdly/dividend-premium-tracker (version 1.0.1)

--- name: dividend-premium-tracker description: Track the dividend premium (dividend yield minus 10-year bond yield) for CSI Dividend Low Volatility Index. Monitor dividend yield, 10-year bond yield, and calculate the premium for investment decisions. version: 1.0.1 --- # Dividend Premium Tracker Track the dividend premium (dividend yield minus 10-year bond yield) for CSI Dividend Low Volatility Index. ## Description This skill tracks the dividend premium for the CSI Dividend Low Volatility Index (H30269), which is crucial for investment decisions in China's dividend-focused market. The dividend premium represents the excess return of dividend-paying stocks over risk-free bonds. ## What It Tracks - **CSI Dividend Low Volatility Index Dividend Yield** - From China Securities Index - **10-Year China Government Bond Yield** - From Ministry of Finance - **Dividend Premium** = Dividend Yield - Bond Yield ## Features - 📊 Auto-download and track dividend and bond yield data - 📈 Generate Excel reports with clean charts - 🔔 Alert when bond yield rises for 3 consecutive days - 🔔 Alert when premium drops below 1% - 📅 Support for historical data backfill ## Commands ### Update Today's Data ```bash python3 scripts/update_dividend_premium.py --update ``` ### Check Monitoring Alerts ```bash python3 scripts/monitor_dividend_premium.py --check ``` ### Backfill Historical Data ```bash python3 scripts/update_dividend_premium.py --backfill 2026-01-01 2026-01-31 ``` ## Files ``` dividend-premium-tracker/ ├── SKILL.md # This file ├── scripts/ │ ├── update_dividend_premium.py # Main update script │ └── monitor_dividend_premium.py # Monitoring script ├── references/ # Documentation (optional) └── assets/ # Output files (optional) ``` ## Setup ### Telegram Alerts (Optional) Set Telegram Bot Token for alerts: ```bash export TELEGRAM_BOT_TOKEN="your_bot_token_here" ``` ### Cron Job (Daily Update) ```bash crontab -e # Add line: 0 17 * * * cd /path/to/skill && python3 scripts/update_dividend_premium.py --update ``` ## Data Sources | Data | Source | URL | |------|--------|-----| | Dividend Yield | China Securities Index | [H30269 Indicator XLS](https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofile/indicator/H30269indicator.xls) | | Bond Yield | Ministry of Finance | [ChinaBond](https://yield.chinabond.com.cn/cbweb-czb-web/czb/moreInfo?locale=cn_ZH&nameType=1) | ## Alert Thresholds | Condition | Action | |-----------|--------| | Bond yield rises 3 consecutive days | Telegram alert | | Premium < 1% | Telegram alert | ## Requirements - Python 3.10+ - pandas - openpyxl - xlrd - curl (for data download) ## Usage Notes - Premium is calculated as: `Dividend Yield (%) - Bond Yield (%)` - Premium < 1% suggests potential buying opportunity - Premium < 0 indicates dividend stocks are cheaper than bonds - Historical data from 2026-01-14 to present included --- **Related Indices:** - CSI Dividend Low Volatility Index (H30269/000966) - 10-Year China Government Bond

path: _meta.json
content: version: 1.0.1

path: scripts/monitor_dividend_premium.py
content: #!/usr/bin/env python3
"""
股息率溢价监控脚本
功能：
1. 检查国债收益率是否连续3天上涨
2. 检查股息率溢价是否低于3%
3. 满足条件时发送Telegram通知
"""

import xlrd
import csv
import subprocess
import re
import os
from datetime import datetime, timedelta
from pathlib import Path

# 配置
DATA_DIR = "/Users/liyi/.openclaw/workspace"
CSV_FILE = os.path.join(DATA_DIR, "股息率溢价跟踪.csv")
EXCEL_FILE = os.path.join(DATA_DIR, "股息率溢价跟踪.xlsx")
TELEGRAM_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = "505395883"

def send_telegram(message):
    """发送Telegram消息"""
    if not TELEGRAM_TOKEN:
        print("未配置Telegram Bot Token")
        return False
    
    cmd = f"""curl -s -X POST https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage \
      -d chat_id={TELEGRAM_CHAT_ID} \
      -d text="{message}" \
      -d parse_mode=HTML"""
    
    os.system(cmd)
    return True

def download_dividend_rate(date_str):
    """下载股息率"""
    url = "https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofile/indicator/H30269indicator.xls"
    local_file = "/tmp/H30269indicator.xls"
    
    os.system(f"curl -s -o {local_file} '{url}'")
    
    try:
        book = xlrd.open_workbook(local_file)
        sheet = book.sheet_by_index(0)
        for row in range(1, sheet.nrows):
            if str(sheet.cell_value(row, 0)) == date_str:
                return sheet.cell_value(row, 8)
    except:
        pass
    return None

def download_bond_yield():
    """下载国债收益率数据（最近7天）"""
    result = subprocess.run(
        ['curl', '-s', 'https://yield.chinabond.com.cn/cbweb-czb-web/czb/moreInfo?locale=cn_ZH&nameType=1'],
        capture_output=True, text=True
    )
    
    data = {}
    for row in range(1, 8):  # 最近7天
        date = (datetime.now() - timedelta(days=row)).strftime('%Y-%m-%d')
        pattern = rf'{date}.*?10年.*?(\d+\.\d{{2}})'
        match = re.search(pattern, result.stdout, re.DOTALL)
        if match:
            data[date] = float(match.group(1))
    
    return data

def check_bond_yield_rising(data):
    """检查国债收益率是否连续3天上涨"""
    if len(data) < 3:
        return False, None
    
    sorted_dates = sorted(data.keys(), reverse=True)
    
    # 检查最近3天
    d1, d2, d3 = sorted_dates[0], sorted_dates[1], sorted_dates[2]
    
    if data[d1] > data[d2] > data[d3]:
        return True, f"⚠️ 国债收益率连续3天上涨！\n{d3}: {data[d3]}%\n{d2}: {data[d2]}%\n{d1}: {data[d1]}%"
    
    return False, None

def check_premium_low(data):
    """检查股息率溢价是否低于1%"""
    sorted_dates = sorted(data.keys(), reverse=True)
    latest = sorted_dates[0]
    
    if data[latest] < 1.0:
        return True, f"⚠️ 股息率溢价低于1%！\n{latest}: {data[latest]}%\n可能出现布局机会，请密切关注！"
    
    return False, None

def load_existing_data():
    """加载现有数据"""
    data = {}
    if os.path.exists(CSV_FILE):
        with open(CSV_FILE, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            for row in reader:
                date = row['日期']
                data[date] = {
                    '股息率': float(row['股息率1']),
                    '国债': float(row['10年国债收益率']),
                    '溢价': float(row['股息率溢价'])
                }
    return data

def run_check():
    """运行监控检查"""
    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 股息率溢价监控检查")
    
    # 加载现有数据
    data = load_existing_data()
    
    if len(data) < 3:
        print("  数据不足3天，跳过检查")
        return
    
    # 检查国债收益率连续上涨
    bond_data = {k: v['国债'] for k, v in data.items()}
    rising, msg = check_bond_yield_rising(bond_data)
    if rising:
        print(f"  🚨 {msg}")
        send_telegram(msg)
    
    # 检查溢价低于3%
    premium_data = {k: v['溢价'] for k, v in data.items()}
    low, msg = check_premium_low(premium_data)
    if low:
        print(f"  💡 {msg}")
        send_telegram(msg)
    
    if not rising and not low:
        print(f"  ✅ 无异常")
    
    print(f"  完成!")

def update_today():
    """更新今天的数据"""
    today = datetime.now().strftime('%Y%m%d')
    formatted = datetime.now().strftime('%Y-%m-%d')
    
    # 下载股息率
    div_rate = download_dividend_rate(today)
    
    # 下载国债收益率
    bond_yields = download_bond_yield()
    bond_yield = bond_yields.get(formatted)
    
    if div_rate and bond_yield:
        premium = div_rate - bond_yield
        
        # 更新数据
        data = load_existing_data()
        data[formatted] = {
            '股息率': div_rate,
            '国债': bond_yield,
            '溢价': round(premium, 2)
        }
        
        # 保存CSV
        with open(CSV_FILE, 'w', encoding='utf-8') as f:
            writer = csv.DictWriter(f, fieldnames=['日期', '股息率1', '10年国债收益率', '股息率溢价'])
            writer.writeheader()
            for date in sorted(data.keys()):
                writer.writerow({
                    '日期': date,
                    '股息率1': data[date]['股息率'],
                    '10年国债收益率': data[date]['国债'],
                    '股息率溢价': data[date]['溢价']
                })
        
        print(f"已更新: {formatted} - 股息率={div_rate}%, 国债={bond_yield}%, 溢价={premium:.2f}%")
        
        # 运行检查
        run_check()
    else:
        print(f"获取数据失败: 股息率={div_rate}, 国债={bond_yield}")

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1:
        if sys.argv[1] == "--check":
            run_check()
        elif sys.argv[1] == "--update":
            update_today()
    else:
        update_today()


path: scripts/update_dividend_premium.py
content: #!/usr/bin/env python3
"""
股息率溢价跟踪 - 自动化更新脚本
数据来源：
- 股息率：中证指数官网 H30269 指数估值
- 10年期国债收益率：财政部官网
"""

import xlrd
import csv
import os
import sys
import subprocess
import re
from datetime import datetime

# 配置
DATA_DIR = "/Users/liyi/.openclaw/workspace"
CSV_FILE = os.path.join(DATA_DIR, "股息率溢价跟踪.csv")
EXCEL_FILE = os.path.join(DATA_DIR, "股息率溢价跟踪.xlsx")

def download_dividend_rate(date_str):
    """从中证指数官网下载股息率数据"""
    url = "https://oss-ch.csindex.com.cn/static/html/csindex/public/uploads/file/autofile/indicator/H30269indicator.xls"
    local_file = "/tmp/H30269indicator.xls"
    
    os.system(f"curl -s -o {local_file} '{url}'")
    
    try:
        book = xlrd.open_workbook(local_file)
        sheet = book.sheet_by_index(0)
        
        for row in range(1, sheet.nrows):
            row_date = str(sheet.cell_value(row, 0))
            if row_date == date_str:
                return sheet.cell_value(row, 8)  # 股息率1
    except Exception as e:
        print(f"下载股息率失败: {e}")
    
    return None

def get_bond_yield(date_str):
    """从财政部官网获取10年期国债收益率"""
    result = subprocess.run(
        ['curl', '-s', 'https://yield.chinabond.com.cn/cbweb-czb-web/czb/moreInfo?locale=cn_ZH&nameType=1'],
        capture_output=True, text=True
    )
    
    text = result.stdout
    
    # 查找对应日期的10年数据
    # 格式: 日期 ... 10年 ... 收益率
    pattern = rf'{date_str}.*?10年.*?(\d+\.\d{{2}})'
    match = re.search(pattern, text, re.DOTALL)
    
    if match:
        return float(match.group(1))
    
    return None

def load_existing_data():
    """加载现有数据"""
    data = []
    if os.path.exists(CSV_FILE):
        with open(CSV_FILE, 'r', encoding='utf-8') as f:
            reader = csv.DictReader(f)
            for row in reader:
                data.append(row)
    return data

def save_data(data):
    """保存数据"""
    if not data:
        return
    
    keys = ['日期', '股息率1', '10年国债收益率', '股息率溢价']
    with open(CSV_FILE, 'w', encoding='utf-8') as f:
        writer = csv.DictWriter(f, fieldnames=keys)
        writer.writeheader()
        writer.writerows(data)

def generate_excel():
    """生成带图表的Excel"""
    import pandas as pd
    from openpyxl import Workbook
    from openpyxl.chart import LineChart, Reference
    from openpyxl.utils.dataframe import dataframe_to_rows
    
    df = pd.read_csv(CSV_FILE)
    
    wb = Workbook()
    ws = wb.active
    ws.title = "数据"
    
    for r_idx, row in enumerate(dataframe_to_rows(df, index=False, header=True), 1):
        for c_idx, value in enumerate(row, 1):
            if isinstance(value, float):
                ws.cell(row=r_idx, column=c_idx, value=value)
            else:
                ws.cell(row=r_idx, column=c_idx, value=str(value))
    
    # 图表
    chart = LineChart()
    chart.title = "股息率溢价走势"
    chart.style = 10
    chart.x_axis.title = "日期"
    chart.y_axis.title = "溢价 (%)"
    chart.width = 18
    chart.height = 10
    
    data_ref = Reference(ws, min_col=4, min_row=1, max_row=len(df)+1, max_col=4)
    cats = Reference(ws, min_col=1, min_row=2, max_row=len(df)+1)
    
    chart.add_data(data_ref, titles_from_data=True)
    chart.set_categories(cats)
    chart.y_axis.scaling.min = 200
    chart.y_axis.scaling.max = 400
    
    ws.add_chart(chart, "F2")
    wb.save(EXCEL_FILE)

def update_today():
    """更新今天的数据"""
    today = datetime.now().strftime('%Y%m%d')
    formatted_today = f"{today[:4]}-{today[4:6]}-{today[6:8]}"
    
    print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 更新 {formatted_today}...")
    
    # 获取股息率
    div_rate = download_dividend_rate(today)
    if div_rate is None:
        print("  股息率: 获取失败")
        return
    print(f"  股息率: {div_rate}%")
    
    # 获取国债收益率
    bond_yield = get_bond_yield(formatted_today)
    if bond_yield is None:
        print("  国债收益率: 获取失败")
        return
    print(f"  国债收益率: {bond_yield}%")
    
    # 计算溢价
    premium = div_rate * 100 - bond_yield
    print(f"  股息率溢价: {premium:.2f}%")
    
    # 更新数据
    data = load_existing_data()
    
    # 检查是否已存在
    updated = False
    for row in data:
        if row['日期'] == formatted_today:
            row['股息率1'] = div_rate
            row['10年国债收益率'] = bond_yield
            row['股息率溢价'] = premium
            updated = True
            break
    
    if not updated:
        data.append({
            '日期': formatted_today,
            '股息率1': div_rate,
            '10年国债收益率': bond_yield,
            '股息率溢价': premium
        })
    
    # 按日期排序
    data.sort(key=lambda x: x['日期'])
    
    save_data(data)
    generate_excel()
    print(f"  ✅ 已保存!")

def backfill_history(start_date, end_date):
    """补录历史数据"""
    start = datetime.strptime(start_date, '%Y-%m-%d')
    end = datetime.strptime(end_date, '%Y-%m-%d')
    
    current = start
    while current <= end:
        date_str = current.strftime('%Y%m%d')
        formatted = current.strftime('%Y-%m-%d')
        
        div_rate = download_dividend_rate(date_str)
        bond_yield = get_bond_yield(formatted)
        
        if div_rate and bond_yield:
            premium = div_rate * 100 - bond_yield
            print(f"{formatted}: 股息率={div_rate}%, 国债={bond_yield}%, 溢价={premium}%")
        
        current += timedelta(days=1)

if __name__ == "__main__":
    if len(sys.argv) > 1:
        if sys.argv[1] == "--update":
            update_today()
        elif sys.argv[1] == "--backfill":
            # python update.py --backfill 2026-01-01 2026-01-31
            backfill_history(sys.argv[2], sys.argv[3])
    else:
        update_today()


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (MEDIUM)