Use lightweight ticker APIs for liquidity rank to cut memory.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-21 09:24:27 +08:00
parent c0f3606ecc
commit bd759c42d6
6 changed files with 175 additions and 297 deletions
+9 -126
View File
@@ -177,6 +177,7 @@ from order_monitor_display_lib import (
)
from wechat_notify_lib import build_wechat_rs_level_message, send_wechat_webhook
from hub_auth import request_allowed as hub_request_allowed
from hub_volume_rank_lib import resolve_daily_volume_rank
from history_window_lib import (
PRESET_CUSTOM,
PRESET_UTC_LAST24H,
@@ -404,7 +405,6 @@ LIQUIDITY_RANK_CACHE = {
"updated_at": 0.0,
"version": 0,
"ranks": {},
"volumes": {},
"total": 0,
}
@@ -3900,137 +3900,20 @@ def _status_by_ema55(symbol, timeframe):
return "横盘", None, None
def _okx_swap_turnover_usdt(ticker_row: dict) -> float | None:
"""
OKX 永续 24h 成交额(USDT)
官方文档SWAP volCcy24h 单位是基础币数量( ZEC)不是 USDT
网页24小时成交额 volCcy24h × last
"""
if not isinstance(ticker_row, dict):
return None
base_vol = _safe_float(ticker_row.get("volCcy24h"))
if base_vol is None or base_vol <= 0:
return None
last = _safe_float(ticker_row.get("last"))
if last is None or last <= 0:
return None
return float(base_vol * last)
def _okx_usdt_swap_volume_by_base() -> dict[str, float]:
"""
OKX USDT 永续全市场 24h 成交额(USDT) App24小时成交额一致
/market/tickers?instType=SWAP成交额 = volCcy24h(基础币) × last
"""
by_base: dict[str, float] = {}
try:
ensure_markets_loaded()
if hasattr(exchange, "publicGetMarketTickers"):
resp = exchange.publicGetMarketTickers({"instType": "SWAP"})
rows = (resp or {}).get("data") or []
for row in rows:
if not isinstance(row, dict):
continue
inst = str(row.get("instId") or "").upper()
# 仅 USDT 本位永续:BTC-USDT-SWAP
parts = inst.split("-")
if len(parts) < 3 or parts[-1] != "SWAP" or parts[1] != "USDT":
continue
base = parts[0].strip()
if not base:
continue
qv = _okx_swap_turnover_usdt(row)
if qv is None or qv <= 0:
continue
by_base[base] = max(by_base.get(base, 0), float(qv))
if by_base:
return by_base
except Exception:
pass
def _ticker_base(sym_text):
s = str(sym_text or "").upper().strip()
if ":" in s:
s = s.split(":", 1)[0]
if "/" in s:
return s.split("/", 1)[0].strip()
if "-" in s:
return s.split("-", 1)[0].strip()
if s.endswith("USDT"):
return s[:-4].strip()
return s
try:
ensure_markets_loaded()
try:
tickers = exchange.fetch_tickers(params={"instType": "SWAP"})
except Exception:
tickers = exchange.fetch_tickers()
for s, t in (tickers or {}).items():
try:
mk = exchange.markets.get(s) if exchange.markets else None
if mk is not None:
if not mk.get("swap"):
continue
if str(mk.get("quote") or "").upper() != "USDT":
continue
if mk.get("linear") is False:
continue
if mk.get("active") is False:
continue
else:
su = str(s).upper()
if "USDT" not in su or ":USDT" not in su:
continue
base = _ticker_base(s)
if not base:
continue
info = (t or {}).get("info") if isinstance((t or {}).get("info"), dict) else {}
row = dict(info)
if row.get("last") is None:
row["last"] = (t or {}).get("last")
qv = _okx_swap_turnover_usdt(row)
if qv is None:
qv = _safe_float((t or {}).get("quoteVolume"))
if qv is None or qv <= 0:
continue
by_base[base] = max(by_base.get(base, 0), float(qv))
except Exception:
continue
except Exception:
pass
return by_base
def _daily_volume_rank(symbol):
"""
返回(symbol_rank, total_count)OKX USDT 永续 24h 成交额(USDT) 在全市场币种中的排名本月
成交额 = volCcy24h(基础币) × last OKX App24小时成交额一致
返回(symbol_rank, total_count)OKX USDT 永续 24h 成交额(USDT) 在全市场币种中的排名
"""
sym_norm = normalize_symbol_input(symbol)
target_base = journal_coin_from_symbol(sym_norm)
now_ts = time.time()
cache_ver = 4
cached_ok = (
LIQUIDITY_RANK_CACHE.get("version") == cache_ver
and LIQUIDITY_RANK_CACHE["updated_at"]
and now_ts - float(LIQUIDITY_RANK_CACHE["updated_at"]) < max(30, BALANCE_REFRESH_SECONDS)
return resolve_daily_volume_rank(
target_base,
LIQUIDITY_RANK_CACHE,
now_ts=time.time(),
ttl_sec=max(30, BALANCE_REFRESH_SECONDS),
exchange=exchange,
ensure_markets_loaded=ensure_markets_loaded,
)
if not cached_ok:
try:
by_base = _okx_usdt_swap_volume_by_base()
scored = sorted(by_base.items(), key=lambda x: x[1], reverse=True)
ranks = {base: idx for idx, (base, _) in enumerate(scored, 1)}
LIQUIDITY_RANK_CACHE["ranks"] = ranks
LIQUIDITY_RANK_CACHE["volumes"] = dict(by_base)
LIQUIDITY_RANK_CACHE["total"] = len(scored)
LIQUIDITY_RANK_CACHE["version"] = cache_ver
LIQUIDITY_RANK_CACHE["updated_at"] = now_ts
except Exception:
pass
ranks = LIQUIDITY_RANK_CACHE.get("ranks") or {}
total = int(LIQUIDITY_RANK_CACHE.get("total") or 0)
return ranks.get(target_base), total
def _key_hard_checks(symbol, direction, upper, lower, monitor_type):