test: reproduce execution cash and long-only violations
This commit is contained in:
@@ -405,6 +405,49 @@ def test_simulate_multi_day_with_audit_records_costs_without_replay():
|
|||||||
assert result.daily_executions[1].executions == ()
|
assert result.daily_executions[1].executions == ()
|
||||||
|
|
||||||
|
|
||||||
|
def test_simulate_multi_day_with_audit_never_spends_more_cash_than_available():
|
||||||
|
"""满仓目标应按可用现金部分成交,不能用负现金隐式加杠杆。"""
|
||||||
|
result = simulate_multi_day_with_audit(
|
||||||
|
[("d1", {"A": 1.0})],
|
||||||
|
[("d1", {"A": 10.0})],
|
||||||
|
1_000.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
execution = result.daily_executions[0].executions[0]
|
||||||
|
assert result.positions[0].cash >= -1e-9
|
||||||
|
assert 0 < execution.partial_fill_pct < 1
|
||||||
|
assert execution.blocked_reason == "insufficient_cash_partial_fill"
|
||||||
|
assert result.final_portfolio_value == pytest.approx(1_000.0 - result.total_costs)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"targets",
|
||||||
|
[
|
||||||
|
{"A": -0.1},
|
||||||
|
{"A": 0.6, "B": 0.5},
|
||||||
|
{"A": float("nan")},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_simulate_multi_day_with_audit_rejects_invalid_long_only_weights(targets):
|
||||||
|
"""多日 A 股目标必须是有限、非负且合计不超过 100% 的权重。"""
|
||||||
|
with pytest.raises(ValueError, match="target weights"):
|
||||||
|
simulate_multi_day_with_audit(
|
||||||
|
[("d1", targets)],
|
||||||
|
[("d1", {"A": 10.0, "B": 10.0})],
|
||||||
|
1_000.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_simulate_multi_day_with_audit_requires_price_for_existing_holding():
|
||||||
|
"""已有持仓缺价时无法可信估值,必须失败而不是把市值记为零。"""
|
||||||
|
with pytest.raises(ValueError, match="missing price for held asset A"):
|
||||||
|
simulate_multi_day_with_audit(
|
||||||
|
[("d1", {"A": 1.0}), ("d2", {"A": 1.0})],
|
||||||
|
[("d1", {"A": 10.0}), ("d2", {})],
|
||||||
|
1_000.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_simulate_multi_day_with_audit_records_unpriced_target_rejection():
|
def test_simulate_multi_day_with_audit_records_unpriced_target_rejection():
|
||||||
"""缺失价格的目标不能吞掉现金,且必须留下拒绝原因。"""
|
"""缺失价格的目标不能吞掉现金,且必须留下拒绝原因。"""
|
||||||
result = simulate_multi_day_with_audit(
|
result = simulate_multi_day_with_audit(
|
||||||
|
|||||||
Reference in New Issue
Block a user