Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """C15: Trend quality features β trend_efficiency_5d (directional purity of 5d move) | |
| + return_accel_5d (momentum acceleration). Pure OHLCV, no external data dependencies. | |
| Source: arxiv.org/html/2512.12924v1 β "trending vs choppy behavior" as top feature class. | |
| 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", | |
| }] | |
| C15_FEATURES = CURRENT_FEATURES + [ | |
| "trend_efficiency_5d", # |return_5d| / (vol_20d * sqrt(5)) β clean trend vs noise | |
| "return_accel_5d", # return_5d.diff(5) β momentum acceleration | |
| ] | |
| PASS_DIR_ACC = 43.5 | |
| PASS_UP_PREC = 54.0 | |
| def main(): | |
| print(f"C15: baseline={len(CURRENT_FEATURES)} β candidate={len(C15_FEATURES)} features") | |
| print(f"New: trend_efficiency_5d, return_accel_5d\n") | |
| cmp = run_comparison( | |
| feature_sets={"baseline": CURRENT_FEATURES, "c15_trend": C15_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("c15_trend", {}) | |
| 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" c15_trend 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": "C15_trend_quality", | |
| "new_features": ["trend_efficiency_5d", "return_accel_5d"], | |
| "aggregate": cmp["aggregate"], | |
| "results": cmp["results"], | |
| "passed": passed, | |
| } | |
| Path("docs").mkdir(exist_ok=True) | |
| with open("docs/c15_result.json", "w") as f: | |
| json.dump(result, f, indent=2) | |
| print(f" Saved β docs/c15_result.json") | |
| if passed: | |
| print("\n ACTION: Add to FEATURE_COLUMNS in models/predictor.py:") | |
| for f in ["trend_efficiency_5d", "return_accel_5d"]: | |
| print(f" \"{f}\",") | |
| if __name__ == "__main__": | |
| main() | |