Files
mike 913d1945d4 feat: 迁移 trading 相关脚本到 skill 仓库 (第2批: 🟡 中优先级)
【迁移内容】
- dividend-investing/scripts/dca_monitor.py + dca_monitor_us.sh
- dividend-scanner/scripts/scan_cn.{py,sh} + scan_hk.sh + scan_us.sh
- okx-auto-position/scripts/signal_queue_retry.sh
- lottery-hk/scripts/verify_lottery.sh
- longbridge-cli/scripts/longport_http.py (公共模块)

【配套修改】
- 5 个 cron 任务 script 路径更新 (jobs.json):
  - 8929ca09 (DCA港股上午) → dividend-investing/scripts/dca_monitor.py
  - 9469c128 (DCA港股下午) → dividend-investing/scripts/dca_monitor.py
  - 3a4bef2c (DCA美股凌晨) → dividend-investing/scripts/dca_monitor_us.sh
  - a82a3ab0 (signal-queue-retry) → okx-auto-position/scripts/
  - b4868849 (lottery-verify-result) → lottery-hk/scripts/

【删除】本地 ~/.hermes/scripts/{dca_monitor,scan_*,signal_queue_retry,verify_lottery,longport_http}
【未迁移】scan_cn/hk/us 仍需挂 cron, 暂不删 (走 scanner skill)
2026-07-24 11:42:13 +08:00

128 lines
5.7 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
A股高股息扫描器(LongPort取价 + 预设股息率)
"""
import os, sys, json
from datetime import datetime
# === 读取LongPort环境变量 ===
bashrc = open(os.path.expanduser("~/.bashrc")).read()
for line in bashrc.splitlines():
if line.startswith("export LONGPORT_") or line.startswith("export LONGBRIDGE_"):
parts = line.replace("export ", "").split("=", 1)
if len(parts) == 2:
os.environ[parts[0]] = parts[1].strip('"').strip("'")
from longport import openapi
cfg = openapi.Config.from_env()
ctx = openapi.QuoteContext(config=cfg)
# === A股候选池 ===
A_SHARE_POOL = {
"601088.SH": {"name": "中国神华", "yield": 6.7, "freq": "年+中期", "sector": "煤炭"},
"601328.SH": {"name": "交通银行", "yield": 6.2, "freq": "年度", "sector": "银行"},
"601398.SH": {"name": "工商银行", "yield": 5.9, "freq": "年度", "sector": "银行"},
"601288.SH": {"name": "农业银行", "yield": 5.8, "freq": "年度", "sector": "银行"},
"601939.SH": {"name": "建设银行", "yield": 6.0, "freq": "年度", "sector": "银行"},
"601988.SH": {"name": "中国银行", "yield": 5.7, "freq": "年度", "sector": "银行"},
"600900.SH": {"name": "长江电力", "yield": 3.8, "freq": "年度", "sector": "电力"},
"601857.SH": {"name": "中国石油", "yield": 5.5, "freq": "年度", "sector": "能源"},
"600028.SH": {"name": "中国石化", "yield": 5.2, "freq": "年度", "sector": "能源"},
"601728.SH": {"name": "中国电信", "yield": 4.8, "freq": "年度", "sector": "电信"},
"600036.SH": {"name": "招商银行", "yield": 4.5, "freq": "年度", "sector": "银行"},
"601166.SH": {"name": "兴业银行", "yield": 5.8, "freq": "年度", "sector": "银行"},
"601818.SH": {"name": "光大银行", "yield": 5.9, "freq": "年度", "sector": "银行"},
"600377.SH": {"name": "宁沪高速", "yield": 6.2, "freq": "年度", "sector": "高速"},
"601666.SH": {"name": "平煤股份", "yield": 6.2, "freq": "年度", "sector": "煤炭"},
"600023.SH": {"name": "浙能电力", "yield": 5.5, "freq": "年度", "sector": "电力"},
"000858.SZ": {"name": "五粮液", "yield": 10.5, "freq": "年度", "sector": "白酒"},
"000568.SZ": {"name": "泸州老窖", "yield": 7.0, "freq": "年度", "sector": "白酒"},
"000937.SZ": {"name": "冀中能源", "yield": 11.0, "freq": "年度", "sector": "煤炭"},
"002304.SZ": {"name": "洋河股份", "yield": 10.8, "freq": "年度", "sector": "白酒"},
"000596.SZ": {"name": "古井贡酒", "yield": 6.9, "freq": "年度", "sector": "白酒"},
"000001.SZ": {"name": "平安银行", "yield": 5.4, "freq": "年度", "sector": "银行"},
"600519.SH": {"name": "贵州茅台", "yield": 5.0, "freq": "年+中期", "sector": "白酒"},
}
def scan_a_share():
min_yield = 5.0
tickers = list(A_SHARE_POOL.keys())
all_quotes = {}
# LongPort批量获取A股价格
for i in range(0, len(tickers), 15):
batch = tickers[i:i+15]
try:
quotes = ctx.quote(batch)
for q in quotes:
all_quotes[q.symbol] = {
"price": float(q.last_done),
"prev_close": float(q.prev_close),
}
except Exception as e:
pass
results = []
for sym, info in A_SHARE_POOL.items():
if info["yield"] < min_yield:
continue
q = all_quotes.get(sym)
if q and q["price"] > 0:
change_pct = (q["price"] - q["prev_close"]) / q["prev_close"] * 100 if q["prev_close"] else 0
price = q["price"]
else:
# LongPort没拿到价格,用预设
price = 0
change_pct = 0
results.append({
"symbol": sym, "name": info["name"],
"price": price, "change_pct": change_pct,
"yield": info["yield"], "freq": info["freq"],
"flag": "🇨🇳", "sector": info["sector"],
})
results.sort(key=lambda x: x["yield"], reverse=True)
return results[:10]
def calc_ladder(price):
return [
{"tier": 1, "pct": -3, "price": round(price * 0.97, 2)},
{"tier": 2, "pct": -6, "price": round(price * 0.94, 2)},
{"tier": 3, "pct": -10, "price": round(price * 0.90, 2)},
]
def format_result(results):
now = datetime.now().strftime("%Y-%m-%d %H:%M")
if not results:
return f"🇨🇳 A股高息扫描 | {now}\n\n暂无符合条件的标的(≥5%"
lines = [f"🇨🇳 A股高息TOP | {now}", ""]
for i, r in enumerate(results, 1):
medal = ["🥇", "🥈", "🥉", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"][min(i-1, 9)]
lines.append(f"{medal} {r['name']} [{r['sector']}]")
lines.append(f" {r['symbol']}")
if r["price"] > 0:
chg = "📈" if r["change_pct"] >= 0 else "📉"
lines.append(f" 💰 现价: {r['price']:.2f} {chg} {r['change_pct']:+.1f}%")
else:
lines.append(f" 💰 价格: 盘后/未获取")
lines.append(f" 📊 股息率: {r['yield']:.1f}% 派息: {r['freq']}")
if r["price"] > 0:
ladder = calc_ladder(r["price"])
lstr = " → ".join([f"T{l['tier']}:{l['price']:.2f}({l['pct']}%)" for l in ladder])
lines.append(f" 🪜 阶梯: {lstr}")
lines.append("")
lines.append("━━━━━━━━━━━━━")
lines.append(f"📋 共扫描 {len(A_SHARE_POOL)} 只,筛出 {len(results)} 只")
return "\n".join(lines)
if __name__ == "__main__":
results = scan_a_share()
print(format_result(results))