feat: compare legacy and live ranking universes
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
from datetime import date
|
||||
from datetime import date, timedelta
|
||||
|
||||
from scripts.run_daily_reentry_matrix import PrecomputedDailyEngine, ReentryPolicy
|
||||
import pytest
|
||||
|
||||
from scripts.run_daily_reentry_matrix import (
|
||||
PrecomputedDailyEngine,
|
||||
ReentryPolicy,
|
||||
_live_universe_rank_map,
|
||||
)
|
||||
|
||||
|
||||
RANKING_KEY = "strategy_rank"
|
||||
@@ -95,3 +101,72 @@ def test_two_session_confirmation_excludes_stop_day_close():
|
||||
emitted = _call(policy, ORD + 2, state, 2)
|
||||
assert emitted is not None
|
||||
assert emitted["_reentry_reason"] == "two_qualified_post_stop_closes"
|
||||
|
||||
|
||||
def _rank_observation(
|
||||
symbol: str,
|
||||
*,
|
||||
raw: float,
|
||||
residual: float,
|
||||
volatility: float,
|
||||
) -> dict:
|
||||
return {
|
||||
"symbol": symbol,
|
||||
"date": date.fromordinal(ORD).isoformat(),
|
||||
"ranking_period": ("date", ORD),
|
||||
"momentum": raw,
|
||||
"residual_momentum": residual,
|
||||
"vol_6m": volatility,
|
||||
}
|
||||
|
||||
|
||||
def test_live_universe_rank_uses_each_ticker_once_and_residual_when_available():
|
||||
observations = [
|
||||
_rank_observation("AAA", raw=0.1, residual=0.3, volatility=0.1),
|
||||
_rank_observation("BBB", raw=0.3, residual=0.1, volatility=0.2),
|
||||
_rank_observation("CCC", raw=0.2, residual=0.2, volatility=0.3),
|
||||
]
|
||||
first_benchmark_day = date.fromordinal(ORD) - timedelta(days=300)
|
||||
benchmark = {
|
||||
first_benchmark_day + timedelta(days=offset): 100.0
|
||||
for offset in range(252)
|
||||
}
|
||||
|
||||
ranks = _live_universe_rank_map(observations, benchmark, 0.8)
|
||||
|
||||
assert ranks[("AAA", date.fromordinal(ORD).isoformat())] == {
|
||||
"momentum_percentile": 100.0,
|
||||
"volatility_percentile": 0.0,
|
||||
"strategy_rank": 80.0,
|
||||
}
|
||||
assert ranks[("BBB", date.fromordinal(ORD).isoformat())][
|
||||
"momentum_percentile"
|
||||
] == 0.0
|
||||
assert ranks[("CCC", date.fromordinal(ORD).isoformat())][
|
||||
"strategy_rank"
|
||||
] == 60.0
|
||||
|
||||
|
||||
def test_live_universe_rank_uses_raw_fallback_before_benchmark_is_ready():
|
||||
observations = [
|
||||
_rank_observation("AAA", raw=0.1, residual=0.3, volatility=0.1),
|
||||
_rank_observation("BBB", raw=0.3, residual=0.1, volatility=0.2),
|
||||
]
|
||||
|
||||
ranks = _live_universe_rank_map(observations, {}, 0.8)
|
||||
|
||||
assert ranks[("AAA", date.fromordinal(ORD).isoformat())][
|
||||
"momentum_percentile"
|
||||
] == 0.0
|
||||
assert ranks[("BBB", date.fromordinal(ORD).isoformat())][
|
||||
"momentum_percentile"
|
||||
] == 100.0
|
||||
|
||||
|
||||
def test_live_universe_rank_rejects_duplicate_ticker_date():
|
||||
observation = _rank_observation(
|
||||
"AAA", raw=0.1, residual=0.2, volatility=0.1
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="one observation"):
|
||||
_live_universe_rank_map([observation, dict(observation)], {}, 0.8)
|
||||
|
||||
Reference in New Issue
Block a user