SPB Git

Repository Public Research preview

events.py 3.4 KB 52 lines python

1"""Scheduled announcement calendar: FOMC statements (with release-time rule), CPI and Employment Situation (08:30 ET)."""2from __future__ import annotations3import json4from pathlib import Path5import pandas as pd6ET = "America/New_York"78def fomc_statement_time(d: pd.Timestamp, press_conf_dates: set[str]) -> str:9    """Release-time rule (ET): 14:15 before April 2011; April 2011–Dec 2012: 12:30 on press-conference days, 14:15 otherwise;10    from January 2013: 14:00. Unscheduled statements use recorded times (see UNSCHEDULED)."""11    if d < pd.Timestamp("2011-04-01"): return "14:15"12    if d < pd.Timestamp("2013-01-01"): return "12:30" if d.strftime("%Y-%m-%d") in press_conf_dates else "14:15"13    return "14:00"1415# Press-conference meetings 2011–2012 (statement at 12:30 ET): April, June, November 2011; January, April, June, September, December 201216PRESS_CONF_2011_2012 = {"2011-04-27", "2011-06-22", "2011-11-02", "2012-01-25", "2012-04-25", "2012-06-20", "2012-09-13", "2012-12-12"}17# Unscheduled policy statements in sample with approximate release time (ET), from the Fed press releases18UNSCHEDULED = {"2008-01-22": "08:20", "2008-10-08": "07:00", "2020-03-03": "10:00", "2020-03-15": "17:00"}19# Extra scheduled meeting end-dates missing from the minutes-link parse20EXTRA_SCHEDULED = {"2008-06-25", "2026-10-28"}21NON_POLICY_STATEMENTS = {"20080311", "20100509", "20191011", "20200319", "20200323", "20200331", "20200827", "20250822"}2223def load_fomc(ext: Path) -> pd.DataFrame:24    d = json.load(open(ext / "fomc/fomc_dates_parsed.json"))25    sched = sorted(set(d["meeting_end_dates"]) | {x.replace("-", "") for x in EXTRA_SCHEDULED})26    unsched_keys = {k.replace("-", "") for k in UNSCHEDULED}27    rows = [{"date": pd.Timestamp(s), "type": "FOMC", "scheduled": True} for s in sched if s >= "20080101" and s not in unsched_keys]28    rows += [{"date": pd.Timestamp(s), "type": "FOMC", "scheduled": False} for s in UNSCHEDULED]29    df = pd.DataFrame(rows).sort_values("date").reset_index(drop=True)30    df["time"] = [UNSCHEDULED.get(d.strftime("%Y-%m-%d")) or fomc_statement_time(d, PRESS_CONF_2011_2012) for d in df.date]31    return df3233def load_bls(ext: Path) -> pd.DataFrame:34    rows = []35    for fn, typ in (("bls/cpi_release_dates_alfred_rid10.txt", "CPI"), ("bls/empsit_release_dates_alfred_rid50.txt", "EMP")):36        ds = [l.strip() for l in open(ext / fn) if l.strip() and not l.startswith("#")]37        s = pd.Series(pd.to_datetime(ds)).sort_values()38        # keep one release per calendar month: the later one is the regular release when two occur (earlier = revision), except39        # known benchmark/revision extras which are the later date (2024-08-21, 2024-01-10, 2013-05-06, 2012-12-12, 2020-05-11).40        drop = {"2024-08-21", "2024-01-10", "2013-05-06", "2012-12-12", "2020-05-11", "2006-05-08", "2003-10-10", "2002-12-09"}41        s = s[~s.dt.strftime("%Y-%m-%d").isin(drop)]42        g = s.groupby(s.dt.to_period("M"))43        keep = g.max() if typ == "CPI" else g.min()44        rows += [{"date": d, "type": typ, "scheduled": True, "time": "08:30"} for d in keep]45    return pd.DataFrame(rows)4647def load_events(ext: Path, start="2008-01-01") -> pd.DataFrame:48    ev = pd.concat([load_fomc(ext), load_bls(ext)], ignore_index=True)49    ev = ev[ev.date >= start].sort_values(["date", "type"]).reset_index(drop=True)50    ev["ts"] = pd.to_datetime(ev.date.dt.strftime("%Y-%m-%d") + " " + ev.time).dt.tz_localize(ET)51    return ev52
Files main
Menu

Theme