mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 16:44:15 +08:00
fix(depth): 五档盘口轮询依赖实时行情开关
depth 盘中轮询原只受「连板梯队监控」开关 + DEPTH5_BATCH 能力门控, 与实时行情开关无关。实时行情关闭时 enriched 内存缓存停留在上一 交易日, 轮询线程整个盘中反复拉取陈旧的涨跌停名单 (如周一开盘仍在 拉上周五的 49 只), 浪费 API 额度且数据无意义。 - start_polling 增加 realtime_quotes_enabled 门控: 三重 AND (监控开关 ∧ 实时行情 ∧ 能力), boot 启动/监控开关切换路径自动生效 - update_realtime_quotes 保存偏好后同步启停 depth 轮询: 开实时行情 → start_polling (仍受监控开关/能力门控), 关 → stop_polling 立即停 盘后 15:02 定版 job 与启动补跑 (boot_check/finalize 单次拉取) 不受 影响, 历史 sealed 数据链路保持完整。 验证: 5 组偏好组合单测门控行为; 13 个 depth 窗口测试通过; 实测重启后 (监控开+实时关) 不再出现「盘中轮询已启动」。
This commit is contained in:
@@ -781,6 +781,19 @@ def update_realtime_quotes(req: RealtimeQuotesPrefs, request: Request) -> dict:
|
||||
"""
|
||||
from app.services import preferences
|
||||
qs = getattr(request.app.state, "quote_service", None)
|
||||
depth_svc = getattr(request.app.state, "depth_service", None)
|
||||
|
||||
def _sync_depth_polling(realtime_on: bool) -> None:
|
||||
"""实时行情开关联动 depth 盘中轮询: 开→恢复(仍受监控开关/能力门控), 关→立即停。
|
||||
|
||||
实时行情关闭时 enriched 停留在上一交易日, depth 轮询只会反复拉陈旧名单。
|
||||
"""
|
||||
if not depth_svc:
|
||||
return
|
||||
if realtime_on:
|
||||
depth_svc.start_polling()
|
||||
else:
|
||||
depth_svc.stop_polling()
|
||||
|
||||
allowed = qs.is_realtime_allowed() if qs else True
|
||||
if req.realtime_quotes_enabled and not allowed:
|
||||
@@ -788,12 +801,14 @@ def update_realtime_quotes(req: RealtimeQuotesPrefs, request: Request) -> dict:
|
||||
preferences.save({"realtime_quotes_enabled": False})
|
||||
if qs:
|
||||
qs.disable()
|
||||
_sync_depth_polling(False)
|
||||
return {"realtime_quotes_enabled": False, "realtime_allowed": False}
|
||||
if req.realtime_quotes_enabled and qs and qs.is_paused():
|
||||
# 管道/数据修正运行期间禁止开启实时行情 — 防止写盘竞态
|
||||
raise HTTPException(status_code=409, detail="数据同步运行中,实时行情已临时暂停,请稍后再开启")
|
||||
if req.realtime_quotes_enabled and qs and qs.realtime_mode() == "watchlist" and not preferences.get_realtime_watchlist_symbols():
|
||||
preferences.save({"realtime_quotes_enabled": False})
|
||||
_sync_depth_polling(False)
|
||||
return {"realtime_quotes_enabled": False, "realtime_allowed": True, "mode": "watchlist", "error": "watchlist_empty"}
|
||||
|
||||
preferences.save({"realtime_quotes_enabled": req.realtime_quotes_enabled})
|
||||
@@ -802,6 +817,7 @@ def update_realtime_quotes(req: RealtimeQuotesPrefs, request: Request) -> dict:
|
||||
qs.enable()
|
||||
else:
|
||||
qs.disable()
|
||||
_sync_depth_polling(req.realtime_quotes_enabled)
|
||||
|
||||
return {"realtime_quotes_enabled": req.realtime_quotes_enabled, "realtime_allowed": allowed}
|
||||
|
||||
|
||||
@@ -146,12 +146,19 @@ class DepthService:
|
||||
logger.warning("depth sealed 从 parquet 恢复失败: %s", e)
|
||||
|
||||
def start_polling(self) -> None:
|
||||
"""启动盘中轮询线程(连板梯队监控开启 + 有能力 + 交易时段)。"""
|
||||
"""启动盘中轮询线程(连板梯队监控开启 + 实时行情开启 + 有能力)。
|
||||
|
||||
依赖实时行情开关: 实时行情关闭时 enriched 内存缓存停留在上一交易日,
|
||||
轮询会反复拉取陈旧的涨跌停名单(浪费 API 额度且数据无意义)。
|
||||
实时行情开关切换时由 settings API 调 stop_polling/start_polling 同步启停。
|
||||
"""
|
||||
if not self._has_capability():
|
||||
return
|
||||
from app.services import preferences
|
||||
if not preferences.get_limit_ladder_monitor_enabled():
|
||||
return
|
||||
if not preferences.get_realtime_quotes_enabled():
|
||||
return
|
||||
# check-then-act 加锁: 两个线程同时 start_polling 不会各起一个轮询线程
|
||||
with self._lock:
|
||||
if self._running:
|
||||
|
||||
Reference in New Issue
Block a user