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>
50 lines
1.5 KiB
Python
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()
|