1import numpy as np2import pandas as pd34from wp46.calendars.sessions import assign_sessions, xnys_early_closes5from wp46.models.baselines import HARRV, _har_X6from wp46.realized_measures import session_measures7from wp46.scoring.losses import mse, qlike, qlike_zero_safe8910def test_qlike_properties():11 y = np.array([1.0, 2.0, 0.5]); h = y.copy()12 assert np.allclose(qlike(y, h), 0.0)13 assert np.all(qlike(y, h * 1.5) > 0) and np.all(qlike(y, h * 0.5) > 0)14 # zero-safe form equals qlike when y > 0 and is finite when y == 015 assert np.allclose(qlike_zero_safe(y, h * 1.3), qlike(y, h * 1.3))16 assert np.isfinite(qlike_zero_safe(np.array([0.0]), np.array([2.0])))[0]17 assert mse(y, h)[0] == 0.0181920def test_session_measures_units_and_grid():21 # 391 one-minute closes with constant 0.1% log return -> rv_1m = 390 * 0.01 = 3.9 (percent^2)22 minutes = np.arange(391)23 closes = 100.0 * np.exp(0.001 * minutes)24 m = session_measures(minutes, closes)25 assert abs(m["rv_1m"] - 3.9) < 1e-926 assert abs(m["rv_5m"] - 78 * 0.25) < 1e-9 # 78 five-minute returns of 0.5%27 assert m["n_5m"] == 78 and m["n_bars"] == 39128 assert abs(m["rv_5m_ss"] - m["rv_5m"]) < 0.3 # offset grids have 77 returns instead of 78 (constant drift)29 assert m["rsv_pos_5m"] > 0 and m["rsv_neg_5m"] == 0303132def test_xnys_early_closes_known_dates():33 ec = xnys_early_closes("2024-01-01", "2024-12-31")34 assert "2024-07-03" in ec and "2024-11-29" in ec and "2024-12-24" in ec35 assert "2024-03-08" not in ec363738def test_assign_sessions_futures_window():39 ts = pd.Series(pd.to_datetime(["2024-07-01T21:30:00Z", "2024-07-01T22:30:00Z", "2024-07-02T13:30:00Z", "2024-07-02T21:30:00Z"]))40 s = assign_sessions(ts, "futures")41 # 17:30 ET Jul 1 is in the maintenance break (no session); 18:30 ET Jul 1 and 09:30 ET Jul 2 belong to session Jul 2; 17:30 ET Jul 2 is a break42 assert not s["in_window"][0] and s["in_window"][1] and s["in_window"][2] and not s["in_window"][3]43 assert str(s["session"][1].date()) == "2024-07-02" and str(s["session"][2].date()) == "2024-07-02"444546def test_har_direct_targets_and_regressors():47 y = np.arange(1.0, 101.0)48 X = _har_X(y)49 assert np.isnan(X[20]).all() and X[21, 1] == 22.0 and X[21, 2] == np.mean(y[17:22]) and X[21, 3] == np.mean(y[0:22])50 f = HARRV(horizons=(1, 5)).fit(np.zeros(100), y)51 fc = HARRV(horizons=(1, 5)).forecast(f, np.zeros(100), y, 5)52 # linear series: h=1 forecast = 101, h=5 cumulative = 101+...+105 = 51553 assert abs(fc.cumulative(1) - 101) < 1e-6 and abs(fc.cumulative(5) - 515) < 1e-554