You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fithia2/tests/unit/test_enrich_peer_surprise_f...

146 lines
5.5 KiB
Python

from __future__ import annotations
import sys
import importlib.util
from pathlib import Path
import pandas as pd
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
_SCRIPT_PATH = Path(__file__).resolve().parents[2] / "scripts" / "enrich_peer_surprise_features.py"
_SPEC = importlib.util.spec_from_file_location("enrich_peer_surprise_features", _SCRIPT_PATH)
assert _SPEC and _SPEC.loader
_MODULE = importlib.util.module_from_spec(_SPEC)
sys.modules[_SPEC.name] = _MODULE
_SPEC.loader.exec_module(_MODULE)
compute_peer_features = _MODULE.compute_peer_features
def test_compute_peer_features_uses_prior_same_sector_peers_only() -> None:
rows = pd.DataFrame(
[
{
"ticker": "AAA",
"event_date": "2022-01-10",
"event_type": "earnings_release",
"sector": "Technology",
"earnings_surprise_pct": 10.0,
"sue_hist_mean_4q": 5.0,
"sue_hist_pos_rate_4q": 0.75,
"__split_name": "train",
"__split_order": 0,
"__split_row_idx": 0,
"__event_date_obj": pd.Timestamp("2022-01-10").date(),
},
{
"ticker": "BBB",
"event_date": "2022-02-10",
"event_type": "earnings_release",
"sector": "Technology",
"earnings_surprise_pct": 20.0,
"sue_hist_mean_4q": 8.0,
"sue_hist_pos_rate_4q": 1.0,
"__split_name": "train",
"__split_order": 0,
"__split_row_idx": 1,
"__event_date_obj": pd.Timestamp("2022-02-10").date(),
},
{
"ticker": "CCC",
"event_date": "2022-03-10",
"event_type": "earnings_release",
"sector": "Technology",
"earnings_surprise_pct": 25.0,
"sue_hist_mean_4q": 6.0,
"sue_hist_pos_rate_4q": 0.5,
"__split_name": "valid",
"__split_order": 1,
"__split_row_idx": 0,
"__event_date_obj": pd.Timestamp("2022-03-10").date(),
},
{
"ticker": "AAA",
"event_date": "2022-04-10",
"event_type": "earnings_release",
"sector": "Technology",
"earnings_surprise_pct": 15.0,
"sue_hist_mean_4q": 7.0,
"sue_hist_pos_rate_4q": 0.75,
"__split_name": "test",
"__split_order": 2,
"__split_row_idx": 0,
"__event_date_obj": pd.Timestamp("2022-04-10").date(),
},
]
)
enriched = compute_peer_features(rows)
ccc = enriched.loc[enriched["ticker"] == "CCC"].iloc[0]
assert ccc["peer_sector_event_count_365d"] == 2.0
assert ccc["peer_sector_surprise_median_365d"] == 15.0
assert ccc["peer_relative_surprise_pct_365d"] == 10.0
assert ccc["peer_sector_sue_hist_mean_4q_median_365d"] == 6.5
assert ccc["peer_relative_sue_hist_mean_4q_365d"] == -0.5
aaa_late = enriched.loc[(enriched["ticker"] == "AAA") & (enriched["event_date"] == "2022-04-10")].iloc[0]
assert aaa_late["peer_sector_event_count_365d"] == 2.0
assert aaa_late["peer_sector_surprise_median_365d"] == 22.5
assert aaa_late["peer_relative_surprise_pct_365d"] == -7.5
def test_compute_peer_features_ignores_same_day_and_other_sectors() -> None:
rows = pd.DataFrame(
[
{
"ticker": "AAA",
"event_date": "2022-01-10",
"event_type": "earnings_release",
"sector": "Technology",
"earnings_surprise_pct": 10.0,
"sue_hist_mean_4q": 4.0,
"sue_hist_pos_rate_4q": 0.5,
"__split_name": "train",
"__split_order": 0,
"__split_row_idx": 0,
"__event_date_obj": pd.Timestamp("2022-01-10").date(),
},
{
"ticker": "BBB",
"event_date": "2022-01-10",
"event_type": "earnings_release",
"sector": "Technology",
"earnings_surprise_pct": 12.0,
"sue_hist_mean_4q": 6.0,
"sue_hist_pos_rate_4q": 0.75,
"__split_name": "train",
"__split_order": 0,
"__split_row_idx": 1,
"__event_date_obj": pd.Timestamp("2022-01-10").date(),
},
{
"ticker": "CCC",
"event_date": "2022-01-20",
"event_type": "earnings_release",
"sector": "Healthcare",
"earnings_surprise_pct": 15.0,
"sue_hist_mean_4q": 8.0,
"sue_hist_pos_rate_4q": 1.0,
"__split_name": "valid",
"__split_order": 1,
"__split_row_idx": 0,
"__event_date_obj": pd.Timestamp("2022-01-20").date(),
},
]
)
enriched = compute_peer_features(rows)
same_day_bbb = enriched.loc[enriched["ticker"] == "BBB"].iloc[0]
health_ccc = enriched.loc[enriched["ticker"] == "CCC"].iloc[0]
assert pd.isna(same_day_bbb["peer_sector_surprise_median_365d"])
assert same_day_bbb["peer_sector_event_count_365d"] == 0.0
assert pd.isna(health_ccc["peer_sector_surprise_median_365d"])
assert health_ccc["peer_sector_event_count_365d"] == 0.0