DockerSpace / scripts /backtest_c13.py
DennisChan0909's picture
feat: integrate local architecture with HF Space
e610a2f
Raw
History Blame Contribute Delete
3.4 kB
#!/usr/bin/env python3
"""C13: Add SOX + TNX cross-asset features (sox_ret_1d, sox_ret_5d, sox_ma20_ratio,
tnx_level, tnx_change_5d). Already computed in fetch_df, just not in FEATURE_COLUMNS.
Pass gate: dir_accuracy > 43.5% AND up_precision > 54% (updated post-C5 thresholds).
"""
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",
}]
SOX_TNX_FEATURES = CURRENT_FEATURES + [
"sox_ret_1d",
"sox_ret_5d",
"sox_ma20_ratio",
"tnx_level",
"tnx_change_5d",
]
PASS_DIR_ACC = 43.5
PASS_UP_PREC = 54.0
def main():
print(f"C13: baseline={len(CURRENT_FEATURES)} features β†’ candidate={len(SOX_TNX_FEATURES)} features")
print(f"New features: sox_ret_1d, sox_ret_5d, sox_ma20_ratio, tnx_level, tnx_change_5d\n")
cmp = run_comparison(
feature_sets={"baseline": CURRENT_FEATURES, "sox_tnx": SOX_TNX_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("sox_tnx", {})
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" sox_tnx 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": "C13_sox_tnx",
"new_features": ["sox_ret_1d", "sox_ret_5d", "sox_ma20_ratio", "tnx_level", "tnx_change_5d"],
"aggregate": cmp["aggregate"],
"results": cmp["results"],
"passed": passed,
}
Path("docs").mkdir(exist_ok=True)
with open("docs/c13_result.json", "w") as f:
json.dump(result, f, indent=2)
print(f" Saved β†’ docs/c13_result.json")
if passed:
print("\n ACTION: Add these to FEATURE_COLUMNS in models/predictor.py:")
for f in ["sox_ret_1d", "sox_ret_5d", "sox_ma20_ratio", "tnx_level", "tnx_change_5d"]:
print(f" \"{f}\",")
if __name__ == "__main__":
main()