Spaces:
Running
Running
| import json | |
| from types import SimpleNamespace | |
| import numpy as np | |
| import pandas as pd | |
| from scripts.run_44factor_gate_variant_report import ( | |
| _bootstrap_buy_delta_ci, | |
| _checks, | |
| _load_locked_finalists, | |
| apply_factor_transform_profile, | |
| build_factor_set, | |
| build_variants, | |
| render_html, | |
| split_events_by_date, | |
| ) | |
| from scripts.search_multi_factor_weight_config import MultiFactorConfig | |
| def _args(**overrides): | |
| values = { | |
| "min_buy_precision_delta_pp": 3.0, | |
| "research_min_sell_precision_delta_pp": 0.0, | |
| "strict_min_sell_precision_delta_pp": 2.0, | |
| "min_direction_accuracy_delta_pp": 0.0, | |
| "min_signal_ratio": 0.70, | |
| "min_buy_signal_ratio": 0.70, | |
| } | |
| values.update(overrides) | |
| return SimpleNamespace(**values) | |
| def test_split_events_by_date_keeps_dates_isolated_and_purges_later_slices(): | |
| dates = pd.date_range("2026-01-01", periods=10, freq="D").strftime("%Y-%m-%d") | |
| events = pd.DataFrame([{"date": date, "stock": stock} for date in dates for stock in ["1101", "2330"]]) | |
| frames, manifest = split_events_by_date(events, ratios=(0.6, 0.2, 0.2), purge_days=1) | |
| discovery = set(frames["discovery"]["date"]) | |
| calibration = set(frames["calibration"]["date"]) | |
| confirmation = set(frames["confirmation"]["date"]) | |
| assert not discovery & calibration | |
| assert not discovery & confirmation | |
| assert not calibration & confirmation | |
| assert manifest["slices"]["discovery"]["end"] == "2026-01-06" | |
| assert manifest["slices"]["calibration"]["start"] == "2026-01-08" | |
| assert manifest["slices"]["confirmation"]["start"] == "2026-01-10" | |
| def test_checks_keep_research_and_strict_sell_floors_separate(): | |
| config = MultiFactorConfig(weights={f"factor_{index}": 0.01 for index in range(44)}) | |
| checks = _checks( | |
| args=_args(), | |
| config=config, | |
| deltas={"buy_precision_delta_pp": 3.5, "sell_precision_delta_pp": 0.5, "direction_accuracy_delta_pp": 0.1}, | |
| signal_ratio=0.9, | |
| buy_signal_ratio=0.8, | |
| ci={"available": True, "lower_95_pp": 0.2}, | |
| covered_stock_count=1000, | |
| expected_factor_count=44, | |
| ) | |
| assert all(checks["research_screen"].values()) | |
| assert checks["strict_promotion_gate"]["sell_precision_delta"] is False | |
| def test_checks_reject_buy_signal_collapse_even_when_overall_ratio_passes(): | |
| config = MultiFactorConfig(weights={f"factor_{index}": 0.01 for index in range(44)}) | |
| checks = _checks( | |
| args=_args(), | |
| config=config, | |
| deltas={"buy_precision_delta_pp": 4.0, "sell_precision_delta_pp": 3.0, "direction_accuracy_delta_pp": 0.1}, | |
| signal_ratio=0.95, | |
| buy_signal_ratio=0.2, | |
| ci={"available": True, "lower_95_pp": 1.0}, | |
| covered_stock_count=1000, | |
| expected_factor_count=44, | |
| ) | |
| assert checks["research_screen"]["signal_ratio"] is True | |
| assert checks["research_screen"]["buy_signal_ratio"] is False | |
| def test_bootstrap_buy_delta_ci_is_date_blocked_and_deterministic(): | |
| events = pd.DataFrame( | |
| { | |
| "date": ["2026-01-01"] * 2 + ["2026-01-02"] * 2 + ["2026-01-03"] * 2, | |
| "y_true": [1, -1, 1, -1, -1, 1], | |
| } | |
| ) | |
| baseline = np.array([1, 1, 1, 1, 1, 1]) | |
| candidate = np.array([1, 0, 1, 0, 0, 1]) | |
| first = _bootstrap_buy_delta_ci(events, baseline, candidate, iterations=50, random_seed=7) | |
| second = _bootstrap_buy_delta_ci(events, baseline, candidate, iterations=50, random_seed=7) | |
| assert first == second | |
| assert first["available"] is True | |
| assert first["iterations"] == 50 | |
| def test_load_locked_finalists_replays_saved_config_without_search(tmp_path): | |
| config = {"weights": {f"factor_{index}": 0.01 for index in range(44)}, "hold_bias": 0.02} | |
| path = tmp_path / "finalists.json" | |
| path.write_text(json.dumps({"locked_finalists": [{"name": "winner", "variant_id": "baseline_ungated", "config": config}]})) | |
| variants = {item.variant_id: item for item in build_variants([-0.95], recent_break_sessions=5)} | |
| finalists = _load_locked_finalists(path, variants) | |
| assert finalists[0][0] == "winner" | |
| assert finalists[0][1].hold_bias == 0.02 | |
| assert finalists[0][2].variant_id == "baseline_ungated" | |
| def test_factor_transform_profile_is_candidate_only_and_reports_changes(): | |
| events = pd.DataFrame( | |
| { | |
| "factor__oldwang_guard": [0.5, -0.25], | |
| "factor__big_player_buy": [0.4, 0.2], | |
| "factor__volume_surge": [0.1, -0.1], | |
| } | |
| ) | |
| transformed, manifest = apply_factor_transform_profile(events, "flip_inverted_zero_low_noisy_v1") | |
| assert events["factor__oldwang_guard"].tolist() == [0.5, -0.25] | |
| assert transformed["factor__oldwang_guard"].tolist() == [-0.5, 0.25] | |
| assert transformed["factor__big_player_buy"].tolist() == [0.0, 0.0] | |
| assert transformed["factor__volume_surge"].tolist() == [0.1, -0.1] | |
| assert "oldwang_guard" in manifest["flipped"] | |
| assert "big_player_buy" in manifest["zeroed"] | |
| def test_split_problem_factor_set_replaces_aggregate_factors_with_nonzero_research_components(): | |
| seed = { | |
| "oldwang_guard": 0.0, | |
| "candle_shadow": 0.2, | |
| "lower_shadow": 0.01, | |
| "bt_yang_gao_pao": 0.03, | |
| "bt_bull_engulf": 0.04, | |
| "volume_surge": 0.01, | |
| } | |
| weights, manifest = build_factor_set(seed, "split_problem_v1") | |
| assert "oldwang_guard" not in weights | |
| assert "candle_shadow" not in weights | |
| assert "oldwang_guard_support" in weights | |
| assert "oldwang_guard_break_risk" in weights | |
| assert "candle_lower_support" in weights | |
| assert "candle_upper_pressure" in weights | |
| assert "bt_yang_gao_pao_risk" in weights | |
| assert "bt_bull_engulf_risk" in weights | |
| assert weights["oldwang_guard_support"] == 0.01 | |
| assert all(value >= 0.01 for value in weights.values()) | |
| assert manifest["factor_set"] == "split_problem_v1" | |
| def test_regime_reversal_factor_set_replaces_inverted_candidates_without_production_defaults(): | |
| seed = { | |
| "oldwang_trend": 0.02, | |
| "oldwang_guard": 0.0, | |
| "intraday_60k_volume_low_guard": 0.03, | |
| "macd_momentum": 0.04, | |
| "rsi_trend": 0.05, | |
| "bt_yi_yin_ya_breakout": 0.06, | |
| "tej_macro_risk_proxy": 0.07, | |
| "volume_surge": 0.01, | |
| } | |
| weights, manifest = build_factor_set(seed, "regime_reversal_v1") | |
| for replaced in [ | |
| "oldwang_trend", | |
| "oldwang_guard", | |
| "intraday_60k_volume_low_guard", | |
| "macd_momentum", | |
| "rsi_trend", | |
| "bt_yi_yin_ya_breakout", | |
| "tej_macro_risk_proxy", | |
| ]: | |
| assert replaced not in weights | |
| assert "oldwang_trend_reversal_pressure" in weights | |
| assert "oldwang_guard_lowbase_support" in weights | |
| assert "oldwang_guard_highbase_risk" in weights | |
| assert "intraday_60k_fresh_low_guard" in weights | |
| assert "intraday_60k_stale_guard_risk" in weights | |
| assert "macd_reversal_pressure" in weights | |
| assert "rsi_trend_reversal" in weights | |
| assert "bt_yi_yin_ya_breakout_risk" in weights | |
| assert "tej_macro_risk_contrarian" in weights | |
| assert weights["oldwang_guard_lowbase_support"] == 0.01 | |
| assert all(value >= 0.01 for value in weights.values()) | |
| assert manifest["factor_set"] == "regime_reversal_v1" | |
| def test_render_html_includes_filterable_complete_config_table(tmp_path): | |
| output = tmp_path / "report.html" | |
| payload = { | |
| "strict_promotion_gate": {"proposed_golden_config": None}, | |
| "research_screen": {"passing_count": 0}, | |
| "covered_stocks": ["1101"], | |
| "comparison_matrix": [ | |
| { | |
| "name": "candidate_00001", | |
| "variant_id": "baseline_ungated", | |
| "deltas": {"buy_precision_delta_pp": 1.0, "sell_precision_delta_pp": 0.0, "direction_accuracy_delta_pp": 0.0}, | |
| "signal_ratio": 1.0, | |
| "buy_signal_ratio": 1.0, | |
| "research_passed": False, | |
| "config": {"weights": {"factor": 0.01}, "hold_bias": 0.0}, | |
| } | |
| ], | |
| "locked_finalists": [], | |
| "confirmation_results": [], | |
| "run_manifest": {}, | |
| "failure_summary": {}, | |
| "warnings": [], | |
| } | |
| render_html(payload, output) | |
| text = output.read_text() | |
| assert "All calibration combinations" in text | |
| assert "filterRows()" in text | |
| assert "candidate_00001" in text | |