Files
sanguo_vnpy_v2/sanguo_trader/scheduler.py
T
claude_dev 6931a7b541 feat(trader): C-S3实走后端骨架—live_orchestrator+全局scheduler job+routes live
架构(简化,避per-account闭包注入):
- live_orchestrator live_step(account_id)自包含: 恢复cash/positions/pending→fetch_day raw当日→engine.step→存状态
- run_live_step(db)遍历live accounts调live_step; scheduler register_live_step_job全局20:30 job
- app startup注册全局job; routes create mode=live存account running(不跑回放)
- TODO(分期项): prev_close昨日raw/listing_days IPO算/realized_pnl恢复
- 113/113通过, live_orchestrator import OK
2026-07-08 06:49:31 +08:00

83 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""模拟盘 C 实走调度(APScheduler 定时 + 启动恢复,spec §9.2)。
每日 20:30 触发 step(拉当日 bar + engine.step)。APScheduler 是 pip 依赖,
lazy import;本机无则单测 mock get_scheduler。
"""
import logging
import sqlite3
logger = logging.getLogger(__name__)
_scheduler = None
def get_scheduler():
global _scheduler
if _scheduler is None:
from apscheduler.schedulers.background import BackgroundScheduler
_scheduler = BackgroundScheduler()
return _scheduler
def start_scheduler():
s = get_scheduler()
if not s.running:
s.start()
return s
def register_paper_job(account_id: int, hour: int = 20, minute: int = 30,
job_func=None) -> str:
"""注册每日定时 job,返回 job_id(存 paper_accounts.scheduler_job_id)。"""
s = start_scheduler()
job_id = f"paper_{account_id}"
s.add_job(
job_func or _default_step,
"cron", # 字符串 trigger,避免函数内 import CronTrigger
hour=hour, minute=minute,
args=[account_id], id=job_id, replace_existing=True,
)
return job_id
def remove_paper_job(account_id: int) -> None:
s = get_scheduler()
job_id = f"paper_{account_id}"
try:
s.remove_job(job_id)
except Exception:
logger.warning("remove_job %s not found", job_id)
def _default_step(account_id: int) -> None:
"""部署时注入真 stepakshare 拉当日 + engine.step);默认 stub。"""
logger.info("paper account %s daily step (stub)", account_id)
def restore_live_jobs(db_path: str, job_func=None) -> int:
"""容器启动:遍历 status=running & mode=live 重建 jobspec §9.2 H-3)。
简化架构:实走用全局 jobregister_live_step_job),此函数保留兼容老 per-account 设计。
"""
with sqlite3.connect(db_path) as conn:
rows = conn.execute(
"SELECT id FROM paper_accounts WHERE status='running' AND mode='live'"
).fetchall()
for (aid,) in rows:
register_paper_job(aid, job_func=job_func)
return len(rows)
def register_live_step_job(db_path: str, hour: int = 20, minute: int = 30) -> str:
"""全局每日 step job20:30 遍历所有 live accounts 调 run_live_stepC-S3 简化架构)。
job_func 用 lambda 闭包 db_pathadd_job 只传无参 callable)。
"""
from .live_orchestrator import run_live_step # lazy 避循环 import
s = start_scheduler()
s.add_job(
lambda: run_live_step(db_path),
"cron", hour=hour, minute=minute,
id="live_step_global", replace_existing=True,
)
return "live_step_global"