Files
qihuo/fee_sync.py
T
dekun 528d9811e3 feat: 导航开关与 CTP 柜台手续费
系统设置可开关五类导航;手续费默认从 CTP 查询同步,本地/AKShare 作离线兜底;补充 FEES.md。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-24 12:19:56 +08:00

87 lines
3.2 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.
"""从第三方(AKShare)同步交易所参考手续费,并按倍率写入本地表。"""
import re
from typing import Any, Optional
from contract_specs import get_contract_spec
from fee_specs import get_fee_multiplier, upsert_fee_rate
def _to_float(val: Any) -> float:
if val is None:
return 0.0
s = str(val).strip().replace(",", "")
if not s or s in ("-", "None", "nan"):
return 0.0
try:
return float(s)
except ValueError:
return 0.0
def _parse_akshare_row(row: dict, multiplier: float) -> Optional[dict]:
code = str(row.get("合约代码") or row.get("代码") or "").strip()
if not code:
return None
m = re.match(r"^([A-Za-z]+)", code)
if not m:
return None
product = m.group(1).lower()
open_ratio = _to_float(row.get("手续费标准-开仓-万分之")) / 10000.0
open_fixed = _to_float(row.get("手续费标准-开仓-元"))
if open_fixed == 0 and row.get("开仓"):
open_fixed = _to_float(row.get("开仓"))
close_y_ratio = _to_float(row.get("手续费标准-平昨-万分之")) / 10000.0
close_y_fixed = _to_float(row.get("手续费标准-平昨-元"))
if close_y_fixed == 0 and row.get("平昨"):
close_y_fixed = _to_float(row.get("平昨"))
close_t_ratio = _to_float(row.get("手续费标准-平今-万分之")) / 10000.0
close_t_fixed = _to_float(row.get("手续费标准-平今-元"))
if close_t_fixed == 0 and row.get("平今"):
close_t_fixed = _to_float(row.get("平今"))
mult = int(get_contract_spec(code)["mult"])
exchange = str(row.get("交易所名称") or row.get("交易所") or "").strip()
return {
"product": product,
"exchange": exchange,
"mult": mult,
"open_fixed": round(open_fixed * multiplier, 6),
"open_ratio": round(open_ratio * multiplier, 8),
"close_yesterday_fixed": round(close_y_fixed * multiplier, 6),
"close_yesterday_ratio": round(close_y_ratio * multiplier, 8),
"close_today_fixed": round(close_t_fixed * multiplier, 6),
"close_today_ratio": round(close_t_ratio * multiplier, 8),
"source": "akshare",
}
def sync_fees_from_akshare(multiplier: Optional[float] = None) -> tuple[int, str]:
multiplier = multiplier if multiplier is not None else get_fee_multiplier()
try:
import akshare as ak
except ImportError:
return 0, "未安装 akshare,请执行 pip install akshare 后重试,或使用默认费率表"
try:
df = ak.futures_comm_info(symbol="所有")
except Exception as exc:
return 0, f"拉取第三方数据失败: {exc}"
if df is None or df.empty:
return 0, "第三方返回空数据"
seen: set[str] = set()
count = 0
for _, series in df.iterrows():
row = series.to_dict()
parsed = _parse_akshare_row(row, multiplier)
if not parsed or parsed["product"] in seen:
continue
seen.add(parsed["product"])
upsert_fee_rate(parsed["product"], parsed)
count += 1
return count, f"已同步 {count} 个品种(标准费率 × {multiplier}"