Files
qihuo/modules/fees/fee_sync.py
T
dekun e5a586f903 Restructure into modules/ with single-process CTP and config/ layout.
Move business code under modules/, env template to config/, PM2 single qihuo process, and _legacy shims for old imports.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-01 14:42:16 +08:00

92 lines
3.5 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.
# 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}"