s-ttp commited on
Commit
261cef9
Β·
verified Β·
1 Parent(s): aaf8a75

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. README.md +12 -6
  2. book.py +6 -4
  3. engine/export_bundle.py +150 -0
  4. risk_screen.py +14 -5
  5. static/app.js +3 -2
  6. static/index.html +42 -36
README.md CHANGED
@@ -13,12 +13,18 @@ short_description: Smart-money, quality, trend-adaptive paper fund + picks
13
 
14
  A quality, trend-adaptive equity **paper fund** that drafts the smart money.
15
 
16
- **Strategy (validated on a survivorship-free 2014–2026 backtest):** hold names being
17
- *bought* by 13F super-investors or insiders, restricted to quality large-caps
18
- (ROE β‰₯ 10%, debt/equity ≀ 1.5), top-20 dollar-weighted (1–15% per name) with a **dynamic sector
19
- cap** (each sector 30% Β± its 12-1m relative strength, 15–45%), and a **regime overlay** that
20
- rotates the book into large-cap momentum when SPY is in a confirmed downtrend. Rebalanced
21
- monthly. Backtest: CAGR 19.5% vs SPY 13.9%, Sharpe 0.92, max drawdown βˆ’32%.
 
 
 
 
 
 
22
 
23
  The page shows the live Alpaca **paper** portfolio, performance vs SPY, the current
24
  target book, and the informational **Top AI Picks of the Month** panels.
 
13
 
14
  A quality, trend-adaptive equity **paper fund** that drafts the smart money.
15
 
16
+ **Strategy (rule v2, Oct 2026):** hold the large-caps that concentrated 13F managers are collectively
17
+ buying β€” every filer with 10–150 positions, $250M–$100B and β‰₯40% in its top 10 (rule-based, ~900–1,500 a
18
+ quarter); signal = 2Β·new + add βˆ’ 2Β·exit conviction positions β€” restricted to the top-1,000 by market cap
19
+ and to companies whose ROA is in the **top 30% of their sector**; top-20 dollar-weighted (**1–10% per
20
+ name**, ≀5 per sector) with a **dynamic sector cap** (each sector 30% Β± its 12-1m relative strength,
21
+ 15–45%) and a **regime overlay** that rotates into large-cap momentum when SPY is in a confirmed
22
+ downtrend. An AI overlay excludes only names hit by a critical adverse event. Rebalanced monthly.
23
+
24
+ Backtest 2014-03 β†’ 2026-10 (survivorship-free, data through *d* βˆ’ 1, 20 bp/side, Sharpe net of T-bills):
25
+ CAGR 19.9% vs SPY 13.9%, Sharpe 0.85 vs 0.73, max drawdown -37.5% vs -33.7%,
26
+ alpha +3.9% (t 1.8), Ξ² 1.17. Chosen on 2016–2021 from ~210 configurations; it trailed SPY over the
27
+ never-used 2014-03 β†’ 2016-02 window. Research and pre-registrations: `Quant Model/data/research/slipstream/`.
28
 
29
  The page shows the live Alpaca **paper** portfolio, performance vs SPY, the current
30
  target book, and the informational **Top AI Picks of the Month** panels.
book.py CHANGED
@@ -18,7 +18,7 @@ import pandas as pd
18
  DATA = Path(__file__).resolve().parent / "data"
19
  TOPN, NAME_CAP, MOM_N = 20, 5, 50
20
  CAP_BASE, CAP_LO, CAP_HI = 0.30, 0.15, 0.45
21
- MAX_POS_W = 0.15 # max weight in any ONE position (see _name_cap / weighting_study.py)
22
  MIN_POS_W = 0.01 # min weight in any one position (see _name_floor)
23
  _CACHE_TTL_S = 15 * 60
24
 
@@ -130,7 +130,9 @@ def _name_cap(w, cap=MAX_POS_W):
130
  See Quant Model/scripts/weighting_study.py: over 2014-2026 (top-20, monthly,
131
  40bps) every cap from 8-30% beat the uncapped book on Sharpe, a smooth plateau
132
  rather than a single lucky point; 15% gave the best drawdown-adjusted return
133
- (Calmar 0.475 vs 0.387 uncapped, maxDD -35.0% vs -39.5%)."""
 
 
134
  for _ in range(50):
135
  over = w > cap + 1e-12
136
  if not over.any():
@@ -236,8 +238,8 @@ def _compute_book(screen: bool = True) -> dict:
236
  "n_holdings": len(holdings),
237
  "holdings": holdings,
238
  "risk_screen": screen_meta,
239
- "rule": "combined 13F+insider Β· top-1000 Β· quality(ROEβ‰₯10%,D/E≀1.5) Β· top-20 $-wt (1–15%/name) Β· "
240
- "dynamic sector cap 15–45% Β· AI event-risk exclusion Β· regimeβ†’momentum (SPY live) Β· monthly",
241
  }
242
 
243
 
 
18
  DATA = Path(__file__).resolve().parent / "data"
19
  TOPN, NAME_CAP, MOM_N = 20, 5, 50
20
  CAP_BASE, CAP_LO, CAP_HI = 0.30, 0.15, 0.45
21
+ MAX_POS_W = 0.10 # max weight in any ONE position (v2, Oct 2026: Study 7 β€” same Sharpe as 15%, top-5 48% vs 56%)
22
  MIN_POS_W = 0.01 # min weight in any one position (see _name_floor)
23
  _CACHE_TTL_S = 15 * 60
24
 
 
130
  See Quant Model/scripts/weighting_study.py: over 2014-2026 (top-20, monthly,
131
  40bps) every cap from 8-30% beat the uncapped book on Sharpe, a smooth plateau
132
  rather than a single lucky point; 15% gave the best drawdown-adjusted return
133
+ (Calmar 0.475 vs 0.387 uncapped, maxDD -35.0% vs -39.5%). Rule v2 (Oct 2026) uses 10%:
134
+ on the concentrated-manager + ROA book it kept Sharpe (0.98 vs 0.98, 2016-26) while
135
+ cutting the top-5 weight from 56% to 48% (data/research/slipstream/quality, Study 7)."""
136
  for _ in range(50):
137
  over = w > cap + 1e-12
138
  if not over.any():
 
238
  "n_holdings": len(holdings),
239
  "holdings": holdings,
240
  "risk_screen": screen_meta,
241
+ "rule": "concentrated-manager 13F consensus Β· top-1000 Β· quality(ROA top-30% in sector) Β· top-20 $-wt "
242
+ "(1–10%/name) Β· dynamic sector cap 15–45% Β· AI critical-event exclusion Β· regimeβ†’momentum (SPY live) Β· monthly",
243
  }
244
 
245
 
engine/export_bundle.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Slipstream β€” data-bundle exporter (runs LOCALLY, where the Sharadar cache lives).
3
+
4
+ Rule (v2, Oct 2026 β€” validated in data/research/slipstream/quality, Studies 4–8):
5
+ managers every 13F filer that is a concentrated stock-picker that quarter (10–150 positions,
6
+ $250M–$100B, top-10 β‰₯ 40%, filed the prior quarter) β€” built by
7
+ scripts/slipstream/manager_universe.py --sets CONC (no curated list, no insiders)
8
+ signal consensus = 2Β·new + add βˆ’ 2Β·exit conviction positions; eligible if > 0; size = 13F $
9
+ quality ROA (SF1 ART, latest filing public by the signal date) in the top 30% of its sector,
10
+ ranked across the month's top-1,000 universe
11
+
12
+ This script exports a small, self-contained bundle the HF Space computes the fund from:
13
+
14
+ data/candidates.parquet β€” latest eligible names (top-1000 & ROA-30 & consensus BUY),
15
+ with score, $-size and sector
16
+ data/prices.parquet β€” daily adj close for the top-1000 universe + SPY, last ~400
17
+ trading days (drives regime, momentum and sector-RS on HF)
18
+ data/meta.json β€” as-of date, universe, generated-at
19
+
20
+ 13F is quarterly and ~45d lagged, so re-running this quarterly (and committing the bundle
21
+ to the Space) keeps the fund current. Run: python3 engine/export_bundle.py
22
+ """
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import sys
27
+ from datetime import datetime, timezone
28
+ from pathlib import Path
29
+
30
+ import pandas as pd
31
+
32
+ import os as _os
33
+ # env-overridable: this runs inside the Refinery container too, where the Quant Model
34
+ # code lives at /app/quantmodel rather than on the Mac.
35
+ QM = Path(_os.environ.get("QM_DIR", "/Users/sttp/Desktop/Quant Model"))
36
+ sys.path.insert(0, str(QM))
37
+ import scripts.follow_the_money_backtest as B # noqa: E402
38
+
39
+ DATA = Path(_os.environ.get("SLIP_BUNDLE_DIR", Path(__file__).resolve().parent.parent / "data"))
40
+ LOOKBACK_DAYS = 400 # β‰₯ 252 for momentum / 200 for regime / 252 for sector-RS
41
+ # the concentrated-manager panel written by manager_universe.py (refresh_everything step 7b)
42
+ CONC_DIR = Path(_os.environ.get("SLIP_CONC_DIR", QM / "data/research/conc/panels/CONC"))
43
+ PULL = Path(_os.environ.get("SLIP_PULL_DIR", QM / "data/raw/ftm_pull"))
44
+ ROA_KEEP = 0.30 # top 30% of each sector by ROA
45
+ # parity testing only: restrict to signal dates before this day / prices through this day
46
+ MAX_DATE = _os.environ.get("SLIP_EXPORT_BEFORE")
47
+ PRICES_THROUGH = _os.environ.get("SLIP_PRICES_THROUGH")
48
+
49
+
50
+ def consensus_frame(rows: pd.DataFrame) -> pd.DataFrame:
51
+ """2Β·new + add βˆ’ 2Β·exit among concentrated managers (scripts/slipstream/backtest.signal_frame 'consensus')."""
52
+ df = rows.copy()
53
+ col = lambda c: df[c].fillna(0.0) if c in df.columns else pd.Series(0.0, index=df.index)
54
+ df["score"] = 2 * col("guru_new_buys") + col("guru_adds") - 2 * col("guru_exits")
55
+ df["ok"] = df["score"] > 0
56
+ df["size"] = col("guru_conv_value").clip(lower=0)
57
+ return df
58
+
59
+
60
+ def roa_gate(d: pd.Timestamp, universe: list, sector: dict) -> set:
61
+ """Names whose latest public ROA is in the top ROA_KEEP of their sector across `universe`
62
+ (scripts/slipstream/backtest.Data.roa_pct / quality_set 'roa_sector')."""
63
+ import duckdb
64
+ f = duckdb.connect().execute(f"""
65
+ SELECT ticker, CAST(datekey AS DATE) AS dk, TRY_CAST(roa AS DOUBLE) AS roa
66
+ FROM read_csv_auto('{PULL / "SF1.csv"}', header=true, all_varchar=true)
67
+ WHERE dimension = 'ART' AND datekey IS NOT NULL AND TRY_CAST(roa AS DOUBLE) IS NOT NULL
68
+ AND CAST(datekey AS DATE) >= DATE '2012-06-01' AND CAST(datekey AS DATE) <= DATE '{d.date()}'""").df()
69
+ f["dk"] = pd.to_datetime(f["dk"])
70
+ f = f[f["ticker"].isin(universe)].sort_values("dk")
71
+ x = f.groupby("ticker")["roa"].last().to_frame()
72
+ x["sector"] = [sector.get(t, "?") for t in x.index]
73
+ x["pct"] = x.groupby("sector")["roa"].rank(pct=True)
74
+ return set(x.index[x["pct"] > 1 - ROA_KEEP])
75
+
76
+
77
+ def main():
78
+ DATA.mkdir(parents=True, exist_ok=True)
79
+ B.PANEL, B.PRICES = CONC_DIR / "ftm_panel.parquet", CONC_DIR / "ftm_prices.parquet"
80
+ B.DAILY, B.SF1, B.TICKERS = PULL / "DAILY.csv", PULL / "SF1.csv", PULL / "TICKERS.csv"
81
+ if not B.PANEL.exists():
82
+ raise SystemExit(f"missing {B.PANEL} β€” run scripts/slipstream/manager_universe.py --sets CONC first")
83
+ base_panel = QM / "data/research/ftm_panel.parquet"
84
+ if not _os.environ.get("SLIP_CONC_DIR") and base_panel.exists() and B.PANEL.stat().st_mtime < base_panel.stat().st_mtime:
85
+ # the concentrated-manager panel must be rebuilt AFTER the base panel in the same run,
86
+ # or the bundle would ship last week's 13F signals as if fresh
87
+ raise SystemExit(f"stale {B.PANEL}: older than {base_panel} β€” the conc_panel step did not run")
88
+ panel, R, spy, sector, wide = B.load()
89
+ if PRICES_THROUGH:
90
+ wide = wide.loc[:PRICES_THROUGH]
91
+ R = R.loc[:PRICES_THROUGH]
92
+ valid = set(R.columns)
93
+ bdr = {pd.Timestamp(d): g for d, g in panel.groupby("date")}
94
+ # Use the LATEST signal rows in the panel (weekly cadence), not only monthly firsts.
95
+ # The monthly-only pick made every live rebalance trade the prior month's signal row,
96
+ # which β€” because 13F filings land mid-quarter (45-day deadline) β€” lagged the fresh
97
+ # quarter by a whole cycle: on 2026-09-01 the fund would have traded the Aug-3 row
98
+ # built on Q1 13F, while the Aug-17 weekly row already carried Q2. The backtest's PIT
99
+ # semantics assume signals as-of the rebalance date, so freshest-usable matches the
100
+ # validated rule more closely, not less. Only the last few dates are screened
101
+ # (universe/quality checks hit the multi-GB DAILY/SF1 CSVs per date).
102
+ dts = sorted(pd.to_datetime(panel["date"]).unique())
103
+ if MAX_DATE:
104
+ dts = [x for x in dts if pd.Timestamp(x) < pd.Timestamp(MAX_DATE)]
105
+ dts = dts[-6:]
106
+ uni = B.mktcap_universe(dts, 1000)
107
+
108
+ # latest rebalance date with a usable book
109
+ d = next((pd.Timestamp(c) for c in reversed(dts)
110
+ if bdr.get(pd.Timestamp(c)) is not None and (valid & uni.get(pd.Timestamp(c), set()))), None)
111
+ if d is None:
112
+ raise SystemExit("no valid rebalance date")
113
+ universe = sorted(uni.get(d, set()) & valid)
114
+ qual = roa_gate(d, universe, sector)
115
+
116
+ # candidates: eligible names with a consensus BUY among concentrated managers at d
117
+ sf = consensus_frame(bdr[d])
118
+ elig = valid & set(universe) & qual
119
+ cand = sf[sf["ok"] & sf["ticker"].isin(elig)].copy()
120
+ cand["sector"] = cand["ticker"].map(lambda t: sector.get(t, "?"))
121
+ cand = cand[["ticker", "sector", "score", "size"]].reset_index(drop=True)
122
+ cand.to_parquet(DATA / "candidates.parquet", index=False)
123
+
124
+ # prices: universe + SPY, last LOOKBACK_DAYS trading days β†’ long form
125
+ cols = [t for t in (set(universe) | {"SPY"} | set(cand["ticker"])) if t in wide.columns]
126
+ px = wide[cols].tail(LOOKBACK_DAYS)
127
+ long = px.reset_index().melt(id_vars=px.index.name or "index", var_name="ticker",
128
+ value_name="px").dropna()
129
+ long.columns = ["date", "ticker", "px"]
130
+ long.to_parquet(DATA / "prices.parquet", index=False)
131
+
132
+ meta = {
133
+ "fund": "Slipstream",
134
+ "rule_version": "v2-2026-10 Β· CONC consensus Β· ROA top-30% in sector Β· 10% cap",
135
+ "as_of": str(d.date()),
136
+ "universe": universe,
137
+ "sectors": {t: sector.get(t, "?") for t in cols},
138
+ "n_candidates": int(len(cand)),
139
+ "price_start": str(px.index.min().date()),
140
+ "price_end": str(px.index.max().date()),
141
+ "generated_at": datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC"),
142
+ }
143
+ (DATA / "meta.json").write_text(json.dumps(meta, indent=1))
144
+ print(f"β†’ bundle in {DATA}")
145
+ print(f" as_of {meta['as_of']} Β· {len(cand)} candidates Β· {len(universe)} universe Β· "
146
+ f"prices {meta['price_start']}β†’{meta['price_end']} ({len(long):,} rows)")
147
+
148
+
149
+ if __name__ == "__main__":
150
+ main()
risk_screen.py CHANGED
@@ -3,7 +3,7 @@
3
  The 20 holdings are chosen by the systematic quant rule. This overlay then scans the candidate
4
  names for RECENT, CONCRETE, MATERIALLY-ADVERSE EVENTS the price/fundamentals may not have caught
5
  yet β€” legal, regulatory/FDA, geopolitical/trade, operational, competitive β€” and HARD-EXCLUDES any
6
- with a high/critical event. It is deliberately NOT a subjective "risk score": it only fires on a
7
  discrete event backed by a real headline, so ongoing/priced risks (general competition, valuation)
8
  can never trip it. Excluded names are replaced deterministically by the next-ranked candidate.
9
 
@@ -23,6 +23,9 @@ MAX_EXCLUSIONS = int(os.getenv("SLIPSTREAM_MAX_EXCLUSIONS", "3"))
23
  ENABLED = os.getenv("SLIPSTREAM_RISK_SCREEN", "1") == "1"
24
  CACHE = config.DATA_DIR / "risk_screen_cache.json"
25
  _SEV_RANK = {"none": 0, "medium": 1, "high": 2, "critical": 3}
 
 
 
26
 
27
  # Deterministic backstop for the prompt's "analyst actions are never events" rule β€” the model
28
  # still returned `NFLX / medium / "Analyst target price cut and downgrade…"` (2026-09), citing a
@@ -63,6 +66,11 @@ approximate market capitalization):
63
  antitrust filings historically resolve over years without impairing 12-month returns.
64
  β€’ Adverse VERDICTS, injunctions, consent decrees, criminal indictments, or forced structural
65
  changes CAN be "high" regardless of company size.
 
 
 
 
 
66
  β€’ If headlines show the stock already fell only modestly (under ~5%) on the news, the market has
67
  likely priced it β€” lean "medium" unless the event meets the tests above.
68
 
@@ -112,7 +120,7 @@ def screen(pool: list[str]) -> dict:
112
  """Return {excluded: set, meta: {...}} for a candidate pool. Cached per UTC day; safe on failure."""
113
  today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
114
  pool = [t for t in pool if t]
115
- key = today + "|" + ",".join(sorted(pool))
116
  if not (ENABLED and config.GEMINI_API_KEY):
117
  return {"excluded": set(), "meta": {"enabled": False, "scanned": 0, "cleared": 0, "excluded": [], "as_of": today}}
118
  cache = _load_cache()
@@ -127,7 +135,7 @@ def screen(pool: list[str]) -> dict:
127
  flags = _classify(pool, news_by_tkr)
128
  ranked = sorted(flags.items(), key=lambda kv: -_SEV_RANK.get(kv[1]["severity"], 0))
129
  for t, f in ranked:
130
- if f["severity"] in ("high", "critical") and len(excluded_list) < MAX_EXCLUSIONS:
131
  excluded_list.append({"ticker": t, **f})
132
  except Exception as e:
133
  # any failure (no news, LLM error, bad JSON) β†’ no exclusions, fund still trades
@@ -136,8 +144,9 @@ def screen(pool: list[str]) -> dict:
136
  return {"excluded": set(), "meta": meta}
137
 
138
  meta = {"enabled": True, "scanned": len(pool), "cleared": len(pool) - len(excluded_list),
139
- "excluded": excluded_list, "flags_medium": [{"ticker": t, **f} for t, f in flags.items()
140
- if f["severity"] == "medium"][:5],
 
141
  "as_of": today}
142
  try:
143
  CACHE.write_text(json.dumps({"key": key, "meta": meta}))
 
3
  The 20 holdings are chosen by the systematic quant rule. This overlay then scans the candidate
4
  names for RECENT, CONCRETE, MATERIALLY-ADVERSE EVENTS the price/fundamentals may not have caught
5
  yet β€” legal, regulatory/FDA, geopolitical/trade, operational, competitive β€” and HARD-EXCLUDES any
6
+ with a CRITICAL event only (since Oct 2026; "high" events are shown as watch flags and held). It is deliberately NOT a subjective "risk score": it only fires on a
7
  discrete event backed by a real headline, so ongoing/priced risks (general competition, valuation)
8
  can never trip it. Excluded names are replaced deterministically by the next-ranked candidate.
9
 
 
23
  ENABLED = os.getenv("SLIPSTREAM_RISK_SCREEN", "1") == "1"
24
  CACHE = config.DATA_DIR / "risk_screen_cache.json"
25
  _SEV_RANK = {"none": 0, "medium": 1, "high": 2, "critical": 3}
26
+ # Only events at or above this severity are excluded. "critical" = very high risk only: the backtested
27
+ # rule has no overlay, so the live fund should deviate from it only for events that threaten the company.
28
+ EXCLUDE_AT = os.getenv("SLIPSTREAM_EXCLUDE_SEVERITY", "critical").lower()
29
 
30
  # Deterministic backstop for the prompt's "analyst actions are never events" rule β€” the model
31
  # still returned `NFLX / medium / "Analyst target price cut and downgrade…"` (2026-09), citing a
 
66
  antitrust filings historically resolve over years without impairing 12-month returns.
67
  β€’ Adverse VERDICTS, injunctions, consent decrees, criminal indictments, or forced structural
68
  changes CAN be "high" regardless of company size.
69
+ β€’ "critical" is reserved for VERY HIGH risk β€” an event that threatens the company's survival or a large
70
+ part of its value: bankruptcy / going-concern warning, fraud or accounting restatement, criminal
71
+ indictment of the company or its CEO/CFO, loss of the license to operate (e.g. a key drug's approval
72
+ withdrawn, delisting), sanctions/export bans cutting off a major share of revenue, or plausible
73
+ exposure above ~20% of market value. When in doubt between "high" and "critical", choose "high".
74
  β€’ If headlines show the stock already fell only modestly (under ~5%) on the news, the market has
75
  likely priced it β€” lean "medium" unless the event meets the tests above.
76
 
 
120
  """Return {excluded: set, meta: {...}} for a candidate pool. Cached per UTC day; safe on failure."""
121
  today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
122
  pool = [t for t in pool if t]
123
+ key = today + "|" + EXCLUDE_AT + "|" + ",".join(sorted(pool))
124
  if not (ENABLED and config.GEMINI_API_KEY):
125
  return {"excluded": set(), "meta": {"enabled": False, "scanned": 0, "cleared": 0, "excluded": [], "as_of": today}}
126
  cache = _load_cache()
 
135
  flags = _classify(pool, news_by_tkr)
136
  ranked = sorted(flags.items(), key=lambda kv: -_SEV_RANK.get(kv[1]["severity"], 0))
137
  for t, f in ranked:
138
+ if _SEV_RANK.get(f["severity"], 0) >= _SEV_RANK.get(EXCLUDE_AT, 3) and len(excluded_list) < MAX_EXCLUSIONS:
139
  excluded_list.append({"ticker": t, **f})
140
  except Exception as e:
141
  # any failure (no news, LLM error, bad JSON) β†’ no exclusions, fund still trades
 
144
  return {"excluded": set(), "meta": meta}
145
 
146
  meta = {"enabled": True, "scanned": len(pool), "cleared": len(pool) - len(excluded_list),
147
+ "excluded": excluded_list, "exclude_at": EXCLUDE_AT,
148
+ "flags_medium": [{"ticker": t, **f} for t, f in sorted(flags.items(), key=lambda kv: -_SEV_RANK.get(kv[1]["severity"], 0))
149
+ if 0 < _SEV_RANK.get(f["severity"], 0) < _SEV_RANK.get(EXCLUDE_AT, 3)][:5],
150
  "as_of": today}
151
  try:
152
  CACHE.write_text(json.dumps({"key": key, "meta": meta}))
static/app.js CHANGED
@@ -91,8 +91,9 @@ function renderRiskScreen(rs) {
91
  (rows ? `<ul class="rs-list">${rows}</ul>` : "") +
92
  (medRows ? `<div class="rs-sub">Monitoring (below exclusion threshold β€” held):</div><ul class="rs-list">${medRows}</ul>` : "") +
93
  `<p class="rs-note">A second-stage AI overlay scans the final candidates for <b>concrete, recent adverse events</b> β€”
94
- legal Β· regulatory/FDA Β· geopolitical/trade Β· operational Β· competitive β€” and hard-excludes any high/critical hit
95
- (replaced by the next-ranked name). Ongoing, already-priced risks are deliberately ignored.</p>`;
 
96
  }
97
 
98
  async function previewRebalance() {
 
91
  (rows ? `<ul class="rs-list">${rows}</ul>` : "") +
92
  (medRows ? `<div class="rs-sub">Monitoring (below exclusion threshold β€” held):</div><ul class="rs-list">${medRows}</ul>` : "") +
93
  `<p class="rs-note">A second-stage AI overlay scans the final candidates for <b>concrete, recent adverse events</b> β€”
94
+ legal Β· regulatory/FDA Β· geopolitical/trade Β· operational Β· competitive β€” and hard-excludes only <b>critical</b> hits
95
+ (threats to the company itself; replaced by the next-ranked name). High and medium events are shown above and held.
96
+ Ongoing, already-priced risks are deliberately ignored.</p>`;
97
  }
98
 
99
  async function previewRebalance() {
static/index.html CHANGED
@@ -85,54 +85,53 @@
85
  <!-- ============ ABOUT / RESEARCH TAB ============ -->
86
  <div id="tab-about" class="tab-panel">
87
  <article class="doc">
88
- <p class="doc-lede">Slipstream is a quality, trend-adaptive equity paper fund that <b>drafts the smart money</b> β€” it holds names being bought by 13F super-investors and insiders, but only quality large-caps, sized with a dynamic sector cap, and it rotates into momentum when the market trend breaks. What follows is the full strategy, the backtest, and an honest account of everything we tried on the way here.</p>
89
 
90
  <h2 class="doc-h">1 Β· Strategy &amp; approach</h2>
91
- <p>The core question was simple: does <em>following the smart money</em> β€” the stocks that celebrated 13F investors and corporate insiders are buying β€” actually work? The honest answer from the research is that the raw signal does <b>not</b> beat the market on its own. Slipstream is what survived once we layered disciplined risk controls on top of it. The rule, applied monthly:</p>
92
  <table class="doc-table">
93
  <tbody>
94
- <tr><td class="k">Signal</td><td>Names being <b>bought</b> by curated 13F super-investors <b>or</b> insiders (net open-market buys)</td></tr>
95
- <tr><td class="k">Universe</td><td>Top ~1,000 US stocks by market cap, point-in-time (removes small-cap "falling knives")</td></tr>
96
- <tr><td class="k">Quality</td><td>ROE β‰₯ 10% <b>and</b> debt/equity ≀ 1.5 (profitable, not over-levered)</td></tr>
97
- <tr><td class="k">Construction</td><td>Top 20 by signal, dollar-weighted</td></tr>
98
- <tr><td class="k">AI event-risk overlay</td><td>A second-stage AI screen reads recent news on the final candidates and <b>hard-excludes</b> any name hit by a concrete, recent, materially-adverse <b>event</b> β€” legal (SEC/DOJ, adverse verdict), regulatory/FDA (CRL, clinical hold, recall), geopolitical/trade (sanctions, entity-list, export ban), operational (going-concern, guidance withdrawal, restatement, abrupt exec exit), or a specific competitive displacement. Excluded names are replaced by the next-ranked candidate.</td></tr>
99
- <tr><td class="k">Dynamic sector cap</td><td>Each sector capped at 30% <b>Β± its 12-1m relative strength vs SPY</b> (band 15–45%) β€” leading sectors run bigger, fading ones get trimmed automatically</td></tr>
100
- <tr><td class="k">Regime overlay</td><td>When SPY is in a <b>confirmed downtrend</b> (below its 200-day MA), the whole book rotates into large-cap momentum; otherwise it runs the smart-money book</td></tr>
101
- <tr><td class="k">Rebalance</td><td>Monthly (~3.8Γ— turnover/yr)</td></tr>
 
102
  </tbody>
103
  </table>
104
- <p class="doc-note">Why these pieces: the signal picks <em>candidates</em>; large-cap + quality remove the parts of the signal that actively lose; the dynamic sector cap keeps it from becoming an accidental one-sector bet; and the regime overlay is what carries it through bear markets. Every element earned its place in the tests below.</p>
105
- <p class="doc-note"><b>On the AI overlay β€” deliberately narrow.</b> Selection stays 100% systematic; the LLM is <em>not</em> a stock-picker or a subjective "risk score" (that would flag nearly every name, reintroduce narrative bias, and can't be backtested). It fires <em>only</em> on a discrete adverse <b>event</b> backed by a real headline β€” the one thing the price/fundamentals data lags on β€” so ongoing, already-priced risks (general competition, valuation, cyclicality) never trip it. It is capped (≀3 exclusions/rebalance), every exclusion cites its headline, and if the news feed or model is unavailable the fund trades the pure quant book unchanged. Severity is judged
106
- <em>relative to company size</em>: a lawsuit filing claiming ~1% of a mega-cap's value is monitored, not excluded β€” exclusion needs plausible exposure above ~5% of market value, a threat to the core
107
- business model, or an actual verdict/indictment (added Sep-2026 after the screen over-reacted to an FTC filing against Amazon that the market priced at βˆ’2.5%). For a full qualitative read on any holding, the sister app <b>Crucible</b> runs a 4-model analyst debate on demand.</p>
108
 
109
  <h2 class="doc-h">2 Β· Backtest results</h2>
110
- <p>Survivorship-free backtest, 2014–2026, net of 40 bps turnover cost, benchmarked against SPY. Rebuilt from a fresh, from-scratch pull of the underlying data (3,267 delisted names included, so there's no survivorship bias).</p>
111
  <div class="doc-kpis">
112
- <div class="dk"><span>CAGR</span><b>19.5%</b><small>SPY 13.9%</small></div>
113
- <div class="dk"><span>Excess / yr</span><b class="pos">+5.6%</b><small>vs SPY</small></div>
114
- <div class="dk"><span>Sharpe</span><b>0.92</b><small>SPY 0.85</small></div>
115
- <div class="dk"><span>Sortino</span><b>1.19</b><small></small></div>
116
- <div class="dk"><span>Alpha (ann)</span><b class="pos">+5.0%</b><small>Ξ² 1.05</small></div>
117
- <div class="dk"><span>Max drawdown</span><b class="neg">βˆ’32%</b><small>SPY β‰ˆ βˆ’33%</small></div>
118
- <div class="dk"><span>Years beat SPY</span><b>8 / 13</b><small></small></div>
119
- <div class="dk"><span>In momentum</span><b>23%</b><small>of months</small></div>
120
  </div>
121
  <figure class="doc-chart">
122
  <div class="dc-head"><span class="dc-title">Growth of $100 β€” Slipstream vs SPY</span>
123
- <span class="dc-leg"><i class="lg-fund"></i> Slipstream <i class="lg-spy" style="margin-left:12px"></i> SPY <span class="faint" style="margin-left:12px">2014–2026 Β· net of cost Β· log scale</span></span></div>
124
- <svg viewBox="0 0 1000 300" class="dc-svg" preserveAspectRatio="none" role="img" aria-label="Growth of $100, Slipstream versus SPY, log scale, 2014 to 2026"><defs><linearGradient id="dcg" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stop-color="#37b8a4" stop-opacity="0.14"/><stop offset="1" stop-color="#37b8a4" stop-opacity="0"/></linearGradient></defs><line x1="48" y1="264.6" x2="986" y2="264.6" stroke="#1e2c42"/><text x="41" y="267.6" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">100</text><line x1="48" y1="220.4" x2="986" y2="220.4" stroke="#1e2c42"/><text x="41" y="223.4" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">150</text><line x1="48" y1="189.1" x2="986" y2="189.1" stroke="#1e2c42"/><text x="41" y="192.1" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">200</text><line x1="48" y1="144.9" x2="986" y2="144.9" stroke="#1e2c42"/><text x="41" y="147.9" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">300</text><line x1="48" y1="89.2" x2="986" y2="89.2" stroke="#1e2c42"/><text x="41" y="92.2" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">500</text><line x1="48" y1="52.5" x2="986" y2="52.5" stroke="#1e2c42"/><text x="41" y="55.5" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">700</text><line x1="48" y1="13.6" x2="986" y2="13.6" stroke="#1e2c42"/><text x="41" y="16.6" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">1000</text><polygon points="48,274 48.0,269.5 54.2,256.2 60.4,256.5 66.6,256.2 72.8,251.4 79.1,250.5 85.3,250.4 91.5,247.9 97.7,248.1 103.9,243.9 110.1,240.9 116.3,242.5 122.5,247.1 128.8,240.2 135.0,244.4 141.2,239.7 147.4,239.7 153.6,243.8 159.8,238.9 166.0,244.5 172.2,250.1 178.5,247.2 184.7,245.1 190.9,246.1 197.1,256.7 203.3,257.5 209.5,250.6 215.7,251.0 221.9,248.2 228.1,251.5 234.4,243.7 240.6,242.1 246.8,239.5 253.0,239.5 259.2,241.9 265.4,240.8 271.6,235.5 277.8,229.7 284.1,228.8 290.3,223.3 296.5,220.3 302.7,221.5 308.9,215.5 315.1,214.0 321.3,211.5 327.5,207.6 333.7,207.4 340.0,206.4 346.2,197.0 352.4,200.7 358.6,203.0 364.8,200.3 371.0,194.4 377.2,194.9 383.4,191.0 389.7,189.4 395.9,190.3 402.1,201.4 408.3,203.4 414.5,215.1 420.7,202.0 426.9,195.8 433.1,195.2 439.4,191.9 445.6,201.1 451.8,195.2 458.0,190.5 464.2,191.4 470.4,193.3 476.6,189.9 482.8,183.7 489.0,179.7 495.3,178.3 501.5,183.3 507.7,195.0 513.9,177.3 520.1,167.9 526.3,158.6 532.5,151.4 538.7,139.5 545.0,145.6 551.2,145.5 557.4,139.0 563.6,139.6 569.8,140.7 576.0,136.5 582.2,133.3 588.4,124.9 594.6,124.7 600.9,120.7 607.1,117.3 613.3,113.4 619.5,120.8 625.7,114.0 631.9,116.8 638.1,113.3 644.3,116.0 650.6,120.9 656.8,113.6 663.0,122.6 669.2,115.3 675.4,132.9 681.6,123.7 687.8,120.6 694.0,135.5 700.3,120.2 706.5,120.7 712.7,129.6 718.9,127.0 725.1,133.9 731.3,122.8 737.5,121.1 743.7,121.1 749.9,117.7 756.2,111.3 762.4,107.0 768.6,113.8 774.8,117.2 781.0,109.4 787.2,107.0 793.4,106.1 799.6,100.2 805.9,94.4 812.1,101.3 818.3,97.4 824.5,90.3 830.7,89.4 836.9,89.5 843.1,87.9 849.3,82.2 855.5,77.9 861.8,76.7 868.0,70.6 874.2,76.5 880.4,83.0 886.6,79.3 892.8,67.7 899.0,57.9 905.2,54.7 911.5,54.5 917.7,50.5 923.9,46.0 930.1,46.4 936.3,48.0 942.5,46.7 948.7,52.1 954.9,56.9 961.2,37.0 967.4,21.1 973.6,27.6 979.8,22.7 986.0,20.3 986,274" fill="url(#dcg)"/><polyline points="48.0,268.5 54.2,263.7 60.4,262.8 66.6,262.1 72.8,259.5 79.1,257.3 85.3,258.8 91.5,254.6 97.7,256.1 103.9,253.6 110.1,250.6 116.3,250.8 122.5,254.2 128.8,248.2 135.0,249.9 141.2,248.8 147.4,247.4 153.6,249.7 159.8,247.3 166.0,254.2 172.2,257.0 178.5,248.0 184.7,247.6 190.9,249.5 197.1,255.1 203.3,255.2 209.5,248.1 215.7,247.6 221.9,245.8 228.1,245.4 234.4,241.5 240.6,241.4 246.8,241.4 253.0,243.3 259.2,239.4 265.4,237.1 271.6,235.2 277.8,231.0 284.1,230.9 290.3,229.9 296.5,228.3 302.7,227.6 308.9,225.3 315.1,225.0 321.3,222.9 327.5,220.4 333.7,217.1 340.0,215.7 346.2,209.8 352.4,213.8 358.6,216.9 364.8,216.3 371.0,213.7 377.2,213.1 383.4,209.1 389.7,205.7 395.9,205.0 402.1,212.8 408.3,210.8 414.5,220.8 420.7,212.5 426.9,208.9 433.1,207.0 439.4,202.6 445.6,209.9 451.8,202.5 458.0,200.9 464.2,202.7 470.4,200.6 476.6,198.2 482.8,194.3 489.0,191.2 495.3,191.3 501.5,200.3 507.7,214.8 513.9,201.7 520.1,196.6 526.3,194.7 532.5,188.5 538.7,181.1 545.0,185.3 551.2,188.1 557.4,176.8 563.6,172.8 569.8,173.9 576.0,170.9 582.2,166.1 588.4,160.5 594.6,159.8 600.9,157.3 607.1,154.7 613.3,151.6 619.5,156.7 625.7,149.3 631.9,150.2 638.1,145.3 644.3,151.2 650.6,154.4 656.8,150.4 663.0,160.4 669.2,160.2 675.4,169.6 681.6,160.0 687.8,164.5 694.0,175.1 700.3,166.6 706.5,160.7 712.7,167.1 718.9,160.5 725.1,163.3 731.3,159.3 737.5,157.6 743.7,157.1 749.9,150.2 756.2,146.7 762.4,148.5 768.6,153.8 774.8,156.2 781.0,146.7 787.2,141.8 793.4,140.1 799.6,134.5 805.9,131.0 812.1,135.5 818.3,130.1 824.5,126.3 830.7,125.0 836.9,122.5 843.1,120.2 849.3,121.2 855.5,114.9 861.8,117.6 868.0,114.7 874.2,116.1 880.4,122.3 886.6,123.3 892.8,116.6 899.0,111.1 905.2,108.7 911.5,106.5 917.7,102.7 923.9,100.1 930.1,99.9 936.3,99.8 942.5,98.2 948.7,99.1 954.9,104.7 961.2,93.8 967.4,88.2 973.6,89.3 979.8,89.3 986.0,86.0" fill="none" stroke="#5d6b83" stroke-width="1.6" stroke-dasharray="4 3"/><polyline points="48.0,269.5 54.2,256.2 60.4,256.5 66.6,256.2 72.8,251.4 79.1,250.5 85.3,250.4 91.5,247.9 97.7,248.1 103.9,243.9 110.1,240.9 116.3,242.5 122.5,247.1 128.8,240.2 135.0,244.4 141.2,239.7 147.4,239.7 153.6,243.8 159.8,238.9 166.0,244.5 172.2,250.1 178.5,247.2 184.7,245.1 190.9,246.1 197.1,256.7 203.3,257.5 209.5,250.6 215.7,251.0 221.9,248.2 228.1,251.5 234.4,243.7 240.6,242.1 246.8,239.5 253.0,239.5 259.2,241.9 265.4,240.8 271.6,235.5 277.8,229.7 284.1,228.8 290.3,223.3 296.5,220.3 302.7,221.5 308.9,215.5 315.1,214.0 321.3,211.5 327.5,207.6 333.7,207.4 340.0,206.4 346.2,197.0 352.4,200.7 358.6,203.0 364.8,200.3 371.0,194.4 377.2,194.9 383.4,191.0 389.7,189.4 395.9,190.3 402.1,201.4 408.3,203.4 414.5,215.1 420.7,202.0 426.9,195.8 433.1,195.2 439.4,191.9 445.6,201.1 451.8,195.2 458.0,190.5 464.2,191.4 470.4,193.3 476.6,189.9 482.8,183.7 489.0,179.7 495.3,178.3 501.5,183.3 507.7,195.0 513.9,177.3 520.1,167.9 526.3,158.6 532.5,151.4 538.7,139.5 545.0,145.6 551.2,145.5 557.4,139.0 563.6,139.6 569.8,140.7 576.0,136.5 582.2,133.3 588.4,124.9 594.6,124.7 600.9,120.7 607.1,117.3 613.3,113.4 619.5,120.8 625.7,114.0 631.9,116.8 638.1,113.3 644.3,116.0 650.6,120.9 656.8,113.6 663.0,122.6 669.2,115.3 675.4,132.9 681.6,123.7 687.8,120.6 694.0,135.5 700.3,120.2 706.5,120.7 712.7,129.6 718.9,127.0 725.1,133.9 731.3,122.8 737.5,121.1 743.7,121.1 749.9,117.7 756.2,111.3 762.4,107.0 768.6,113.8 774.8,117.2 781.0,109.4 787.2,107.0 793.4,106.1 799.6,100.2 805.9,94.4 812.1,101.3 818.3,97.4 824.5,90.3 830.7,89.4 836.9,89.5 843.1,87.9 849.3,82.2 855.5,77.9 861.8,76.7 868.0,70.6 874.2,76.5 880.4,83.0 886.6,79.3 892.8,67.7 899.0,57.9 905.2,54.7 911.5,54.5 917.7,50.5 923.9,46.0 930.1,46.4 936.3,48.0 942.5,46.7 948.7,52.1 954.9,56.9 961.2,37.0 967.4,21.1 973.6,27.6 979.8,22.7 986.0,20.3" fill="none" stroke="#37b8a4" stroke-width="2.4"/><circle cx="986.0" cy="20.3" r="3.5" fill="#37b8a4"/><text x="982.0" y="12.3" fill="#3ed88f" font-size="11" text-anchor="end" font-family="monospace">$941</text><text x="982.0" y="100.0" fill="#8695ad" font-size="11" text-anchor="end" font-family="monospace">$515</text><text x="48.0" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2014</text><text x="197.1" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2016</text><text x="346.2" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2018</text><text x="495.3" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2020</text><text x="644.3" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2022</text><text x="793.4" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2024</text><text x="942.5" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2026</text></svg>
125
  </figure>
126
  <table class="doc-table wide">
127
- <thead><tr><th>Regime</th><th>Fund CAGR</th><th>SPY</th><th>Excess</th><th>Sharpe</th></tr></thead>
128
  <tbody>
129
- <tr><td>2014–2019 (calm bull)</td><td>17.6%</td><td>11.9%</td><td class="pos">+5.7%*</td><td>β€”</td></tr>
130
- <tr><td>2020–2022 (COVID + rate shock)</td><td class="mono">+8.9% excess</td><td></td><td class="pos">+8.9%</td><td>0.68</td></tr>
131
- <tr><td>2023–2026 (AI mega-cap rally)</td><td class="mono">+9.2% excess</td><td></td><td class="pos">+9.2%</td><td>1.43</td></tr>
132
  </tbody>
133
  </table>
134
- <p class="doc-note">The regime overlay + dynamic cap turn the strategy's old weak spot (2020–22) into its <em>strongest</em> relative stretch; the trade-off is it gives up a little edge in long calm bull runs. <a href="https://claude.ai/code/artifact/76fe070f-00b6-4853-9ded-af77be1d1e5a" target="_blank" rel="noopener">Open the full interactive tear-sheet β†—</a></p>
135
- <p class="doc-warn"><b>Read honestly.</b> This is a <em>simulated backtest</em>, not a live track record. The edge is real but <b>modest and hard-won</b>: Sharpe only marginally above the market, higher beta (1.05) and vol (~22%), a full βˆ’32% drawdown, and it's the most parameter-rich version we tested β€” so live results will likely land below the backtest. The raw 13F/insider signals were weak-to-negative on their own; all the performance comes from the disciplines layered on top. Not investment advice.</p>
136
 
137
  <h2 class="doc-h">3 Β· Everything we explored</h2>
138
  <p>We stress-tested the idea from every angle before settling on the rule above. Each row is a real backtest; the pattern that emerged: <b>every "buy it cheap / beaten-down" tilt hurt, and every "quality / large-cap / diversify / adapt" control helped.</b></p>
@@ -151,14 +150,21 @@
151
  <tr><td>Momentum factor (in the 2020–22 window)</td><td>The one thing that beat the fund <em>and</em> SPY in that stretch β€” because it's regime-adaptive</td><td class="pos">βœ“ informed overlay</td></tr>
152
  <tr><td><b>Regime switch β†’ momentum (200DMA, confirmed)</b></td><td>Fixes 2020–22 (βˆ’2.8% β†’ +6.0%), lifts full-period excess to +5.0%, same drawdown</td><td class="pos">βœ“ adopted</td></tr>
153
  <tr><td>Multi-signal regime consensus (5 signals, K-of-N)</td><td>No better than the simple single 200DMA filter; more knobs = more overfitting risk</td><td class="warn">~ kept it simple</td></tr>
154
- <tr><td><b>Dynamic cap + regime overlay (final)</b></td><td>The two overlays are <b>additive</b>: best on every metric β€” CAGR 19.5%, Sharpe 0.92, βˆ’32% DD</td><td class="pos">β˜… Slipstream</td></tr>
 
 
 
 
 
 
 
155
  </tbody>
156
  </table>
157
  <p class="doc-note">A recurring lesson worth keeping: the flashiest backtest numbers came from the configs taking the most <em>uncompensated</em> risk (concentration, single regime). Each time we tightened the methodology β€” survivorship, costs, sub-period robustness, sector control, multiple-testing thresholds β€” the "edge" shrank toward the market. Slipstream is what was left standing after all of that.</p>
158
 
159
  <h2 class="doc-h">4 Β· Data &amp; honesty notes</h2>
160
  <ul class="doc-list">
161
- <li><b>Data:</b> SEC 13F (Sharadar SF3), Form 4 insider (SF2), fundamentals (SF1), prices (SEP) via Nasdaq Data Link. Survivorship-free.</li>
162
  <li><b>Signal freshness:</b> 13F is quarterly and ~45 days lagged by law β€” so the smart-money signal is inherently stale; the fund is built to work <em>despite</em> that, not to pretend otherwise.</li>
163
  <li><b>Picks panels</b> are informational and LLM-screened for manipulation/pump patterns; they are <em>not</em> individual buy recommendations. The fund trades a disciplined, risk-controlled subset automatically.</li>
164
  <li><b>Paper only.</b> Slipstream runs on an Alpaca paper account. Nothing here is investment advice.</li>
@@ -174,13 +180,13 @@
174
  asserts every dataset actually advanced β€” a stale input fails the run loudly instead of silently
175
  trading on old data.</td></tr>
176
  <tr><td><b>Monthly rebalance</b> (1st)</td><td>Trades the freshest weekly signal row through the
177
- construction rules above (quality gate β†’ AI event screen β†’ 15% name cap alternating with dynamic
178
  sector caps). Idempotent β€” a re-run trades only target-minus-actual.</td></tr>
179
  <tr><td><b>Daily supervisor</b> (weekdays)</td><td>A deterministic health monitor β€” it <em>never
180
  trades</em> β€” checking three things: <b>tracking</b> (trailing 4-week fund-vs-SPY gap; WATCH &lt;βˆ’3pp,
181
  ALERT &lt;βˆ’6pp), <b>guardrails</b> (paper-only invariant, no margin, exposure ≀100.5%, and position
182
- drift β€” the 15% cap applies <em>at</em> rebalance, so intra-month drift only flags above 18%, alerts
183
- above 22%), and <b>freshness</b> (signals ≀10 days old, last rebalance ≀35 days). Results appear as
184
  the OK / WATCH / ALERT chips at the top of the Fund tab, and an ALERT fails the scheduled run so it
185
  can't be missed.</td></tr>
186
  </tbody>
 
85
  <!-- ============ ABOUT / RESEARCH TAB ============ -->
86
  <div id="tab-about" class="tab-panel">
87
  <article class="doc">
88
+ <p class="doc-lede">Slipstream is a quality, trend-adaptive equity paper fund that <b>drafts the smart money</b> β€” it holds the large-caps that concentrated, high-conviction 13F managers are collectively buying, keeps only the most profitable companies in each sector, caps any one stock at 10%, and rotates into momentum when the market trend breaks. What follows is the rule, the backtest, and an honest account of everything we tried on the way here.</p>
89
 
90
  <h2 class="doc-h">1 Β· Strategy &amp; approach</h2>
91
+ <p>The core question: does <em>following the smart money</em> actually work? Our October 2026 re-validation, run from a fresh data pull, found that the original rule (curated super-investors + insiders, ROE/debt quality gate) had <b>no demonstrated edge</b> over SPY. Eight pre-registered follow-up studies then identified what does carry information: <b>breadth of conviction buying among concentrated managers</b>, filtered for <b>profitability within each sector</b>. The rule (v2, from November 2026), applied monthly:</p>
92
  <table class="doc-table">
93
  <tbody>
94
+ <tr><td class="k">Managers</td><td>Every 13F filer that behaves like a concentrated stock-picker <em>that quarter</em>: 10–150 positions, $250M–$100B reported equity, β‰₯40% in its top 10, and a filing the previous quarter. Rule-based, ~900–1,500 managers a quarter β€” new managers join automatically, nobody curates the list</td></tr>
95
+ <tr><td class="k">Signal</td><td><b>Consensus:</b> for each stock, 2 Γ— managers opening a conviction position + managers adding βˆ’ 2 Γ— managers exiting (a conviction position is β‰₯$1M and β‰₯0.5% of the manager's portfolio). Buy candidates have a positive count. 13F only β€” insider buying is no longer used</td></tr>
96
+ <tr><td class="k">Universe</td><td>Top ~1,000 US stocks by market cap, point-in-time</td></tr>
97
+ <tr><td class="k">Quality</td><td>Return on assets in the <b>top 30% of its own sector</b> (latest filing public at the time) β€” so every sector contributes its most profitable companies, and banks or utilities aren't screened out wholesale</td></tr>
98
+ <tr><td class="k">Construction</td><td>Top 20 by consensus, weighted by the dollars managers committed, each stock <b>1–10%</b>, at most 5 per sector</td></tr>
99
+ <tr><td class="k">AI event-risk overlay</td><td>A second-stage AI screen reads recent news on the final candidates and <b>hard-excludes only critical events</b> β€” threats to the company itself: going-concern / bankruptcy, fraud or restatement, criminal indictment, loss of the license to operate, sanctions cutting off a major share of revenue. Lesser events are shown and held. Excluded names are replaced by the next-ranked candidate</td></tr>
100
+ <tr><td class="k">Dynamic sector cap</td><td>Each sector capped at 30% <b>Β± its 12-1m relative strength vs SPY</b> (band 15–45%)</td></tr>
101
+ <tr><td class="k">Regime overlay</td><td>When SPY is in a <b>confirmed downtrend</b> (below its 200-day MA, confirmed a month earlier), the whole book rotates into the 50 large-caps with the strongest 12-month momentum</td></tr>
102
+ <tr><td class="k">Rebalance</td><td>Monthly (~3.5Γ— one-way turnover a year), 1% cash buffer, 0.5% trade deadband</td></tr>
103
  </tbody>
104
  </table>
105
+ <p class="doc-note">Why these pieces: counting <em>how many</em> conviction managers are buying works better than following any curated few β€” no 13F manager's individual record proved persistent enough to pick on. The within-sector ROA filter is the single biggest improvement we found; it lifted every manager list we tested. The 10% stock cap keeps the same risk-adjusted return as 15% with a less concentrated book. The regime overlay is what carries the fund through bear markets.</p>
106
+ <p class="doc-note"><b>On the AI overlay β€” deliberately narrow.</b> Selection stays 100% systematic; the LLM is <em>not</em> a stock-picker. Because no backtest can include it, it now fires <b>only on critical events</b>, so the live fund deviates from the tested rule only when a company itself is under threat. It is capped (≀3 exclusions/rebalance), every exclusion cites its headline, and if the news feed or model is unavailable the fund trades the pure quant book unchanged.</p>
 
 
107
 
108
  <h2 class="doc-h">2 Β· Backtest results</h2>
109
+ <p>Survivorship-free backtest, 2014-03 β†’ 2026-10, rebuilt from a fresh Sharadar pull (4,323 delisted names included; delisting returns from corporate actions). Trades use only data available the day before, net of 20 bp per side, 1% cash; Sharpe and Sortino are net of T-bills. The AI overlay is not included (it can't be backtested).</p>
110
  <div class="doc-kpis">
111
+ <div class="dk"><span>CAGR</span><b>19.9%</b><small>SPY 13.9%</small></div>
112
+ <div class="dk"><span>Excess / yr</span><b class="pos">+5.9%</b><small>vs SPY</small></div>
113
+ <div class="dk"><span>Sharpe</span><b>0.85</b><small>SPY 0.73</small></div>
114
+ <div class="dk"><span>Sortino</span><b>1.04</b><small></small></div>
115
+ <div class="dk"><span>Alpha (ann)</span><b class="pos">+3.9%</b><small>t 1.8 Β· Ξ² 1.17</small></div>
116
+ <div class="dk"><span>Max drawdown</span><b class="neg">-37.5%</b><small>SPY -33.7%</small></div>
117
+ <div class="dk"><span>Years beat SPY</span><b>6 / 11</b><small>2015–2025</small></div>
118
+ <div class="dk"><span>In momentum</span><b>24%</b><small>of months</small></div>
119
  </div>
120
  <figure class="doc-chart">
121
  <div class="dc-head"><span class="dc-title">Growth of $100 β€” Slipstream vs SPY</span>
122
+ <span class="dc-leg"><i class="lg-fund"></i> Slipstream <i class="lg-spy" style="margin-left:12px"></i> SPY <span class="faint" style="margin-left:12px">2014-03 β†’ 2026-10 Β· net of cost Β· log scale</span></span></div>
123
+ <svg viewBox="0 0 1000 300" class="dc-svg" preserveAspectRatio="none" role="img" aria-label="Growth of $100, Slipstream versus SPY, log scale, March 2014 to October 2026"><defs><linearGradient id="dcg" x1="0" x2="0" y1="0" y2="1"><stop offset="0" stop-color="#37b8a4" stop-opacity="0.14"/><stop offset="1" stop-color="#37b8a4" stop-opacity="0"/></linearGradient></defs><line x1="48" y1="264.6" x2="986" y2="264.6" stroke="#1e2c42"/><text x="41" y="267.6" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">100</text><line x1="48" y1="220.4" x2="986" y2="220.4" stroke="#1e2c42"/><text x="41" y="223.4" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">150</text><line x1="48" y1="189.0" x2="986" y2="189.0" stroke="#1e2c42"/><text x="41" y="192.0" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">200</text><line x1="48" y1="144.8" x2="986" y2="144.8" stroke="#1e2c42"/><text x="41" y="147.8" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">300</text><line x1="48" y1="89.2" x2="986" y2="89.2" stroke="#1e2c42"/><text x="41" y="92.2" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">500</text><line x1="48" y1="52.5" x2="986" y2="52.5" stroke="#1e2c42"/><text x="41" y="55.5" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">700</text><line x1="48" y1="13.6" x2="986" y2="13.6" stroke="#1e2c42"/><text x="41" y="16.6" fill="#5d6b83" font-size="10" text-anchor="end" font-family="monospace">1000</text><polygon points="48,274 48.0,264.8 53.7,264.8 59.8,261.4 66.1,257.8 72.1,257.6 78.4,257.2 84.7,254.0 90.8,254.1 97.1,250.3 103.2,245.6 109.5,247.4 115.7,251.1 121.4,243.9 127.7,247.0 133.8,244.6 140.1,244.4 146.2,250.1 152.4,246.1 158.7,253.3 164.8,259.4 171.1,257.4 177.2,255.1 183.5,257.5 189.8,267.2 195.6,268.9 201.9,261.7 208.0,261.5 214.3,260.4 220.4,263.5 226.7,259.4 233.0,256.7 239.0,255.4 245.3,257.1 251.4,257.3 257.7,256.3 264.0,252.2 269.7,246.2 276.0,244.4 282.0,240.3 288.3,236.1 294.4,235.8 300.7,232.3 307.0,231.4 313.1,229.8 319.4,224.4 325.4,222.8 331.7,222.3 338.0,213.0 343.7,216.3 350.0,219.3 356.1,218.7 362.4,211.0 368.4,210.8 374.7,209.9 381.0,208.0 387.1,207.6 393.4,215.5 399.5,217.0 405.8,228.2 412.0,214.2 417.7,208.2 424.0,207.3 430.1,200.7 436.4,208.4 442.5,202.6 448.8,199.9 455.0,199.6 461.1,199.8 467.4,196.1 473.5,190.8 479.8,186.6 486.1,184.9 492.0,190.6 498.2,210.7 504.3,192.7 510.6,183.7 516.7,173.6 523.0,167.4 529.3,155.5 535.4,159.8 541.6,161.6 547.7,154.8 554.0,152.3 560.3,153.7 566.0,152.1 572.3,150.0 578.4,142.7 584.6,144.7 590.7,138.3 597.0,135.5 603.3,133.2 609.4,139.3 615.7,131.5 621.8,130.4 628.0,127.0 634.3,131.7 640.0,140.9 646.3,136.0 652.4,144.7 658.7,137.4 664.7,154.6 671.0,145.0 677.3,142.7 683.4,156.8 689.7,141.6 695.8,142.1 702.1,151.0 708.4,147.7 714.0,154.6 720.3,144.1 726.4,143.0 732.7,136.5 738.8,131.0 745.1,125.9 751.3,127.1 757.4,131.3 763.7,132.7 769.8,118.1 776.1,112.7 782.4,109.6 788.3,101.8 794.5,100.2 800.6,102.4 806.9,94.8 813.0,87.9 819.3,90.1 825.6,84.5 831.7,79.0 837.9,78.3 844.0,75.6 850.3,77.3 856.6,70.7 862.3,72.0 868.6,80.8 874.7,77.0 880.9,66.5 887.0,57.3 893.3,56.2 899.6,54.7 905.7,49.8 912.0,46.2 918.1,45.1 924.3,46.4 930.6,46.5 936.3,49.4 942.6,55.8 948.7,35.9 955.0,20.4 961.1,27.2 967.3,22.4 973.6,19.6 979.7,17.5 986.0,16.5 986,274" fill="url(#dcg)"/><polyline points="48.0,264.6 53.7,262.9 59.8,262.2 66.1,259.7 72.1,257.4 78.4,258.9 84.7,254.7 90.8,256.2 97.1,253.7 103.2,250.7 109.5,251.0 115.7,254.3 121.4,248.3 127.7,250.1 133.8,249.0 140.1,247.6 146.2,249.8 152.4,247.4 158.7,254.2 164.8,257.1 171.1,248.2 177.2,247.8 183.5,249.6 189.8,255.2 195.6,255.3 201.9,248.2 208.0,247.8 214.3,245.9 220.4,245.6 226.7,241.7 233.0,241.5 239.0,241.5 245.3,243.4 251.4,239.5 257.7,237.3 264.0,235.4 269.7,231.2 276.0,231.0 282.0,229.9 288.3,228.4 294.4,227.7 300.7,225.5 307.0,225.2 313.1,223.0 319.4,220.5 325.4,217.2 331.7,215.9 338.0,209.9 343.7,213.9 350.0,217.0 356.1,216.4 362.4,213.8 368.4,213.2 374.7,209.2 381.0,205.8 387.1,205.1 393.4,212.9 399.5,210.9 405.8,221.0 412.0,212.6 417.7,209.1 424.0,207.1 430.1,202.8 436.4,210.0 442.5,202.6 448.8,201.0 455.0,202.8 461.1,200.7 467.4,198.3 473.5,194.5 479.8,191.3 486.1,191.4 492.0,200.4 498.2,214.9 504.3,201.9 510.6,196.8 516.7,194.9 523.0,188.6 529.3,181.3 535.4,185.4 541.6,188.2 547.7,176.9 554.0,173.0 560.3,174.1 566.0,171.1 572.3,166.2 578.4,160.6 584.6,159.9 590.7,157.5 597.0,154.9 603.3,151.7 609.4,156.9 615.7,149.5 621.8,150.4 628.0,145.4 634.3,151.3 640.0,154.6 646.3,150.6 652.4,160.6 658.7,160.3 664.7,169.7 671.0,160.1 677.3,164.7 683.4,175.2 689.7,166.7 695.8,160.8 702.1,167.3 708.4,160.6 714.0,163.4 720.3,159.4 726.4,157.7 732.7,157.2 738.8,150.4 745.1,146.8 751.3,148.6 757.4,153.9 763.7,156.3 769.8,146.8 776.1,141.9 782.4,140.2 788.3,134.7 794.5,131.1 800.6,135.6 806.9,130.3 813.0,126.5 819.3,125.2 825.6,122.6 831.7,120.4 837.9,121.4 844.0,115.0 850.3,117.7 856.6,114.8 862.3,116.2 868.6,122.5 874.7,123.4 880.9,116.8 887.0,111.3 893.3,108.8 899.6,106.6 905.7,102.8 912.0,100.2 918.1,100.0 924.3,99.9 930.6,98.3 936.3,99.3 942.6,104.8 948.7,93.9 955.0,88.3 961.1,89.4 967.3,89.4 973.6,86.5 979.7,86.9 986.0,85.9" fill="none" stroke="#5d6b83" stroke-width="1.6" stroke-dasharray="4 3"/><polyline points="48.0,264.8 53.7,264.8 59.8,261.4 66.1,257.8 72.1,257.6 78.4,257.2 84.7,254.0 90.8,254.1 97.1,250.3 103.2,245.6 109.5,247.4 115.7,251.1 121.4,243.9 127.7,247.0 133.8,244.6 140.1,244.4 146.2,250.1 152.4,246.1 158.7,253.3 164.8,259.4 171.1,257.4 177.2,255.1 183.5,257.5 189.8,267.2 195.6,268.9 201.9,261.7 208.0,261.5 214.3,260.4 220.4,263.5 226.7,259.4 233.0,256.7 239.0,255.4 245.3,257.1 251.4,257.3 257.7,256.3 264.0,252.2 269.7,246.2 276.0,244.4 282.0,240.3 288.3,236.1 294.4,235.8 300.7,232.3 307.0,231.4 313.1,229.8 319.4,224.4 325.4,222.8 331.7,222.3 338.0,213.0 343.7,216.3 350.0,219.3 356.1,218.7 362.4,211.0 368.4,210.8 374.7,209.9 381.0,208.0 387.1,207.6 393.4,215.5 399.5,217.0 405.8,228.2 412.0,214.2 417.7,208.2 424.0,207.3 430.1,200.7 436.4,208.4 442.5,202.6 448.8,199.9 455.0,199.6 461.1,199.8 467.4,196.1 473.5,190.8 479.8,186.6 486.1,184.9 492.0,190.6 498.2,210.7 504.3,192.7 510.6,183.7 516.7,173.6 523.0,167.4 529.3,155.5 535.4,159.8 541.6,161.6 547.7,154.8 554.0,152.3 560.3,153.7 566.0,152.1 572.3,150.0 578.4,142.7 584.6,144.7 590.7,138.3 597.0,135.5 603.3,133.2 609.4,139.3 615.7,131.5 621.8,130.4 628.0,127.0 634.3,131.7 640.0,140.9 646.3,136.0 652.4,144.7 658.7,137.4 664.7,154.6 671.0,145.0 677.3,142.7 683.4,156.8 689.7,141.6 695.8,142.1 702.1,151.0 708.4,147.7 714.0,154.6 720.3,144.1 726.4,143.0 732.7,136.5 738.8,131.0 745.1,125.9 751.3,127.1 757.4,131.3 763.7,132.7 769.8,118.1 776.1,112.7 782.4,109.6 788.3,101.8 794.5,100.2 800.6,102.4 806.9,94.8 813.0,87.9 819.3,90.1 825.6,84.5 831.7,79.0 837.9,78.3 844.0,75.6 850.3,77.3 856.6,70.7 862.3,72.0 868.6,80.8 874.7,77.0 880.9,66.5 887.0,57.3 893.3,56.2 899.6,54.7 905.7,49.8 912.0,46.2 918.1,45.1 924.3,46.4 930.6,46.5 936.3,49.4 942.6,55.8 948.7,35.9 955.0,20.4 961.1,27.2 967.3,22.4 973.6,19.6 979.7,17.5 986.0,16.5" fill="none" stroke="#37b8a4" stroke-width="2.4"/><circle cx="986.0" cy="16.5" r="3.5" fill="#37b8a4"/><text x="982.0" y="8.5" fill="#3ed88f" font-size="11" text-anchor="end" font-family="monospace">$973</text><text x="982.0" y="99.9" fill="#8695ad" font-size="11" text-anchor="end" font-family="monospace">$515</text><text x="109.7" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2015</text><text x="257.9" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2017</text><text x="406.0" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2019</text><text x="554.2" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2021</text><text x="702.3" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2023</text><text x="850.5" y="294" fill="#5d6b83" font-size="10" text-anchor="middle" font-family="monospace">2025</text></svg>
124
  </figure>
125
  <table class="doc-table wide">
126
+ <thead><tr><th>Period</th><th>Fund CAGR</th><th>SPY</th><th>Excess</th><th>Sharpe (SPY)</th></tr></thead>
127
  <tbody>
128
+ <tr><td>2014–2019 (calm bull)</td><td>13.1%</td><td>12.2%</td><td class="pos">+0.9%</td><td>0.77 (0.88)</td></tr>
129
+ <tr><td>2020–2022 (COVID + rate shock)</td><td>11.5%</td><td>7.6%</td><td class="pos">+3.9%</td><td>0.49 (0.39)</td></tr>
130
+ <tr><td>2023–2026 (AI mega-cap rally)</td><td>39.1%</td><td>22.1%</td><td class="pos">+17.0%</td><td>1.46 (1.11)</td></tr>
131
  </tbody>
132
  </table>
133
+ <p class="doc-note">How the rule was chosen: settings were selected on 2016-03 β†’ 2021-12 only (Sharpe 1.08 vs SPY 1.00). 2022 onward was then reviewed across several studies, so it is not a clean out-of-sample test (Sharpe 0.86 vs 0.52). The two years before selection, 2014-03 β†’ 2016-02, were never used β€” and the fund <b>trailed SPY</b> there (βˆ’1.8% vs +4.4% a year, hurt by risk-off whipsaws in 2015–16).</p>
134
+ <p class="doc-warn"><b>Read honestly.</b> This is a <em>simulated backtest</em>, not a live track record, and it is the best of ~210 configurations tested β€” so expect live results below it. Over the full period the alpha is positive but only borderline significant (t 1.8); the fund carries more market risk than SPY (Ξ² 1.17, volatility ~22%, drawdowns to -37.5%); roughly half the book is usually tech-related; and much of the excess return came after 2023. Candidate rules are tracked in a forward "shadow book" whose books are recorded before their returns exist β€” that record, not this chart, is the real test. Not investment advice.</p>
135
 
136
  <h2 class="doc-h">3 Β· Everything we explored</h2>
137
  <p>We stress-tested the idea from every angle before settling on the rule above. Each row is a real backtest; the pattern that emerged: <b>every "buy it cheap / beaten-down" tilt hurt, and every "quality / large-cap / diversify / adapt" control helped.</b></p>
 
150
  <tr><td>Momentum factor (in the 2020–22 window)</td><td>The one thing that beat the fund <em>and</em> SPY in that stretch β€” because it's regime-adaptive</td><td class="pos">βœ“ informed overlay</td></tr>
151
  <tr><td><b>Regime switch β†’ momentum (200DMA, confirmed)</b></td><td>Fixes 2020–22 (βˆ’2.8% β†’ +6.0%), lifts full-period excess to +5.0%, same drawdown</td><td class="pos">βœ“ adopted</td></tr>
152
  <tr><td>Multi-signal regime consensus (5 signals, K-of-N)</td><td>No better than the simple single 200DMA filter; more knobs = more overfitting risk</td><td class="warn">~ kept it simple</td></tr>
153
+ <tr><td>Dynamic cap + regime overlay (v1, Aug 2026)</td><td>Reported 19.5% CAGR / Sharpe 0.92 β€” <b>not reproducible</b> (its 13F input was overwritten); rebuilt on fresh data with live execution: 15.5% CAGR, Sharpe 0.67 vs SPY 0.73, no significant alpha</td><td class="warn">~ superseded</td></tr>
154
+ <tr><td>Wider / different manager lists (102, 210 curated; top-200 track records; "emerging" managers; top inflows)</td><td>No list beat the simple rule-based concentrated-manager list; past 13F skill doesn't persist (rank correlation β‰ˆ 0 across 44 quarters)</td><td class="neg">βœ— rejected</td></tr>
155
+ <tr><td>Accumulation Radar (volume footprint nowcast of 13F buying)</td><td>Detects institutional accumulation well (AUC 0.76) but adds no return on top of 13F consensus</td><td class="neg">βœ— rejected</td></tr>
156
+ <tr><td><b>Quality = ROA, top 30% within sector</b></td><td>Lifted every manager list (e.g. Sharpe 0.89 β†’ 1.07 on 2016–21); smart-money book now beats SPY in risk-on months</td><td class="pos">βœ“ adopted</td></tr>
157
+ <tr><td>Add debt/equity screen</td><td>Lowered return in all 4 variants, no drawdown benefit β€” mostly removes high-ROA buyback compounders</td><td class="neg">βœ— rejected</td></tr>
158
+ <tr><td><b>10% stock cap (vs 15%)</b></td><td>Same Sharpe, top-5 weight 56% β†’ 48%</td><td class="pos">βœ“ adopted</td></tr>
159
+ <tr><td>Tech cap (Technology + Communication ≀ 30–40%)</td><td>Costs 1.4–2.5%/yr, no drawdown benefit β€” a view on tech, not a free risk reduction</td><td class="warn">~ optional, not used</td></tr>
160
+ <tr><td><b>Concentrated-manager consensus + ROA-30 + 10% cap (v2)</b></td><td>19.9% CAGR vs SPY 13.9%, Sharpe 0.85 vs 0.73, -37.5% max DD (2014–2026)</td><td class="pos">β˜… Slipstream</td></tr>
161
  </tbody>
162
  </table>
163
  <p class="doc-note">A recurring lesson worth keeping: the flashiest backtest numbers came from the configs taking the most <em>uncompensated</em> risk (concentration, single regime). Each time we tightened the methodology β€” survivorship, costs, sub-period robustness, sector control, multiple-testing thresholds β€” the "edge" shrank toward the market. Slipstream is what was left standing after all of that.</p>
164
 
165
  <h2 class="doc-h">4 Β· Data &amp; honesty notes</h2>
166
  <ul class="doc-list">
167
+ <li><b>Data:</b> SEC 13F (Sharadar SF3, every filer), fundamentals (SF1), prices (SEP), corporate actions (delistings) via Nasdaq Data Link. Survivorship-free. Sector labels are current, not historical. Form 4 insider data (SF2) feeds the Insider picks panel only.</li>
168
  <li><b>Signal freshness:</b> 13F is quarterly and ~45 days lagged by law β€” so the smart-money signal is inherently stale; the fund is built to work <em>despite</em> that, not to pretend otherwise.</li>
169
  <li><b>Picks panels</b> are informational and LLM-screened for manipulation/pump patterns; they are <em>not</em> individual buy recommendations. The fund trades a disciplined, risk-controlled subset automatically.</li>
170
  <li><b>Paper only.</b> Slipstream runs on an Alpaca paper account. Nothing here is investment advice.</li>
 
180
  asserts every dataset actually advanced β€” a stale input fails the run loudly instead of silently
181
  trading on old data.</td></tr>
182
  <tr><td><b>Monthly rebalance</b> (1st)</td><td>Trades the freshest weekly signal row through the
183
+ construction rules above (ROA quality gate β†’ AI critical-event screen β†’ 10% name cap alternating with dynamic
184
  sector caps). Idempotent β€” a re-run trades only target-minus-actual.</td></tr>
185
  <tr><td><b>Daily supervisor</b> (weekdays)</td><td>A deterministic health monitor β€” it <em>never
186
  trades</em> β€” checking three things: <b>tracking</b> (trailing 4-week fund-vs-SPY gap; WATCH &lt;βˆ’3pp,
187
  ALERT &lt;βˆ’6pp), <b>guardrails</b> (paper-only invariant, no margin, exposure ≀100.5%, and position
188
+ drift β€” the 10% cap applies <em>at</em> rebalance, so intra-month drift only flags above 13%, alerts
189
+ above 17%), and <b>freshness</b> (signals ≀10 days old, last rebalance ≀35 days). Results appear as
190
  the OK / WATCH / ALERT chips at the top of the Fund tab, and an ALERT fails the scheduled run so it
191
  can't be missed.</td></tr>
192
  </tbody>