feat: Trading Economics API for upcoming events with forecasts
- New services/te_calendar.py: fetch_upcoming(weeks_ahead) calls TE API for 9 countries (USD/EUR/GBP/JPY/AUD/CAD/NZD/CHF/CNY), converts to ff_calendar format, upserts with source='te_api' - New endpoints: GET/POST /api/eco/te-key, POST /api/eco/te-sync, GET /api/eco/te-sync/status - Daily scheduler in main.py: FF live sync + TE sync (if key configured) run 60s after startup then every 24h - CalendarPage: TEPanel with key input (password field, Enter to save, "Get free key" link to tradingeconomics.com/api/login), "Sync upcoming (6 weeks)" button with polling FF HTML scraper kept as fallback but TE API is the primary source for upcoming forecasts (no Cloudflare blocking on server IPs). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,21 +95,33 @@ def startup():
|
||||
from services.institutional_scheduler import start_institutional_scheduler
|
||||
start_institutional_scheduler()
|
||||
|
||||
# Daily FF scraper — runs once at startup, then every 24h
|
||||
# Daily calendars sync — FF live (this week) + TE upcoming (if key configured)
|
||||
import threading, time as _time
|
||||
def _ff_scrape_loop():
|
||||
_time.sleep(30) # let server fully boot first
|
||||
def _daily_calendar_sync():
|
||||
_time.sleep(60) # let server fully boot first
|
||||
while True:
|
||||
try:
|
||||
print("[Startup] FF scrape upcoming weeks …", flush=True)
|
||||
from services.ff_calendar import scrape_upcoming
|
||||
result = scrape_upcoming(weeks_ahead=5)
|
||||
print(f"[FF scrape] done: {result.get('total_upserted', 0)} upserted", flush=True)
|
||||
# FF live JSON — this week actuals
|
||||
from services.ff_calendar import sync_live
|
||||
r = sync_live()
|
||||
print(f"[Daily] FF live sync: {r}", flush=True)
|
||||
except Exception as e:
|
||||
print(f"[FF scrape] loop error: {e}", flush=True)
|
||||
_time.sleep(86400) # 24h
|
||||
print(f"[Daily] FF live sync error: {e}", flush=True)
|
||||
|
||||
threading.Thread(target=_ff_scrape_loop, daemon=True).start()
|
||||
try:
|
||||
# Trading Economics — upcoming forecasts (only if key is set)
|
||||
from services.database import get_config
|
||||
te_key = get_config("te_api_key") or ""
|
||||
if te_key:
|
||||
from services.te_calendar import fetch_upcoming
|
||||
r = fetch_upcoming(weeks_ahead=6)
|
||||
print(f"[Daily] TE sync: {r.get('total_upserted', 0)} upserted", flush=True)
|
||||
except Exception as e:
|
||||
print(f"[Daily] TE sync error: {e}", flush=True)
|
||||
|
||||
_time.sleep(86400) # repeat every 24h
|
||||
|
||||
threading.Thread(target=_daily_calendar_sync, daemon=True).start()
|
||||
|
||||
# Auto-import Forex Factory CSV if file is present (force, then delete CSV)
|
||||
import threading
|
||||
|
||||
Reference in New Issue
Block a user