diff --git a/backend/app/api/settings.py b/backend/app/api/settings.py index a106025..8e062b8 100644 --- a/backend/app/api/settings.py +++ b/backend/app/api/settings.py @@ -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} diff --git a/backend/app/services/depth_service.py b/backend/app/services/depth_service.py index c239530..9e7abcf 100644 --- a/backend/app/services/depth_service.py +++ b/backend/app/services/depth_service.py @@ -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: