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>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
# 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})"
|
||||
Reference in New Issue
Block a user