From 55529a4c62c5be59cee3d652031c8666e3c08633 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Aug 2026 20:05:28 +0000 Subject: [PATCH 1/4] Add VIX threshold-crossing backtest on QQQ Signal: VIX prior-day High < threshold and current-day High >= threshold; buy QQQ at the close, measure 5/20/60-day forward returns for thresholds 17-22. Reports N, mean, median, win rate, best/worst per horizon and compares against a QQQ buy-and-hold benchmark. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01JXFxuoYQvap2iq4EHbf9GW --- vix_qqq_backtest.py | 168 ++++++ vix_qqq_results.json | 1308 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1476 insertions(+) create mode 100644 vix_qqq_backtest.py create mode 100644 vix_qqq_results.json diff --git a/vix_qqq_backtest.py b/vix_qqq_backtest.py new file mode 100644 index 0000000..8152d39 --- /dev/null +++ b/vix_qqq_backtest.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +""" +VIX threshold-crossing backtest on QQQ. + +Strategy / signal +----------------- +For each threshold T in {17, 18, 19, 20, 21, 22}: + A signal fires on day D when: + * VIX High on day D-1 (previous trading day) < T + * VIX High on day D (current day) >= T + On a signal, buy QQQ at day D's close. + Measure the forward return of QQQ close over the next 5 / 20 / 60 trading days. + +For each threshold and horizon we report: + sample count, mean, median, win rate, best, worst. + +Benchmark: QQQ buy & hold average forward return over the same 5/20/60-day +horizons, computed over every trading day (so the strategy's edge can be +compared against "just being in the market on a random day"). + +Data: Yahoo Finance daily OHLC (^VIX and QQQ). +""" + +import io +import json +import sys + +import numpy as np +import pandas as pd +import requests + +CA_BUNDLE = "/root/.ccr/ca-bundle.crt" +THRESHOLDS = [17, 18, 19, 20, 21, 22] +HORIZONS = [5, 20, 60] +HEADERS = {"User-Agent": "Mozilla/5.0"} + + +def fetch_yahoo(symbol): + """Return a DataFrame indexed by date with OHLC columns for a Yahoo symbol.""" + url = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}" + params = {"period1": 0, "period2": 9999999999, "interval": "1d"} + r = requests.get(url, params=params, headers=HEADERS, + timeout=60, verify=CA_BUNDLE) + r.raise_for_status() + res = r.json()["chart"]["result"][0] + ts = res["timestamp"] + q = res["indicators"]["quote"][0] + df = pd.DataFrame({ + "open": q["open"], + "high": q["high"], + "low": q["low"], + "close": q["close"], + }, index=pd.to_datetime(ts, unit="s").normalize()) + df.index.name = "date" + df = df.dropna(subset=["high", "close"]) + return df + + +def main(): + print("Fetching data from Yahoo Finance ...", file=sys.stderr) + vix = fetch_yahoo("%5EVIX") # ^VIX + qqq = fetch_yahoo("QQQ") + + # Align to the common trading calendar (QQQ starts 1999-03-10). + df = pd.DataFrame({ + "vix_high": vix["high"], + "qqq_close": qqq["close"], + }).dropna() + df = df.sort_index() + + df["vix_high_prev"] = df["vix_high"].shift(1) + + # Forward returns of QQQ close for each horizon. + for h in HORIZONS: + df[f"fwd_{h}"] = df["qqq_close"].shift(-h) / df["qqq_close"] - 1.0 + + n_days = len(df) + span = f"{df.index[0].date()} to {df.index[-1].date()}" + print(f"Aligned trading days: {n_days} ({span})\n") + + # ---- Buy & Hold benchmark (every trading day) ---- + bh = {} + for h in HORIZONS: + s = df[f"fwd_{h}"].dropna() + bh[h] = { + "n": int(s.shape[0]), + "mean": float(s.mean()), + "median": float(s.median()), + "win": float((s > 0).mean()), + "best": float(s.max()), + "worst": float(s.min()), + } + + # ---- Strategy per threshold ---- + results = {} + for T in THRESHOLDS: + signal = (df["vix_high_prev"] < T) & (df["vix_high"] >= T) + sig = df[signal] + per_h = {} + for h in HORIZONS: + s = sig[f"fwd_{h}"].dropna() + if s.empty: + per_h[h] = None + continue + per_h[h] = { + "n": int(s.shape[0]), + "mean": float(s.mean()), + "median": float(s.median()), + "win": float((s > 0).mean()), + "best": float(s.max()), + "worst": float(s.min()), + } + results[T] = { + "total_signals": int(signal.sum()), + "horizons": per_h, + "signal_dates": [d.strftime("%Y-%m-%d") for d in sig.index], + } + + out = { + "data_span": span, + "trading_days": n_days, + "thresholds": THRESHOLDS, + "horizons": HORIZONS, + "buy_and_hold": bh, + "strategy": results, + } + + with open("vix_qqq_results.json", "w") as f: + json.dump(out, f, indent=2) + + # ---- Pretty print ---- + def pct(x): + return f"{x * 100:+6.2f}%" + + print("=" * 78) + print("QQQ BUY & HOLD BENCHMARK (average forward return over ALL trading days)") + print("=" * 78) + print(f"{'Horizon':>8} {'N':>7} {'Mean':>9} {'Median':>9} {'Win%':>7} " + f"{'Best':>9} {'Worst':>9}") + for h in HORIZONS: + b = bh[h] + print(f"{h:>6}d {b['n']:>7} {pct(b['mean']):>9} {pct(b['median']):>9} " + f"{b['win'] * 100:>6.1f}% {pct(b['best']):>9} {pct(b['worst']):>9}") + + for T in THRESHOLDS: + r = results[T] + print("\n" + "=" * 78) + print(f"THRESHOLD {T} (VIX High crosses up through {T}: " + f"prev High < {T} and today High >= {T})") + print(f"Total signal days: {r['total_signals']}") + print("=" * 78) + print(f"{'Horizon':>8} {'N':>7} {'Mean':>9} {'Median':>9} {'Win%':>7} " + f"{'Best':>9} {'Worst':>9} {' vs B&H(mean)':>14}") + for h in HORIZONS: + d = r["horizons"][h] + if d is None: + print(f"{h:>6}d - (no completed samples)") + continue + edge = d["mean"] - bh[h]["mean"] + print(f"{h:>6}d {d['n']:>7} {pct(d['mean']):>9} {pct(d['median']):>9} " + f"{d['win'] * 100:>6.1f}% {pct(d['best']):>9} {pct(d['worst']):>9} " + f"{pct(edge):>14}") + + print("\nSaved detailed results (incl. signal dates) to vix_qqq_results.json") + + +if __name__ == "__main__": + main() diff --git a/vix_qqq_results.json b/vix_qqq_results.json new file mode 100644 index 0000000..5097130 --- /dev/null +++ b/vix_qqq_results.json @@ -0,0 +1,1308 @@ +{ + "data_span": "1999-03-10 to 2026-08-07", + "trading_days": 6896, + "thresholds": [ + 17, + 18, + 19, + 20, + 21, + 22 + ], + "horizons": [ + 5, + 20, + 60 + ], + "buy_and_hold": { + "5": { + "n": 6891, + "mean": 0.002523692004638869, + "median": 0.004903517352039755, + "win": 0.573937019300537, + "best": 0.207194533762058, + "worst": -0.24618991793669398 + }, + "20": { + "n": 6876, + "mean": 0.009848641640827618, + "median": 0.015784057977988653, + "win": 0.6226003490401396, + "best": 0.4131563692402447, + "worst": -0.3110076791047518 + }, + "60": { + "n": 6836, + "mean": 0.030091280088844253, + "median": 0.0411333545186473, + "win": 0.6781743709771796, + "best": 0.565040650406504, + "worst": -0.4530280394537497 + } + }, + "strategy": { + "17": { + "total_signals": 188, + "horizons": { + "5": { + "n": 187, + "mean": 0.0013001972605903636, + "median": 0.0037890012209134127, + "win": 0.5828877005347594, + "best": 0.04833122322580041, + "worst": -0.12411619192928469 + }, + "20": { + "n": 185, + "mean": 0.00786408187269913, + "median": 0.01826691590942331, + "win": 0.6216216216216216, + "best": 0.09488220723349117, + "worst": -0.2432915725963638 + }, + "60": { + "n": 182, + "mean": 0.02838536033357705, + "median": 0.044786533188208244, + "win": 0.6978021978021978, + "best": 0.20070137492494355, + "worst": -0.17956826849498064 + } + }, + "signal_dates": [ + "2003-11-05", + "2003-11-10", + "2003-12-01", + "2003-12-05", + "2003-12-15", + "2003-12-22", + "2003-12-26", + "2004-01-12", + "2004-01-28", + "2004-03-10", + "2004-04-01", + "2004-04-13", + "2004-04-29", + "2004-05-06", + "2004-06-03", + "2004-07-22", + "2004-07-26", + "2004-08-05", + "2005-04-15", + "2005-04-20", + "2005-05-13", + "2005-10-13", + "2006-05-18", + "2006-05-30", + "2006-06-05", + "2006-06-28", + "2006-07-13", + "2006-07-21", + "2007-02-27", + "2007-03-13", + "2007-03-16", + "2007-06-07", + "2007-06-25", + "2007-06-29", + "2007-07-10", + "2007-07-18", + "2007-07-20", + "2010-03-19", + "2010-04-16", + "2010-04-22", + "2010-04-26", + "2010-12-27", + "2011-01-19", + "2011-01-28", + "2011-02-10", + "2011-02-17", + "2011-02-22", + "2011-04-18", + "2011-05-03", + "2011-05-11", + "2011-05-20", + "2011-06-01", + "2011-07-06", + "2011-07-08", + "2012-03-28", + "2012-04-04", + "2012-04-30", + "2012-07-05", + "2012-07-20", + "2012-08-29", + "2012-09-26", + "2012-10-19", + "2012-12-04", + "2012-12-14", + "2012-12-19", + "2013-02-25", + "2013-04-15", + "2013-04-17", + "2013-06-03", + "2013-06-11", + "2013-06-19", + "2013-06-28", + "2013-07-03", + "2013-08-27", + "2013-08-30", + "2013-09-30", + "2013-10-03", + "2013-10-14", + "2014-01-24", + "2014-03-14", + "2014-04-11", + "2014-07-31", + "2014-08-05", + "2014-09-29", + "2014-10-01", + "2014-10-07", + "2014-12-10", + "2014-12-31", + "2015-03-11", + "2015-03-26", + "2015-06-29", + "2015-08-20", + "2015-11-09", + "2015-11-12", + "2015-11-24", + "2015-12-03", + "2015-12-28", + "2015-12-30", + "2016-04-29", + "2016-05-19", + "2016-06-10", + "2016-07-06", + "2016-09-09", + "2016-10-13", + "2016-10-17", + "2016-10-28", + "2017-08-11", + "2018-02-02", + "2018-02-27", + "2018-03-14", + "2018-03-19", + "2018-04-20", + "2018-05-03", + "2018-05-29", + "2018-06-25", + "2018-07-02", + "2018-10-05", + "2019-02-07", + "2019-02-14", + "2019-03-07", + "2019-03-22", + "2019-05-06", + "2019-05-20", + "2019-05-23", + "2019-05-28", + "2019-08-01", + "2019-09-24", + "2019-12-03", + "2020-01-27", + "2020-01-30", + "2020-02-20", + "2021-04-19", + "2021-06-01", + "2021-06-14", + "2021-06-30", + "2021-07-06", + "2021-08-16", + "2021-08-31", + "2021-09-03", + "2021-10-18", + "2021-10-27", + "2021-11-05", + "2023-05-02", + "2023-07-06", + "2023-08-03", + "2023-08-17", + "2023-09-21", + "2024-02-13", + "2024-04-11", + "2024-04-25", + "2024-07-19", + "2024-07-24", + "2024-08-01", + "2024-08-21", + "2024-08-28", + "2024-09-03", + "2024-09-30", + "2024-11-15", + "2024-12-18", + "2024-12-27", + "2025-01-07", + "2025-01-27", + "2025-01-31", + "2025-02-12", + "2025-02-21", + "2025-06-27", + "2025-07-07", + "2025-07-11", + "2025-07-22", + "2025-07-30", + "2025-08-20", + "2025-09-02", + "2025-09-23", + "2025-10-01", + "2025-10-03", + "2025-10-29", + "2025-12-08", + "2025-12-12", + "2026-01-14", + "2026-01-20", + "2026-01-26", + "2026-01-28", + "2026-06-05", + "2026-06-17", + "2026-07-08", + "2026-07-13", + "2026-07-16", + "2026-08-05" + ] + }, + "18": { + "total_signals": 191, + "horizons": { + "5": { + "n": 190, + "mean": 0.002228695555235771, + "median": 0.006793328516890851, + "win": 0.6210526315789474, + "best": 0.06005524439913912, + "worst": -0.10626655998038559 + }, + "20": { + "n": 188, + "mean": 0.00793389339156047, + "median": 0.018983520690392885, + "win": 0.6329787234042553, + "best": 0.11160072299361556, + "worst": -0.258696340031045 + }, + "60": { + "n": 184, + "mean": 0.026603852717065, + "median": 0.03367443737916054, + "win": 0.7010869565217391, + "best": 0.20070137492494355, + "worst": -0.36746231155778897 + } + }, + "signal_dates": [ + "2000-09-05", + "2002-04-01", + "2003-09-22", + "2003-10-16", + "2003-10-20", + "2003-10-23", + "2003-11-11", + "2003-11-17", + "2003-12-10", + "2003-12-31", + "2004-01-13", + "2004-02-04", + "2004-03-10", + "2004-05-07", + "2004-08-05", + "2005-04-15", + "2006-05-19", + "2006-05-30", + "2006-06-06", + "2006-06-08", + "2006-07-14", + "2007-02-27", + "2007-03-01", + "2007-03-13", + "2007-06-26", + "2007-07-20", + "2007-07-24", + "2007-09-28", + "2007-10-11", + "2008-05-20", + "2010-01-12", + "2010-03-09", + "2010-03-22", + "2010-03-25", + "2010-04-01", + "2010-04-16", + "2010-04-22", + "2010-04-27", + "2010-12-15", + "2010-12-27", + "2010-12-31", + "2011-01-04", + "2011-01-07", + "2011-01-20", + "2011-01-28", + "2011-02-22", + "2011-04-08", + "2011-04-12", + "2011-04-14", + "2011-04-18", + "2011-05-05", + "2011-05-16", + "2011-05-23", + "2011-06-01", + "2011-07-11", + "2011-07-25", + "2012-02-06", + "2012-02-27", + "2012-03-05", + "2012-04-09", + "2012-05-04", + "2012-07-05", + "2012-07-23", + "2012-07-30", + "2012-08-30", + "2012-10-23", + "2012-11-05", + "2012-11-14", + "2012-12-21", + "2013-02-25", + "2013-04-18", + "2013-06-06", + "2013-06-12", + "2013-06-20", + "2013-10-03", + "2013-10-07", + "2013-10-15", + "2014-01-24", + "2014-01-29", + "2014-01-31", + "2014-03-14", + "2014-10-08", + "2014-10-22", + "2014-10-24", + "2014-12-10", + "2014-12-31", + "2015-01-27", + "2015-02-06", + "2015-06-29", + "2015-07-06", + "2015-08-20", + "2015-10-14", + "2015-11-12", + "2015-12-03", + "2015-12-08", + "2015-12-28", + "2015-12-31", + "2016-03-07", + "2016-06-13", + "2016-09-12", + "2016-11-01", + "2018-02-05", + "2018-02-27", + "2018-03-19", + "2018-04-24", + "2018-05-03", + "2018-05-29", + "2018-06-25", + "2018-06-27", + "2018-07-02", + "2018-10-08", + "2018-10-10", + "2018-11-09", + "2018-12-04", + "2019-03-08", + "2019-05-06", + "2019-05-23", + "2019-05-29", + "2019-08-01", + "2019-08-23", + "2019-09-25", + "2019-09-27", + "2019-10-01", + "2020-01-27", + "2020-01-30", + "2020-02-21", + "2021-04-19", + "2021-04-29", + "2021-06-01", + "2021-06-10", + "2021-06-16", + "2021-07-08", + "2021-07-15", + "2021-07-26", + "2021-08-17", + "2021-08-26", + "2021-09-07", + "2021-10-29", + "2021-11-09", + "2021-11-18", + "2021-12-31", + "2022-01-05", + "2023-04-24", + "2023-05-02", + "2023-05-10", + "2023-05-15", + "2023-05-22", + "2023-08-08", + "2023-08-17", + "2023-09-25", + "2023-10-02", + "2023-10-12", + "2024-04-12", + "2024-07-24", + "2024-07-30", + "2024-08-01", + "2024-08-22", + "2024-09-03", + "2024-09-17", + "2024-10-01", + "2024-11-20", + "2024-12-18", + "2024-12-27", + "2025-01-02", + "2025-01-07", + "2025-01-27", + "2025-02-03", + "2025-02-21", + "2025-03-26", + "2025-05-19", + "2025-06-11", + "2025-07-07", + "2025-07-16", + "2025-08-01", + "2025-09-02", + "2025-10-10", + "2025-10-31", + "2025-12-17", + "2026-01-14", + "2026-01-20", + "2026-01-29", + "2026-02-11", + "2026-05-04", + "2026-05-11", + "2026-06-05", + "2026-06-17", + "2026-06-23", + "2026-07-08", + "2026-07-17", + "2026-07-22", + "2026-08-05" + ] + }, + "19": { + "total_signals": 177, + "horizons": { + "5": { + "n": 177, + "mean": 0.003526418153314111, + "median": 0.00758437839065218, + "win": 0.6101694915254238, + "best": 0.06005524439913912, + "worst": -0.08165829145728642 + }, + "20": { + "n": 175, + "mean": 0.007170011873600577, + "median": 0.016128753968992937, + "win": 0.6114285714285714, + "best": 0.12384656729048382, + "worst": -0.23004649178459047 + }, + "60": { + "n": 172, + "mean": 0.026277365790454702, + "median": 0.03671182158162045, + "win": 0.686046511627907, + "best": 0.21174882001450723, + "worst": -0.36746231155778897 + } + }, + "signal_dates": [ + "1999-07-12", + "1999-07-19", + "2000-08-07", + "2000-09-05", + "2000-09-18", + "2002-03-18", + "2002-04-01", + "2002-04-22", + "2002-05-20", + "2003-07-14", + "2003-07-29", + "2003-08-25", + "2003-09-02", + "2003-09-09", + "2003-09-22", + "2003-11-17", + "2004-03-11", + "2004-05-10", + "2004-05-14", + "2004-05-20", + "2004-08-06", + "2004-08-12", + "2006-05-22", + "2006-05-24", + "2006-06-08", + "2006-06-12", + "2006-07-18", + "2007-02-27", + "2007-03-01", + "2007-03-05", + "2007-03-14", + "2007-07-24", + "2007-10-11", + "2007-10-15", + "2008-05-22", + "2008-06-02", + "2010-01-12", + "2010-01-15", + "2010-01-20", + "2010-03-11", + "2010-04-16", + "2010-04-27", + "2010-11-08", + "2011-01-28", + "2011-02-22", + "2011-03-28", + "2011-04-18", + "2011-05-05", + "2011-05-17", + "2011-05-23", + "2011-06-03", + "2011-06-10", + "2011-06-15", + "2011-06-23", + "2011-07-11", + "2011-07-25", + "2012-02-10", + "2012-02-27", + "2012-03-06", + "2012-04-10", + "2012-04-18", + "2012-04-23", + "2012-05-04", + "2012-06-20", + "2012-07-10", + "2012-07-23", + "2012-07-31", + "2012-10-23", + "2012-11-07", + "2012-12-21", + "2012-12-26", + "2013-02-25", + "2013-06-20", + "2013-10-07", + "2014-02-03", + "2014-10-09", + "2014-12-11", + "2014-12-31", + "2015-01-12", + "2015-01-28", + "2015-02-09", + "2015-06-29", + "2015-07-07", + "2015-08-20", + "2015-11-13", + "2015-12-03", + "2015-12-09", + "2015-12-31", + "2016-03-09", + "2016-06-13", + "2016-06-22", + "2016-09-12", + "2016-11-01", + "2018-02-05", + "2018-02-28", + "2018-03-19", + "2018-03-22", + "2018-04-24", + "2018-06-25", + "2018-10-10", + "2018-11-12", + "2018-12-04", + "2019-01-22", + "2019-01-28", + "2019-05-07", + "2019-05-29", + "2019-05-31", + "2019-08-01", + "2019-08-23", + "2019-10-02", + "2019-10-08", + "2020-01-27", + "2020-01-31", + "2020-02-24", + "2021-04-20", + "2021-04-30", + "2021-05-10", + "2021-06-03", + "2021-06-16", + "2021-07-08", + "2021-07-19", + "2021-07-26", + "2021-07-30", + "2021-08-17", + "2021-08-26", + "2021-09-08", + "2021-11-10", + "2021-11-19", + "2021-12-27", + "2022-01-05", + "2022-01-13", + "2023-04-25", + "2023-05-02", + "2023-05-04", + "2023-05-23", + "2023-09-26", + "2023-10-03", + "2023-10-13", + "2023-10-18", + "2024-04-12", + "2024-04-19", + "2024-07-25", + "2024-08-01", + "2024-09-03", + "2024-09-18", + "2024-10-01", + "2024-12-18", + "2024-12-30", + "2025-01-02", + "2025-01-08", + "2025-01-27", + "2025-02-03", + "2025-02-21", + "2025-03-26", + "2025-05-15", + "2025-05-19", + "2025-05-21", + "2025-06-13", + "2025-07-16", + "2025-08-01", + "2025-09-02", + "2025-10-10", + "2025-10-22", + "2025-11-04", + "2025-11-13", + "2026-01-20", + "2026-01-29", + "2026-02-12", + "2026-04-16", + "2026-04-20", + "2026-05-04", + "2026-05-12", + "2026-05-15", + "2026-06-05", + "2026-06-23", + "2026-07-17", + "2026-07-22" + ] + }, + "20": { + "total_signals": 183, + "horizons": { + "5": { + "n": 183, + "mean": 0.0037891947092253105, + "median": 0.006530760175192052, + "win": 0.6010928961748634, + "best": 0.08397686211051614, + "worst": -0.09866931541941393 + }, + "20": { + "n": 181, + "mean": 0.005115673278668865, + "median": 0.012599121901678556, + "win": 0.6022099447513812, + "best": 0.19849246231155782, + "worst": -0.23004649178459047 + }, + "60": { + "n": 178, + "mean": 0.026690534052821756, + "median": 0.051752859486369096, + "win": 0.7078651685393258, + "best": 0.3685092127303182, + "worst": -0.3904065577671426 + } + }, + "signal_dates": [ + "1999-07-06", + "1999-07-12", + "1999-07-20", + "1999-11-22", + "1999-12-06", + "2000-07-03", + "2000-07-17", + "2000-07-27", + "2000-09-05", + "2000-09-18", + "2001-07-05", + "2002-04-03", + "2002-04-08", + "2002-04-11", + "2002-04-22", + "2002-05-21", + "2002-05-28", + "2003-05-19", + "2003-06-02", + "2003-06-23", + "2003-07-01", + "2003-07-07", + "2003-07-16", + "2003-08-01", + "2003-08-26", + "2003-09-10", + "2003-09-22", + "2003-09-24", + "2004-03-11", + "2004-03-22", + "2004-05-10", + "2004-05-12", + "2004-05-17", + "2006-06-08", + "2006-06-12", + "2007-03-05", + "2007-03-14", + "2007-07-26", + "2007-09-25", + "2007-10-15", + "2007-10-19", + "2007-12-27", + "2008-05-09", + "2008-05-27", + "2008-06-02", + "2008-08-25", + "2008-08-29", + "2009-12-28", + "2010-01-21", + "2010-04-27", + "2010-10-12", + "2010-10-14", + "2010-10-26", + "2010-11-12", + "2010-11-22", + "2010-11-26", + "2011-01-28", + "2011-02-22", + "2011-03-01", + "2011-03-04", + "2011-05-23", + "2011-06-13", + "2011-06-15", + "2011-06-23", + "2011-07-12", + "2011-07-26", + "2012-01-24", + "2012-01-30", + "2012-02-10", + "2012-02-14", + "2012-03-06", + "2012-04-10", + "2012-04-16", + "2012-04-23", + "2012-05-08", + "2012-05-14", + "2012-06-20", + "2012-06-25", + "2012-07-23", + "2012-12-27", + "2013-06-20", + "2013-10-08", + "2014-02-03", + "2014-10-10", + "2014-12-11", + "2015-01-02", + "2015-01-12", + "2015-01-28", + "2015-07-09", + "2015-08-21", + "2015-11-13", + "2015-12-09", + "2015-12-11", + "2015-12-18", + "2015-12-31", + "2016-06-13", + "2016-06-22", + "2016-06-24", + "2016-09-12", + "2016-11-01", + "2016-11-03", + "2016-11-09", + "2018-02-05", + "2018-02-28", + "2018-03-07", + "2018-03-19", + "2018-03-22", + "2018-10-10", + "2018-10-18", + "2018-11-12", + "2018-11-29", + "2018-12-04", + "2019-01-22", + "2019-01-28", + "2019-05-07", + "2019-08-02", + "2019-08-12", + "2019-08-23", + "2019-09-03", + "2019-10-02", + "2019-10-08", + "2020-02-24", + "2021-05-04", + "2021-05-06", + "2021-05-11", + "2021-06-18", + "2021-07-08", + "2021-07-19", + "2021-07-27", + "2021-08-03", + "2021-08-18", + "2021-09-10", + "2021-09-17", + "2021-09-28", + "2021-10-11", + "2021-11-23", + "2022-01-05", + "2022-01-13", + "2022-03-30", + "2023-01-17", + "2023-01-30", + "2023-02-08", + "2023-02-16", + "2023-03-08", + "2023-03-30", + "2023-04-04", + "2023-04-10", + "2023-05-04", + "2023-05-24", + "2023-10-03", + "2023-10-13", + "2023-10-18", + "2024-04-19", + "2024-08-02", + "2024-09-03", + "2024-10-01", + "2024-10-23", + "2024-10-29", + "2024-12-18", + "2025-01-10", + "2025-01-27", + "2025-02-03", + "2025-02-24", + "2025-03-28", + "2025-05-21", + "2025-05-29", + "2025-06-13", + "2025-08-01", + "2025-10-10", + "2025-10-22", + "2025-11-04", + "2025-11-13", + "2026-01-20", + "2026-02-03", + "2026-02-12", + "2026-02-26", + "2026-04-21", + "2026-04-23", + "2026-06-05", + "2026-06-23", + "2026-06-26", + "2026-07-23", + "2026-07-29" + ] + }, + "21": { + "total_signals": 178, + "horizons": { + "5": { + "n": 178, + "mean": 0.0020092677587955432, + "median": 0.006431957705823499, + "win": 0.5617977528089888, + "best": 0.06610940521499553, + "worst": -0.09866931541941393 + }, + "20": { + "n": 178, + "mean": 0.002592636268539343, + "median": 0.01605016111934854, + "win": 0.6123595505617978, + "best": 0.18924551896623587, + "worst": -0.2676946838299752 + }, + "60": { + "n": 176, + "mean": 0.019879742979264356, + "median": 0.047897584245304214, + "win": 0.6704545454545454, + "best": 0.341914722445696, + "worst": -0.3904065577671426 + } + }, + "signal_dates": [ + "1999-07-07", + "1999-07-20", + "1999-11-23", + "1999-11-26", + "1999-12-06", + "2000-01-18", + "2000-03-06", + "2000-06-19", + "2000-07-05", + "2000-07-31", + "2000-09-20", + "2000-09-22", + "2000-10-02", + "2001-06-11", + "2001-06-26", + "2001-07-06", + "2001-08-03", + "2001-08-16", + "2001-08-28", + "2002-03-05", + "2002-04-25", + "2002-05-06", + "2002-05-30", + "2002-06-03", + "2003-04-29", + "2003-05-20", + "2003-06-03", + "2003-06-05", + "2003-06-12", + "2003-06-16", + "2003-06-25", + "2003-08-04", + "2003-09-24", + "2004-03-15", + "2004-03-22", + "2006-06-12", + "2007-03-14", + "2007-07-26", + "2007-10-19", + "2007-10-30", + "2007-12-28", + "2008-04-21", + "2008-06-03", + "2008-06-06", + "2008-08-12", + "2008-08-18", + "2008-08-25", + "2008-09-02", + "2009-11-27", + "2009-12-31", + "2010-01-21", + "2010-04-27", + "2010-04-30", + "2010-10-14", + "2010-10-19", + "2010-10-26", + "2010-11-12", + "2010-11-16", + "2010-11-23", + "2010-11-26", + "2011-02-22", + "2011-03-01", + "2011-03-07", + "2011-03-10", + "2011-03-23", + "2011-06-15", + "2011-06-23", + "2011-07-14", + "2011-07-27", + "2012-01-11", + "2012-02-10", + "2012-02-15", + "2012-03-06", + "2012-04-10", + "2012-05-09", + "2012-05-14", + "2012-06-25", + "2012-06-28", + "2012-07-24", + "2012-12-28", + "2013-06-20", + "2013-06-24", + "2013-10-08", + "2014-02-03", + "2014-10-10", + "2014-12-12", + "2015-01-05", + "2015-01-13", + "2015-01-29", + "2015-08-21", + "2015-12-11", + "2015-12-18", + "2016-01-04", + "2016-02-23", + "2016-06-13", + "2016-06-16", + "2016-06-22", + "2016-06-24", + "2016-11-03", + "2016-11-09", + "2018-02-05", + "2018-02-20", + "2018-03-01", + "2018-03-19", + "2018-03-22", + "2018-04-06", + "2018-10-10", + "2018-10-18", + "2018-10-23", + "2018-11-13", + "2018-11-20", + "2018-12-04", + "2019-01-22", + "2019-05-07", + "2019-05-13", + "2019-08-05", + "2019-08-12", + "2019-08-23", + "2019-09-03", + "2019-10-02", + "2020-02-24", + "2020-12-02", + "2021-03-18", + "2021-05-04", + "2021-05-11", + "2021-06-18", + "2021-07-08", + "2021-07-19", + "2021-08-18", + "2021-09-10", + "2021-09-17", + "2021-09-28", + "2021-11-26", + "2022-01-06", + "2022-01-10", + "2022-01-14", + "2022-03-31", + "2022-04-05", + "2022-08-15", + "2022-08-19", + "2022-12-05", + "2023-01-19", + "2023-02-09", + "2023-02-17", + "2023-03-09", + "2023-05-04", + "2023-10-19", + "2023-10-25", + "2024-04-19", + "2024-08-02", + "2024-09-03", + "2024-09-11", + "2024-10-07", + "2024-10-16", + "2024-10-31", + "2024-12-18", + "2025-01-13", + "2025-01-27", + "2025-02-25", + "2025-02-27", + "2025-03-28", + "2025-05-21", + "2025-06-13", + "2025-06-17", + "2025-08-01", + "2025-10-10", + "2025-10-14", + "2025-10-22", + "2025-11-07", + "2025-11-13", + "2026-02-04", + "2026-02-12", + "2026-02-19", + "2026-02-27", + "2026-04-13", + "2026-04-23", + "2026-06-05", + "2026-06-09" + ] + }, + "22": { + "total_signals": 160, + "horizons": { + "5": { + "n": 160, + "mean": -0.0014847935185072173, + "median": 0.003294149672387503, + "win": 0.51875, + "best": 0.11400544317046268, + "worst": -0.11227155225906105 + }, + "20": { + "n": 160, + "mean": -0.009098996967542461, + "median": 0.012440513998633662, + "win": 0.56875, + "best": 0.15446500402252616, + "worst": -0.27467569091934574 + }, + "60": { + "n": 159, + "mean": 0.003642889876465111, + "median": 0.03233000220966664, + "win": 0.5911949685534591, + "best": 0.3911671924290221, + "worst": -0.3892788745044078 + } + }, + "signal_dates": [ + "1999-06-23", + "1999-07-22", + "1999-08-27", + "1999-09-07", + "1999-10-12", + "1999-11-26", + "1999-12-09", + "1999-12-20", + "1999-12-27", + "2000-01-19", + "2000-01-24", + "2000-02-07", + "2000-03-07", + "2000-03-13", + "2000-03-17", + "2000-06-05", + "2000-06-22", + "2000-09-22", + "2000-09-26", + "2000-10-04", + "2000-10-06", + "2001-02-05", + "2001-02-09", + "2001-02-14", + "2001-02-16", + "2001-05-23", + "2001-05-29", + "2001-06-14", + "2001-07-09", + "2001-08-06", + "2001-08-08", + "2001-08-16", + "2001-08-28", + "2001-12-31", + "2002-01-07", + "2002-01-29", + "2002-02-04", + "2002-02-15", + "2002-04-26", + "2002-05-06", + "2002-05-10", + "2002-06-03", + "2003-05-01", + "2003-06-09", + "2003-08-04", + "2003-09-25", + "2004-03-22", + "2006-06-13", + "2007-07-26", + "2007-10-19", + "2007-10-24", + "2007-10-31", + "2007-12-11", + "2007-12-31", + "2008-06-06", + "2008-06-18", + "2008-08-13", + "2008-08-19", + "2008-09-02", + "2009-10-21", + "2009-11-27", + "2009-12-17", + "2010-01-21", + "2010-02-25", + "2010-04-27", + "2010-04-30", + "2010-09-15", + "2010-10-27", + "2010-11-01", + "2010-11-03", + "2010-11-16", + "2010-11-26", + "2011-02-23", + "2011-03-10", + "2011-03-14", + "2011-06-16", + "2011-07-27", + "2011-12-27", + "2012-01-12", + "2012-05-15", + "2012-12-28", + "2014-10-10", + "2014-12-12", + "2015-01-06", + "2015-01-14", + "2015-01-30", + "2015-08-21", + "2015-12-11", + "2015-12-18", + "2016-01-04", + "2016-01-07", + "2016-02-01", + "2016-02-24", + "2016-06-14", + "2016-06-16", + "2016-06-24", + "2016-11-03", + "2018-02-05", + "2018-03-01", + "2018-03-22", + "2018-04-06", + "2018-10-10", + "2018-10-23", + "2018-11-14", + "2018-11-20", + "2018-12-06", + "2018-12-14", + "2019-01-23", + "2019-05-09", + "2019-08-05", + "2019-08-14", + "2020-02-24", + "2020-11-30", + "2020-12-07", + "2021-03-18", + "2021-03-25", + "2021-05-11", + "2021-05-19", + "2021-07-19", + "2021-08-19", + "2021-09-20", + "2021-09-28", + "2021-11-26", + "2021-12-14", + "2022-01-10", + "2022-01-14", + "2022-02-10", + "2022-04-06", + "2022-04-21", + "2022-08-22", + "2022-11-28", + "2022-12-06", + "2022-12-22", + "2023-01-10", + "2023-02-21", + "2023-03-09", + "2023-10-23", + "2023-10-27", + "2024-08-02", + "2024-09-04", + "2024-09-06", + "2024-10-07", + "2024-10-31", + "2024-12-18", + "2025-01-13", + "2025-01-27", + "2025-02-28", + "2025-03-28", + "2025-05-22", + "2025-06-13", + "2025-06-23", + "2025-10-10", + "2025-10-14", + "2025-11-07", + "2025-11-14", + "2026-02-05", + "2026-02-13", + "2026-02-23", + "2026-03-02", + "2026-06-09" + ] + } + } +} \ No newline at end of file From 23ad29fa9d95fdf882bd7de082293ef4b4a4a4dc Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 05:53:59 +0000 Subject: [PATCH 2/4] Add --start window option; include 5-year (2021-08 to 2026-08) results Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01JXFxuoYQvap2iq4EHbf9GW --- vix_qqq_backtest.py | 16 +- vix_qqq_results.json | 1014 +++++---------------------------------- vix_qqq_results_5y.json | 538 +++++++++++++++++++++ 3 files changed, 675 insertions(+), 893 deletions(-) create mode 100644 vix_qqq_results_5y.json diff --git a/vix_qqq_backtest.py b/vix_qqq_backtest.py index 8152d39..7a950ae 100644 --- a/vix_qqq_backtest.py +++ b/vix_qqq_backtest.py @@ -57,6 +57,13 @@ def fetch_yahoo(symbol): def main(): + # Optional signal-window start date (YYYY-MM-DD). Forward returns are always + # computed on the full price history; only signals/benchmark are windowed. + start = None + for a in sys.argv[1:]: + if a.startswith("--start="): + start = pd.Timestamp(a.split("=", 1)[1]) + print("Fetching data from Yahoo Finance ...", file=sys.stderr) vix = fetch_yahoo("%5EVIX") # ^VIX qqq = fetch_yahoo("QQQ") @@ -74,9 +81,16 @@ def main(): for h in HORIZONS: df[f"fwd_{h}"] = df["qqq_close"].shift(-h) / df["qqq_close"] - 1.0 + # Full price history is kept for forward-return lookups above; the analysis + # window (signals + benchmark) can be restricted to a start date. + full = df + if start is not None: + df = df[df.index >= start] + n_days = len(df) span = f"{df.index[0].date()} to {df.index[-1].date()}" - print(f"Aligned trading days: {n_days} ({span})\n") + window_note = f" [signal window >= {start.date()}]" if start is not None else "" + print(f"Aligned trading days: {n_days} ({span}){window_note}\n") # ---- Buy & Hold benchmark (every trading day) ---- bh = {} diff --git a/vix_qqq_results.json b/vix_qqq_results.json index 5097130..ea0bf5b 100644 --- a/vix_qqq_results.json +++ b/vix_qqq_results.json @@ -1,6 +1,6 @@ { - "data_span": "1999-03-10 to 2026-08-07", - "trading_days": 6896, + "data_span": "2021-08-10 to 2026-08-07", + "trading_days": 1254, "thresholds": [ 17, 18, @@ -16,196 +16,60 @@ ], "buy_and_hold": { "5": { - "n": 6891, - "mean": 0.002523692004638869, - "median": 0.004903517352039755, - "win": 0.573937019300537, - "best": 0.207194533762058, - "worst": -0.24618991793669398 + "n": 1249, + "mean": 0.003138296789026028, + "median": 0.0051984480660698384, + "win": 0.5748598879103283, + "best": 0.10077871682407125, + "worst": -0.11982232533480563 }, "20": { - "n": 6876, - "mean": 0.009848641640827618, - "median": 0.015784057977988653, - "win": 0.6226003490401396, - "best": 0.4131563692402447, - "worst": -0.3110076791047518 + "n": 1234, + "mean": 0.01202913585405011, + "median": 0.01545511618643891, + "win": 0.6191247974068071, + "best": 0.20525969712266257, + "worst": -0.15937638583593183 }, "60": { - "n": 6836, - "mean": 0.030091280088844253, - "median": 0.0411333545186473, - "win": 0.6781743709771796, - "best": 0.565040650406504, - "worst": -0.4530280394537497 + "n": 1194, + "mean": 0.03836659718447432, + "median": 0.04653715628976818, + "win": 0.6758793969849246, + "best": 0.3268039045717981, + "worst": -0.24105061455776944 } }, "strategy": { "17": { - "total_signals": 188, + "total_signals": 52, "horizons": { "5": { - "n": 187, - "mean": 0.0013001972605903636, - "median": 0.0037890012209134127, - "win": 0.5828877005347594, - "best": 0.04833122322580041, - "worst": -0.12411619192928469 + "n": 51, + "mean": -0.000397887254264299, + "median": 0.0029504630475947202, + "win": 0.6078431372549019, + "best": 0.03794034703293514, + "worst": -0.04930729886574403 }, "20": { - "n": 185, - "mean": 0.00786408187269913, - "median": 0.01826691590942331, - "win": 0.6216216216216216, - "best": 0.09488220723349117, - "worst": -0.2432915725963638 + "n": 49, + "mean": 0.009383555926493871, + "median": 0.01501830979627572, + "win": 0.6530612244897959, + "best": 0.08957976364882358, + "worst": -0.11349610607709382 }, "60": { - "n": 182, - "mean": 0.02838536033357705, - "median": 0.044786533188208244, - "win": 0.6978021978021978, + "n": 46, + "mean": 0.028079584256733712, + "median": 0.047912148321742065, + "win": 0.6739130434782609, "best": 0.20070137492494355, "worst": -0.17956826849498064 } }, "signal_dates": [ - "2003-11-05", - "2003-11-10", - "2003-12-01", - "2003-12-05", - "2003-12-15", - "2003-12-22", - "2003-12-26", - "2004-01-12", - "2004-01-28", - "2004-03-10", - "2004-04-01", - "2004-04-13", - "2004-04-29", - "2004-05-06", - "2004-06-03", - "2004-07-22", - "2004-07-26", - "2004-08-05", - "2005-04-15", - "2005-04-20", - "2005-05-13", - "2005-10-13", - "2006-05-18", - "2006-05-30", - "2006-06-05", - "2006-06-28", - "2006-07-13", - "2006-07-21", - "2007-02-27", - "2007-03-13", - "2007-03-16", - "2007-06-07", - "2007-06-25", - "2007-06-29", - "2007-07-10", - "2007-07-18", - "2007-07-20", - "2010-03-19", - "2010-04-16", - "2010-04-22", - "2010-04-26", - "2010-12-27", - "2011-01-19", - "2011-01-28", - "2011-02-10", - "2011-02-17", - "2011-02-22", - "2011-04-18", - "2011-05-03", - "2011-05-11", - "2011-05-20", - "2011-06-01", - "2011-07-06", - "2011-07-08", - "2012-03-28", - "2012-04-04", - "2012-04-30", - "2012-07-05", - "2012-07-20", - "2012-08-29", - "2012-09-26", - "2012-10-19", - "2012-12-04", - "2012-12-14", - "2012-12-19", - "2013-02-25", - "2013-04-15", - "2013-04-17", - "2013-06-03", - "2013-06-11", - "2013-06-19", - "2013-06-28", - "2013-07-03", - "2013-08-27", - "2013-08-30", - "2013-09-30", - "2013-10-03", - "2013-10-14", - "2014-01-24", - "2014-03-14", - "2014-04-11", - "2014-07-31", - "2014-08-05", - "2014-09-29", - "2014-10-01", - "2014-10-07", - "2014-12-10", - "2014-12-31", - "2015-03-11", - "2015-03-26", - "2015-06-29", - "2015-08-20", - "2015-11-09", - "2015-11-12", - "2015-11-24", - "2015-12-03", - "2015-12-28", - "2015-12-30", - "2016-04-29", - "2016-05-19", - "2016-06-10", - "2016-07-06", - "2016-09-09", - "2016-10-13", - "2016-10-17", - "2016-10-28", - "2017-08-11", - "2018-02-02", - "2018-02-27", - "2018-03-14", - "2018-03-19", - "2018-04-20", - "2018-05-03", - "2018-05-29", - "2018-06-25", - "2018-07-02", - "2018-10-05", - "2019-02-07", - "2019-02-14", - "2019-03-07", - "2019-03-22", - "2019-05-06", - "2019-05-20", - "2019-05-23", - "2019-05-28", - "2019-08-01", - "2019-09-24", - "2019-12-03", - "2020-01-27", - "2020-01-30", - "2020-02-20", - "2021-04-19", - "2021-06-01", - "2021-06-14", - "2021-06-30", - "2021-07-06", "2021-08-16", "2021-08-31", "2021-09-03", @@ -261,168 +125,34 @@ ] }, "18": { - "total_signals": 191, + "total_signals": 57, "horizons": { "5": { - "n": 190, - "mean": 0.002228695555235771, - "median": 0.006793328516890851, - "win": 0.6210526315789474, + "n": 56, + "mean": 0.002526733304778989, + "median": 0.006194204073668996, + "win": 0.6071428571428571, "best": 0.06005524439913912, - "worst": -0.10626655998038559 + "worst": -0.06184163412063948 }, "20": { - "n": 188, - "mean": 0.00793389339156047, - "median": 0.018983520690392885, - "win": 0.6329787234042553, + "n": 54, + "mean": 0.011578655551448581, + "median": 0.014493890245094954, + "win": 0.6481481481481481, "best": 0.11160072299361556, - "worst": -0.258696340031045 + "worst": -0.08747019674920486 }, "60": { - "n": 184, - "mean": 0.026603852717065, - "median": 0.03367443737916054, - "win": 0.7010869565217391, + "n": 50, + "mean": 0.04132396163462907, + "median": 0.06108182125506367, + "win": 0.72, "best": 0.20070137492494355, - "worst": -0.36746231155778897 + "worst": -0.17956826849498064 } }, "signal_dates": [ - "2000-09-05", - "2002-04-01", - "2003-09-22", - "2003-10-16", - "2003-10-20", - "2003-10-23", - "2003-11-11", - "2003-11-17", - "2003-12-10", - "2003-12-31", - "2004-01-13", - "2004-02-04", - "2004-03-10", - "2004-05-07", - "2004-08-05", - "2005-04-15", - "2006-05-19", - "2006-05-30", - "2006-06-06", - "2006-06-08", - "2006-07-14", - "2007-02-27", - "2007-03-01", - "2007-03-13", - "2007-06-26", - "2007-07-20", - "2007-07-24", - "2007-09-28", - "2007-10-11", - "2008-05-20", - "2010-01-12", - "2010-03-09", - "2010-03-22", - "2010-03-25", - "2010-04-01", - "2010-04-16", - "2010-04-22", - "2010-04-27", - "2010-12-15", - "2010-12-27", - "2010-12-31", - "2011-01-04", - "2011-01-07", - "2011-01-20", - "2011-01-28", - "2011-02-22", - "2011-04-08", - "2011-04-12", - "2011-04-14", - "2011-04-18", - "2011-05-05", - "2011-05-16", - "2011-05-23", - "2011-06-01", - "2011-07-11", - "2011-07-25", - "2012-02-06", - "2012-02-27", - "2012-03-05", - "2012-04-09", - "2012-05-04", - "2012-07-05", - "2012-07-23", - "2012-07-30", - "2012-08-30", - "2012-10-23", - "2012-11-05", - "2012-11-14", - "2012-12-21", - "2013-02-25", - "2013-04-18", - "2013-06-06", - "2013-06-12", - "2013-06-20", - "2013-10-03", - "2013-10-07", - "2013-10-15", - "2014-01-24", - "2014-01-29", - "2014-01-31", - "2014-03-14", - "2014-10-08", - "2014-10-22", - "2014-10-24", - "2014-12-10", - "2014-12-31", - "2015-01-27", - "2015-02-06", - "2015-06-29", - "2015-07-06", - "2015-08-20", - "2015-10-14", - "2015-11-12", - "2015-12-03", - "2015-12-08", - "2015-12-28", - "2015-12-31", - "2016-03-07", - "2016-06-13", - "2016-09-12", - "2016-11-01", - "2018-02-05", - "2018-02-27", - "2018-03-19", - "2018-04-24", - "2018-05-03", - "2018-05-29", - "2018-06-25", - "2018-06-27", - "2018-07-02", - "2018-10-08", - "2018-10-10", - "2018-11-09", - "2018-12-04", - "2019-03-08", - "2019-05-06", - "2019-05-23", - "2019-05-29", - "2019-08-01", - "2019-08-23", - "2019-09-25", - "2019-09-27", - "2019-10-01", - "2020-01-27", - "2020-01-30", - "2020-02-21", - "2021-04-19", - "2021-04-29", - "2021-06-01", - "2021-06-10", - "2021-06-16", - "2021-07-08", - "2021-07-15", - "2021-07-26", "2021-08-17", "2021-08-26", "2021-09-07", @@ -483,157 +213,34 @@ ] }, "19": { - "total_signals": 177, + "total_signals": 54, "horizons": { "5": { - "n": 177, - "mean": 0.003526418153314111, - "median": 0.00758437839065218, - "win": 0.6101694915254238, + "n": 54, + "mean": 0.005179920047556141, + "median": 0.008431420238394827, + "win": 0.6111111111111112, "best": 0.06005524439913912, - "worst": -0.08165829145728642 + "worst": -0.0687655588859718 }, "20": { - "n": 175, - "mean": 0.007170011873600577, - "median": 0.016128753968992937, - "win": 0.6114285714285714, + "n": 52, + "mean": 0.016763236651556733, + "median": 0.014847447458760099, + "win": 0.6923076923076923, "best": 0.12384656729048382, - "worst": -0.23004649178459047 + "worst": -0.14466646189504417 }, "60": { - "n": 172, - "mean": 0.026277365790454702, - "median": 0.03671182158162045, - "win": 0.686046511627907, + "n": 49, + "mean": 0.0526922446635316, + "median": 0.07757908753862908, + "win": 0.7551020408163265, "best": 0.21174882001450723, - "worst": -0.36746231155778897 + "worst": -0.177732089231886 } }, "signal_dates": [ - "1999-07-12", - "1999-07-19", - "2000-08-07", - "2000-09-05", - "2000-09-18", - "2002-03-18", - "2002-04-01", - "2002-04-22", - "2002-05-20", - "2003-07-14", - "2003-07-29", - "2003-08-25", - "2003-09-02", - "2003-09-09", - "2003-09-22", - "2003-11-17", - "2004-03-11", - "2004-05-10", - "2004-05-14", - "2004-05-20", - "2004-08-06", - "2004-08-12", - "2006-05-22", - "2006-05-24", - "2006-06-08", - "2006-06-12", - "2006-07-18", - "2007-02-27", - "2007-03-01", - "2007-03-05", - "2007-03-14", - "2007-07-24", - "2007-10-11", - "2007-10-15", - "2008-05-22", - "2008-06-02", - "2010-01-12", - "2010-01-15", - "2010-01-20", - "2010-03-11", - "2010-04-16", - "2010-04-27", - "2010-11-08", - "2011-01-28", - "2011-02-22", - "2011-03-28", - "2011-04-18", - "2011-05-05", - "2011-05-17", - "2011-05-23", - "2011-06-03", - "2011-06-10", - "2011-06-15", - "2011-06-23", - "2011-07-11", - "2011-07-25", - "2012-02-10", - "2012-02-27", - "2012-03-06", - "2012-04-10", - "2012-04-18", - "2012-04-23", - "2012-05-04", - "2012-06-20", - "2012-07-10", - "2012-07-23", - "2012-07-31", - "2012-10-23", - "2012-11-07", - "2012-12-21", - "2012-12-26", - "2013-02-25", - "2013-06-20", - "2013-10-07", - "2014-02-03", - "2014-10-09", - "2014-12-11", - "2014-12-31", - "2015-01-12", - "2015-01-28", - "2015-02-09", - "2015-06-29", - "2015-07-07", - "2015-08-20", - "2015-11-13", - "2015-12-03", - "2015-12-09", - "2015-12-31", - "2016-03-09", - "2016-06-13", - "2016-06-22", - "2016-09-12", - "2016-11-01", - "2018-02-05", - "2018-02-28", - "2018-03-19", - "2018-03-22", - "2018-04-24", - "2018-06-25", - "2018-10-10", - "2018-11-12", - "2018-12-04", - "2019-01-22", - "2019-01-28", - "2019-05-07", - "2019-05-29", - "2019-05-31", - "2019-08-01", - "2019-08-23", - "2019-10-02", - "2019-10-08", - "2020-01-27", - "2020-01-31", - "2020-02-24", - "2021-04-20", - "2021-04-30", - "2021-05-10", - "2021-06-03", - "2021-06-16", - "2021-07-08", - "2021-07-19", - "2021-07-26", - "2021-07-30", "2021-08-17", "2021-08-26", "2021-09-08", @@ -691,164 +298,34 @@ ] }, "20": { - "total_signals": 183, + "total_signals": 53, "horizons": { "5": { - "n": 183, - "mean": 0.0037891947092253105, - "median": 0.006530760175192052, - "win": 0.6010928961748634, + "n": 53, + "mean": 0.007293232225419666, + "median": 0.00934738410944691, + "win": 0.660377358490566, "best": 0.08397686211051614, "worst": -0.09866931541941393 }, "20": { - "n": 181, - "mean": 0.005115673278668865, - "median": 0.012599121901678556, - "win": 0.6022099447513812, - "best": 0.19849246231155782, - "worst": -0.23004649178459047 + "n": 51, + "mean": 0.016870468211586862, + "median": 0.016128753968992937, + "win": 0.6274509803921569, + "best": 0.1217066098444064, + "worst": -0.10645887101835971 }, "60": { - "n": 178, - "mean": 0.026690534052821756, - "median": 0.051752859486369096, - "win": 0.7078651685393258, - "best": 0.3685092127303182, - "worst": -0.3904065577671426 + "n": 48, + "mean": 0.06360778893320072, + "median": 0.08571230647702632, + "win": 0.8333333333333334, + "best": 0.21070940407956984, + "worst": -0.2033288427237785 } }, "signal_dates": [ - "1999-07-06", - "1999-07-12", - "1999-07-20", - "1999-11-22", - "1999-12-06", - "2000-07-03", - "2000-07-17", - "2000-07-27", - "2000-09-05", - "2000-09-18", - "2001-07-05", - "2002-04-03", - "2002-04-08", - "2002-04-11", - "2002-04-22", - "2002-05-21", - "2002-05-28", - "2003-05-19", - "2003-06-02", - "2003-06-23", - "2003-07-01", - "2003-07-07", - "2003-07-16", - "2003-08-01", - "2003-08-26", - "2003-09-10", - "2003-09-22", - "2003-09-24", - "2004-03-11", - "2004-03-22", - "2004-05-10", - "2004-05-12", - "2004-05-17", - "2006-06-08", - "2006-06-12", - "2007-03-05", - "2007-03-14", - "2007-07-26", - "2007-09-25", - "2007-10-15", - "2007-10-19", - "2007-12-27", - "2008-05-09", - "2008-05-27", - "2008-06-02", - "2008-08-25", - "2008-08-29", - "2009-12-28", - "2010-01-21", - "2010-04-27", - "2010-10-12", - "2010-10-14", - "2010-10-26", - "2010-11-12", - "2010-11-22", - "2010-11-26", - "2011-01-28", - "2011-02-22", - "2011-03-01", - "2011-03-04", - "2011-05-23", - "2011-06-13", - "2011-06-15", - "2011-06-23", - "2011-07-12", - "2011-07-26", - "2012-01-24", - "2012-01-30", - "2012-02-10", - "2012-02-14", - "2012-03-06", - "2012-04-10", - "2012-04-16", - "2012-04-23", - "2012-05-08", - "2012-05-14", - "2012-06-20", - "2012-06-25", - "2012-07-23", - "2012-12-27", - "2013-06-20", - "2013-10-08", - "2014-02-03", - "2014-10-10", - "2014-12-11", - "2015-01-02", - "2015-01-12", - "2015-01-28", - "2015-07-09", - "2015-08-21", - "2015-11-13", - "2015-12-09", - "2015-12-11", - "2015-12-18", - "2015-12-31", - "2016-06-13", - "2016-06-22", - "2016-06-24", - "2016-09-12", - "2016-11-01", - "2016-11-03", - "2016-11-09", - "2018-02-05", - "2018-02-28", - "2018-03-07", - "2018-03-19", - "2018-03-22", - "2018-10-10", - "2018-10-18", - "2018-11-12", - "2018-11-29", - "2018-12-04", - "2019-01-22", - "2019-01-28", - "2019-05-07", - "2019-08-02", - "2019-08-12", - "2019-08-23", - "2019-09-03", - "2019-10-02", - "2019-10-08", - "2020-02-24", - "2021-05-04", - "2021-05-06", - "2021-05-11", - "2021-06-18", - "2021-07-08", - "2021-07-19", - "2021-07-27", - "2021-08-03", "2021-08-18", "2021-09-10", "2021-09-17", @@ -905,162 +382,34 @@ ] }, "21": { - "total_signals": 178, + "total_signals": 50, "horizons": { "5": { - "n": 178, - "mean": 0.0020092677587955432, - "median": 0.006431957705823499, - "win": 0.5617977528089888, + "n": 50, + "mean": 0.0025563136078792592, + "median": 0.0068010314914316305, + "win": 0.56, "best": 0.06610940521499553, "worst": -0.09866931541941393 }, "20": { - "n": 178, - "mean": 0.002592636268539343, - "median": 0.01605016111934854, - "win": 0.6123595505617978, - "best": 0.18924551896623587, - "worst": -0.2676946838299752 + "n": 50, + "mean": 0.012299137922432953, + "median": 0.018978022799173933, + "win": 0.64, + "best": 0.1553312510788094, + "worst": -0.13595743196109733 }, "60": { - "n": 176, - "mean": 0.019879742979264356, - "median": 0.047897584245304214, - "win": 0.6704545454545454, - "best": 0.341914722445696, - "worst": -0.3904065577671426 + "n": 48, + "mean": 0.0482895516351726, + "median": 0.07565524390627876, + "win": 0.7291666666666666, + "best": 0.2126699564530663, + "worst": -0.2186928825419765 } }, "signal_dates": [ - "1999-07-07", - "1999-07-20", - "1999-11-23", - "1999-11-26", - "1999-12-06", - "2000-01-18", - "2000-03-06", - "2000-06-19", - "2000-07-05", - "2000-07-31", - "2000-09-20", - "2000-09-22", - "2000-10-02", - "2001-06-11", - "2001-06-26", - "2001-07-06", - "2001-08-03", - "2001-08-16", - "2001-08-28", - "2002-03-05", - "2002-04-25", - "2002-05-06", - "2002-05-30", - "2002-06-03", - "2003-04-29", - "2003-05-20", - "2003-06-03", - "2003-06-05", - "2003-06-12", - "2003-06-16", - "2003-06-25", - "2003-08-04", - "2003-09-24", - "2004-03-15", - "2004-03-22", - "2006-06-12", - "2007-03-14", - "2007-07-26", - "2007-10-19", - "2007-10-30", - "2007-12-28", - "2008-04-21", - "2008-06-03", - "2008-06-06", - "2008-08-12", - "2008-08-18", - "2008-08-25", - "2008-09-02", - "2009-11-27", - "2009-12-31", - "2010-01-21", - "2010-04-27", - "2010-04-30", - "2010-10-14", - "2010-10-19", - "2010-10-26", - "2010-11-12", - "2010-11-16", - "2010-11-23", - "2010-11-26", - "2011-02-22", - "2011-03-01", - "2011-03-07", - "2011-03-10", - "2011-03-23", - "2011-06-15", - "2011-06-23", - "2011-07-14", - "2011-07-27", - "2012-01-11", - "2012-02-10", - "2012-02-15", - "2012-03-06", - "2012-04-10", - "2012-05-09", - "2012-05-14", - "2012-06-25", - "2012-06-28", - "2012-07-24", - "2012-12-28", - "2013-06-20", - "2013-06-24", - "2013-10-08", - "2014-02-03", - "2014-10-10", - "2014-12-12", - "2015-01-05", - "2015-01-13", - "2015-01-29", - "2015-08-21", - "2015-12-11", - "2015-12-18", - "2016-01-04", - "2016-02-23", - "2016-06-13", - "2016-06-16", - "2016-06-22", - "2016-06-24", - "2016-11-03", - "2016-11-09", - "2018-02-05", - "2018-02-20", - "2018-03-01", - "2018-03-19", - "2018-03-22", - "2018-04-06", - "2018-10-10", - "2018-10-18", - "2018-10-23", - "2018-11-13", - "2018-11-20", - "2018-12-04", - "2019-01-22", - "2019-05-07", - "2019-05-13", - "2019-08-05", - "2019-08-12", - "2019-08-23", - "2019-09-03", - "2019-10-02", - "2020-02-24", - "2020-12-02", - "2021-03-18", - "2021-05-04", - "2021-05-11", - "2021-06-18", - "2021-07-08", - "2021-07-19", "2021-08-18", "2021-09-10", "2021-09-17", @@ -1114,153 +463,34 @@ ] }, "22": { - "total_signals": 160, + "total_signals": 41, "horizons": { "5": { - "n": 160, - "mean": -0.0014847935185072173, - "median": 0.003294149672387503, - "win": 0.51875, - "best": 0.11400544317046268, - "worst": -0.11227155225906105 + "n": 41, + "mean": 0.004729890061364004, + "median": 0.00758437839065218, + "win": 0.5853658536585366, + "best": 0.06486923070532713, + "worst": -0.09866931541941393 }, "20": { - "n": 160, - "mean": -0.009098996967542461, - "median": 0.012440513998633662, - "win": 0.56875, - "best": 0.15446500402252616, - "worst": -0.27467569091934574 + "n": 41, + "mean": 0.009766392712114847, + "median": 0.021827291629354928, + "win": 0.6585365853658537, + "best": 0.127016351044682, + "worst": -0.13338323548803055 }, "60": { - "n": 159, - "mean": 0.003642889876465111, - "median": 0.03233000220966664, - "win": 0.5911949685534591, - "best": 0.3911671924290221, - "worst": -0.3892788745044078 + "n": 40, + "mean": 0.04572229219669499, + "median": 0.07306306891310688, + "win": 0.675, + "best": 0.2346876983518864, + "worst": -0.1876805086274399 } }, "signal_dates": [ - "1999-06-23", - "1999-07-22", - "1999-08-27", - "1999-09-07", - "1999-10-12", - "1999-11-26", - "1999-12-09", - "1999-12-20", - "1999-12-27", - "2000-01-19", - "2000-01-24", - "2000-02-07", - "2000-03-07", - "2000-03-13", - "2000-03-17", - "2000-06-05", - "2000-06-22", - "2000-09-22", - "2000-09-26", - "2000-10-04", - "2000-10-06", - "2001-02-05", - "2001-02-09", - "2001-02-14", - "2001-02-16", - "2001-05-23", - "2001-05-29", - "2001-06-14", - "2001-07-09", - "2001-08-06", - "2001-08-08", - "2001-08-16", - "2001-08-28", - "2001-12-31", - "2002-01-07", - "2002-01-29", - "2002-02-04", - "2002-02-15", - "2002-04-26", - "2002-05-06", - "2002-05-10", - "2002-06-03", - "2003-05-01", - "2003-06-09", - "2003-08-04", - "2003-09-25", - "2004-03-22", - "2006-06-13", - "2007-07-26", - "2007-10-19", - "2007-10-24", - "2007-10-31", - "2007-12-11", - "2007-12-31", - "2008-06-06", - "2008-06-18", - "2008-08-13", - "2008-08-19", - "2008-09-02", - "2009-10-21", - "2009-11-27", - "2009-12-17", - "2010-01-21", - "2010-02-25", - "2010-04-27", - "2010-04-30", - "2010-09-15", - "2010-10-27", - "2010-11-01", - "2010-11-03", - "2010-11-16", - "2010-11-26", - "2011-02-23", - "2011-03-10", - "2011-03-14", - "2011-06-16", - "2011-07-27", - "2011-12-27", - "2012-01-12", - "2012-05-15", - "2012-12-28", - "2014-10-10", - "2014-12-12", - "2015-01-06", - "2015-01-14", - "2015-01-30", - "2015-08-21", - "2015-12-11", - "2015-12-18", - "2016-01-04", - "2016-01-07", - "2016-02-01", - "2016-02-24", - "2016-06-14", - "2016-06-16", - "2016-06-24", - "2016-11-03", - "2018-02-05", - "2018-03-01", - "2018-03-22", - "2018-04-06", - "2018-10-10", - "2018-10-23", - "2018-11-14", - "2018-11-20", - "2018-12-06", - "2018-12-14", - "2019-01-23", - "2019-05-09", - "2019-08-05", - "2019-08-14", - "2020-02-24", - "2020-11-30", - "2020-12-07", - "2021-03-18", - "2021-03-25", - "2021-05-11", - "2021-05-19", - "2021-07-19", "2021-08-19", "2021-09-20", "2021-09-28", diff --git a/vix_qqq_results_5y.json b/vix_qqq_results_5y.json new file mode 100644 index 0000000..ea0bf5b --- /dev/null +++ b/vix_qqq_results_5y.json @@ -0,0 +1,538 @@ +{ + "data_span": "2021-08-10 to 2026-08-07", + "trading_days": 1254, + "thresholds": [ + 17, + 18, + 19, + 20, + 21, + 22 + ], + "horizons": [ + 5, + 20, + 60 + ], + "buy_and_hold": { + "5": { + "n": 1249, + "mean": 0.003138296789026028, + "median": 0.0051984480660698384, + "win": 0.5748598879103283, + "best": 0.10077871682407125, + "worst": -0.11982232533480563 + }, + "20": { + "n": 1234, + "mean": 0.01202913585405011, + "median": 0.01545511618643891, + "win": 0.6191247974068071, + "best": 0.20525969712266257, + "worst": -0.15937638583593183 + }, + "60": { + "n": 1194, + "mean": 0.03836659718447432, + "median": 0.04653715628976818, + "win": 0.6758793969849246, + "best": 0.3268039045717981, + "worst": -0.24105061455776944 + } + }, + "strategy": { + "17": { + "total_signals": 52, + "horizons": { + "5": { + "n": 51, + "mean": -0.000397887254264299, + "median": 0.0029504630475947202, + "win": 0.6078431372549019, + "best": 0.03794034703293514, + "worst": -0.04930729886574403 + }, + "20": { + "n": 49, + "mean": 0.009383555926493871, + "median": 0.01501830979627572, + "win": 0.6530612244897959, + "best": 0.08957976364882358, + "worst": -0.11349610607709382 + }, + "60": { + "n": 46, + "mean": 0.028079584256733712, + "median": 0.047912148321742065, + "win": 0.6739130434782609, + "best": 0.20070137492494355, + "worst": -0.17956826849498064 + } + }, + "signal_dates": [ + "2021-08-16", + "2021-08-31", + "2021-09-03", + "2021-10-18", + "2021-10-27", + "2021-11-05", + "2023-05-02", + "2023-07-06", + "2023-08-03", + "2023-08-17", + "2023-09-21", + "2024-02-13", + "2024-04-11", + "2024-04-25", + "2024-07-19", + "2024-07-24", + "2024-08-01", + "2024-08-21", + "2024-08-28", + "2024-09-03", + "2024-09-30", + "2024-11-15", + "2024-12-18", + "2024-12-27", + "2025-01-07", + "2025-01-27", + "2025-01-31", + "2025-02-12", + "2025-02-21", + "2025-06-27", + "2025-07-07", + "2025-07-11", + "2025-07-22", + "2025-07-30", + "2025-08-20", + "2025-09-02", + "2025-09-23", + "2025-10-01", + "2025-10-03", + "2025-10-29", + "2025-12-08", + "2025-12-12", + "2026-01-14", + "2026-01-20", + "2026-01-26", + "2026-01-28", + "2026-06-05", + "2026-06-17", + "2026-07-08", + "2026-07-13", + "2026-07-16", + "2026-08-05" + ] + }, + "18": { + "total_signals": 57, + "horizons": { + "5": { + "n": 56, + "mean": 0.002526733304778989, + "median": 0.006194204073668996, + "win": 0.6071428571428571, + "best": 0.06005524439913912, + "worst": -0.06184163412063948 + }, + "20": { + "n": 54, + "mean": 0.011578655551448581, + "median": 0.014493890245094954, + "win": 0.6481481481481481, + "best": 0.11160072299361556, + "worst": -0.08747019674920486 + }, + "60": { + "n": 50, + "mean": 0.04132396163462907, + "median": 0.06108182125506367, + "win": 0.72, + "best": 0.20070137492494355, + "worst": -0.17956826849498064 + } + }, + "signal_dates": [ + "2021-08-17", + "2021-08-26", + "2021-09-07", + "2021-10-29", + "2021-11-09", + "2021-11-18", + "2021-12-31", + "2022-01-05", + "2023-04-24", + "2023-05-02", + "2023-05-10", + "2023-05-15", + "2023-05-22", + "2023-08-08", + "2023-08-17", + "2023-09-25", + "2023-10-02", + "2023-10-12", + "2024-04-12", + "2024-07-24", + "2024-07-30", + "2024-08-01", + "2024-08-22", + "2024-09-03", + "2024-09-17", + "2024-10-01", + "2024-11-20", + "2024-12-18", + "2024-12-27", + "2025-01-02", + "2025-01-07", + "2025-01-27", + "2025-02-03", + "2025-02-21", + "2025-03-26", + "2025-05-19", + "2025-06-11", + "2025-07-07", + "2025-07-16", + "2025-08-01", + "2025-09-02", + "2025-10-10", + "2025-10-31", + "2025-12-17", + "2026-01-14", + "2026-01-20", + "2026-01-29", + "2026-02-11", + "2026-05-04", + "2026-05-11", + "2026-06-05", + "2026-06-17", + "2026-06-23", + "2026-07-08", + "2026-07-17", + "2026-07-22", + "2026-08-05" + ] + }, + "19": { + "total_signals": 54, + "horizons": { + "5": { + "n": 54, + "mean": 0.005179920047556141, + "median": 0.008431420238394827, + "win": 0.6111111111111112, + "best": 0.06005524439913912, + "worst": -0.0687655588859718 + }, + "20": { + "n": 52, + "mean": 0.016763236651556733, + "median": 0.014847447458760099, + "win": 0.6923076923076923, + "best": 0.12384656729048382, + "worst": -0.14466646189504417 + }, + "60": { + "n": 49, + "mean": 0.0526922446635316, + "median": 0.07757908753862908, + "win": 0.7551020408163265, + "best": 0.21174882001450723, + "worst": -0.177732089231886 + } + }, + "signal_dates": [ + "2021-08-17", + "2021-08-26", + "2021-09-08", + "2021-11-10", + "2021-11-19", + "2021-12-27", + "2022-01-05", + "2022-01-13", + "2023-04-25", + "2023-05-02", + "2023-05-04", + "2023-05-23", + "2023-09-26", + "2023-10-03", + "2023-10-13", + "2023-10-18", + "2024-04-12", + "2024-04-19", + "2024-07-25", + "2024-08-01", + "2024-09-03", + "2024-09-18", + "2024-10-01", + "2024-12-18", + "2024-12-30", + "2025-01-02", + "2025-01-08", + "2025-01-27", + "2025-02-03", + "2025-02-21", + "2025-03-26", + "2025-05-15", + "2025-05-19", + "2025-05-21", + "2025-06-13", + "2025-07-16", + "2025-08-01", + "2025-09-02", + "2025-10-10", + "2025-10-22", + "2025-11-04", + "2025-11-13", + "2026-01-20", + "2026-01-29", + "2026-02-12", + "2026-04-16", + "2026-04-20", + "2026-05-04", + "2026-05-12", + "2026-05-15", + "2026-06-05", + "2026-06-23", + "2026-07-17", + "2026-07-22" + ] + }, + "20": { + "total_signals": 53, + "horizons": { + "5": { + "n": 53, + "mean": 0.007293232225419666, + "median": 0.00934738410944691, + "win": 0.660377358490566, + "best": 0.08397686211051614, + "worst": -0.09866931541941393 + }, + "20": { + "n": 51, + "mean": 0.016870468211586862, + "median": 0.016128753968992937, + "win": 0.6274509803921569, + "best": 0.1217066098444064, + "worst": -0.10645887101835971 + }, + "60": { + "n": 48, + "mean": 0.06360778893320072, + "median": 0.08571230647702632, + "win": 0.8333333333333334, + "best": 0.21070940407956984, + "worst": -0.2033288427237785 + } + }, + "signal_dates": [ + "2021-08-18", + "2021-09-10", + "2021-09-17", + "2021-09-28", + "2021-10-11", + "2021-11-23", + "2022-01-05", + "2022-01-13", + "2022-03-30", + "2023-01-17", + "2023-01-30", + "2023-02-08", + "2023-02-16", + "2023-03-08", + "2023-03-30", + "2023-04-04", + "2023-04-10", + "2023-05-04", + "2023-05-24", + "2023-10-03", + "2023-10-13", + "2023-10-18", + "2024-04-19", + "2024-08-02", + "2024-09-03", + "2024-10-01", + "2024-10-23", + "2024-10-29", + "2024-12-18", + "2025-01-10", + "2025-01-27", + "2025-02-03", + "2025-02-24", + "2025-03-28", + "2025-05-21", + "2025-05-29", + "2025-06-13", + "2025-08-01", + "2025-10-10", + "2025-10-22", + "2025-11-04", + "2025-11-13", + "2026-01-20", + "2026-02-03", + "2026-02-12", + "2026-02-26", + "2026-04-21", + "2026-04-23", + "2026-06-05", + "2026-06-23", + "2026-06-26", + "2026-07-23", + "2026-07-29" + ] + }, + "21": { + "total_signals": 50, + "horizons": { + "5": { + "n": 50, + "mean": 0.0025563136078792592, + "median": 0.0068010314914316305, + "win": 0.56, + "best": 0.06610940521499553, + "worst": -0.09866931541941393 + }, + "20": { + "n": 50, + "mean": 0.012299137922432953, + "median": 0.018978022799173933, + "win": 0.64, + "best": 0.1553312510788094, + "worst": -0.13595743196109733 + }, + "60": { + "n": 48, + "mean": 0.0482895516351726, + "median": 0.07565524390627876, + "win": 0.7291666666666666, + "best": 0.2126699564530663, + "worst": -0.2186928825419765 + } + }, + "signal_dates": [ + "2021-08-18", + "2021-09-10", + "2021-09-17", + "2021-09-28", + "2021-11-26", + "2022-01-06", + "2022-01-10", + "2022-01-14", + "2022-03-31", + "2022-04-05", + "2022-08-15", + "2022-08-19", + "2022-12-05", + "2023-01-19", + "2023-02-09", + "2023-02-17", + "2023-03-09", + "2023-05-04", + "2023-10-19", + "2023-10-25", + "2024-04-19", + "2024-08-02", + "2024-09-03", + "2024-09-11", + "2024-10-07", + "2024-10-16", + "2024-10-31", + "2024-12-18", + "2025-01-13", + "2025-01-27", + "2025-02-25", + "2025-02-27", + "2025-03-28", + "2025-05-21", + "2025-06-13", + "2025-06-17", + "2025-08-01", + "2025-10-10", + "2025-10-14", + "2025-10-22", + "2025-11-07", + "2025-11-13", + "2026-02-04", + "2026-02-12", + "2026-02-19", + "2026-02-27", + "2026-04-13", + "2026-04-23", + "2026-06-05", + "2026-06-09" + ] + }, + "22": { + "total_signals": 41, + "horizons": { + "5": { + "n": 41, + "mean": 0.004729890061364004, + "median": 0.00758437839065218, + "win": 0.5853658536585366, + "best": 0.06486923070532713, + "worst": -0.09866931541941393 + }, + "20": { + "n": 41, + "mean": 0.009766392712114847, + "median": 0.021827291629354928, + "win": 0.6585365853658537, + "best": 0.127016351044682, + "worst": -0.13338323548803055 + }, + "60": { + "n": 40, + "mean": 0.04572229219669499, + "median": 0.07306306891310688, + "win": 0.675, + "best": 0.2346876983518864, + "worst": -0.1876805086274399 + } + }, + "signal_dates": [ + "2021-08-19", + "2021-09-20", + "2021-09-28", + "2021-11-26", + "2021-12-14", + "2022-01-10", + "2022-01-14", + "2022-02-10", + "2022-04-06", + "2022-04-21", + "2022-08-22", + "2022-11-28", + "2022-12-06", + "2022-12-22", + "2023-01-10", + "2023-02-21", + "2023-03-09", + "2023-10-23", + "2023-10-27", + "2024-08-02", + "2024-09-04", + "2024-09-06", + "2024-10-07", + "2024-10-31", + "2024-12-18", + "2025-01-13", + "2025-01-27", + "2025-02-28", + "2025-03-28", + "2025-05-22", + "2025-06-13", + "2025-06-23", + "2025-10-10", + "2025-10-14", + "2025-11-07", + "2025-11-14", + "2026-02-05", + "2026-02-13", + "2026-02-23", + "2026-03-02", + "2026-06-09" + ] + } + } +} \ No newline at end of file From aaeda923ecf20d50f439b0887385e5cf3bf33931 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 07:05:46 +0000 Subject: [PATCH 3/4] Add equity-curve backtester comparing 5 QQQ long/flat strategies vs buy&hold Strategies: 200d trend filter, Connors RSI2 mean reversion, dip-buy, and a VIX-spike 10-day dip-buy. Reports total return, CAGR, vol, Sharpe, max drawdown, exposure and trade frequency over full history and last 5 years. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01JXFxuoYQvap2iq4EHbf9GW --- vix_qqq_strategies.py | 211 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 vix_qqq_strategies.py diff --git a/vix_qqq_strategies.py b/vix_qqq_strategies.py new file mode 100644 index 0000000..9398d3b --- /dev/null +++ b/vix_qqq_strategies.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python3 +""" +Compare several long/flat QQQ trading strategies against buy & hold. + +Execution model (no look-ahead): + * A strategy outputs a target position (1 = long QQQ, 0 = cash) that is + DECIDED using data up to and including day t's close. + * That position earns the QQQ close-to-close return from day t to t+1. + * A round-trip costs COST per side (applied when the position changes). + +Metrics per strategy: + total return, CAGR, annual vol, Sharpe (rf=0), max drawdown, + exposure (% of days invested), number of trades, average trades/year. + +Strategies: + BH Buy & Hold + SMA 200-day trend filter: long when Close > SMA200 else cash + RSI2 Connors-style mean reversion: (Close>SMA200) & RSI(2)<10 -> long, + exit when Close>SMA5 or RSI(2)>70 (frequent, short holds) + DIP Above SMA200, buy after 3 consecutive down days, exit on first up day + VIXR VIX spike dip-buy: above SMA200, enter when VIX High >= 1.10 * prior + VIX close, hold 10 trading days (overlaps extend the hold) +""" + +import sys +import numpy as np +import pandas as pd +import requests + +CA_BUNDLE = "/root/.ccr/ca-bundle.crt" +HEADERS = {"User-Agent": "Mozilla/5.0"} +COST = 0.0002 # 0.02% per side +TRADING_DAYS = 252 + + +def fetch_yahoo(symbol): + url = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}" + params = {"period1": 0, "period2": 9999999999, "interval": "1d"} + r = requests.get(url, params=params, headers=HEADERS, timeout=60, verify=CA_BUNDLE) + r.raise_for_status() + res = r.json()["chart"]["result"][0] + q = res["indicators"]["quote"][0] + df = pd.DataFrame( + {"open": q["open"], "high": q["high"], "low": q["low"], "close": q["close"]}, + index=pd.to_datetime(res["timestamp"], unit="s").normalize(), + ).dropna(subset=["high", "close"]) + df.index.name = "date" + return df + + +def rsi(series, n): + delta = series.diff() + up = delta.clip(lower=0).rolling(n).mean() + down = (-delta.clip(upper=0)).rolling(n).mean() + rs = up / down.replace(0, np.nan) + return 100 - 100 / (1 + rs) + + +def build(df): + d = pd.DataFrame(index=df.index) + d["close"] = df["qqq_close"] + d["ret"] = d["close"].pct_change() + d["sma200"] = d["close"].rolling(200).mean() + d["sma5"] = d["close"].rolling(5).mean() + d["rsi2"] = rsi(d["close"], 2) + d["up"] = d["close"].diff() > 0 + d["vix_high"] = df["vix_high"] + d["vix_close"] = df["vix_close"] + return d + + +# --- position generators: return a 0/1 Series aligned to d.index --- + +def pos_bh(d): + return pd.Series(1.0, index=d.index) + + +def pos_sma(d): + return (d["close"] > d["sma200"]).astype(float) + + +def pos_rsi2(d): + above = d["close"] > d["sma200"] + pos = np.zeros(len(d)) + invested = False + r2 = d["rsi2"].values + c = d["close"].values + s5 = d["sma5"].values + ab = above.values + for i in range(len(d)): + if invested: + if c[i] > s5[i] or r2[i] > 70: + invested = False + else: + if ab[i] and r2[i] < 10: + invested = True + pos[i] = 1.0 if invested else 0.0 + return pd.Series(pos, index=d.index) + + +def pos_dip(d): + above = d["close"] > d["sma200"] + down = ~d["up"] + three_down = down & down.shift(1) & down.shift(2) + pos = np.zeros(len(d)) + invested = False + td = three_down.fillna(False).values + upv = d["up"].values + ab = above.values + for i in range(len(d)): + if invested: + if upv[i]: + invested = False + else: + if ab[i] and td[i]: + invested = True + pos[i] = 1.0 if invested else 0.0 + return pd.Series(pos, index=d.index) + + +def pos_vixr(d, hold=10): + above = d["close"] > d["sma200"] + spike = d["vix_high"] >= 1.10 * d["vix_close"].shift(1) + entry = (above & spike).fillna(False).values + pos = np.zeros(len(d)) + remaining = 0 + for i in range(len(d)): + if entry[i]: + remaining = hold + if remaining > 0: + pos[i] = 1.0 + remaining -= 1 + return pd.Series(pos, index=d.index) + + +STRATS = { + "BH": pos_bh, + "SMA": pos_sma, + "RSI2": pos_rsi2, + "DIP": pos_dip, + "VIXR": pos_vixr, +} + + +def evaluate(d, pos): + # position decided at t's close earns t->t+1 return: shift position by 1. + held = pos.shift(1).fillna(0.0) + trades_series = pos.diff().abs().fillna(0.0) # 1 each time exposure flips + cost = trades_series * COST + strat_ret = held * d["ret"].fillna(0.0) - cost + equity = (1 + strat_ret).cumprod() + + n = len(d) + years = n / TRADING_DAYS + total = equity.iloc[-1] - 1 + cagr = equity.iloc[-1] ** (1 / years) - 1 if years > 0 else np.nan + vol = strat_ret.std() * np.sqrt(TRADING_DAYS) + sharpe = (strat_ret.mean() * TRADING_DAYS) / vol if vol > 0 else np.nan + dd = (equity / equity.cummax() - 1).min() + exposure = held.mean() + # count entries (0->1) as trades + entries = int(((pos > 0) & (pos.shift(1).fillna(0) == 0)).sum()) + return { + "total": total, "cagr": cagr, "vol": vol, "sharpe": sharpe, + "maxdd": dd, "exposure": exposure, "trades": entries, + "trades_yr": entries / years if years > 0 else np.nan, + "equity": equity, + } + + +def run(d, label): + print("=" * 92) + print(f"{label} ({d.index[0].date()} -> {d.index[-1].date()}, " + f"{len(d)} trading days)") + print("=" * 92) + hdr = (f"{'Strat':>5} {'TotRet':>9} {'CAGR':>8} {'Vol':>7} {'Sharpe':>7} " + f"{'MaxDD':>8} {'Expo':>6} {'Trades':>7} {'Tr/yr':>6}") + print(hdr) + for name, fn in STRATS.items(): + m = evaluate(d, fn(d)) + print(f"{name:>5} {m['total']*100:>8.1f}% {m['cagr']*100:>7.1f}% " + f"{m['vol']*100:>6.1f}% {m['sharpe']:>7.2f} {m['maxdd']*100:>7.1f}% " + f"{m['exposure']*100:>5.0f}% {m['trades']:>7} {m['trades_yr']:>6.1f}") + print() + + +def main(): + vix = fetch_yahoo("%5EVIX") + qqq = fetch_yahoo("QQQ") + base = pd.DataFrame({ + "vix_high": vix["high"], + "vix_close": vix["close"], + "qqq_close": qqq["close"], + }).dropna().sort_index() + d_full = build(base) + + # 5-year window; keep SMA200 warm-up by computing indicators on full history + # then slicing. + start = pd.Timestamp("2021-08-10") + d_5y = d_full[d_full.index >= start].copy() + + run(d_full, "FULL HISTORY") + run(d_5y, "LAST 5 YEARS") + + print("Legend: BH=buy&hold SMA=200d trend filter RSI2=Connors mean-revert") + print(" DIP=3-down-days dip buy VIXR=VIX-spike 10d dip buy") + print("Execution: next-day fills, 0.02%/side cost, long/flat only.") + + +if __name__ == "__main__": + main() From 1d9e172bb53a58a72ecff908b7a153bfa40af399 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 10 Aug 2026 07:11:43 +0000 Subject: [PATCH 4/4] Add multiple-testing-aware strategy discovery pipeline (FDR + OOS) Enumerates 252 candidate QQQ timing strategies, tests market-timing alpha (equity premium stripped out) with HAC/Newey-West t-stats, applies Benjamini-Hochberg and Benjamini-Yekutieli FDR correction in-sample (1999-2016), then confirms survivors out-of-sample (2017-2026). Zero strategies pass both gates once beta is separated from skill. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01JXFxuoYQvap2iq4EHbf9GW --- pipeline_is_results.csv | 253 +++++++++++++++++++++++++++++ pipeline_oos_survivors.csv | 2 + strategy_pipeline.py | 321 +++++++++++++++++++++++++++++++++++++ 3 files changed, 576 insertions(+) create mode 100644 pipeline_is_results.csv create mode 100644 pipeline_oos_survivors.csv create mode 100644 strategy_pipeline.py diff --git a/pipeline_is_results.csv b/pipeline_is_results.csv new file mode 100644 index 0000000..c26964a --- /dev/null +++ b/pipeline_is_results.csv @@ -0,0 +1,253 @@ +filt,kind,param,hold,p_ret,p,is_cagr,is_sharpe,is_maxdd,name,bh,by +,vix_spike,1.05,5,0.23186905728715682,0.9098025090562097,0.004046750659648657,0.14993341259547585,-0.8674497440768423,vix_spike=1.05|H5|Fnan,False,False +,vix_spike,1.05,10,0.03889315146800972,0.05346637013101885,0.06538684396651573,0.3641079752804774,-0.781526735980781,vix_spike=1.05|H10|Fnan,False,False +,vix_spike,1.05,20,0.0616981516859197,0.2258732126632905,0.051415432477833756,0.3175965454236944,-0.8190365331722551,vix_spike=1.05|H20|Fnan,False,False +,vix_spike,1.08,5,0.045033634300708315,0.15239926526879005,0.052831641535623364,0.3342096043700541,-0.7410760358954781,vix_spike=1.08|H5|Fnan,False,False +,vix_spike,1.08,10,0.0158783860554467,0.006635729053244371,0.08942751839678542,0.45182527102692543,-0.7162925616967659,vix_spike=1.08|H10|Fnan,False,False +,vix_spike,1.08,20,0.0785960320421324,0.47810244046787564,0.044758896337864895,0.29575383342015443,-0.8163534619458387,vix_spike=1.08|H20|Fnan,False,False +,vix_spike,1.1,5,0.021151610504492224,0.0637694002980969,0.06437007567294617,0.4040090081809,-0.6282650092887803,vix_spike=1.1|H5|Fnan,False,False +,vix_spike,1.1,10,0.02358823161109913,0.05827416120098083,0.0710584672899679,0.40243801928079054,-0.6543485812997568,vix_spike=1.1|H10|Fnan,False,False +,vix_spike,1.1,20,0.08504673383068406,0.41294520122800865,0.041047525575622856,0.283477132473777,-0.7842762839610652,vix_spike=1.1|H20|Fnan,False,False +,vix_spike,1.12,5,0.0248822161027146,0.078257604705334,0.053094633416370884,0.3809800932567761,-0.4366333698071494,vix_spike=1.12|H5|Fnan,False,False +,vix_spike,1.12,10,0.02800571339211376,0.07364439088802029,0.0647885762920335,0.39472074523834544,-0.5222433179161381,vix_spike=1.12|H10|Fnan,False,False +,vix_spike,1.12,20,0.05584427240912487,0.174542004521682,0.05035201080753571,0.3192158679648455,-0.6862089671295577,vix_spike=1.12|H20|Fnan,False,False +,vix_spike,1.15,5,0.10111534757313632,0.22022860259247717,0.02334283007010396,0.24368118649763712,-0.3906781699604652,vix_spike=1.15|H5|Fnan,False,False +,vix_spike,1.15,10,0.2470136852714971,0.5488608583922397,0.007798091228578663,0.12957261974601186,-0.5280265309980647,vix_spike=1.15|H10|Fnan,False,False +,vix_spike,1.15,20,0.02319529033496274,0.10825270941357512,0.05693251434344759,0.3708294952982853,-0.4316772586946026,vix_spike=1.15|H20|Fnan,False,False +,vix_cross,17.0,5,0.13783548663568085,0.3184827596283648,0.012381575703294567,0.24271446114200232,-0.15952654804373234,vix_cross=17.0|H5|Fnan,False,False +,vix_cross,17.0,10,0.1559699912499763,0.48806984992927527,0.012469329702878174,0.2011458596299774,-0.1707032325139023,vix_cross=17.0|H10|Fnan,False,False +,vix_cross,17.0,20,0.05310716079116677,0.36491662006097536,0.027677099314039832,0.34367788180047887,-0.2894412324257224,vix_cross=17.0|H20|Fnan,False,False +,vix_cross,18.0,5,0.17138892191154104,0.33907621505731234,0.01125897454564595,0.21527551204385012,-0.18243514625368906,vix_cross=18.0|H5|Fnan,False,False +,vix_cross,18.0,10,0.19134117608255563,0.44709366889181856,0.013401636603895373,0.2036891960310375,-0.2500816895210626,vix_cross=18.0|H10|Fnan,False,False +,vix_cross,18.0,20,0.272059300085876,0.66546697912894,0.008569881830187587,0.13412942682618254,-0.31741196862331,vix_cross=18.0|H20|Fnan,False,False +,vix_cross,19.0,5,0.49116094740444805,0.6720517008794704,-0.002278830213069072,0.004657408663292134,-0.3780800976063379,vix_cross=19.0|H5|Fnan,False,False +,vix_cross,19.0,10,0.5658722228663143,0.8028923173839578,-0.007703545274536983,-0.038028500257960354,-0.44781305616507483,vix_cross=19.0|H10|Fnan,False,False +,vix_cross,19.0,20,0.4344118857732907,0.7883420383032556,-0.002981433350050855,0.03382417029825522,-0.46341931381283696,vix_cross=19.0|H20|Fnan,False,False +,vix_cross,20.0,5,0.2925091167826485,0.46048406019067845,0.0056048793166769695,0.1089845585810213,-0.31700920390213516,vix_cross=20.0|H5|Fnan,False,False +,vix_cross,20.0,10,0.3088814676599603,0.5416889071907488,0.006625899563688309,0.11570536244973627,-0.4536770615723775,vix_cross=20.0|H10|Fnan,False,False +,vix_cross,20.0,20,0.30887261029786006,0.6372945008945603,0.005610157330224963,0.1087386050291828,-0.5480106098301637,vix_cross=20.0|H20|Fnan,False,False +,vix_cross,22.0,5,0.7646982634494961,0.8609212576992508,-0.022203900549696787,-0.16336311321408825,-0.5530191183932165,vix_cross=22.0|H5|Fnan,False,False +,vix_cross,22.0,10,0.7011894577147268,0.8723864010984073,-0.025199939863543186,-0.11431384942925643,-0.635696370739857,vix_cross=22.0|H10|Fnan,False,False +,vix_cross,22.0,20,0.7310492960256105,0.9353724685049216,-0.039968757518548115,-0.15087086261744181,-0.8380568903258399,vix_cross=22.0|H20|Fnan,False,False +,vix_cross,25.0,5,0.9759654866327843,0.9901949569136005,-0.059289757212646066,-0.46164601695556756,-0.7869035055788995,vix_cross=25.0|H5|Fnan,False,False +,vix_cross,25.0,10,0.6426975700435076,0.8017177148683788,-0.02454153761830602,-0.07647623966980377,-0.7512413699852116,vix_cross=25.0|H10|Fnan,False,False +,vix_cross,25.0,20,0.5131746861704368,0.7532187402374206,-0.021065402391948096,-0.006993656933932437,-0.7973570686133038,vix_cross=25.0|H20|Fnan,False,False +,rsi2,5.0,5,0.045446618325321056,0.08545083628640401,0.05733096542652083,0.3455294459674733,-0.6832694879480132,rsi2=5.0|H5|Fnan,False,False +,rsi2,5.0,10,0.0845554286001612,0.3508753273270343,0.0428101972347541,0.2891623240133005,-0.7627945984522062,rsi2=5.0|H10|Fnan,False,False +,rsi2,5.0,20,0.07250548721499342,0.3647427364887835,0.0482098750507276,0.30702348862680295,-0.8296390703529309,rsi2=5.0|H20|Fnan,False,False +,rsi2,10.0,5,0.05882842179763881,0.1277580802528135,0.05138171781315237,0.32244462783037053,-0.7245560930648984,rsi2=10.0|H5|Fnan,False,False +,rsi2,10.0,10,0.0698789752303542,0.2296684329717484,0.04959329384627398,0.3121066317759991,-0.7711384239718434,rsi2=10.0|H10|Fnan,False,False +,rsi2,10.0,20,0.07588029328638204,0.4849189115200436,0.04661246439953648,0.3017179660166222,-0.8296390703529309,rsi2=10.0|H20|Fnan,False,False +,rsi2,15.0,5,0.03350263636061023,0.04517432994431553,0.06793360862140285,0.38158380010832993,-0.6995857687896974,rsi2=15.0|H5|Fnan,False,False +,rsi2,15.0,10,0.07055966988325635,0.24341419804342143,0.049393206477577056,0.31136101942390576,-0.7827244689121401,rsi2=15.0|H10|Fnan,False,False +,rsi2,15.0,20,0.07506478634076756,0.5345012241100006,0.0461710391513912,0.30024625641487146,-0.8296390703529309,rsi2=15.0|H20|Fnan,False,False +,rsi2,20.0,5,0.031043498656302043,0.03767260980333109,0.07014269020206387,0.3877192455844986,-0.6953591928443265,rsi2=20.0|H5|Fnan,False,False +,rsi2,20.0,10,0.07348538092999493,0.30127783812284353,0.04760389099857942,0.3052630889982055,-0.7892301969147344,rsi2=20.0|H10|Fnan,False,False +,rsi2,20.0,20,0.06632288819366117,0.17104902458585078,0.05039094820731038,0.3141848706146761,-0.8296390703529307,rsi2=20.0|H20|Fnan,False,False +,down_days,2.0,5,0.026105058129923458,0.037701608546254956,0.0683229553161897,0.3884277831310506,-0.6479799352296767,down_days=2.0|H5|Fnan,False,False +,down_days,2.0,10,0.09262459824342491,0.37739766116282086,0.03978775708961235,0.27881354183857165,-0.7504148316770001,down_days=2.0|H10|Fnan,False,False +,down_days,2.0,20,0.05643773062919316,0.0830699013958887,0.057208100195930145,0.3368157013600291,-0.8159809573816585,down_days=2.0|H20|Fnan,False,False +,down_days,3.0,5,0.0001380540554841701,0.0001320479221337519,0.12970970351169786,0.7161580962126374,-0.2970604025979515,down_days=3.0|H5|Fnan,True,False +,down_days,3.0,10,0.0018072229267039079,0.0008295716783577406,0.12005340313217672,0.5962371779561062,-0.4586767705973125,down_days=3.0|H10|Fnan,False,False +,down_days,3.0,20,0.03170062590322207,0.05863137990020653,0.07096304939937004,0.3911637780793498,-0.6941678014176599,down_days=3.0|H20|Fnan,False,False +,down_days,4.0,5,0.004783304297770245,0.009020879007613255,0.0627793036534845,0.5092847799177956,-0.35778802507921337,down_days=4.0|H5|Fnan,False,False +,down_days,4.0,10,0.020726304364671978,0.051770357062067875,0.05278909456727221,0.3828875793827523,-0.546182070929156,down_days=4.0|H10|Fnan,False,False +,down_days,4.0,20,0.1411971332404841,0.36838161414588655,0.023176931771007103,0.2134910923711392,-0.7307800251657253,down_days=4.0|H20|Fnan,False,False +,pullback,3.0,5,0.07630157475871417,0.13462827044101006,0.04467701712363459,0.2969629216102173,-0.77494368295283,pullback=3.0|H5|Fnan,False,False +,pullback,3.0,10,0.10510348505938448,0.26858913800545925,0.034624395791059914,0.2606350865449363,-0.8275597119040932,pullback=3.0|H10|Fnan,False,False +,pullback,3.0,20,0.06611516747753478,0.1189405856699832,0.05228180506514968,0.3214647612201571,-0.8296390703529308,pullback=3.0|H20|Fnan,False,False +,pullback,5.0,5,0.1269219375058242,0.21476978392055066,0.02858905267352596,0.2367874184867915,-0.6837199401176215,pullback=5.0|H5|Fnan,False,False +,pullback,5.0,10,0.24338577711365472,0.5170694315790212,0.0037231094130352194,0.14213756211909082,-0.7886573557271254,pullback=5.0|H10|Fnan,False,False +,pullback,5.0,20,0.09980172506983644,0.2044376787998574,0.03803885144890562,0.27273272096682166,-0.8296390703529313,pullback=5.0|H20|Fnan,False,False +,pullback,7.0,5,0.16995999079925136,0.26235390203119224,0.018954548185946107,0.19553419926927368,-0.6811016980641784,pullback=7.0|H5|Fnan,False,False +,pullback,7.0,10,0.21248845655526236,0.37239061900021797,0.009501265653054425,0.15945303699353272,-0.7622317421442026,pullback=7.0|H10|Fnan,False,False +,pullback,7.0,20,0.1658589731913924,0.3308508261400216,0.01888444660934363,0.2002808781637786,-0.828892395885948,pullback=7.0|H20|Fnan,False,False +50.0,vix_spike,1.05,5,0.11491690527520093,0.5124697871172941,0.030257906975612814,0.2663017103713767,-0.3951416549466913,vix_spike=1.05|H5|F50.0,False,False +50.0,vix_spike,1.05,10,0.029258068976247525,0.30797039033622725,0.05949187534499156,0.4054659041099349,-0.39460348658562294,vix_spike=1.05|H10|F50.0,False,False +50.0,vix_spike,1.05,20,0.026756617805732807,0.31289484747984087,0.06533074065422806,0.40855266549488806,-0.5760972437441589,vix_spike=1.05|H20|F50.0,False,False +50.0,vix_spike,1.08,5,0.029776428154773323,0.1569279771435376,0.046196979814163264,0.4087097871969418,-0.27654181062745853,vix_spike=1.08|H5|F50.0,False,False +50.0,vix_spike,1.08,10,0.002375138701744216,0.03923329081110501,0.0868920693387587,0.6036520056911016,-0.40089651784999913,vix_spike=1.08|H10|F50.0,False,False +50.0,vix_spike,1.08,20,0.03933002434363068,0.28680144135060165,0.060949738711198576,0.40890428201725415,-0.618188160906179,vix_spike=1.08|H20|F50.0,False,False +50.0,vix_spike,1.1,5,0.0038329606487395927,0.021198293906221178,0.058202959012690014,0.5787523966882088,-0.20230688596639457,vix_spike=1.1|H5|F50.0,False,False +50.0,vix_spike,1.1,10,0.0033619149010242493,0.033075461826677116,0.0731851128496277,0.5877591099708408,-0.29819406447548935,vix_spike=1.1|H10|F50.0,False,False +50.0,vix_spike,1.1,20,0.003901852529594752,0.051061843585310254,0.08169535131719807,0.5649131456256061,-0.3630918145268862,vix_spike=1.1|H20|F50.0,False,False +50.0,vix_spike,1.12,5,0.011534981259732263,0.04216032782515672,0.039535947463051446,0.4730592621780363,-0.17476250523338166,vix_spike=1.12|H5|F50.0,False,False +50.0,vix_spike,1.12,10,0.022599400500410018,0.10704062256273256,0.045362081464305426,0.4332885801747065,-0.2942642516603634,vix_spike=1.12|H10|F50.0,False,False +50.0,vix_spike,1.12,20,0.01662099062962401,0.12135631157390492,0.05599754926699285,0.44587726941512906,-0.3081603558247501,vix_spike=1.12|H20|F50.0,False,False +50.0,vix_spike,1.15,5,0.06655537112086682,0.14881244836833207,0.014948378598446554,0.28833633591814595,-0.11531400006271908,vix_spike=1.15|H5|F50.0,False,False +50.0,vix_spike,1.15,10,0.27388878825780694,0.5189073625929851,0.006580654954212006,0.12568489778364864,-0.2190827591307143,vix_spike=1.15|H10|F50.0,False,False +50.0,vix_spike,1.15,20,0.07763235435687708,0.2545789450197549,0.026488978499773497,0.3127253091893947,-0.25417028882303483,vix_spike=1.15|H20|F50.0,False,False +50.0,vix_cross,17.0,5,0.47400114611505456,0.6604836873264311,-0.0002545447743752538,0.01497814868874769,-0.15193611463939394,vix_cross=17.0|H5|F50.0,False,False +50.0,vix_cross,17.0,10,0.40520306774463993,0.6812702173182121,0.001252239105514752,0.05077043852582053,-0.20541518144215531,vix_cross=17.0|H10|F50.0,False,False +50.0,vix_cross,17.0,20,0.5043732494340046,0.8180849080716364,-0.0029457231746677914,-0.002451744001352129,-0.3401391480363678,vix_cross=17.0|H20|F50.0,False,False +50.0,vix_cross,18.0,5,0.2072326807429029,0.34951935382664684,0.007645543783726394,0.18921613290784808,-0.13627998422176035,vix_cross=18.0|H5|F50.0,False,False +50.0,vix_cross,18.0,10,0.12332742182112966,0.29087747006567183,0.014769206304998228,0.26320743060604407,-0.15377562275748247,vix_cross=18.0|H10|F50.0,False,False +50.0,vix_cross,18.0,20,0.5922276598237454,0.851759746259523,-0.0077938248357865,-0.05085739182853664,-0.34006209268497956,vix_cross=18.0|H20|F50.0,False,False +50.0,vix_cross,19.0,5,0.60717581241468,0.7290642373217975,-0.00387751820331228,-0.058872373737557646,-0.2531949836504068,vix_cross=19.0|H5|F50.0,False,False +50.0,vix_cross,19.0,10,0.4479272813687859,0.6543779439136954,-0.00027528014238598075,0.027317596785946283,-0.23932368826725336,vix_cross=19.0|H10|F50.0,False,False +50.0,vix_cross,19.0,20,0.8956323813803201,0.9747966336060477,-0.02644901885498263,-0.2747650691961257,-0.4745509101688966,vix_cross=19.0|H20|F50.0,False,False +50.0,vix_cross,20.0,5,0.5203202070406391,0.6599650422187473,-0.0023158437239217955,-0.011009133788715856,-0.22408735659910572,vix_cross=20.0|H5|F50.0,False,False +50.0,vix_cross,20.0,10,0.2705351186610266,0.4532038671761012,0.007700022835598563,0.13724238961140367,-0.3121689313765529,vix_cross=20.0|H10|F50.0,False,False +50.0,vix_cross,20.0,20,0.6382735583140622,0.8602123194179636,-0.013921725088251957,-0.080393161754053,-0.4890137834701248,vix_cross=20.0|H20|F50.0,False,False +50.0,vix_cross,22.0,5,0.28965018323161407,0.38029422398015067,0.005612049495321791,0.11502122187071354,-0.18162308515389602,vix_cross=22.0|H5|F50.0,False,False +50.0,vix_cross,22.0,10,0.39576018690863657,0.5559051821231125,1.0668957135751e-05,0.04897000138237283,-0.32140527492766935,vix_cross=22.0|H10|F50.0,False,False +50.0,vix_cross,22.0,20,0.35384561897082945,0.5306435222453404,0.003170193685026357,0.08776952989688734,-0.45699152025058143,vix_cross=22.0|H20|F50.0,False,False +50.0,vix_cross,25.0,5,0.8468104257876966,0.8821617201246715,-0.020600415710535613,-0.26196482592842635,-0.4220892607591551,vix_cross=25.0|H5|F50.0,False,False +50.0,vix_cross,25.0,10,0.35516118726048523,0.4580951784454355,0.002579396078043583,0.07521675137707483,-0.4096192339883439,vix_cross=25.0|H10|F50.0,False,False +50.0,vix_cross,25.0,20,0.20380470326760752,0.319747149254563,0.012981796598196649,0.1667396006118765,-0.39401121963538854,vix_cross=25.0|H20|F50.0,False,False +50.0,rsi2,5.0,5,0.01979877256409636,0.0959583270780798,0.051993046878439975,0.4450027080495945,-0.22381650858086855,rsi2=5.0|H5|F50.0,False,False +50.0,rsi2,5.0,10,0.03179841422309668,0.22508929336722366,0.053318491663371326,0.3992286684282221,-0.3417690711212784,rsi2=5.0|H10|F50.0,False,False +50.0,rsi2,5.0,20,0.013482138841563206,0.13031611723378178,0.07820308465402648,0.4864963147836796,-0.4326013305363653,rsi2=5.0|H20|F50.0,False,False +50.0,rsi2,10.0,5,0.03532658129468094,0.15132046416109304,0.04640349151099632,0.3983293278679488,-0.2420395436120888,rsi2=10.0|H5|F50.0,False,False +50.0,rsi2,10.0,10,0.03326801832605915,0.23697605410092296,0.05376643792720137,0.3990233002579942,-0.34824976200746427,rsi2=10.0|H10|F50.0,False,False +50.0,rsi2,10.0,20,0.030965728239339765,0.24957783039019704,0.06414883104008462,0.4166676336434801,-0.47774119406660953,rsi2=10.0|H20|F50.0,False,False +50.0,rsi2,15.0,5,0.015656255632238446,0.0830329067267737,0.0587731899434174,0.4782229942087543,-0.24771440614230122,rsi2=15.0|H5|F50.0,False,False +50.0,rsi2,15.0,10,0.029051651615051476,0.21849782333556028,0.05669702982182612,0.41236697815349754,-0.3421949234651599,rsi2=15.0|H10|F50.0,False,False +50.0,rsi2,15.0,20,0.035645265055987405,0.29639894134687006,0.05965522663868228,0.3931349229494862,-0.4708151111611315,rsi2=15.0|H20|F50.0,False,False +50.0,rsi2,20.0,5,0.0190179258686902,0.11194291216263978,0.055671866168017115,0.4508570536271904,-0.2329554148079408,rsi2=20.0|H5|F50.0,False,False +50.0,rsi2,20.0,10,0.04161392027410214,0.2980206471839985,0.04990771098814761,0.37264829443441033,-0.3618911169814526,rsi2=20.0|H10|F50.0,False,False +50.0,rsi2,20.0,20,0.02572854059330416,0.24092581547931743,0.06592679614257868,0.4227877699377804,-0.4708151111611315,rsi2=20.0|H20|F50.0,False,False +50.0,down_days,2.0,5,0.010730375077300491,0.05183392612257233,0.05810224917952511,0.4941291938341844,-0.21584208309861164,down_days=2.0|H5|F50.0,False,False +50.0,down_days,2.0,10,0.038959054181860894,0.24692635235251997,0.04842391887727837,0.3745874746496353,-0.3417690711212783,down_days=2.0|H10|F50.0,False,False +50.0,down_days,2.0,20,0.010300375259660833,0.09692402514728912,0.08212420529260989,0.5075408480506023,-0.4326013305363656,down_days=2.0|H20|F50.0,False,False +50.0,down_days,3.0,5,0.0008686270014716886,0.002962387844185687,0.05341026203980559,0.7009541251737211,-0.09935364157856508,down_days=3.0|H5|F50.0,False,False +50.0,down_days,3.0,10,0.0011593040683485093,0.00575443830576318,0.06902218566673768,0.7139743838052309,-0.2703888671872092,down_days=3.0|H10|F50.0,False,False +50.0,down_days,3.0,20,0.09568850551906874,0.3556311642173294,0.028220918410425178,0.27188209175493633,-0.3174097664543525,down_days=3.0|H20|F50.0,False,False +50.0,down_days,4.0,5,0.014632400330276879,0.024422194016740582,0.02231405111586926,0.6059893584319144,-0.05595380467741995,down_days=4.0|H5|F50.0,False,False +50.0,down_days,4.0,10,0.014861318093432859,0.03937264762465245,0.022088589515130375,0.443020469802561,-0.10181279101013996,down_days=4.0|H10|F50.0,False,False +50.0,down_days,4.0,20,0.46599904258618446,0.6875389177508867,-0.0012963940959276332,0.019128509215291294,-0.22973323306902915,down_days=4.0|H20|F50.0,False,False +50.0,pullback,3.0,5,0.16429915727583325,0.27048011353584955,0.022905060638466868,0.23462632201942504,-0.44851015879850886,pullback=3.0|H5|F50.0,False,False +50.0,pullback,3.0,10,0.038210518831305426,0.08472068271403554,0.04998135357951394,0.38567642211331876,-0.4490336923220434,pullback=3.0|H10|F50.0,False,False +50.0,pullback,3.0,20,0.09715555804374344,0.2291553312433209,0.03983160887256898,0.30314387221381484,-0.5858639307058975,pullback=3.0|H20|F50.0,False,False +50.0,pullback,5.0,5,0.09054496061343285,0.11801860664280772,0.02735199785771969,0.3274713921343109,-0.336915280260233,pullback=5.0|H5|F50.0,False,False +50.0,pullback,5.0,10,0.05636860196153258,0.0850082902396397,0.03216842506824613,0.327334409860397,-0.31740976645435226,pullback=5.0|H10|F50.0,False,False +50.0,pullback,5.0,20,0.039843097705450616,0.06197648924607278,0.0454967751026818,0.3900396411057434,-0.37817811060319595,pullback=5.0|H20|F50.0,False,False +50.0,pullback,7.0,5,0.18766078583824097,0.21640219812391112,0.015199218240975476,0.22926632738139974,-0.26628923726027387,pullback=7.0|H5|F50.0,False,False +50.0,pullback,7.0,10,0.09381143497870809,0.12192674062519052,0.02225700660664276,0.2775696971597437,-0.3001935068334495,pullback=7.0|H10|F50.0,False,False +50.0,pullback,7.0,20,0.18213801908260774,0.25509859184150585,0.012573273865384316,0.16657265278850245,-0.36452835089697966,pullback=7.0|H20|F50.0,False,False +100.0,vix_spike,1.05,5,0.03162257549926164,0.2785903218301512,0.05281777244143582,0.3999441818197166,-0.3934289393058763,vix_spike=1.05|H5|F100.0,False,False +100.0,vix_spike,1.05,10,0.00824416400562302,0.16349738080439857,0.07722039010353332,0.5057991638267096,-0.500009212332034,vix_spike=1.05|H10|F100.0,False,False +100.0,vix_spike,1.05,20,0.013449754211634225,0.21097855959591538,0.07589794401331806,0.47373634673544024,-0.5096685492633304,vix_spike=1.05|H20|F100.0,False,False +100.0,vix_spike,1.08,5,0.051879006215892406,0.2545223929065965,0.037877461144127045,0.33552182457246327,-0.3826467709942136,vix_spike=1.08|H5|F100.0,False,False +100.0,vix_spike,1.08,10,0.011210922217712966,0.13416347332007464,0.06776258672380231,0.48317659700369897,-0.46761127738029984,vix_spike=1.08|H10|F100.0,False,False +100.0,vix_spike,1.08,20,0.01112584565264542,0.1615669287691902,0.07716518970202912,0.4926918274147296,-0.5084463581081783,vix_spike=1.08|H20|F100.0,False,False +100.0,vix_spike,1.1,5,0.01728829927014547,0.08611336219141535,0.04562302678663799,0.4470113929048279,-0.26220952742689374,vix_spike=1.1|H5|F100.0,False,False +100.0,vix_spike,1.1,10,0.007669658952477778,0.07050368323795307,0.06620212071406262,0.517928708515317,-0.32470645416997046,vix_spike=1.1|H10|F100.0,False,False +100.0,vix_spike,1.1,20,0.0076317324572160025,0.10520201565324071,0.07273129733087469,0.4963946104865935,-0.4275478618670311,vix_spike=1.1|H20|F100.0,False,False +100.0,vix_spike,1.12,5,0.03337955311747648,0.11713607562430489,0.032552670643838155,0.3703458912321156,-0.22638931202144752,vix_spike=1.12|H5|F100.0,False,False +100.0,vix_spike,1.12,10,0.03909822910801226,0.16464562605963293,0.04188572408282054,0.3781060644541164,-0.332570393130165,vix_spike=1.12|H10|F100.0,False,False +100.0,vix_spike,1.12,20,0.017100877179147732,0.12746041486054324,0.05829699795108745,0.43245401510010906,-0.42875117288560594,vix_spike=1.12|H20|F100.0,False,False +100.0,vix_spike,1.15,5,0.24666055437812667,0.4190392456133486,0.007621071129094048,0.1427791806759634,-0.18007979863631607,vix_spike=1.15|H5|F100.0,False,False +100.0,vix_spike,1.15,10,0.27055514429154304,0.5334285203676359,0.007471948321496891,0.12600173110228802,-0.25885568522932734,vix_spike=1.15|H10|F100.0,False,False +100.0,vix_spike,1.15,20,0.06948372967003377,0.2704725580541129,0.02960297023229841,0.3018575811926266,-0.24618991793669387,vix_spike=1.15|H20|F100.0,False,False +100.0,vix_cross,17.0,5,0.282558449236898,0.4737731475417754,0.005153651134605308,0.137917651403789,-0.13519229670551747,vix_cross=17.0|H5|F100.0,False,False +100.0,vix_cross,17.0,10,0.18303554937831334,0.4571121050035924,0.009791535165108556,0.1918555067780301,-0.14626085729314808,vix_cross=17.0|H10|F100.0,False,False +100.0,vix_cross,17.0,20,0.3994858820916899,0.7535881525817587,0.0014676355356439963,0.057089819207714096,-0.3241840240804208,vix_cross=17.0|H20|F100.0,False,False +100.0,vix_cross,18.0,5,0.18924975018561663,0.33193038952797654,0.009401847350848369,0.21626680807555906,-0.13627998422176035,vix_cross=18.0|H5|F100.0,False,False +100.0,vix_cross,18.0,10,0.25292422983560714,0.4889979202968297,0.008533022653527622,0.15879034059029473,-0.20497386250534344,vix_cross=18.0|H10|F100.0,False,False +100.0,vix_cross,18.0,20,0.5672917604407743,0.8539734261737737,-0.007245679591807885,-0.03691849683989663,-0.33563985966111853,vix_cross=18.0|H20|F100.0,False,False +100.0,vix_cross,19.0,5,0.48341350691012314,0.6251851205601691,-0.0007435722239288456,0.009476438162150623,-0.16552492038287525,vix_cross=19.0|H5|F100.0,False,False +100.0,vix_cross,19.0,10,0.3654332917620051,0.5801992778574225,0.0030323449181319795,0.07892753543913274,-0.17909061892971345,vix_cross=19.0|H10|F100.0,False,False +100.0,vix_cross,19.0,20,0.6418574431881411,0.8677100782606608,-0.010954225673984852,-0.0831439843491573,-0.42780468623766976,vix_cross=19.0|H20|F100.0,False,False +100.0,vix_cross,20.0,5,0.46850536412809063,0.6199849726914132,-0.0007218274251947765,0.017100150641451442,-0.17845475617335438,vix_cross=20.0|H5|F100.0,False,False +100.0,vix_cross,20.0,10,0.24741322383550954,0.4248509013588012,0.009751265775029383,0.16377046974133389,-0.23977504302118757,vix_cross=20.0|H10|F100.0,False,False +100.0,vix_cross,20.0,20,0.34961764752545743,0.6144009959826425,0.0039042573442791273,0.08919903725716277,-0.41163109554645494,vix_cross=20.0|H20|F100.0,False,False +100.0,vix_cross,22.0,5,0.43737740993809426,0.553223827042653,3.624198461604777e-05,0.035284185402412904,-0.2643056618979106,vix_cross=22.0|H5|F100.0,False,False +100.0,vix_cross,22.0,10,0.6740053023118271,0.826730463093318,-0.014148056573686563,-0.09354766672827182,-0.43887792220523514,vix_cross=22.0|H10|F100.0,False,False +100.0,vix_cross,22.0,20,0.34978281159630314,0.5478797259852126,0.0036604496430860944,0.09297562580102826,-0.5098423512811117,vix_cross=22.0|H20|F100.0,False,False +100.0,vix_cross,25.0,5,0.8652460181503414,0.900304131548474,-0.02235676517133811,-0.2810026514714476,-0.45249666105440667,vix_cross=25.0|H5|F100.0,False,False +100.0,vix_cross,25.0,10,0.49224294868942087,0.5989925872471671,-0.004851738355385216,0.00414251942210956,-0.5015803666996647,vix_cross=25.0|H10|F100.0,False,False +100.0,vix_cross,25.0,20,0.24385495931923573,0.38476465051619896,0.009520915847839095,0.13841893207988334,-0.3895872152377482,vix_cross=25.0|H20|F100.0,False,False +100.0,rsi2,5.0,5,0.1335790913411375,0.42838405193962686,0.022879189564958713,0.23107510221232333,-0.26946431818181793,rsi2=5.0|H5|F100.0,False,False +100.0,rsi2,5.0,10,0.10974846432651053,0.5351902731217828,0.028739448967871617,0.25283394285967664,-0.43255925297675735,rsi2=5.0|H10|F100.0,False,False +100.0,rsi2,5.0,20,0.012834611826805821,0.15309687841022745,0.07794332840815099,0.4938436333123085,-0.5012299704108705,rsi2=5.0|H20|F100.0,False,False +100.0,rsi2,10.0,5,0.11211120497125493,0.3934564633108142,0.026606984670332068,0.2547994811704666,-0.2997043572984748,rsi2=10.0|H5|F100.0,False,False +100.0,rsi2,10.0,10,0.0887071431761708,0.48239950178840374,0.03408209887514091,0.28281391440575665,-0.43255925297675735,rsi2=10.0|H10|F100.0,False,False +100.0,rsi2,10.0,20,0.012898971779002278,0.15709882030252337,0.07804023865736709,0.4924923605724907,-0.5012299704108705,rsi2=10.0|H20|F100.0,False,False +100.0,rsi2,15.0,5,0.05824581374153365,0.26786707437537727,0.03816423328496743,0.3305802479814404,-0.29970435729847467,rsi2=15.0|H5|F100.0,False,False +100.0,rsi2,15.0,10,0.08926232353657552,0.4848577072501425,0.03492199126973272,0.2869385082040893,-0.4325592529767578,rsi2=15.0|H10|F100.0,False,False +100.0,rsi2,15.0,20,0.009816613503607404,0.14798030834349826,0.08013015965861303,0.5011083661198207,-0.5012299704108707,rsi2=15.0|H20|F100.0,False,False +100.0,rsi2,20.0,5,0.08523736669606312,0.3681672706324707,0.031971760135681704,0.2856174868545125,-0.2997043572984749,rsi2=20.0|H5|F100.0,False,False +100.0,rsi2,20.0,10,0.09020800757374982,0.5101625604934367,0.03422291466499705,0.2820530120139712,-0.44954973110026764,rsi2=20.0|H10|F100.0,False,False +100.0,rsi2,20.0,20,0.0077035959171288795,0.12824187934802506,0.08434917381569496,0.5207460056984712,-0.5012299704108707,rsi2=20.0|H20|F100.0,False,False +100.0,down_days,2.0,5,0.10813041986536273,0.3511647979614423,0.026313087581619543,0.25660539711789526,-0.26946431818181804,down_days=2.0|H5|F100.0,False,False +100.0,down_days,2.0,10,0.14051270397047272,0.5901625797016119,0.0226462364532789,0.21812283528124116,-0.4325592529767571,down_days=2.0|H10|F100.0,False,False +100.0,down_days,2.0,20,0.010840523522276276,0.12598517428978603,0.08074350730661384,0.5085903108009437,-0.5012299704108705,down_days=2.0|H20|F100.0,False,False +100.0,down_days,3.0,5,0.007065039604600188,0.0213553851640484,0.04253535037399647,0.5260838095177494,-0.16016389123287644,down_days=3.0|H5|F100.0,False,False +100.0,down_days,3.0,10,0.00462305764119685,0.02238288560948374,0.063539104989907,0.604460704379602,-0.3001935068334496,down_days=3.0|H10|F100.0,False,False +100.0,down_days,3.0,20,0.04653712026864504,0.24384853696292666,0.04300792930615316,0.3675668568807289,-0.3246579754640849,down_days=3.0|H20|F100.0,False,False +100.0,down_days,4.0,5,0.009985400469915001,0.029134826818940043,0.021927074900612187,0.49189646913598467,-0.06349487419695166,down_days=4.0|H5|F100.0,False,False +100.0,down_days,4.0,10,0.013114634351503562,0.050931593443017585,0.029865798740614125,0.501438548453988,-0.1216524664420886,down_days=4.0|H10|F100.0,False,False +100.0,down_days,4.0,20,0.32626673623473557,0.6129301152179327,0.005671875595755216,0.1090816837574057,-0.24500733002414843,down_days=4.0|H20|F100.0,False,False +100.0,pullback,3.0,5,0.03544116122280814,0.09330338234599826,0.04442185435843404,0.39032206308344575,-0.4250357884574907,pullback=3.0|H5|F100.0,False,False +100.0,pullback,3.0,10,0.020899660828588438,0.07894384988327278,0.05524765704586532,0.4256048301544215,-0.5073941310139259,pullback=3.0|H10|F100.0,False,False +100.0,pullback,3.0,20,0.017539910187831683,0.08516025059155603,0.06825811162471007,0.4613428772455652,-0.5084874426929893,pullback=3.0|H20|F100.0,False,False +100.0,pullback,5.0,5,0.07255384671123406,0.11653684227412053,0.02550337182784146,0.2935591209057109,-0.3267743015086061,pullback=5.0|H5|F100.0,False,False +100.0,pullback,5.0,10,0.09252399908246399,0.1678450096574311,0.026210578869479972,0.2739374622612479,-0.4204460391039705,pullback=5.0|H10|F100.0,False,False +100.0,pullback,5.0,20,0.04134867943301516,0.08874425584616373,0.047512928654837916,0.39341107919860674,-0.4895253780381654,pullback=5.0|H20|F100.0,False,False +100.0,pullback,7.0,5,0.2941573815279796,0.3615048978138394,0.004528811849949799,0.09494588285046149,-0.26598173515981705,pullback=7.0|H5|F100.0,False,False +100.0,pullback,7.0,10,0.36332368267704307,0.45547529729680303,0.0018037685298830652,0.06799256478398849,-0.3871656110112949,pullback=7.0|H10|F100.0,False,False +100.0,pullback,7.0,20,0.3023592452237763,0.41285497283712325,0.0049897884954783756,0.10133883550384319,-0.4728621406213638,pullback=7.0|H20|F100.0,False,False +200.0,vix_spike,1.05,5,0.08458847385943064,0.5381192020404051,0.03188433179989514,0.27835854214308275,-0.35766130734284785,vix_spike=1.05|H5|F200.0,False,False +200.0,vix_spike,1.05,10,0.08558829064495901,0.6040989276969813,0.033924332851026806,0.27854018268277725,-0.535866719531539,vix_spike=1.05|H10|F200.0,False,False +200.0,vix_spike,1.05,20,0.03354840104580592,0.4716811809789316,0.050716522592828994,0.35747938883735586,-0.47222676745260883,vix_spike=1.05|H20|F200.0,False,False +200.0,vix_spike,1.08,5,0.11223090804567548,0.46408896972067926,0.024558947803197784,0.24463557695289737,-0.4089192003069757,vix_spike=1.08|H5|F200.0,False,False +200.0,vix_spike,1.08,10,0.018511907629985804,0.2652814479439943,0.054495254479170585,0.41223055396868563,-0.31826450033826703,vix_spike=1.08|H10|F200.0,False,False +200.0,vix_spike,1.08,20,0.061792198670830016,0.5304725176080096,0.04001653308325426,0.30786116225251553,-0.5039476514771157,vix_spike=1.08|H20|F200.0,False,False +200.0,vix_spike,1.1,5,0.00920650989429476,0.08106366235279032,0.04817523696738446,0.45619891844382476,-0.2835333093452964,vix_spike=1.1|H5|F200.0,False,False +200.0,vix_spike,1.1,10,0.007157756464143174,0.11687129247104919,0.06048945281393148,0.47827121701224257,-0.31867854527577255,vix_spike=1.1|H10|F200.0,False,False +200.0,vix_spike,1.1,20,0.0243997827249784,0.3377874184443562,0.049359199794641206,0.3710423271433096,-0.3970098790254898,vix_spike=1.1|H20|F200.0,False,False +200.0,vix_spike,1.12,5,0.01810214265326211,0.08915246425387176,0.03894534196149446,0.4132827202497332,-0.24394151079341897,vix_spike=1.12|H5|F200.0,False,False +200.0,vix_spike,1.12,10,0.013925235589981683,0.10771190487844182,0.05196336562639381,0.4455603165209534,-0.2981649411561862,vix_spike=1.12|H10|F200.0,False,False +200.0,vix_spike,1.12,20,0.03375298146131438,0.2911873343182647,0.044037612337248566,0.35248809746900817,-0.37405469039256733,vix_spike=1.12|H20|F200.0,False,False +200.0,vix_spike,1.15,5,0.08587544031884031,0.1983362777077585,0.019444798411803577,0.29399966999030014,-0.20054604982616886,vix_spike=1.15|H5|F200.0,False,False +200.0,vix_spike,1.15,10,0.05096544956443737,0.19497993186424795,0.028602270479603398,0.3325978393790604,-0.2461899179366941,vix_spike=1.15|H10|F200.0,False,False +200.0,vix_spike,1.15,20,0.08811956052139701,0.3934723887659666,0.024981102947759792,0.2594624434027295,-0.29835873388042233,vix_spike=1.15|H20|F200.0,False,False +200.0,vix_cross,17.0,5,0.23500495183567038,0.4361847200064614,0.007245311777566599,0.16345855924857994,-0.15952654804373334,vix_cross=17.0|H5|F200.0,False,False +200.0,vix_cross,17.0,10,0.17398639431118273,0.49026828021404706,0.010661603326503899,0.18576670447705637,-0.17070323251390207,vix_cross=17.0|H10|F200.0,False,False +200.0,vix_cross,17.0,20,0.08365753777112374,0.4141137405977448,0.02179681159833713,0.2944171737760748,-0.28944123242572073,vix_cross=17.0|H20|F200.0,False,False +200.0,vix_cross,18.0,5,0.12788907216739595,0.2580973956437701,0.013312727743874708,0.2659152204296021,-0.13627998422176035,vix_cross=18.0|H5|F200.0,False,False +200.0,vix_cross,18.0,10,0.25283853047374816,0.5079693777573866,0.008999621601308405,0.1565086596699654,-0.25008168952106324,vix_cross=18.0|H10|F200.0,False,False +200.0,vix_cross,18.0,20,0.3287462712293519,0.6983145159150869,0.004558041776323796,0.09554972038350898,-0.3119447002472917,vix_cross=18.0|H20|F200.0,False,False +200.0,vix_cross,19.0,5,0.26883332207321764,0.4232773000721115,0.006096547505329619,0.135939327773965,-0.1712723861522839,vix_cross=19.0|H5|F200.0,False,False +200.0,vix_cross,19.0,10,0.28283383499623505,0.5161886271059256,0.007093811418517504,0.13086142787937388,-0.19104889500371514,vix_cross=19.0|H10|F200.0,False,False +200.0,vix_cross,19.0,20,0.3644051845268006,0.6975742274655226,0.0025060669121765855,0.07442490067419633,-0.3696943146813779,vix_cross=19.0|H20|F200.0,False,False +200.0,vix_cross,20.0,5,0.17220369982728867,0.2925017354352206,0.01133543408219606,0.20724752212803088,-0.16557782207418015,vix_cross=20.0|H5|F200.0,False,False +200.0,vix_cross,20.0,10,0.08796546246877016,0.21780464252877185,0.022745832467286897,0.30974859023297496,-0.23977504302118757,vix_cross=20.0|H10|F200.0,False,False +200.0,vix_cross,20.0,20,0.12701096584397703,0.3743542205599768,0.020425936931547373,0.24807083962241322,-0.36498723792251364,vix_cross=20.0|H20|F200.0,False,False +200.0,vix_cross,22.0,5,0.5686270672513004,0.685271208117573,-0.004291457644623464,-0.03577107966743543,-0.23418866244242398,vix_cross=22.0|H5|F200.0,False,False +200.0,vix_cross,22.0,10,0.33133748532534124,0.50958930485903,0.003277830784163882,0.08189945004553505,-0.26526958923305977,vix_cross=22.0|H10|F200.0,False,False +200.0,vix_cross,22.0,20,0.39830322454254125,0.615284571474411,0.00011929676875732653,0.060983618435353805,-0.4458725618575896,vix_cross=22.0|H20|F200.0,False,False +200.0,vix_cross,25.0,5,0.9149875202715212,0.9414462086553144,-0.025637242155159168,-0.34542341890989514,-0.47361111194938377,vix_cross=25.0|H5|F200.0,False,False +200.0,vix_cross,25.0,10,0.46249958503635646,0.575088215077938,-0.0027989066324007883,0.01989616257237771,-0.43050679772499223,vix_cross=25.0|H10|F200.0,False,False +200.0,vix_cross,25.0,20,0.3023903078240801,0.485907040053239,0.004403476036386911,0.09542081842667115,-0.3361393665999639,vix_cross=25.0|H20|F200.0,False,False +200.0,rsi2,5.0,5,0.22013977531177448,0.6259540798124849,0.010757066894711231,0.1462954523262906,-0.34214948247572363,rsi2=5.0|H5|F200.0,False,False +200.0,rsi2,5.0,10,0.10875393409736847,0.5812179936247303,0.026499540090944906,0.23997299253735818,-0.3712595863550048,rsi2=5.0|H10|F200.0,False,False +200.0,rsi2,5.0,20,0.014980936922448994,0.3011307034506203,0.06200869885903981,0.42179985663330627,-0.3646496815286626,rsi2=5.0|H20|F200.0,False,False +200.0,rsi2,10.0,5,0.2086029719266942,0.622287665076653,0.0121007971597622,0.15533401840215924,-0.37902572306066906,rsi2=10.0|H5|F200.0,False,False +200.0,rsi2,10.0,10,0.10136694970431878,0.5615519704285242,0.02927824012245983,0.25495025416195966,-0.3646496815286622,rsi2=10.0|H10|F200.0,False,False +200.0,rsi2,10.0,20,0.01616765752996294,0.32087074830940454,0.06065911934566204,0.41239551206546604,-0.36510263649492025,rsi2=10.0|H20|F200.0,False,False +200.0,rsi2,15.0,5,0.14409037871698738,0.5377628864804632,0.019383875437670506,0.203753552104246,-0.34586054129896004,rsi2=15.0|H5|F200.0,False,False +200.0,rsi2,15.0,10,0.12832871779591618,0.6254898366155035,0.024336654595776608,0.22622640814960784,-0.36953700987926463,rsi2=15.0|H10|F200.0,False,False +200.0,rsi2,15.0,20,0.017855842229764492,0.333515745168237,0.059376821841778726,0.4050529308611155,-0.37767472418348713,rsi2=15.0|H20|F200.0,False,False +200.0,rsi2,20.0,5,0.14868249763957478,0.5724348682480171,0.0186970665991677,0.1986106803668439,-0.33884051522303615,rsi2=20.0|H5|F200.0,False,False +200.0,rsi2,20.0,10,0.11101569798465508,0.6012342251849253,0.027534584258208206,0.24439882444755665,-0.36953700987926463,rsi2=20.0|H10|F200.0,False,False +200.0,rsi2,20.0,20,0.015479054968370707,0.3156672525002071,0.061703381145572056,0.41675562589866033,-0.37767472418348746,rsi2=20.0|H20|F200.0,False,False +200.0,down_days,2.0,5,0.13799959959993474,0.4748872821906225,0.019000370325624738,0.20420056160073596,-0.33344732111384523,down_days=2.0|H5|F200.0,False,False +200.0,down_days,2.0,10,0.09360940204037577,0.5228049798277176,0.028969316891070296,0.2559224516254325,-0.3646496815286622,down_days=2.0|H10|F200.0,False,False +200.0,down_days,2.0,20,0.010520392921814524,0.2336222971147439,0.06721087897523681,0.4508411776443816,-0.3646496815286626,down_days=2.0|H20|F200.0,False,False +200.0,down_days,3.0,5,0.015877522673991906,0.04895141086099168,0.04125838232445411,0.44945892089851125,-0.26598173515981705,down_days=3.0|H5|F200.0,False,False +200.0,down_days,3.0,10,0.004001003480119735,0.03212169516953349,0.06379612900820719,0.5730679730586814,-0.3001935068334495,down_days=3.0|H10|F200.0,False,False +200.0,down_days,3.0,20,0.008352465318124036,0.1191543558041325,0.06550941901478002,0.5117101106148555,-0.3227176220806789,down_days=3.0|H20|F200.0,False,False +200.0,down_days,4.0,5,0.04908125972933508,0.10755430539016211,0.018544104879174794,0.3229079179109799,-0.12621497856250585,down_days=4.0|H5|F200.0,False,False +200.0,down_days,4.0,10,0.022473691365086847,0.08683320513398293,0.02979479052903522,0.4037767475809072,-0.14978155839678864,down_days=4.0|H10|F200.0,False,False +200.0,down_days,4.0,20,0.162640480696669,0.44384816555504225,0.01619010539925414,0.20564920853658342,-0.29222410738057336,down_days=4.0|H20|F200.0,False,False +200.0,pullback,3.0,5,0.011628452124871017,0.04390129395609931,0.05645848025926825,0.4571588413826526,-0.32002238636363645,pullback=3.0|H5|F200.0,False,False +200.0,pullback,3.0,10,0.02232691906779312,0.11383026185134953,0.05133104712583236,0.3950520524716593,-0.3646496815286626,pullback=3.0|H10|F200.0,False,False +200.0,pullback,3.0,20,0.02150942169196609,0.17808505991285406,0.05376232896722977,0.39351180612038317,-0.39525007204373164,pullback=3.0|H20|F200.0,False,False +200.0,pullback,5.0,5,0.015322458677549564,0.03132300245420504,0.04039008742132988,0.4034561101886273,-0.32002238636363645,pullback=5.0|H5|F200.0,False,False +200.0,pullback,5.0,10,0.017783844651431093,0.04423504723136921,0.04304963236866177,0.3915271868824861,-0.3646496815286624,pullback=5.0|H10|F200.0,False,False +200.0,pullback,5.0,20,0.015437249828530638,0.05588934590474086,0.04784685689944501,0.3997149272040639,-0.3646496815286623,pullback=5.0|H20|F200.0,False,False +200.0,pullback,7.0,5,0.0979024335536864,0.1392245029536006,0.017651933726425817,0.2275421564836367,-0.3167808219178082,pullback=7.0|H5|F200.0,False,False +200.0,pullback,7.0,10,0.023813660197096034,0.04087634608377302,0.03290011293176587,0.3447818405649843,-0.34862490488307896,pullback=7.0|H10|F200.0,False,False +200.0,pullback,7.0,20,0.060589108962013506,0.11892916160699205,0.02634145989585135,0.27478995721603006,-0.3646496815286624,pullback=7.0|H20|F200.0,False,False diff --git a/pipeline_oos_survivors.csv b/pipeline_oos_survivors.csv new file mode 100644 index 0000000..dbd7dd3 --- /dev/null +++ b/pipeline_oos_survivors.csv @@ -0,0 +1,2 @@ +name,is_sharpe,is_p,oos_cagr,oos_sharpe,oos_maxdd,oos_p,by,live +down_days=3.0|H5|Fnan,0.7161580962126374,0.0001320479221337519,0.060870904639343415,0.4850645183649593,-0.20296100686264607,0.29897054474261964,False,False diff --git a/strategy_pipeline.py b/strategy_pipeline.py new file mode 100644 index 0000000..5d647ec --- /dev/null +++ b/strategy_pipeline.py @@ -0,0 +1,321 @@ +#!/usr/bin/env python3 +""" +Multiple-testing-aware strategy discovery pipeline for QQQ. + +Guards against data-mining bias (Harvey & Liu, 2014; "...and the Cross-Section +of Expected Returns"). Steps: + + 1. Enumerate a LARGE grid of candidate long/flat timing strategies + (trend filter x entry trigger x holding period). + 2. In-sample (IS) test: for each candidate compute the daily net-of-cost P&L + and a HAC (Newey-West) t-statistic for H0: mean daily return <= 0. + HAC standard errors account for the autocorrelation induced by + overlapping holding windows. + 3. Multiple-testing correction on the IS one-sided p-values: + Benjamini-Hochberg FDR (assumes positive dependence) AND the more + conservative Benjamini-Yekutieli FDR (valid under arbitrary dependence). + 4. Out-of-sample (OOS) confirmation on a held-out period the search never + touched: survivors must stay profitable and significant there. + 5. Strategies passing BOTH gates are flagged 'LIVE-ELIGIBLE'. + +Educational research tooling, not investment advice. Backtests overstate +live performance (slippage, regime change, survivorship). +""" + +import itertools +import sys +import numpy as np +import pandas as pd +import requests + +CA_BUNDLE = "/root/.ccr/ca-bundle.crt" +HEADERS = {"User-Agent": "Mozilla/5.0"} +COST = 0.0002 +TD = 252 +IS_END = pd.Timestamp("2016-12-31") # in-sample: start .. 2016 +OOS_START = pd.Timestamp("2017-01-01") # out-of-sample: 2017 .. now +FDR_Q = 0.10 +OOS_ALPHA = 0.05 + + +# ---------------- data ---------------- +def fetch_yahoo(symbol): + url = f"https://query1.finance.yahoo.com/v8/finance/chart/{symbol}" + params = {"period1": 0, "period2": 9999999999, "interval": "1d"} + r = requests.get(url, params=params, headers=HEADERS, timeout=60, verify=CA_BUNDLE) + r.raise_for_status() + res = r.json()["chart"]["result"][0] + q = res["indicators"]["quote"][0] + df = pd.DataFrame( + {"open": q["open"], "high": q["high"], "low": q["low"], "close": q["close"]}, + index=pd.to_datetime(res["timestamp"], unit="s").normalize(), + ).dropna(subset=["high", "close"]) + df.index.name = "date" + return df + + +def rsi(series, n): + delta = series.diff() + up = delta.clip(lower=0).rolling(n).mean() + down = (-delta.clip(upper=0)).rolling(n).mean() + rs = up / down.replace(0, np.nan) + return 100 - 100 / (1 + rs) + + +def load(): + vix = fetch_yahoo("%5EVIX") + qqq = fetch_yahoo("QQQ") + d = pd.DataFrame({ + "vix_high": vix["high"], "vix_close": vix["close"], "close": qqq["close"], + }).dropna().sort_index() + d["ret"] = d["close"].pct_change() + for n in (50, 100, 200): + d[f"sma{n}"] = d["close"].rolling(n).mean() + d["rsi2"] = rsi(d["close"], 2) + d["down"] = d["close"].diff() < 0 + d["roll_max20"] = d["close"].rolling(20).max() + return d + + +# ---------------- candidate signals ---------------- +def trend_ok(d, filt): + if filt is None or (isinstance(filt, float) and pd.isna(filt)): + return pd.Series(True, index=d.index) + return d["close"] > d[f"sma{int(filt)}"] + + +def entry_signal(d, kind, param): + if kind == "vix_spike": + return d["vix_high"] >= param * d["vix_close"].shift(1) + if kind == "vix_cross": + return (d["vix_high"].shift(1) < param) & (d["vix_high"] >= param) + if kind == "rsi2": + return d["rsi2"] < param + if kind == "down_days": + s = d["down"] + cond = s.copy() + for k in range(1, int(param)): + cond = cond & s.shift(k) + return cond + if kind == "pullback": + return d["close"] <= d["roll_max20"] * (1 - param / 100.0) + raise ValueError(kind) + + +def position(d, filt, kind, param, hold): + sig = (entry_signal(d, kind, param) & trend_ok(d, filt)).fillna(False).values + pos = np.zeros(len(d)) + remaining = 0 + for i in range(len(d)): + if sig[i]: + remaining = hold + if remaining > 0: + pos[i] = 1.0 + remaining -= 1 + return pd.Series(pos, index=d.index) + + +def candidates(): + filters = [None, 50, 100, 200] + triggers = ( + [("vix_spike", k) for k in (1.05, 1.08, 1.10, 1.12, 1.15)] + + [("vix_cross", L) for L in (17, 18, 19, 20, 22, 25)] + + [("rsi2", th) for th in (5, 10, 15, 20)] + + [("down_days", n) for n in (2, 3, 4)] + + [("pullback", x) for x in (3, 5, 7)] + ) + holds = [5, 10, 20] + out = [] + for filt, (kind, param), hold in itertools.product(filters, triggers, holds): + out.append({"filt": filt, "kind": kind, "param": param, "hold": hold}) + return out + + +# ---------------- stats ---------------- +def hac_tstat(x, lag): + """Newey-West HAC t-stat for H0: mean(x) <= 0 (one-sided).""" + x = np.asarray(x, float) + n = len(x) + if n < 30: + return np.nan, np.nan + xbar = x.mean() + xc = x - xbar + gamma0 = np.dot(xc, xc) / n + lrv = gamma0 + for l in range(1, lag + 1): + w = 1 - l / (lag + 1) + g = np.dot(xc[l:], xc[:-l]) / n + lrv += 2 * w * g + if lrv <= 0: + return np.nan, np.nan + se = np.sqrt(lrv / n) + t = xbar / se + return t, se + + +def norm_sf(z): + # one-sided upper-tail p-value via erfc (no scipy dependency) + from math import erfc, sqrt + return 0.5 * erfc(z / sqrt(2)) + + +def metrics(pnl): + pnl = pnl.dropna() + n = len(pnl) + if n == 0: + return {} + eq = (1 + pnl).cumprod() + yrs = n / TD + total = eq.iloc[-1] - 1 + cagr = eq.iloc[-1] ** (1 / yrs) - 1 if yrs > 0 else np.nan + vol = pnl.std() * np.sqrt(TD) + sharpe = (pnl.mean() * TD) / vol if vol > 0 else np.nan + dd = (eq / eq.cummax() - 1).min() + return {"total": total, "cagr": cagr, "sharpe": sharpe, "maxdd": dd} + + +def strat_pnl(d, spec): + pos = position(d, spec["filt"], spec["kind"], spec["param"], spec["hold"]) + trades = pos.diff().abs().fillna(0.0) + held = pos.shift(1).fillna(0.0) + ret = d["ret"].fillna(0.0) + pnl = held * ret - trades * COST + # Timing-alpha (active) return: strips the passive equity premium by + # benchmarking against a constant-exposure position at the strategy's own + # average exposure. mean>0 <=> the strategy is invested MORE on up days than + # its average -- i.e. genuine market-timing skill, not just being long. + active = (held - held.mean()) * ret + return pnl, active, pos + + +# ---------------- FDR ---------------- +def bh_reject(pvals, q): + p = np.asarray(pvals, float) + m = len(p) + order = np.argsort(p) + thresh = q * (np.arange(1, m + 1)) / m + passed = p[order] <= thresh + kmax = np.where(passed)[0].max() + 1 if passed.any() else 0 + rej = np.zeros(m, bool) + if kmax > 0: + rej[order[:kmax]] = True + return rej + + +def by_reject(pvals, q): + m = len(pvals) + c_m = np.sum(1.0 / np.arange(1, m + 1)) # harmonic number + return bh_reject(pvals, q / c_m) + + +# ---------------- run ---------------- +def main(): + print("Loading data ...", file=sys.stderr) + d = load() + d_is = d[d.index <= IS_END] + d_oos = d[d.index >= OOS_START] + print(f"IS : {d_is.index[0].date()} -> {d_is.index[-1].date()} ({len(d_is)} days)") + print(f"OOS: {d_oos.index[0].date()} -> {d_oos.index[-1].date()} ({len(d_oos)} days)\n") + + specs = candidates() + print(f"Candidate strategies: {len(specs)}\n") + + rows = [] + bh_is = metrics(d_is["ret"]) + bh_oos = metrics(d_oos["ret"]) + + for i, spec in enumerate(specs): + pnl_is, active_is, pos_is = strat_pnl(d_is, spec) + lag = spec["hold"] + 5 + t_ret, _ = hac_tstat(pnl_is.fillna(0.0).values, lag) + t_a, _ = hac_tstat(active_is.fillna(0.0).values, lag) + if np.isnan(t_ret) or np.isnan(t_a): + continue + m_is = metrics(pnl_is) + rows.append({ + **spec, + "p_ret": norm_sf(t_ret), # raw return > 0 (captures beta) + "p": norm_sf(t_a), # timing-alpha > 0 (skill) -- FDR gate + "is_cagr": m_is["cagr"], "is_sharpe": m_is["sharpe"], + "is_maxdd": m_is["maxdd"], + }) + + res = pd.DataFrame(rows) + res["name"] = res.apply( + lambda r: f"{r['kind']}={r['param']}|H{r['hold']}|" + f"F{r['filt'] if r['filt'] else '-'}", axis=1) + + # FDR correction on IS p-values + res["bh"] = bh_reject(res["p"].values, FDR_Q) + res["by"] = by_reject(res["p"].values, FDR_Q) + n_beta = int((res["p_ret"] < 0.05).sum()) + n_naive = int((res["p"] < 0.05).sum()) + print("IS gate = market-timing ALPHA (raw-return premium stripped out)") + print(f" would pass on raw return p<0.05 (beta-driven) : {n_beta}/{len(res)}") + print(f" significant timing-alpha at naive p<0.05 : {n_naive}/{len(res)}") + print(f" survive Benjamini-Hochberg FDR<{FDR_Q} (pos. dep.) : {int(res['bh'].sum())}") + print(f" survive Benjamini-Yekutieli FDR<{FDR_Q} (arb. dep.): {int(res['by'].sum())}\n") + + survivors = res[res["bh"]].copy() + + # OOS confirmation on BH survivors + oos_rec = [] + for _, r in survivors.iterrows(): + spec = {"filt": r["filt"], "kind": r["kind"], + "param": r["param"], "hold": r["hold"]} + pnl_oos, active_oos, _ = strat_pnl(d_oos, spec) + t_o, _ = hac_tstat(active_oos.fillna(0.0).values, spec["hold"] + 5) + p_o = norm_sf(t_o) if not np.isnan(t_o) else np.nan + m_o = metrics(pnl_oos) + oos_rec.append({ + "name": r["name"], "is_sharpe": r["is_sharpe"], "is_p": r["p"], + "oos_cagr": m_o["cagr"], "oos_sharpe": m_o["sharpe"], + "oos_maxdd": m_o["maxdd"], "oos_p": p_o, + "by": bool(r["by"]), + # OOS gate is also on timing-alpha, not raw return. + "live": (not np.isnan(p_o)) and (p_o < OOS_ALPHA) and (m_o["cagr"] > 0), + }) + oos = pd.DataFrame(oos_rec).sort_values("oos_sharpe", ascending=False) + + pd.set_option("display.width", 200) + print("=" * 100) + print(f"BENCHMARK Buy&Hold IS: CAGR {bh_is['cagr']*100:.1f}% Sharpe " + f"{bh_is['sharpe']:.2f} MaxDD {bh_is['maxdd']*100:.1f}% | " + f"OOS: CAGR {bh_oos['cagr']*100:.1f}% Sharpe {bh_oos['sharpe']:.2f} " + f"MaxDD {bh_oos['maxdd']*100:.1f}%") + print("=" * 100) + + if oos.empty: + print("No strategies survived the FDR gate.") + else: + print(f"\nBH-FDR survivors carried to OOS ({len(oos)}):\n") + show = oos.copy() + for c in ["is_sharpe", "oos_sharpe"]: + show[c] = show[c].map(lambda v: f"{v:.2f}") + for c in ["oos_cagr", "oos_maxdd"]: + show[c] = show[c].map(lambda v: f"{v*100:+.1f}%") + for c in ["is_p", "oos_p"]: + show[c] = show[c].map(lambda v: f"{v:.3f}" if pd.notnull(v) else "na") + print(show[["name", "is_sharpe", "is_p", "oos_cagr", "oos_sharpe", + "oos_maxdd", "oos_p", "by", "live"]].to_string(index=False)) + + live = oos[oos["live"]] + print("\n" + "=" * 100) + print(f"LIVE-ELIGIBLE (passed FDR IS-gate AND OOS p<{OOS_ALPHA} with " + f"positive OOS CAGR): {len(live)}") + print("=" * 100) + if not live.empty: + for _, r in live.iterrows(): + tag = " [also survives BY]" if r["by"] else "" + print(f" {r['name']:<28} OOS CAGR {r['oos_cagr']*100:+.1f}% " + f"Sharpe {r['oos_sharpe']:.2f} MaxDD {r['oos_maxdd']*100:.1f}%" + f"{tag}") + + res.to_csv("pipeline_is_results.csv", index=False) + if not oos.empty: + oos.to_csv("pipeline_oos_survivors.csv", index=False) + print("\nSaved pipeline_is_results.csv and pipeline_oos_survivors.csv") + + +if __name__ == "__main__": + main()