fix(backtest): A股适配层—定寸/做空拦截/真实费用/口径统一(Phase1+2)
审计发现包装层系统性失真(2 CRITICAL+7 HIGH),vnpy底座可信但A股场景未适配: - C1 定寸: engine.size=N(满仓手数),策略volume=1手=N股,开平对称(pos归零) - C2 做空拦截: SHORT+OPEN拒单,long-only,SHORT+CLOSE平多允许 - H3 A股费用: AShareDailyResult重算(佣金保底5元/印花税卖方/过户费沪市) - H4 收益口径: simple return从balance算(不再用vnpy log return喂empyrical) - H5+口径: benchmark ffill对齐不缩样本; sizing_shares_per_lot暴露 - H7 退化检测: 零成交/空数据标degenerate不静默done - H8 task_id: optimize/factor用uuid4(原id()内存地址) - 静默except改warning 验证: 容器内真实vnpy DoubleMa 600000 2022-2024, total_return 1e-6→42.3%, end_balance 100万→142万, SHORT+OPEN成交0笔, N=7800股/手. 22 backtest测试全绿(含集成测试), API健康200.
This commit is contained in:
@@ -76,7 +76,9 @@ async def submit_cta(req: CtaBacktestRequest):
|
||||
start=req.start,
|
||||
end=req.end,
|
||||
cfg=None,
|
||||
benchmark=req.benchmark
|
||||
benchmark=req.benchmark,
|
||||
capital=req.capital,
|
||||
position_pct=req.position_pct
|
||||
)
|
||||
return {"task_id": tid}
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@ class CtaBacktestRequest(BaseModel):
|
||||
start: str
|
||||
end: str
|
||||
benchmark: str = "hs300"
|
||||
capital: float = 1_000_000
|
||||
position_pct: float = 0.95
|
||||
# A 股费用参数(可选,前端先不暴露,给默认值)
|
||||
commission_rate: float = 0.00025 # 万 2.5
|
||||
min_commission: float = 5.0 # 最低 5 元
|
||||
stamp_duty_rate: float = 0.0005 # 卖方 0.05%
|
||||
transfer_fee_rate: float = 0.00001 # 沪市 0.001%
|
||||
|
||||
|
||||
class OptimizeRequest(BaseModel):
|
||||
|
||||
@@ -7,8 +7,11 @@ Task S1.3.
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import logging
|
||||
import pkgutil
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Fallback strategy names (when vnpy_ctastrategy import fails).
|
||||
STRATEGY_NAMES: list[str] = ["DoubleMaStrategy", "BollChannelStrategy", "AtrRsiStrategy"]
|
||||
|
||||
@@ -25,10 +28,11 @@ def _load_strategy_classes() -> dict[str, type]:
|
||||
obj = getattr(m, attr)
|
||||
if isinstance(obj, type) and attr.endswith("Strategy") and hasattr(obj, "parameters"):
|
||||
classes[attr] = obj
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.warning("导入策略模块 %s 失败: %s", name, e)
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.warning("加载 vnpy_ctastrategy 策略列表失败(降级为静态列表): %s", e)
|
||||
return classes
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user