feat: eliminate duplicate price fetches — stale_push_wlin + per_stock_reassess now read from DB instead of self-pulling Tencent API
This commit is contained in:
@@ -41,41 +41,35 @@ def main():
|
|||||||
# Always fetch live price for accurate reassessment
|
# Always fetch live price for accurate reassessment
|
||||||
price = 0
|
price = 0
|
||||||
try:
|
try:
|
||||||
import urllib.request
|
# 价格从 DB 读取(price_monitor 每2分钟更新,唯一价格入口)
|
||||||
code_raw = entry.get("code", "")
|
code_raw = entry.get("code", "")
|
||||||
# 港股5位代码(含0开头)→ 前缀hk
|
price = 0
|
||||||
if len(code_raw) == 5 and code_raw[0] in '01':
|
import sqlite3
|
||||||
prefix = "hk"
|
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||||
|
db.row_factory = sqlite3.Row
|
||||||
|
row = db.execute("SELECT price FROM holdings WHERE code=? AND is_active=1", (code_raw,)).fetchone()
|
||||||
|
if not row:
|
||||||
|
row = db.execute("SELECT price FROM watchlist_stocks WHERE code=? AND is_active=1", (code_raw,)).fetchone()
|
||||||
|
if not row:
|
||||||
|
row = db.execute("SELECT price FROM holding_strategies WHERE code=? AND status='active' ORDER BY updated_at DESC LIMIT 1", (code_raw,)).fetchone()
|
||||||
|
if row:
|
||||||
|
price = row['price'] or 0
|
||||||
|
db.close()
|
||||||
|
if price > 0:
|
||||||
|
print(f" 实时价: {price} (来自DB)")
|
||||||
else:
|
else:
|
||||||
sym_map = {"6":"sh","5":"sh","0":"sz","3":"sz"}
|
# fallback to portfolio.json
|
||||||
for k, v in sym_map.items():
|
|
||||||
if code_raw.startswith(k):
|
|
||||||
prefix = v
|
|
||||||
break
|
|
||||||
if not prefix:
|
|
||||||
prefix = "sz"
|
|
||||||
url = f"http://qt.gtimg.cn/q={prefix}{code_raw}"
|
|
||||||
resp = urllib.request.urlopen(url, timeout=5)
|
|
||||||
text = resp.read().decode("gbk")
|
|
||||||
fields = text.split('"')[1].split("~")
|
|
||||||
price = float(fields[3]) if fields[3] else 0
|
|
||||||
print(f" 实时价: {price} {'(港股HKD)' if len(code_raw) == 5 and code_raw[0] in '01' else ''}")
|
|
||||||
except Exception as e:
|
|
||||||
print(f" 实时价获取失败: {e}", file=sys.stderr)
|
|
||||||
# Try portfolio.json as fallback (price_monitor keeps live prices)
|
|
||||||
try:
|
|
||||||
with open("/home/hmo/web-dashboard/data/portfolio.json") as _pf:
|
with open("/home/hmo/web-dashboard/data/portfolio.json") as _pf:
|
||||||
_pf_data = json.load(_pf)
|
_pf_data = json.load(_pf)
|
||||||
for _h in _pf_data.get("holdings", []):
|
for _h in _pf_data.get("holdings", []):
|
||||||
if _h["code"] == code_raw:
|
if _h["code"] == code_raw:
|
||||||
price = float(_h.get("price", 0))
|
price = float(_h.get("price", 0))
|
||||||
print(f" 从portfolio.json取实时价: {price}")
|
|
||||||
break
|
break
|
||||||
except Exception:
|
if price <= 0:
|
||||||
pass
|
|
||||||
if price == 0:
|
|
||||||
price = entry.get("current_price") or entry.get("price") or 0
|
price = entry.get("current_price") or entry.get("price") or 0
|
||||||
print(f" fallback到存储价: {price}", file=sys.stderr)
|
except Exception as e:
|
||||||
|
print(f" 价格获取失败: {e}", file=sys.stderr)
|
||||||
|
price = entry.get("current_price") or entry.get("price") or 0
|
||||||
|
|
||||||
# Price diff debounce: skip reassessment if price changed < 1% since last update
|
# Price diff debounce: skip reassessment if price changed < 1% since last update
|
||||||
last_price = entry.get("last_reassessed_price", 0)
|
last_price = entry.get("last_reassessed_price", 0)
|
||||||
|
|||||||
@@ -74,18 +74,30 @@ from stock_scorer import score_future_outlook, is_hk_stock, settlement_delay_not
|
|||||||
|
|
||||||
# ── 趋势检查 ────────────────────────────────────────────────────
|
# ── 趋势检查 ────────────────────────────────────────────────────
|
||||||
def fetch_trend_data(code):
|
def fetch_trend_data(code):
|
||||||
"""取均线数据判断趋势状态。返回 (current_price, ma5, trend_label) 或 None"""
|
"""取均线数据判断趋势状态。价格从 DB 读取(price_monitor 唯一入口)。返回 (current_price, ma5, trend_label) 或 None"""
|
||||||
|
# 价格从 DB 读取,不再自拉腾讯 API
|
||||||
|
current = 0
|
||||||
try:
|
try:
|
||||||
prefix = "sh" if code.startswith(('60','68','51','56','50')) else "sz" if code.startswith(('00','30','15')) else "hk"
|
import sqlite3
|
||||||
url = f"http://qt.gtimg.cn/q={prefix}{code}"
|
db = sqlite3.connect('/home/hmo/web-dashboard/data/mofin.db')
|
||||||
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
db.row_factory = sqlite3.Row
|
||||||
resp = urlopen(req, timeout=5).read().decode('gbk')
|
row = db.execute("SELECT price FROM holdings WHERE code=? AND is_active=1", (code,)).fetchone()
|
||||||
fld = resp.split('=')[1].strip().strip('"').strip(';').split('~')
|
if not row:
|
||||||
current = float(fld[3]) if len(fld) > 3 else 0
|
row = db.execute("SELECT price FROM watchlist_stocks WHERE code=? AND is_active=1", (code,)).fetchone()
|
||||||
except:
|
if not row:
|
||||||
|
row = db.execute("SELECT price FROM holding_strategies WHERE code=? AND status='active' ORDER BY updated_at DESC LIMIT 1", (code,)).fetchone()
|
||||||
|
if row:
|
||||||
|
current = row['price'] or 0
|
||||||
|
db.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if current <= 0:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# K线数据仍从腾讯取(均线计算需要历史K线,DB 里 stock_daily 表有但不一定有最新数据)
|
||||||
try:
|
try:
|
||||||
|
prefix = "sh" if code.startswith(('60','68','51','56','50')) else "sz" if code.startswith(('00','30','15')) else "hk"
|
||||||
url = f"http://ifzq.gtimg.cn/appstock/app/fqkline/get?param={prefix}{code},day,,,30,qfq"
|
url = f"http://ifzq.gtimg.cn/appstock/app/fqkline/get?param={prefix}{code},day,,,30,qfq"
|
||||||
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
||||||
resp = urlopen(req, timeout=5).read().decode('utf-8')
|
resp = urlopen(req, timeout=5).read().decode('utf-8')
|
||||||
|
|||||||
Reference in New Issue
Block a user