#!/usr/bin/env python3 """C14: TAIEX regime features — taiex_ma200_ratio (market above/below 200MA) + taiex_return_20d (monthly momentum). Literature: regime filter cuts false BUY signals by ~20% when market is below 200-day MA. Pass gate: dir_accuracy > 43.5% AND up_precision > 54%. """ import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) try: from dotenv import load_dotenv; load_dotenv(ROOT / ".env") except ImportError: pass import warnings; warnings.filterwarnings("ignore") import json sys.path.insert(0, str(ROOT / "scripts")) from improvement_harness import BASELINE_FEATURES, run_comparison STOCKS = ["2330", "0050", "2317", "2454", "2881"] CURRENT_FEATURES = [f for f in BASELINE_FEATURES if f not in { "macd_cross_up", "macd_cross_down", "price_volume_div", "foreign_net_vol_ratio", "trust_net_vol_ratio", "dealer_net_vol_ratio", "institutional_net_vol_ratio", "institutional_5d_net_vol_ratio", "institutional_20d_zscore", "foreign_trust_alignment", "institutional_streak", }] C14_FEATURES = CURRENT_FEATURES + [ "taiex_ma200_ratio", # TAIEX / 200-day MA — regime state (>1 = bull, <1 = bear) "taiex_return_20d", # TAIEX 20-day return — monthly momentum direction ] PASS_DIR_ACC = 43.5 PASS_UP_PREC = 54.0 def main(): print(f"C14: baseline={len(CURRENT_FEATURES)} → candidate={len(C14_FEATURES)} features") print(f"New: taiex_ma200_ratio, taiex_return_20d\n") cmp = run_comparison( feature_sets={"baseline": CURRENT_FEATURES, "c14_regime": C14_FEATURES}, label_mode="triple_barrier", stocks=STOCKS, output_path=None, pass_criterion={"dir_accuracy": PASS_DIR_ACC}, verbose=True, ) b = cmp["aggregate"].get("baseline", {}) c = cmp["aggregate"].get("c14_regime", {}) dir_delta = c.get("dir_accuracy", 0) - b.get("dir_accuracy", 0) prec_delta = c.get("up_precision", 0) - b.get("up_precision", 0) passed = ( c.get("dir_accuracy", 0) >= PASS_DIR_ACC and c.get("up_precision", 0) >= PASS_UP_PREC and dir_delta >= -0.5 and prec_delta >= -0.5 ) print("\n── Results ──────────────────────────────────────") print(f" baseline dir_acc={b.get('dir_accuracy')}% up_prec={b.get('up_precision')}%") print(f" c14_regime dir_acc={c.get('dir_accuracy')}% up_prec={c.get('up_precision')}%") print(f" Δ dir_acc={dir_delta:+.1f}pp Δ up_prec={prec_delta:+.1f}pp") print(f" Pass gate: dir>{PASS_DIR_ACC}% AND up_prec>{PASS_UP_PREC}%") print(f" Result: {'PASSED' if passed else 'FAILED'}") result = { "experiment": "C14_taiex_regime", "new_features": ["taiex_ma200_ratio", "taiex_return_20d"], "aggregate": cmp["aggregate"], "results": cmp["results"], "passed": passed, } Path("docs").mkdir(exist_ok=True) with open("docs/c14_result.json", "w") as f: json.dump(result, f, indent=2) print(f" Saved → docs/c14_result.json") if passed: print("\n ACTION: Add to FEATURE_COLUMNS in models/predictor.py:") for f in ["taiex_ma200_ratio", "taiex_return_20d"]: print(f" \"{f}\",") if __name__ == "__main__": main()