feat(mcp-macro): fetch_cot_disaggregated async fetcher with cache
This commit is contained in:
@@ -664,3 +664,43 @@ async def fetch_cot_tff(symbol: str, lookback_weeks: int = 52) -> dict[str, Any]
|
||||
_COT_CACHE[key] = out
|
||||
_COT_CACHE_TS[key] = now
|
||||
return out
|
||||
|
||||
|
||||
async def fetch_cot_disaggregated(symbol: str, lookback_weeks: int = 52) -> dict[str, Any]:
|
||||
"""Fetch COT Disaggregated report per simbolo commodity. Returns ASC by date."""
|
||||
import time
|
||||
|
||||
symbol = symbol.upper()
|
||||
if symbol not in SYMBOL_TO_CFTC_CODE_DISAGG:
|
||||
return {"error": "unknown_symbol", "available": ALL_DISAGG_SYMBOLS}
|
||||
|
||||
key = (symbol, "disaggregated", lookback_weeks)
|
||||
now = time.monotonic()
|
||||
if key in _COT_CACHE and (now - _COT_CACHE_TS[key]) < _COT_TTL:
|
||||
return _COT_CACHE[key]
|
||||
|
||||
code = SYMBOL_TO_CFTC_CODE_DISAGG[symbol]
|
||||
url = f"{CFTC_BASE_URL}/{DISAGG_DATASET_ID}.json"
|
||||
async with async_client(timeout=10.0) as client:
|
||||
resp = await client.get(
|
||||
url,
|
||||
params={
|
||||
"cftc_contract_market_code": code,
|
||||
"$order": "report_date_as_yyyy_mm_dd DESC",
|
||||
"$limit": str(lookback_weeks),
|
||||
},
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
return {"symbol": symbol, "report_type": "disaggregated", "rows": [], "error": "cftc_unavailable"}
|
||||
raw_rows = resp.json() or []
|
||||
parsed = [parse_disagg_row(r) for r in raw_rows]
|
||||
parsed.sort(key=lambda r: r["report_date"])
|
||||
out = {
|
||||
"symbol": symbol,
|
||||
"report_type": "disaggregated",
|
||||
"rows": parsed,
|
||||
"data_timestamp": datetime.now(UTC).isoformat(),
|
||||
}
|
||||
_COT_CACHE[key] = out
|
||||
_COT_CACHE_TS[key] = now
|
||||
return out
|
||||
|
||||
Reference in New Issue
Block a user