Files
foxhunt/scripts/surfer/fetch_earnings.py
jgrusewski 9bf67e731d research: AI4Finance debunked + PEAD dies OOS (efficient-market wall confirmed again)
3 omnisearch researchers + clean PEAD test answer 'why does AI4Finance find what we cant':
they dont. FinRL flagship (Sharpe 1.30) = single-split, slippage-free, no-deflation, bull-market,
survivorship, hand-coded crash rule; their own people (Gort/Liu AAAI'23) published the overfitting
rebuttal; zero live track record. ML-trading decays 73%+ backtest->live, faster for complexity.
PEAD tested properly (real Nasdaq surprises x DBEQ, leak-free, 23bp cost, OOS): full-sample looked
good (20d +0.29% t=2.9) but pure in-sample bull-beta -> OOS NEGATIVE every horizon; surprise-size
signature fails. Strongest classic anomaly dies OOS. Untested real pulse left: prediction markets
(uncorrelated). Tooling: fetch_earnings.py, pead_real.py, dbeq_symbology resolved (17605 tickers).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 17:15:22 +02:00

50 lines
1.5 KiB
Python

#!/usr/bin/env python3
"""Fetch Nasdaq earnings calendar (date + symbol + surprise%) for all weekdays in the DBEQ range,
for a proper PEAD test. Free, no key. Cached per date; gentle pacing + backoff.
"""
import datetime
import json
import os
import time
import urllib.request
OUT = "data/surfer/earnings"
START = datetime.date(2023, 3, 28)
END = datetime.date(2026, 5, 31)
def get(u):
for a in range(4):
try:
req = urllib.request.Request(u, headers={"User-Agent": "Mozilla/5.0", "Accept": "application/json"})
return json.loads(urllib.request.urlopen(req, timeout=25).read())
except Exception:
if a == 3:
return None
time.sleep(4 * (a + 1))
return None
def main():
os.makedirs(OUT, exist_ok=True)
d = START
n = fail = 0
while d <= END:
if d.weekday() < 5:
f = f"{OUT}/{d}.json"
if not os.path.exists(f):
r = get(f"https://api.nasdaq.com/api/calendar/earnings?date={d}")
if r is None:
fail += 1
else:
rows = (r.get("data") or {}).get("rows") or []
json.dump([(x.get("symbol"), x.get("surprise")) for x in rows], open(f, "w"))
n += 1
time.sleep(1.3)
d += datetime.timedelta(days=1)
print(f"DONE: fetched {n} new days, {fail} failed; cache dir {OUT}")
if __name__ == "__main__":
main()