From b218ac3a2cdad48c72e81b7190d9e1000c850049 Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Tue, 28 Apr 2026 23:43:40 +0200 Subject: [PATCH] docs: spec design COT report per mcp-macro TFF (gpe5-46if) per equity/financial: ES, NQ, RTY, ZN, ZB, 6E, 6J, DX Disaggregated (72hh-3qpy) per commodities: CL, GC, SI, HG, ZW, ZC, ZS 3 tool MCP: get_cot_tff, get_cot_disaggregated, get_cot_extreme_positioning (scanner percentile 5/95). Pure-logic helper + httpx integration test + ACL. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../specs/2026-04-27-cot-report-design.md | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-27-cot-report-design.md diff --git a/docs/superpowers/specs/2026-04-27-cot-report-design.md b/docs/superpowers/specs/2026-04-27-cot-report-design.md new file mode 100644 index 0000000..f845b55 --- /dev/null +++ b/docs/superpowers/specs/2026-04-27-cot-report-design.md @@ -0,0 +1,204 @@ +# COT Report — design spec (mcp-macro) + +**Data**: 2026-04-27 +**Servizio target**: `mcp-macro` +**Scope**: aggiungere supporto al Commitment of Traders (COT) report +pubblicato dalla CFTC come fonte di posizionamento istituzionale per +opzioni, ETF azionari e materie prime. + +## 1. Motivazione + +Il COT settimanale CFTC è uno dei segnali di posizionamento più seguiti +per futures sotto la giurisdizione USA (equity, bond, valute, energia, +metalli, agricoli). Manca completamente in `mcp-macro`, che oggi copre +solo yields, FRED, calendar, equity futures spot prices. + +L'uso primario nel contesto Cerbero: + +- **Overlay opzioni Deribit**: BTC ha correlazione strutturale con + Nasdaq, e il posizionamento dei *Leveraged Funds* su NQ è un proxy di + rischio sistemico equity. Quando i lev funds sono short estremo + equity, IV upside premium si comprime → squeeze probabile. +- **Segnali ETF**: *Asset Manager net* (TFF) approssima il flow + istituzionale long-only (SPY, QQQ). +- **Materie prime**: *Producer/Merchant* (hedger commerciale) e + *Managed Money* (hedge fund / CTA) sono i veri segnali di top/bottom + per oil, gold, copper, agricoli. + +## 2. Decisione: due report, non uno + +Approccio adottato: + +- **Equity / financial** (S&P, NDX, Russell, treasuries, currencies) → + **TFF** (*Traders in Financial Futures*). +- **Materie prime** (oil, gold, silver, copper, grains) → + **Disaggregated** (futures-only & options combined). +- **Legacy** (non-commercial vs commercial) → **escluso**: report + obsoleto, troppo aggregato, perde la granularità sui 4 ruoli + istituzionali. + +Motivazione: i due report coprono i 13 simboli watchlist con la +massima granularità senza overlap. + +## 3. Sorgenti dati + +API CFTC pubblica (no API key richiesta), endpoint Socrata: +`https://publicreporting.cftc.gov/resource/.json`. + +| Report | Dataset ID | Frequenza | Contenuto | +|--------|-----------|-----------|-----------| +| TFF F&O combined | `gpe5-46if` | settimanale (ven 15:30 ET) | Dealer/Intermediary, Asset Manager, Leveraged Funds, Other Reportables | +| Disaggregated F&O combined | `72hh-3qpy` | settimanale (ven 15:30 ET) | Producer/Merchant, Swap Dealer, Managed Money, Other Reportables | + +Dati osservati al **martedì** della settimana, pubblicati il +**venerdì** seguente alle 15:30 ET. + +## 4. Watchlist simboli + +### TFF +- `ES` (E-mini S&P 500) +- `NQ` (E-mini Nasdaq-100) +- `RTY` (E-mini Russell 2000) +- `ZN` (10-Year T-Note) +- `ZB` (30-Year T-Bond) +- `6E` (Euro FX) +- `6J` (Japanese Yen) +- `DX` (US Dollar Index) + +### Disaggregated +- `CL` (Crude Oil WTI) +- `GC` (Gold) +- `SI` (Silver) +- `HG` (Copper) +- `ZW` (Wheat) +- `ZC` (Corn) +- `ZS` (Soybeans) + +Mapping `ticker → cftc_contract_market_code` mantenuto in costante +nel modulo (es. ES → `13874A`, CL → `067651`). I codici sono pubblici +CFTC e non cambiano. + +## 5. Tool MCP esposti + +Tre tool, tutti `reads` (core + observer): + +### 5.1 `get_cot_tff(symbol, lookback_weeks=52)` +Ritorna serie temporale TFF per un simbolo equity/financial. + +Output: +```json +{ + "symbol": "ES", + "report_type": "tff", + "rows": [ + { + "report_date": "2026-04-22", + "dealer_long": 12345, "dealer_short": 23456, "dealer_net": -11111, + "asset_mgr_long": 654321, "asset_mgr_short": 200000, "asset_mgr_net": 454321, + "lev_funds_long": 100000, "lev_funds_short": 350000, "lev_funds_net": -250000, + "other_long": 50000, "other_short": 50000, "other_net": 0, + "open_interest": 2500000 + }, + ... + ], + "data_timestamp": "2026-04-27T20:00:00Z" +} +``` + +### 5.2 `get_cot_disaggregated(symbol, lookback_weeks=52)` +Stessa shape, campi diversi: `producer_*`, `swap_*`, `managed_money_*`, +`other_*`. + +### 5.3 `get_cot_extreme_positioning(lookback_weeks=156)` +Scanner che restituisce, per ogni simbolo della watchlist, il +percentile storico (1y o 3y) dell'ultimo *net position* per il ruolo +chiave (Leveraged Funds per TFF, Managed Money per Disaggregated). +Flagga estremi a percentili ≤ 5 o ≥ 95. + +Output: +```json +{ + "lookback_weeks": 156, + "extremes": [ + { + "symbol": "ES", "report_type": "tff", + "key_role": "lev_funds", + "current_net": -250000, + "percentile": 3.2, + "signal": "extreme_short", + "report_date": "2026-04-22" + }, + ... + ], + "data_timestamp": "2026-04-27T20:00:00Z" +} +``` + +`signal` ∈ `{"extreme_short", "extreme_long", "neutral"}`. + +## 6. Architettura + +``` +mcp-macro/ + src/mcp_macro/ + fetchers.py # esistente — aggiunge fetch_cot_tff, fetch_cot_disaggregated, fetch_cot_extreme_positioning + cot_contracts.py # NUOVO — costanti SYMBOL_TO_CFTC_CODE, CFTC_FIELD_MAPPINGS + server.py # esistente — aggiunge 3 endpoint + body models + tests/ + test_cot.py # NUOVO — pure-logic test su parsing + percentile + extreme detection + test_fetchers.py # esistente — aggiunge integration test con httpx_mock +``` + +Logica pura (calcolo percentile, classificazione extreme) in `fetchers` +testata indipendentemente dal layer HTTP. I fetcher async usano +`mcp_common.http.async_client` (retry transport già in place). + +## 7. Cache + +- Chiamata Socrata risponde tipicamente in 200-800ms. +- COT esce settimanalmente venerdì sera ET → cache TTL 1 ora è + eccessiva ma sicura. Riusa il pattern `_TREASURY_CACHE` esistente in + `fetchers.py` (chiave `(symbol, report_type, lookback_weeks)`). + +## 8. Edge cases + +- **Pre-pubblicazione (es. mercoledì)**: ultimo report è quello della + settimana precedente. Niente da gestire — l'API ritorna l'ultimo + disponibile. +- **Simbolo fuori watchlist**: `get_cot_tff("INVALID")` → 400 con + payload `{"error": "unknown_symbol", "available": [...]}`. +- **API CFTC down**: retry transport gestisce transient. Su 5xx + persistente: ritorna `{"rows": [], "error": "cftc_unavailable"}`. +- **Lookback troppo corto** (< 4 settimane) → percentile inattendibile + in extreme positioning. Validation Pydantic: `lookback_weeks ≥ 4`. + +## 9. Test plan + +Pure-logic (no HTTP): +- `compute_percentile(value, history)` con casi noti. +- `classify_extreme(percentile, threshold=5)` → boundary cases. +- `parse_tff_row()` e `parse_disaggregated_row()` su payload Socrata + mock (campi reali documentati). + +Integration (httpx_mock): +- `fetch_cot_tff("ES", lookback_weeks=52)` con risposta CFTC mock → + verifica shape output + ordering rows ASC per data. +- `fetch_cot_extreme_positioning()` con dati che includono casi + extreme + casi neutral → verifica filtering e signal. + +ACL test (TestClient): +- `POST /tools/get_cot_tff` con core/observer/no-auth → 200/200/401. +- `POST /tools/get_cot_extreme_positioning` idem. + +## 10. Out of scope (versione 1) + +- **Storico oltre 3 anni**: l'API CFTC ha tutto da 2010, ma `lookback` + default 52w (= 1 anno) e max ragionevole 156w. Storico decennale può + essere aggiunto in v2 se serve per backtest. +- **Disaggregated futures-only** (dataset diverso da F&O combined): + meno usato, skip. +- **Notification al rilascio settimanale**: il bot deve schedulare a + venerdì 16:00 ET; non è responsabilità del MCP server. +- **Legacy report**: escluso (vedi §2). +- **Aggregazione cross-symbol** (es. "tutti i metalli combinati"): + l'utente compone via tool individuali.