feat: institutional reports — CFTC COT + EIA petroleum weekly

- New institutional_reports table (DB) with importance, signals per asset class, key points, absorption tracking
- cot_fetcher.py: CFTC Socrata API (6dca-aqww), 7 instruments (Gold/Silver/Copper/WTI/NatGas/SP500/EURUSD), net positioning + 52-week z-score
- eia_fetcher.py: EIA API v2, 4 series (crude/Cushing/gasoline/distillates), WoW surprise detection
- institutional.py router: GET /reports, GET /reports/{id}, POST /refresh, GET /stats
- institutional_scheduler.py: weekly auto-fetch (COT Saturdays, EIA Wednesday afternoons)
- ai_analyzer.py: build_institutional_block() + institutional_block param injected into AI scoring prompt
- auto_cycle.py: inject institutional block into suggestion + scoring, absorption tracking via keyword overlap after each cycle commentary
- InstitutionalReports.tsx: full page with filter bar (type/category/importance/period), cards with key point bullets, EXTREME alerts highlighted, signal badges, absorption badge, trading implications, expandable detail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 13:45:07 +02:00
parent 4423ad91db
commit 3edbd6b0b7
12 changed files with 1228 additions and 2 deletions

View File

@@ -914,3 +914,32 @@ export const useRemoveWatchlistTicker = () =>
useMutation({
mutationFn: (ticker: string) => api.delete(`/options-vol/watchlist-tickers/${encodeURIComponent(ticker)}`).then(r => r.data),
})
// ── Institutional Reports ─────────────────────────────────────────────────────
export const useInstitutionalReports = (params: {
report_type?: string
category?: string
importance?: number
days?: number
}) =>
useQuery({
queryKey: ['institutional-reports', params],
queryFn: () =>
api.get('/institutional/reports', { params }).then(r => r.data),
refetchInterval: 3_600_000,
})
export const useInstitutionalStats = () =>
useQuery({
queryKey: ['institutional-stats'],
queryFn: () => api.get('/institutional/stats').then(r => r.data),
staleTime: 300_000,
})
export const useRefreshInstitutionalReports = () =>
useMutation({
mutationFn: (report_type?: string) =>
api.post('/institutional/refresh', null, { params: report_type ? { report_type } : {} }).then(r => r.data),
})