Files
stock/backend/tests/test_events.py
2026-09-09 15:07:58 +08:00

61 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""事件回测纯函数:入场/出场索引语义、汇总统计(含空样本与分年)。"""
from __future__ import annotations
from datetime import datetime
import pytest
from app.backtest.events import _entry_exit_indices, _stats_block
from app.schemas import EventBacktestSpec
def _spec(holding_days: int = 5) -> EventBacktestSpec:
return EventBacktestSpec.model_validate({
"holding_days": holding_days,
"entry": {"indicator": []},
})
def test_entry_exit_next_day_and_hold():
spec = _spec(holding_days=5)
assert _entry_exit_indices(10, spec, n=100) == (11, 16) # 次日入,持有 5 日出
def test_entry_exit_out_of_range_none():
spec = _spec(holding_days=5)
# 出场索引越界exit_i >= n
assert _entry_exit_indices(94, spec, n=100) is None
assert _entry_exit_indices(99, spec, n=100) is None
def test_entry_exit_boundary_exact_fit():
spec = _spec(holding_days=5)
# exit_i == n-1 恰好可用
assert _entry_exit_indices(93, spec, n=100) == (94, 99)
def test_stats_block_empty():
s = _stats_block([])
assert s["samples"] == 0 and s["stocks"] == 0
assert s["by_year"] == []
assert s["win_rate"] == 0.0
def test_stats_block_aggregates():
trades = [
{"ts_code": "000001.SZ", "ret_pct": 10.0,
"entry_date": datetime(2024, 1, 5), "entry_price": 10, "exit_price": 11},
{"ts_code": "000001.SZ", "ret_pct": -4.0,
"entry_date": datetime(2024, 3, 6), "entry_price": 10, "exit_price": 9.6},
{"ts_code": "600519.SH", "ret_pct": 2.0,
"entry_date": datetime(2023, 5, 10), "entry_price": 10, "exit_price": 10.2},
]
s = _stats_block(trades)
assert s["samples"] == 3
assert s["stocks"] == 2
assert s["mean_pct"] == pytest.approx((10.0 - 4.0 + 2.0) / 3, abs=1e-3) # 统计块保留 3 位小数
assert s["win_rate"] == round(2 / 3 * 100, 2)
assert [y["year"] for y in s["by_year"]] == [2023, 2024] # 分年升序
assert s["by_year"][1]["samples"] == 2
assert s["max_pct"] == 10.0 and s["min_pct"] == -4.0