#!/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))