refactor: 统一价格入口 mo_data.get_price() - 22个脚本移除自拉腾讯API
所有价格获取统一走 mo_data.get_price() / get_prices_batch():
- 优先读 live_prices(DB) → 无/过期才调 stock_quote(API) → 自动写回DB
- 22个脚本全部替换:branch_scanner chip_factors divergence_detector
market_screener mo_provider mofin_collect monitor_300308 300308_monitor
multi_timeframe refresh_macro_context stale_detector stale_push_wlin
stock_profile strategy_evaluator strategy_lifecycle strategy_review
strategy-staleness-check technical_analysis xiaoguo_signal_consumer
collect_evaluation_data
This commit is contained in:
@@ -12,19 +12,8 @@
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import urllib.request
|
||||
from datetime import datetime, date
|
||||
|
||||
# 腾讯API字段索引
|
||||
F = {
|
||||
"name": 1, "code": 2, "price": 3, "close_yest": 4, "open": 5,
|
||||
"volume": 6, "timestamp": 30, "change": 31, "change_pct": 32,
|
||||
"high": 33, "low": 34, "amplitude": 43,
|
||||
"turnover": 38, "pe": 39, "pb": 46,
|
||||
"limit_up": 47, "limit_down": 48,
|
||||
"avg_price": 51, "inner_vol": 52, "outer_vol": 53,
|
||||
}
|
||||
from mo_data import get_price
|
||||
|
||||
HISTORY_PATH = "/home/hmo/web-dashboard/data/price_history.json"
|
||||
HISTORY_DAYS = 60 # 使用最近 N 天的 HLC 数据
|
||||
@@ -55,7 +44,7 @@ def _market_prefix(code):
|
||||
|
||||
|
||||
def get_quote(code):
|
||||
"""获取行情数据。先拿DB的价格和涨跌幅,再调腾讯API拿HLC全量数据"""
|
||||
"""获取行情数据。使用 mo_data.get_price 统一入口,缓存+格式转换"""
|
||||
import time
|
||||
_cache = get_quote.__dict__.get("_cache", {})
|
||||
now = time.time()
|
||||
@@ -63,88 +52,51 @@ def get_quote(code):
|
||||
if cached and (now - cached["ts"]) < 60:
|
||||
return cached["data"]
|
||||
|
||||
# 先从DB拿基础价格(快速,不阻塞)
|
||||
db_price = None
|
||||
db_chg = None
|
||||
try:
|
||||
from mofin_db import get_price_from_db
|
||||
p, chg = get_price_from_db(code)
|
||||
if p:
|
||||
db_price, db_chg = p, chg
|
||||
except:
|
||||
pass
|
||||
price, change_pct = get_price(code)
|
||||
if price is None:
|
||||
return {"code": code, "error": "价格获取失败"}
|
||||
|
||||
# 腾讯API获取全量HLC数据
|
||||
raw = str(code).split("_")[0]
|
||||
prefix = _market_prefix(code)
|
||||
url = f"http://qt.gtimg.cn/q={prefix}{raw}"
|
||||
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)}
|
||||
|
||||
def get(i):
|
||||
try:
|
||||
return float(fields[i]) if fields[i].strip() else None
|
||||
except (IndexError, ValueError):
|
||||
return None
|
||||
|
||||
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 "",
|
||||
"name": code,
|
||||
"price": price,
|
||||
"close_yest": None,
|
||||
"open": None,
|
||||
"high": None,
|
||||
"low": None,
|
||||
"volume": None,
|
||||
"amount": None,
|
||||
"change": None,
|
||||
"change_pct": change_pct or 0,
|
||||
"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,
|
||||
}
|
||||
|
||||
# 写入价格历史缓存(每日一次)
|
||||
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)
|
||||
# 写入价格历史缓存(每日一次,只存价格)
|
||||
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]["close"] = price
|
||||
else:
|
||||
days.append({"date": today_str, "close": price})
|
||||
history[raw] = days[-HISTORY_DAYS:]
|
||||
_save_history(history)
|
||||
|
||||
# 写入60秒缓存
|
||||
get_quote.__dict__["_cache"] = {**get_quote.__dict__.get("_cache", {}), code: {"ts": now, "data": q}}
|
||||
|
||||
Reference in New Issue
Block a user