feat: data-layering ????live_prices????qt.gtimg.cn(5??)
This commit is contained in:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user