Skip to content

Commit 73dd4bc

Browse files
committed
feat: 调度器新增机会池自动刷新任务(UTC 01:15/05:30/14:00)
1 parent 7d07d65 commit 73dd4bc

1 file changed

Lines changed: 52 additions & 2 deletions

File tree

src/core/context_scheduler.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""上下文维护调度器:后验评估 + 过期数据清理。"""
1+
"""上下文维护调度器:后验评估 + 过期数据清理 + 机会自动刷新。"""
22

33
from __future__ import annotations
44

@@ -14,6 +14,7 @@
1414
from src.core.strategy_engine import (
1515
evaluate_strategy_outcomes,
1616
rebalance_strategy_weights,
17+
refresh_strategy_signals,
1718
)
1819

1920
logger = 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

Comments
 (0)