Files
MoFin/deploy/profile-scripts/hk_fundamentals_collector.py

97 lines
4.0 KiB
Python
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
# -*- coding: utf-8 -*-
"""hk_fundamentals_collector.py — 港股通基本面采集(PE/PB/市值,阶段2数据补采)
数据源:腾讯批量行情 hk 前缀(qt.gtimg.cn/q=hk00700,...)。
复用 fundamentals_full_refresh 的解析模式,港股字段位置:
pe=parts[39] pb=parts[43]A股是46,港股是43 总市值=parts[44] 流通市值=parts[45](亿)
写入:stock_fundamentals 表(与A股同表复用,code=5位港股代码,eps=price/pe)。
调度:每日盘后(随A股基本面刷新节奏)。
限速:批量100只/批,批间0.5s。
"""
import sqlite3
import sys
import time
import urllib.request
# ── 消息通道统一路由(broadcast/xmpp by delivery) ──
try:
from messenger import install_stdio_hook as _msh
_msh()
except Exception:
pass
DB_PATH = "/home/hmo/MoFin/data/mofin.db"
UA = "Mozilla/5.0"
BATCH = 100
def fetch_hk_batch(codes):
"""腾讯批量行情(hk前缀,每批100只),返回 {code: {pe,pb,price,mcap_total,mcap_flow}}"""
if not codes:
return {}
results = {}
symbols = [f"hk{c}" for c in codes]
url = f"http://qt.gtimg.cn/q={','.join(symbols)}"
try:
req = urllib.request.Request(url, headers={"User-Agent": UA})
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
with opener.open(req, timeout=15) as r:
text = r.read().decode("gbk", errors="ignore")
for line in text.strip().split("\n"):
if "~" not in line:
continue
parts = line.split("~")
if len(parts) < 46:
continue
code = parts[2] # 港股代码(00700
price = float(parts[3]) if parts[3] else 0
pe = float(parts[39]) if parts[39] else 0
pb = float(parts[43]) if parts[43] else 0 # 港股 PB 在 43A股在46
mcap_t = float(parts[44]) if parts[44] else 0 # 总市值(亿HKD
mcap_f = float(parts[45]) if parts[45] else 0 # 流通市值(亿HKD
if price > 0 and code:
results[code] = {"price": price, "pe": pe, "pb": pb,
"mcap_total": mcap_t, "mcap_flow": mcap_f}
except Exception as e:
print(f" batch fetch error: {str(e)[:60]}", flush=True)
return results
def main():
conn = sqlite3.connect(DB_PATH, timeout=30)
conn.execute("PRAGMA busy_timeout=30000")
codes = [r[0] for r in conn.execute(
"SELECT code FROM hk_connect_stocks WHERE is_active=1 ORDER BY code").fetchall()]
print(f"港股通基本面采集:{len(codes)} 只(腾讯行情 PE/PB/市值)", flush=True)
ok = 0
t0 = time.time()
for i in range(0, len(codes), BATCH):
batch = codes[i:i + BATCH]
data = fetch_hk_batch(batch)
for code, d in data.items():
eps = round(d["price"] / d["pe"], 2) if d["pe"] > 0 else 0
conn.execute(
"INSERT OR REPLACE INTO stock_fundamentals (code, pe, pb, eps, mcap_total, mcap_flow, updated_at) "
"VALUES (?,?,?,?,?,?,datetime('now','localtime'))",
(code, d["pe"], d["pb"], eps, d["mcap_total"], d["mcap_flow"]))
ok += 1
conn.commit()
print(f" [{i+len(batch)}/{len(codes)}] 本批{len(data)}只 | {time.time()-t0:.0f}s", flush=True)
time.sleep(0.5)
n = conn.execute("SELECT COUNT(*) FROM stock_fundamentals WHERE length(code)=5").fetchone()[0]
sample = conn.execute(
"SELECT code, pe, pb, mcap_total FROM stock_fundamentals WHERE code IN ('00700','09988','01810')").fetchall()
conn.close()
print(f"\n完成:{ok} 只入 stock_fundamentals(港股 {n} 条),耗时{time.time()-t0:.0f}s", flush=True)
print("样例(code/pe/pb/总市值亿HKD:", flush=True)
for r in sample:
print(f" {r[0]}: pe={r[1]} pb={r[2]} mcap={r[3]:.0f}亿", flush=True)
return 0
if __name__ == "__main__":
sys.exit(main())