fix(portfolio): 滑点语义修正 FixedSlippage→PriceRelatedSlippage——--slippage 声明比率(万10=0.001)但实挂 FixedSlippage=每股固定元数(0.002→±0.001元/股≈零成本),09-13 第五跑 slip2 组(滑点0.2%)比零滑点 base 同日净值反高12.4%第一层实锤;换聚宽语义比率滑点 price×(1±ratio/2),回归测试钉死不回潮+验证真挂进 settings slippage_map [vps]
CI/CD / test (push) Successful in 0s
CI/CD / nas-deploy (push) Successful in 0s
CI/CD / nas-verify (push) Successful in 27s

This commit is contained in:
2026-09-13 08:09:16 +08:00
parent ca7bb287b7
commit 47ab3257c2
2 changed files with 33 additions and 2 deletions
+5 -2
View File
@@ -331,7 +331,7 @@ def run_backtest(args: argparse.Namespace) -> Dict[str, Any]:
strategy.broker = holder["broker"]
# A 股费用 + 滑点(聚宽风格全局函数,对齐个股回测;BulletTrade 默认费用不全)
from bullet_trade.core.api import set_order_cost, set_slippage # type: ignore
from bullet_trade.core.settings import OrderCost, FixedSlippage # type: ignore
from bullet_trade.core.settings import OrderCost, PriceRelatedSlippage # type: ignore
set_order_cost(
OrderCost(
open_tax=0.0,
@@ -343,7 +343,10 @@ def run_backtest(args: argparse.Namespace) -> Dict[str, Any]:
type="stock",
)
if args.slippage:
set_slippage(FixedSlippage(value=args.slippage))
# 比率滑点(聚宽语义 price×(1±ratio/2),engine._apply_slippage_config);
# FixedSlippage 是每股固定元数(value=0.002 → ±0.001元/股≈零成本,
# 2026-09-13 矩阵 slip2 组比零滑点 base 反赚 12% 的第一层实锤)
set_slippage(PriceRelatedSlippage(ratio=args.slippage))
strategy.initialize(context)
def build_broker_facade_inner(strategy: Any, context: Any):
+28
View File
@@ -90,3 +90,31 @@ def test_holdings_curve_empty_inputs():
import pandas as pd
assert _extract_holdings_curve(pd.DataFrame()) == []
assert _extract_holdings_curve(pd.DataFrame({"code": ["600000"]})) == [] # 无 date 列
# ======================== 滑点语义(2026-09-13 矩阵 slip 组修复) ========================
def test_runner_uses_price_related_slippage():
"""--slippage 声明是比率(万10=0.001),必须走 PriceRelatedSlippage(聚宽语义
price×(1±ratio/2));FixedSlippage 是每股固定元数(value=0.002→±0.001元/股
≈零成本)——09-13 第五跑 slip2 组比零滑点 base 反赚 12% 的第一层实锤,
钉死源码不再回潮 FixedSlippage(value=args.slippage)。"""
import pathlib
src = (pathlib.Path(__file__).resolve().parents[2]
/ "sanguo_portfolio" / "runner_backtest.py").read_text(encoding="utf-8")
assert "FixedSlippage(value=args.slippage)" not in src
assert "PriceRelatedSlippage(ratio=args.slippage)" in src
def test_price_related_slippage_sets_ratio():
"""set_slippage(PriceRelatedSlippage) 真挂进 bullet_trade 全局 settings
(类型+ratio 保留,引擎 _apply_slippage_config 才会走 price×(1±ratio/2))。"""
from bullet_trade.core.api import set_slippage
from bullet_trade.core import settings as bt_settings
set_slippage(bt_settings.PriceRelatedSlippage(ratio=0.002))
try:
# runner 不传 type → _normalize_slippage_keys 落默认键 'all'(引擎全类型回退匹配)
cfg = bt_settings._settings.slippage_map.get("all")
assert isinstance(cfg, bt_settings.PriceRelatedSlippage)
assert cfg.ratio == pytest.approx(0.002)
finally:
bt_settings._settings.reset()