1- """上下文维护调度器:后验评估 + 过期数据清理。"""
1+ """上下文维护调度器:后验评估 + 过期数据清理 + 机会自动刷新 。"""
22
33from __future__ import annotations
44
1414from src .core .strategy_engine import (
1515 evaluate_strategy_outcomes ,
1616 rebalance_strategy_weights ,
17+ refresh_strategy_signals ,
1718)
1819
1920logger = logging .getLogger (__name__ )
@@ -33,6 +34,7 @@ def __init__(
3334 self .outcome_retention_days = max (60 , int (outcome_retention_days ))
3435 self ._evaluating = False
3536 self ._cleaning = False
37+ self ._refreshing = False
3638
3739 async def _evaluate_job (self ):
3840 if self ._evaluating :
@@ -148,6 +150,42 @@ async def evaluate_once(self) -> dict:
148150 "strategy_rebalance" : strategy_rebalance_stats ,
149151 }
150152
153+ async def _refresh_opportunities_job (self ):
154+ """定时刷新机会池(候选 + 策略信号)。"""
155+ if self ._refreshing :
156+ logger .info ("[上下文维护] 上一轮机会刷新仍在执行,跳过本轮" )
157+ return
158+ self ._refreshing = True
159+ try :
160+ result = await asyncio .to_thread (
161+ refresh_strategy_signals ,
162+ rebuild_candidates = True ,
163+ max_inputs = 500 ,
164+ market_scan_limit = 80 ,
165+ max_kline_symbols = 60 ,
166+ limit_candidates = 2000 ,
167+ )
168+ logger .info (
169+ "[上下文维护] 机会自动刷新完成: snapshot_date=%s count=%s" ,
170+ result .get ("snapshot_date" , "" ),
171+ result .get ("count" , 0 ),
172+ )
173+ except Exception as e :
174+ logger .exception (f"[上下文维护] 机会自动刷新异常: { e } " )
175+ finally :
176+ self ._refreshing = False
177+
178+ async def refresh_opportunities_once (self ) -> dict :
179+ """手动触发一次机会刷新。"""
180+ return await asyncio .to_thread (
181+ refresh_strategy_signals ,
182+ rebuild_candidates = True ,
183+ max_inputs = 500 ,
184+ market_scan_limit = 80 ,
185+ max_kline_symbols = 60 ,
186+ limit_candidates = 2000 ,
187+ )
188+
151189 async def cleanup_once (self ) -> dict :
152190 return await asyncio .to_thread (
153191 cleanup_context_data ,
@@ -177,6 +215,18 @@ def start(self):
177215 coalesce = True ,
178216 max_instances = 1 ,
179217 )
218+ # 机会自动刷新(北京时间 09:15 / 13:30 / 22:00)
219+ for job_hour , job_minute in ((1 , 15 ), (5 , 30 ), (14 , 0 )):
220+ self .scheduler .add_job (
221+ self ._refresh_opportunities_job ,
222+ "cron" ,
223+ hour = job_hour ,
224+ minute = job_minute ,
225+ id = f"context_maintenance_refresh_opportunities_{ job_hour :02d} { job_minute :02d} " ,
226+ replace_existing = True ,
227+ coalesce = True ,
228+ max_instances = 1 ,
229+ )
180230 # Run a bootstrap evaluation shortly after startup to warm up outcome stats.
181231 self .scheduler .add_job (
182232 self ._evaluate_job ,
@@ -189,7 +239,7 @@ def start(self):
189239 )
190240 self .scheduler .start ()
191241 logger .info (
192- "上下文维护调度器已启动(后验评估间隔 %sh,启动补跑 +15s,快照保留 %s 天,后验保留 %s 天)" ,
242+ "上下文维护调度器已启动(后验评估间隔 %sh,启动补跑 +15s,快照保留 %s 天,后验保留 %s 天,机会自动刷新 01:15/05:30/14:00 UTC )" ,
193243 self .eval_interval_hours ,
194244 self .snapshot_retention_days ,
195245 self .outcome_retention_days ,
0 commit comments