49 lines
2.4 KiB
Python
49 lines
2.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""ishortfall:三价链分量+恒等式可加和+paper 机制性零+拒单两分法分标签。"""
|
||
from sanguo_portfolio.ishortfall import OrderLeg, compute_components
|
||
|
||
|
||
def test_identity_additivity_and_signs():
|
||
legs = [OrderLeg(action="buy", qty=2300,
|
||
fills=((14.00, 600), (14.01, 1700)),
|
||
decision_price=13.98, arrival_price=13.99, close_price=14.05,
|
||
fee=31.0),
|
||
OrderLeg(action="sell", qty=1000, fills=((9.90, 400),),
|
||
decision_price=9.95, arrival_price=9.94, close_price=9.90,
|
||
reject_reason="TIMEOUT", fee=7.0)]
|
||
r = compute_components(legs)
|
||
fill_avg = (14.00 * 600 + 14.01 * 1700) / 2300
|
||
assert abs(r["delay_cost"] - ((13.99 - 13.98) * 2300 - (9.94 - 9.95) * 400)) < 1e-9
|
||
assert abs(r["impact_cost"] - ((fill_avg - 13.99) * 2300 - (9.90 - 9.94) * 400)) < 1e-9
|
||
# 机会=未成交×(决策−收盘)×方向:卖出 600 股未成交=(9.95−9.90)×600
|
||
assert abs(r["opportunity_cost"] - (9.95 - 9.90) * 600) < 1e-9
|
||
assert abs(r["fee_total"] - 38.0) < 1e-9
|
||
# 恒等式:Σ分量 == 直算 IS(金额级残差)
|
||
assert r["identity_resid"] < 1e-6
|
||
assert r["legs_count"] == 2 and r["legs_no_anchor"] == 0
|
||
assert r["by_reason"]["TIMEOUT"] > 0 and r["by_reason_legs"]["TIMEOUT"] == 1
|
||
|
||
|
||
def test_missing_anchor_counted_not_silent():
|
||
r = compute_components([OrderLeg(action="buy", qty=100,
|
||
fills=((10.0, 100),), fee=5.0)])
|
||
assert r["legs_no_anchor"] == 1
|
||
assert r["delay_cost"] == 0.0 and r["impact_cost"] == 0.0
|
||
assert abs(r["fee_total"] - 5.0) < 1e-9 # 费用不依赖价格锚照算
|
||
|
||
|
||
def test_filled_qty_without_fill_px():
|
||
"""超时行场景:有累计成交量无逐笔价——qf 用 filled_qty,冲击不可算=0 不冒充。"""
|
||
r = compute_components([OrderLeg(action="buy", qty=9000, filled_qty=4000,
|
||
decision_price=10.5, arrival_price=10.5,
|
||
close_price=10.3)])
|
||
assert abs(r["opportunity_cost"] - (10.3 - 10.5) * 5000) < 1e-9
|
||
assert r["impact_cost"] == 0.0
|
||
assert abs(r["delay_cost"] - 0.0) < 1e-9 # 到达==决策(同锚)
|
||
|
||
|
||
def test_paper_mechanism_zero_note():
|
||
r = compute_components([])
|
||
assert r["paper"]["mechanism_zero"] is True
|
||
assert "机制性零" in r["paper"]["note"]
|