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
+62 -63
View File
@@ -1,4 +1,4 @@
"""期货手续费:优先 CTP 柜台费率,本地/AKShare 为离线兜底"""
"""期货手续费: CTP 柜台同步入库,前端只读展示"""
import json
import os
import re
@@ -37,6 +37,26 @@ def _get_db():
return connect_db()
def get_setting(key: str, default: str = "") -> str:
conn = _get_db()
row = conn.execute("SELECT value FROM settings WHERE key=?", (key,)).fetchone()
conn.close()
if not row:
return default
return (row["value"] or default) if row["value"] is not None else default
def set_setting(key: str, value: str) -> None:
conn = _get_db()
conn.execute(
"""INSERT INTO settings (key, value) VALUES (?,?)
ON CONFLICT(key) DO UPDATE SET value=excluded.value""",
(key, value),
)
conn.commit()
conn.close()
def get_fee_multiplier() -> float:
conn = _get_db()
row = conn.execute(
@@ -52,14 +72,20 @@ def get_fee_multiplier() -> float:
def get_fee_source_mode() -> str:
"""ctp=优先柜台同步费率;local=本地/AKShare 表"""
"""固定 CTP 柜台"""
return "ctp"
def purge_non_ctp_fee_rates() -> int:
"""删除非 CTP 来源的费率缓存。"""
conn = _get_db()
row = conn.execute(
"SELECT value FROM settings WHERE key='fee_source_mode'"
).fetchone()
cur = conn.execute(
"DELETE FROM fee_rates WHERE COALESCE(source, '') != 'ctp'"
)
n = cur.rowcount
conn.commit()
conn.close()
mode = (row["value"] if row else "ctp") or "ctp"
return mode if mode in ("ctp", "local") else "ctp"
return n
def _row_to_spec(row, mult: int) -> dict:
@@ -84,46 +110,21 @@ def get_fee_spec(ths_code: str, *, trading_mode: str = "simulation") -> dict:
return {**DEFAULT_FEE, "mult": spec["mult"], "product": "", "exchange": "", "source": "default"}
mult = get_contract_spec(ths_code)["mult"]
source_mode = get_fee_source_mode()
conn = _get_db()
if source_mode == "ctp":
row = conn.execute(
"SELECT * FROM fee_rates WHERE product=? AND source='ctp'",
(product,),
).fetchone()
if not row:
row = conn.execute(
"SELECT * FROM fee_rates WHERE product=? ORDER BY CASE source WHEN 'ctp' THEN 0 ELSE 1 END",
(product,),
).fetchone()
conn.close()
if row:
return _row_to_spec(row, mult)
# 按需向 CTP 查询
try:
from ctp_fee_sync import sync_fee_for_symbol
fields = sync_fee_for_symbol(trading_mode, ths_code)
if fields:
return {"product": product, **fields}
except Exception:
pass
conn = _get_db()
row = conn.execute(
"SELECT * FROM fee_rates WHERE product=?", (product,)
).fetchone()
conn.close()
if row:
spec = _row_to_spec(row, mult)
spec["source"] = spec.get("source") or "local_fallback"
return spec
else:
row = conn.execute(
"SELECT * FROM fee_rates WHERE product=?", (product,)
).fetchone()
conn.close()
if row:
return _row_to_spec(row, mult)
row = conn.execute(
"SELECT * FROM fee_rates WHERE product=? AND source='ctp'",
(product,),
).fetchone()
conn.close()
if row:
return _row_to_spec(row, mult)
try:
from ctp_fee_sync import sync_fee_for_symbol
fields = sync_fee_for_symbol(trading_mode, ths_code)
if fields:
return {"product": product, **fields}
except Exception:
pass
if product in _INDEX_PRODUCTS:
return {
@@ -287,6 +288,16 @@ def load_fee_rates_from_json(path: Optional[str] = None) -> int:
return count
def list_ctp_fee_rates() -> list:
"""手续费页:仅展示 CTP 同步结果。"""
conn = _get_db()
rows = conn.execute(
"SELECT * FROM fee_rates WHERE source='ctp' ORDER BY product"
).fetchall()
conn.close()
return [dict(r) for r in rows]
def list_all_fee_rates() -> list:
conn = _get_db()
rows = conn.execute(
@@ -297,28 +308,16 @@ def list_all_fee_rates() -> list:
def list_fee_rates_for_ui() -> list:
"""手续费页展示:CTP 模式下 ctp 来源优先排前。"""
rows = list_all_fee_rates()
if get_fee_source_mode() == "ctp":
rows.sort(
key=lambda r: (
0 if (r.get("source") or "") == "ctp" else 1,
r.get("product") or "",
)
)
return rows
return list_ctp_fee_rates()
def count_fee_rates_by_source() -> dict[str, int]:
conn = _get_db()
rows = conn.execute(
"SELECT source, COUNT(*) AS n FROM fee_rates GROUP BY source"
).fetchall()
n = conn.execute(
"SELECT COUNT(*) FROM fee_rates WHERE source='ctp'"
).fetchone()[0]
conn.close()
out: dict[str, int] = {}
for row in rows:
out[str(row["source"] or "local")] = int(row["n"] or 0)
return out
return {"ctp": int(n or 0)}
def upsert_fee_rate(product: str, fields: dict) -> None: