feat: strategy_lifecycle + stale_detector + server — DB-first price reads, Tencent API as fallback only
This commit is contained in:
@@ -889,31 +889,49 @@ def upload_confirm():
|
||||
try:
|
||||
codes = [s["code"] for s in stocks if s.get("code")]
|
||||
if codes:
|
||||
qs = " ".join(
|
||||
f"hk{c}" if len(c) == 5 # 港股5位代码
|
||||
else f"sz{c}" if c.startswith("0") or c.startswith("3")
|
||||
else f"sh{c}" if c.startswith("6")
|
||||
else f"hk{c}"
|
||||
for c in codes
|
||||
)
|
||||
url = f"https://qt.gtimg.cn/q={qs}"
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
||||
resp = urllib.request.urlopen(req, timeout=10)
|
||||
qt_text = resp.read().decode("gbk", errors="replace")
|
||||
# map realtime prices
|
||||
# DB 优先(price_monitor 维护的实时价)
|
||||
db_prices = {}
|
||||
try:
|
||||
import sqlite3
|
||||
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||
db.row_factory = sqlite3.Row
|
||||
for code in codes:
|
||||
row = db.execute("SELECT price, change_pct FROM holdings WHERE code=? AND is_active=1", (code,)).fetchone()
|
||||
if row and row['price']:
|
||||
db_prices[code] = (row['price'], row['change_pct'] or 0)
|
||||
db.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Fallback: 腾讯 API
|
||||
need_tencent = [c for c in codes if c not in db_prices]
|
||||
if need_tencent:
|
||||
qs = " ".join(
|
||||
f"hk{c}" if len(c) == 5
|
||||
else f"sz{c}" if c.startswith("0") or c.startswith("3")
|
||||
else f"sh{c}" if c.startswith("6")
|
||||
else f"hk{c}"
|
||||
for c in need_tencent
|
||||
)
|
||||
url = f"https://qt.gtimg.cn/q={qs}"
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
||||
resp = urllib.request.urlopen(req, timeout=10)
|
||||
qt_text = resp.read().decode("gbk", errors="replace")
|
||||
# 优先 DB 价格,再补腾讯
|
||||
for stock in stocks:
|
||||
code = stock.get("code", "")
|
||||
prefix = "hk" if len(code) == 5 else "sz" if code.startswith(("0","3")) else "sh" if code.startswith("6") else "hk"
|
||||
# 腾讯 API 格式: prefix+code="市场~名称~代码~当前价~昨收~今开~成交量~..."
|
||||
m = re.search(rf'{prefix}{code}="([^"]+)"', qt_text)
|
||||
if m:
|
||||
fields = m.group(1).split('~')
|
||||
name = fields[1]
|
||||
price = fields[3] # 当前价
|
||||
if code in db_prices:
|
||||
if not stock.get("price"):
|
||||
stock["price"] = price
|
||||
if not stock.get("name"):
|
||||
stock["name"] = name
|
||||
stock["price"] = db_prices[code][0]
|
||||
elif need_tencent and code in need_tencent:
|
||||
prefix = "hk" if len(code) == 5 else "sz" if code.startswith(("0","3")) else "sh" if code.startswith("6") else "hk"
|
||||
m = re.search(rf'{prefix}{code}="([^"]+)"', qt_text)
|
||||
if m:
|
||||
fields = m.group(1).split('~')
|
||||
if not stock.get("name"):
|
||||
stock["name"] = fields[1]
|
||||
if not stock.get("price"):
|
||||
stock["price"] = fields[3]
|
||||
except:
|
||||
pass # 行情获取失败不影响主流程
|
||||
|
||||
|
||||
Reference in New Issue
Block a user