from datetime import datetime, timezone from pathlib import Path from typing import Any, Dict import sys import time from fastapi import APIRouter PROJECT_ROOT = Path(__file__).resolve().parents[1] if str(PROJECT_ROOT) not in sys.path: sys.path.append(str(PROJECT_ROOT)) from indian_paper_trading_strategy.engine.data import fetch_live_price, get_price_snapshot NIFTY = "NIFTYBEES.NS" GOLD = "GOLDBEES.NS" router = APIRouter(prefix="/api/market", tags=["market"]) _LTP_CACHE: Dict[str, Any] = { "ts_epoch": 0.0, "data": None, } CACHE_TTL_SECONDS = 5 STALE_SECONDS = 60 @router.get("/ltp") def get_ltp(allow_cache: bool = False): now_epoch = time.time() cached = _LTP_CACHE["data"] if cached is not None and (now_epoch - _LTP_CACHE["ts_epoch"]) < CACHE_TTL_SECONDS: return cached nifty_ltp = None gold_ltp = None try: nifty_ltp = fetch_live_price(NIFTY) except Exception: nifty_ltp = None try: gold_ltp = fetch_live_price(GOLD) except Exception: gold_ltp = None nifty_meta = get_price_snapshot(NIFTY) or {} gold_meta = get_price_snapshot(GOLD) or {} now = datetime.now(timezone.utc) def _is_stale(meta: Dict[str, Any], ltp: float | None) -> bool: if ltp is None: return True source = meta.get("source") ts = meta.get("ts") if source != "live": return True if isinstance(ts, datetime): return (now - ts).total_seconds() > STALE_SECONDS return False nifty_source = str(nifty_meta.get("source") or "").lower() gold_source = str(gold_meta.get("source") or "").lower() stale_map = { NIFTY: _is_stale(nifty_meta, nifty_ltp), GOLD: _is_stale(gold_meta, gold_ltp), } stale_any = stale_map[NIFTY] or stale_map[GOLD] if allow_cache and stale_any: cache_sources = {"cache", "cached", "history"} if nifty_source in cache_sources and gold_source in cache_sources: stale_map = {NIFTY: False, GOLD: False} stale_any = False payload = { "ts": now.isoformat(), "ltp": { NIFTY: float(nifty_ltp) if nifty_ltp is not None else None, GOLD: float(gold_ltp) if gold_ltp is not None else None, }, "source": { NIFTY: nifty_meta.get("source"), GOLD: gold_meta.get("source"), }, "stale": stale_map, "stale_any": stale_any, } _LTP_CACHE["ts_epoch"] = now_epoch _LTP_CACHE["data"] = payload return payload