---
type: calendar-recommendations
status: proposal
created: 2026-06-15
updated: 2026-06-15
audience: Dennis
phase: pre-build
---

# Calendar Recommendations

> PA-dealing clearance is in. Calendar build deferred. This doc captures the architecture, source mapping, and cost analysis so the work is ready to start whenever you want it.

## TL;DR

**Recommended stack: $0-49/month.** Run a single Python script on the Pi/NAS that pulls from FRED (free, authoritative for US), RSS feeds (free, authoritative for refunding + central banks), and a small hand-maintained `events.yaml` for the deterministic Tier 1 schedule. Add Trading Economics ($49/mo personal tier) only when you find yourself manually filling gaps for SNB/BoJ/China.

The mechanism: one ICS export → Google Calendar (cross-device sync + native notifications) → Telegram reminders for the 1h-before and 24h-before windows.

## What the PDF requires us to track

From [[../00-methodology/process#3. Data and event coverage]]:

**Tier 1 (always previewed + reviewed):**
FOMC, US CPI, NFP, ECB, SNB, BoJ.

**Tier 2 (commented in weekly note):**
ISM/PMIs, retail sales, PCE, Eurozone HICP, China credit/PMI, refunding announcements.

**Weekly structural data:**
CFTC COT (Friday release), CTA positioning estimates, ETF flows for gold.

## Source-by-source mapping

| Event | Primary source | Secondary | Cost | Reliability |
|---|---|---|---|---|
| FOMC | Federal Reserve press release RSS + FOMC meeting calendar (PDF published Dec) | Treasury yield curve | $0 | Authoritative, 12-month forward schedule |
| US CPI | FRED API (series `CPIAUCSL`) release calendar | BLS API | $0 | Authoritative, schedule published ~1yr ahead |
| NFP | BLS release calendar | FRED `PAYEMS` | $0 | Authoritative, schedule published ~1yr ahead |
| ECB rate | ECB RSS + SDMX API | Trading Economics | $0 | Authoritative, schedule published years ahead |
| Eurozone HICP | ECB SDMX | Eurostat | $0 | Authoritative |
| SNB rate | SNB press release RSS | Trading Economics | $0 | Authoritative, schedule known ~quarter ahead |
| SNB data | SNB data portal | Trading Economics | $0 | Authoritative |
| BoJ rate | BoJ statistical RSS | Trading Economics | $0 | Authoritative |
| ISM/PMI | S&P Global (paid) | Trading Economics API | $0 (via TE) | TE is the de-facto free source |
| Retail sales | FRED `RSAFS` | Census Bureau | $0 | Authoritative |
| PCE | FRED `PCEPI` | BEA | $0 | Authoritative |
| China credit/PMI | NBS China | Trading Economics | $0 (via TE) | TE best for schedule |
| Refunding | Treasury Direct RSS | Treasury auction calendar | $0 | Authoritative |
| CFTC COT | CFTC RSS (Friday) | Quandl (paid) | $0 | Authoritative, deterministic Friday |
| CTA positioning | Derived from price data (no calendar) | — | $0 | n/a — compute not fetch |
| Gold ETF flows | SPDR GLD daily NAV | World Gold Council | $0 | Daily, automated |
| Refunding | Treasury Direct RSS | — | $0 | Authoritative |

**Coverage verdict:** All Tier 1 and Tier 2 events have a free authoritative source. The exceptions where free sources are awkward:
- **ISM/PMI** — S&P Global owns the data and charges; Trading Economics is the de-facto free relay
- **SNB and BoJ** — official RSS exists but is sparse on forward schedules; TE fills the gap
- **China credit/PMI** — NBS site is bureaucratic; TE is much cleaner

## Architecture (recommended)

```
┌─────────────────────────────────────────────────────────────────┐
│  Pi / NAS (cron)                                                │
│                                                                 │
│  scripts/calendar_sync.py                                       │
│  ├─ reads 07-calendar/events.yaml (hand-maintained Tier 1 dates)│
│  ├─ pulls FRED release calendar (US indicators)                 │
│  ├─ polls central bank RSS (ECB, SNB, BoJ)                      │
│  ├─ polls CFTC RSS, Treasury Direct RSS                        │
│  ├─ (optional) polls Trading Economics API for SNB/BoJ/China    │
│  └─ generates 07-calendar/macro-book.ics                       │
│                                                                 │
│  Cron: daily 06:00 Europe/Zurich — refresh next 90 days         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
            │
            ▼
┌─────────────────────────────────────────────────────────────────┐
│  Google Calendar (free, cross-device sync, native notifications)│
│                                                                 │
│  Macro Calendar (subscribed via ics URL or API push)            │
│  ├─ Tier 1: T-7d, T-24h, T-1h reminders                        │
│  ├─ Tier 2: T-24h reminder                                      │
│  └─ Structural: morning-of reminder                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
            │
            ▼
┌─────────────────────────────────────────────────────────────────┐
│  Telegram (already wired)                                       │
│                                                                 │
│  scripts/calendar_sync.py also sends Telegram messages:        │
│  ├─ T-24h: "FOMC tomorrow 14:00 ET. Preview doc ready?"        │
│  └─ T-1h: "FOMC in 1h. Consensus + your skew in 03-research/.." │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

### Why Google Calendar as the sync target

- Cross-device (iOS, Android, web, Mac) — fits the "sync across devices" requirement
- Native notifications (no extra infra)
- Free
- Subscribable via public ICS URL (zero auth for read-side) OR push via Google Calendar API (OAuth, one-time setup)
- iCloud and Outlook work too but Google is the most reliable free CalDAV target

### Why one Python script, not multiple

A single source of truth (the script) means one cron, one failure mode, one place to add a new event type. The alternatives — three separate integrations, one per source — are over-engineered for the volume here (~30-50 events/quarter, of which maybe 20-25 are Tier 1).

### Why not a SaaS (Google Calendar add-on, Zapier, etc.)

- Adds monthly cost for something that runs on existing infrastructure
- The PDF ethos: "cheap, standard, layered" — running a cron is cheaper than any SaaS at this volume
- Your Pi + NAS are already running scripts; this fits naturally

## Cost

| Layer | Cost | Notes |
|---|---|---|
| FRED API | $0 | Free for individuals, 120 req/min |
| BLS API | $0 | Free, 25 req/day unregistered, 500/day registered |
| RSS feeds (FOMC, ECB, SNB, BoJ, CFTC, Treasury) | $0 | Public |
| Google Calendar | $0 | Free tier is unlimited calendars |
| Telegram | $0 | Bot API free |
| **Sub-total without Trading Economics** | **$0/month** | Covers ~85% of the need |
| Trading Economics API (personal tier) | ~$49/month | For SNB/BoJ/China + consensus surprise data |
| **Total with Trading Economics** | **~$49/month** | Covers 100% |
| Polygon.io (Developer tier) | $79/month | NOT recommended for calendar — equities/options focused |
| Finnhub (Economic-1 tier) | $50/month | Alternative to TE, comparable coverage, more developer-friendly |
| Bloomberg / Refinitiv | $5k+/year | Out of scope — institutional pricing |

**Paid verdict:** Trading Economics is the only paid service worth considering. $49/month buys you:
- 196 countries
- Real-time calendar with consensus, previous, forecast, actual
- Webhook subscriptions
- Point-in-time historical (so you can see what was on the calendar at any past moment — useful for "what did I know when" backtests)
- iCal export

**Worth it when:** you find yourself hand-filling SNB/BoJ/China dates more than once a quarter. **Not worth it** if you're happy to maintain a small `events.yaml` for those events (the schedule is published ~6 months ahead and changes rarely).

## Why not these alternatives

### MCP scraping (Apify `rag-web-browser`)

We have the tool. It's not the right fit here:
- ForexFactory / Investing.com / MQL5 economic calendars are scrapable but change their HTML frequently
- No SLA — page structure changes break the script
- No historical calendar data
- Per-call cost (Apify charges per run)
- **Use it for one-off enrichment, not the calendar backbone**

### Web search polling

- Same brittleness as scraping
- Latency: by the time you scrape, the event is already in the news
- No consensus / forecast data
- **Don't use for the calendar; use for research queries**

### Pre-built ICS subscriptions

- ForexFactory and some sites offer free ICS — fine as a fallback, but:
  - Time zone handling is inconsistent
  - No per-event metadata (consensus, importance)
  - Often only Tier 1, not Tier 2
  - **Use as backup if the script is down, not as primary**

### Finnhub economic calendar API ($50/mo)

- Comparable to Trading Economics on coverage
- More developer-friendly (cleaner API, free WebSocket)
- Less international coverage (60 countries vs TE's 196)
- **Reasonable alternative if you already have a Finnhub account**

## Open design questions (to answer when you pick this up)

1. **Calendar backend** — Google Calendar (recommended), iCloud, Outlook, or Telegram-only?
2. **Tier 1 event dates** — hand-maintained `events.yaml` (recommended, full control), or pull from FRED/TE API (less control, depends on the feed)?
3. **Trading Economics** — sign up day 1, or wait until you hit a gap?
4. **Reminder windows** — defaults above (T-7d/T-24h/T-1h for Tier 1) work for you, or different?
5. **Vault integration** — install Obsidian Calendar plugin and subscribe to the same ICS? Or keep the vault and the calendar as separate views?

## Implementation effort estimate

| Task | Time | Blocker |
|---|---|---|
| `events.yaml` schema + first 6 months of Tier 1 dates | 2h | none |
| `scripts/calendar_sync.py` skeleton + FRED pull | 3h | none |
| RSS polling (4 feeds) + ICS generation | 3h | none |
| Cron setup on Pi/NAS | 30min | none |
| Google Calendar OAuth + push | 2h | Google Cloud project |
| Telegram reminder messages | 1h | bot already wired |
| Obsidian Calendar plugin config | 30min | Obsidian install |
| Trading Economics integration (optional) | 2h | TE API key |
| **Total without TE** | **~12h** | |
| **Total with TE** | **~14h** | |

That's a long weekend. Achievable in one focused session.

## What I'll build when you say go

(I'll ask the open design questions first; assume the defaults in this doc unless you say otherwise.)

1. `07-calendar/events.yaml` — schema + Tier 1 dates for the next 12 months
2. `scripts/calendar_sync.py` — pulls FRED + RSS, generates ICS
3. Cron entry on the Pi (06:00 Europe/Zurich daily)
4. Google Calendar subscription (via ICS URL — zero auth, simplest)
5. Telegram reminder job (T-24h + T-1h for Tier 1)
6. Obsidian Calendar plugin + .ics subscription
7. `07-calendar/MAINTENANCE.md` — how to add a new event type, troubleshoot failures, update YAML

## Related

- [[README#Gates]] — PA-dealing clearance is now ✓; this doc lifts the calendar-track gate
- [[../TODO#H. Calendar (phase 2)]] — task list
- [[../00-methodology/process#3. Data and event coverage]] — source spec
