# Copyright (c) 2025-2026 马建军. All rights reserved. # 专有软件 — 未经授权禁止复制、传播、转售。 # 严禁用于:带单/代客理财、向他人推荐期货品种或买卖建议、融资配资等业务。 # 详见 LICENSE.zh-CN.txt 与 docs/软件购买与使用协议.md """从第三方(AKShare)同步交易所参考手续费,并按倍率写入本地表。""" import re from typing import Any, Optional from modules.core.contract_specs import get_contract_spec from modules.fees.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})"