research: commit the 2026-10-07/08 studies left in the working tree, overnight mid/small (STOP)

Studies run by earlier sessions and documented in CLAUDE.md, but never
committed: FINRA short volume (SVR) and the research-only svr_momentum veto,
SEC fails-to-deliver, 13D activists and the 13D event sleeve, 13F
institutional flow, GDELT news volume, S&P 400/600 Form 4 insiders,
union_shield, shield_lab; plus the mid/small insider and Tiingo fetcher
changes and midsmall_rebuild.

overnight_midsmall: the overnight-only momentum book on S&P 400/600 earns
0.93 net Sharpe at 3 bp a side (2019-26) with corr 0.83 to the S&P 500 book
(STOP).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 22:20:43 -07:00
parent 36cb125719
commit 04e2c5c3be
21 changed files with 2543 additions and 45 deletions

View File

@@ -5,8 +5,10 @@ Used for: (1) completing delisted/missing names in the research panels,
from TIINGO_API_KEY (environment or .env) and is never logged or written.
Writes data/research/tiingo/<ticker>.csv (resume-safe; a cached symbol never
counts against the monthly quota again). Columns: as-traded open/high/low/
close/volume (Tiingo's close is NOT split-adjusted), split/dividend-adjusted
counts against the monthly quota again) and <ticker>.miss for symbols Tiingo
does not serve (also skipped on later runs, so dead names do not re-burn the
500-symbol monthly quota). Columns: as-traded open/high/low/close/volume
(Tiingo's close is NOT split-adjusted), split/dividend-adjusted
adjOpen..adjVolume, plus splitFactor and divCash.
PYTHONPATH=. uv run python -m research.lab.fetch_tiingo TICKER [TICKER ...]
@@ -91,7 +93,8 @@ def main() -> None:
os.makedirs(DIR, exist_ok=True)
key = api_key()
todo = [t for t in tickers if not os.path.exists(os.path.join(DIR, f"{t.upper()}.csv"))]
todo = [t for t in tickers if not os.path.exists(os.path.join(DIR, f"{t.upper()}.csv"))
and not os.path.exists(os.path.join(DIR, f"{t.upper()}.miss"))]
print(f"{len(tickers)} tickers, {len(todo)} to fetch", flush=True)
fetched = failed = 0
last = 0.0
@@ -107,6 +110,8 @@ def main() -> None:
continue
if df is None:
failed += 1
with open(os.path.join(DIR, f"{t.upper()}.miss"), "w") as fh:
fh.write("404\n")
print(f"[{i + 1}/{len(todo)}] {t:8s} not found", flush=True)
continue
df.to_csv(os.path.join(DIR, f"{t.upper()}.csv"))