Spaces:
Running
Running
File size: 4,598 Bytes
e610a2f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | import json
from scripts.render_factor_weight_grid_report import generate_html_report, render_report
def _grid_payload():
candidate = {
"config": {"buy_bull_weight": 0.03, "buy_bear_weight": -0.01},
"passed": True,
"gate": {
"checks": {
"accuracy_delta": True,
"buy_precision_delta": True,
"signal_ratio": True,
"buy_count_ratio": True,
},
"signal_ratio": 1.04,
"buy_count_ratio": 1.25,
},
"validation": {
"metrics": {
"accuracy": 41.16,
"direction_accuracy": 46.27,
"buy_precision": 50.46,
"sell_precision": 39.83,
"signal_count": 2671,
"coverage": 0.7949,
},
"deltas": {
"accuracy_delta_pp": 2.83,
"direction_accuracy_delta_pp": 2.09,
"buy_precision_delta_pp": 1.24,
"sell_precision_delta_pp": 0.79,
"signal_count_delta": 111,
"coverage_delta": 0.033,
},
},
}
return {
"experiment": "factor_weight_grid_search",
"generated_at": "2026-05-18T00:00:00+00:00",
"stocks": ["2330", "0050"],
"factors": {"bull_column": "oldwang_bull_score", "bear_column": "oldwang_bear_score"},
"grid_preset": "wide",
"result": {
"split": {
"tune_events": 10,
"validation_events": 8,
"tune_date_range": ["2025-01-01", "2025-06-01"],
"validation_date_range": ["2025-06-02", "2025-12-31"],
},
"grid_size": 63504,
"thresholds": {
"min_accuracy_delta_pp": 2.0,
"min_buy_precision_delta_pp": 0.0,
"min_signal_ratio": 0.7,
"max_buy_count_ratio": 1.3,
},
"baseline": {
"validation": {
"accuracy": 38.33,
"direction_accuracy": 44.18,
"buy_precision": 49.23,
"sell_precision": 39.04,
"signal_count": 2560,
"coverage": 0.7619,
}
},
"passing_count": 139,
"best_passing": candidate,
"top_passing": [candidate],
"top_overall": [candidate],
},
}
def test_generate_html_report_contains_validation_details():
html = generate_html_report(
_grid_payload(),
popular_payload={
"source": "yahoo_rank",
"count": 2,
"fallback_used": True,
"stocks": [{"rank": 1, "code": "2330", "name": "台積電", "source": "yahoo_rank"}],
},
raw_json_path="docs/result.json",
command="venv/bin/python scripts/search_factor_weight_grid.py ...",
)
assert "Factor Weight Grid Search Report" in html
assert "Grid Size" in html
assert "63504" in html
assert "oldwang_bull_score" in html
assert "buy_bull_weight" in html
assert "台積電" in html
assert "venv/bin/python" in html
def test_render_report_writes_html(tmp_path):
input_json = tmp_path / "grid.json"
popular_json = tmp_path / "popular.json"
output_html = tmp_path / "report.html"
input_json.write_text(json.dumps(_grid_payload(), ensure_ascii=False))
popular_json.write_text(
json.dumps({"source": "fixture", "stocks": [{"code": "2330", "rank": 1}]}, ensure_ascii=False)
)
output = render_report(input_json=input_json, popular_json=popular_json, output_html=output_html)
assert output.exists()
assert "Top Passing Candidates" in output.read_text()
def test_generate_html_report_includes_external_factor_metadata():
payload = _grid_payload()
payload["experiment"] = "external_factor_weight_grid_search"
payload["external_factors"] = {
"csv_paths": ["data/external/chipk_scores.csv", "data/external/crowd_scores.csv"],
"stock_column": "stock",
"date_column": "date",
"bull_column": "bull_score",
"bear_column": "bear_score",
"combine": "sum",
"merge_summary": {"event_count": 100, "matched_event_count": 80, "coverage": 0.8},
"promotion_note": "validation-only",
}
html = generate_html_report(payload)
assert "External Factor Source" in html
assert "chipk_scores.csv" in html
assert "80 / 100" in html
assert "validation-only" in html
|