feat: data-layering 消费层读live_prices替换直连qt.gtimg.cn(5脚本)

This commit is contained in:
xxm
2026-08-26 19:55:38 +08:00
parent ad5adbee4a
commit bd1ef0c9a4
5 changed files with 181 additions and 219 deletions
+88 -69
View File
@@ -14,7 +14,6 @@
import json
import os
import sys
import urllib.request
from datetime import datetime, date
# 确保本文件所在目录可导入(market_config 与之同目录;本模块会被 MoFin 根脚本跨目录 import
@@ -75,82 +74,102 @@ def get_quote(code):
except:
pass
# 腾讯API获取全量HLC数据
# 行情数据:读 DB(2026-08-26 分层铁律:消费层不直连腾讯API,改读 live_prices + stock_daily
raw = str(code).split("_")[0]
prefix = _market_prefix(code)
url = f"http://qt.gtimg.cn/q={prefix}{raw}"
_lp_row = None
_sd_rows = None
_nm_row = None
try:
r = urllib.request.urlopen(url, timeout=5)
fields = r.read().decode("gbk").split('"')[1].split("~")
except Exception as e:
if db_price:
return {"code": code, "price": db_price, "change_pct": db_chg or 0}
return {"code": code, "error": str(e)}
import sqlite3 as _sq
_db = _sq.connect('/home/hmo/MoFin/data/mofin.db', timeout=5)
_lp_row = _db.execute("SELECT price, change_pct FROM live_prices WHERE code=?", (raw,)).fetchone()
_sd_rows = _db.execute(
"SELECT date, open, close, high, low, volume, amount FROM stock_daily "
"WHERE code=? ORDER BY date DESC LIMIT 2", (raw,)
).fetchall()
_nm_row = _db.execute("SELECT name FROM stocks WHERE code=?", (raw,)).fetchone()
_db.close()
except Exception:
pass
def get(i):
try:
return float(fields[i]) if fields[i].strip() else None
except (IndexError, ValueError):
return None
_lp_price = _lp_row[0] if _lp_row and _lp_row[0] else None
_lp_chg = _lp_row[1] if _lp_row and _lp_row[1] is not None else 0.0
if _lp_price or db_price:
today_str = date.today().isoformat()
price_v = _lp_price or db_price
change_v = _lp_chg if _lp_price else (db_chg or 0)
close_yest_v = price_v / (1 + change_v / 100) if change_v else price_v
# stock_daily 最近一根日K(收盘级 HLC,缺实时盘中H高)
_sd = _sd_rows[0] if _sd_rows else None
_sd_open = _sd[1] if _sd else None
_sd_high = _sd[3] if _sd else None
_sd_low = _sd[4] if _sd else None
_sd_vol = _sd[5] if _sd else None
_sd_amt = _sd[6] if _sd else None
_name_v = _nm_row[0] if _nm_row and _nm_row[0] else code
q = {
"code": raw,
"market": prefix,
"name": _name_v,
"price": price_v,
"close_yest": close_yest_v,
"open": _sd_open if _sd_open else price_v,
"high": _sd_high if _sd_high else price_v,
"low": _sd_low if _sd_low else price_v,
"volume": _sd_vol,
"amount": _sd_amt,
"change": price_v - close_yest_v,
"change_pct": change_v,
"amplitude": None,
"turnover_rate": None,
"pe": None,
"pb": None,
"limit_up": None,
"limit_down": None,
"avg_price": None,
"inner_vol": None,
"outer_vol": None,
"timestamp": "",
"_date": today_str,
}
today_str = date.today().isoformat()
q = {
"code": raw,
"market": prefix,
"name": fields[F["name"]] if len(fields) > F["name"] else code,
"price": get(3),
"close_yest": get(4),
"open": get(5),
"high": get(33),
"low": get(34),
"volume": get(6),
"amount": get(37),
"change": get(31),
"change_pct": get(32),
"amplitude": get(43),
"turnover_rate": get(38),
"pe": get(39),
"pb": get(46),
"limit_up": get(47),
"limit_down": get(48),
"avg_price": get(51),
"inner_vol": get(52),
"outer_vol": get(53),
"timestamp": fields[F["timestamp"]] if len(fields) > F["timestamp"] else "",
"_date": today_str,
}
# 写入价格历史缓存(每日一次;仅最近K线日期==今天才更新,避免用旧日数据冒充今日)
h = _sd_high if _sd_high else price_v
l = _sd_low if _sd_low else price_v
c = price_v
v = _sd_vol
amt = _sd_amt
_sd_date = _sd[0] if _sd else None
if h and l and c and (_sd_date == today_str or _sd is None):
history = _load_history()
if raw not in history:
history[raw] = []
days = history[raw]
# 如果今天已有记录,更新(盘中数据更精确)
if days and len(days) > 0 and days[-1].get("date") == today_str:
days[-1]["high"] = max(days[-1]["high"], h)
days[-1]["low"] = min(days[-1]["low"], l)
days[-1]["close"] = c # 盘中用最新价,收盘后是收盘价
if v: days[-1]["volume"] = v
if amt: days[-1]["amount"] = amt
else:
entry = {"date": today_str, "high": h, "low": l, "close": c}
if v: entry["volume"] = v
if amt: entry["amount"] = amt
days.append(entry)
# 只保留最近 HISTORY_DAYS 天
history[raw] = days[-HISTORY_DAYS:]
_save_history(history)
# 写入价格历史缓存(每日一次)
h = get(33) # high
l = get(34) # low
c = get(3) # price / close
v = get(6) # volume(手)
amt = get(37) # 成交额
if h and l and c:
history = _load_history()
if raw not in history:
history[raw] = []
days = history[raw]
# 如果今天已有记录,更新(盘中数据更精确)
if days and len(days) > 0 and days[-1].get("date") == today_str:
days[-1]["high"] = max(days[-1]["high"], h)
days[-1]["low"] = min(days[-1]["low"], l)
days[-1]["close"] = c # 盘中用最新价,收盘后是收盘价
if v: days[-1]["volume"] = v
if amt: days[-1]["amount"] = amt
else:
entry = {"date": today_str, "high": h, "low": l, "close": c}
if v: entry["volume"] = v
if amt: entry["amount"] = amt
days.append(entry)
# 只保留最近 HISTORY_DAYS 天
history[raw] = days[-HISTORY_DAYS:]
_save_history(history)
# 写入60秒缓存
get_quote.__dict__["_cache"] = {**get_quote.__dict__.get("_cache", {}), code: {"ts": now, "data": q}}
# 写入60秒缓存
get_quote.__dict__["_cache"] = {**get_quote.__dict__.get("_cache", {}), code: {"ts": now, "data": q}}
return q
return q
if db_price:
return {"code": code, "price": db_price, "change_pct": db_chg or 0}
return {"code": code, "error": "数据不足(无本地行情)"}
def calc_support_resistance(q):