DockerSpace / tests /test_ml_method_ladder.py
DennisChan0909's picture
feat: integrate local architecture with HF Space
e610a2f
Raw
History Blame Contribute Delete
3.35 kB
import json
import numpy as np
import pandas as pd
from scripts.run_ml_method_ladder import (
_date_group_sizes,
_ranking_metrics,
_ranker_relevance,
_split_panel,
build_sequence_features,
render_html_report,
)
def test_build_sequence_features_uses_current_and_prior_rows_only():
df = pd.DataFrame(
{
"close": [10, 11, 12, 11, 13, 14, 15, 15, 16, 18, 19, 20],
"high": [11, 12, 13, 12, 14, 15, 16, 16, 17, 19, 20, 21],
"low": [9, 10, 11, 10, 12, 13, 14, 14, 15, 17, 18, 19],
"volume": [100, 110, 120, 130, 140, 160, 180, 190, 200, 220, 240, 260],
}
)
seq = build_sequence_features(df)
assert "seq_ret_5_sum" in seq
assert "seq_sax_up_ratio_10" in seq
assert len(seq) == len(df)
assert np.isfinite(seq.to_numpy()).all()
def test_split_panel_embargoes_label_horizon_between_train_and_validation():
rows = []
for stock in ["2330", "2454"]:
for idx in range(180):
rows.append(
{
"stock": stock,
"date": f"2026-01-{(idx % 28) + 1:02d}",
"row_idx": idx,
"label": 1 if idx % 3 == 0 else 0,
"f": float(idx),
}
)
panel = pd.DataFrame(rows)
train, valid, split = _split_panel(panel, train_ratio=0.7)
assert not train.empty
assert not valid.empty
for stock, info in split["stocks"].items():
assert info["validation_start_idx"] - info["train_end_idx"] > 1
assert train[train["stock"] == stock]["row_idx"].max() < valid[valid["stock"] == stock]["row_idx"].min()
def test_ranking_metrics_scores_top_k_hits_by_date():
frame = pd.DataFrame(
{
"date": ["2026-01-01"] * 4 + ["2026-01-02"] * 4,
"stock": list("ABCDEFGH"),
"label": [1, 0, -1, 1, 0, 1, -1, 1],
"p_buy": [0.9, 0.8, 0.1, 0.2, 0.2, 0.95, 0.1, 0.8],
"pred": [1, 1, -1, 0, 0, 1, -1, 1],
}
)
metrics = _ranking_metrics(frame, top_k=2)
assert metrics["dates"] == 2
assert metrics["hit_rate"] == 75.0
def test_ranker_helpers_build_date_groups_and_non_negative_relevance():
frame = pd.DataFrame(
{
"date": ["2026-01-01", "2026-01-01", "2026-01-02"],
"label": [-1, 0, 1],
}
)
assert _date_group_sizes(frame) == [2, 1]
assert _ranker_relevance(frame["label"]).to_list() == [0, 1, 2]
def test_render_html_report_contains_method_rows():
payload = {
"generated_at": "2026-05-21T00:00:00+00:00",
"stocks": ["2330"],
"split": {"validation_date_range": ["2026-01-01", "2026-02-01"]},
"methods": {
"panel_global_model": {
"baseline": {"accuracy": 40, "up_precision": 50},
"candidate": {"accuracy": 44, "up_precision": 51, "n_signals": 10},
"deltas": {"accuracy_delta_pp": 4, "up_precision_delta_pp": 1},
"gate": {"passed": True},
},
"ranking_from_panel": {"ranking": {"baseline": {}, "candidate": {}, "deltas": {}}},
},
}
html = render_html_report(payload)
assert "ML Method Ladder Validation" in html
assert "panel_global_model" in html
assert "PASS" in html