feat: 手续费仅CTP每日后台同步入库,前端只读展示

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-24 13:33:14 +08:00
parent de6815d481
commit e01c011df5
7 changed files with 240 additions and 214 deletions
+90
View File
@@ -0,0 +1,90 @@
"""CTP 手续费后台同步:每日一次写入数据库,前端只读展示。"""
from __future__ import annotations
import logging
import threading
import time
from datetime import date, datetime
from typing import Callable, Optional
from zoneinfo import ZoneInfo
logger = logging.getLogger(__name__)
TZ = ZoneInfo("Asia/Shanghai")
FEE_SYNC_KEY = "ctp_fee_last_sync"
CHECK_INTERVAL_SEC = 3600
_sync_lock = threading.Lock()
def _today_str() -> str:
return datetime.now(TZ).date().isoformat()
def get_fee_last_sync(get_setting: Callable[[str, str], str]) -> str:
return (get_setting(FEE_SYNC_KEY, "") or "").strip()
def fees_synced_today(get_setting: Callable[[str, str], str]) -> bool:
last = get_fee_last_sync(get_setting)
return bool(last) and last[:10] == _today_str()
def mark_fees_synced(set_setting: Callable[[str, str], None]) -> None:
set_setting(FEE_SYNC_KEY, datetime.now(TZ).isoformat(timespec="seconds"))
def try_daily_ctp_fee_sync(
mode: str,
*,
get_setting: Callable[[str, str], str],
set_setting: Callable[[str, str], None],
force: bool = False,
) -> tuple[int, str]:
"""CTP 已连接且今日未同步时拉取费率入库;force=True 忽略日期限制。"""
if not force and fees_synced_today(get_setting):
return 0, "今日已从 CTP 同步过,无需重复(可点「立即同步」强制刷新)"
with _sync_lock:
if not force and fees_synced_today(get_setting):
return 0, "今日已从 CTP 同步过"
from ctp_fee_sync import sync_fees_from_ctp
count, msg = sync_fees_from_ctp(mode)
if count > 0:
mark_fees_synced(set_setting)
logger.info("CTP 手续费每日同步: %s", msg)
elif force:
logger.warning("CTP 手续费强制同步未写入: %s", msg)
return count, msg
def start_ctp_fee_worker(
*,
get_mode_fn: Callable[[], str],
get_setting_fn: Callable[[str, str], str],
set_setting_fn: Callable[[str, str], None],
interval: int = CHECK_INTERVAL_SEC,
) -> None:
"""后台线程:每小时检查,CTP 已连接且当日未同步则自动同步。"""
def _loop() -> None:
time.sleep(20)
while True:
try:
from vnpy_bridge import ctp_status
mode = get_mode_fn()
st = ctp_status(mode)
if st.get("connected") and not fees_synced_today(get_setting_fn):
try_daily_ctp_fee_sync(
mode,
get_setting=get_setting_fn,
set_setting=set_setting_fn,
force=False,
)
except Exception as exc:
logger.warning("CTP fee worker: %s", exc)
time.sleep(max(300, interval))
threading.Thread(target=_loop, daemon=True, name="ctp-fee-worker").start()