""" fetchers/derivatives.py — Fetches derivatives data from data_provider API. Clean consumer: no direct ccxt dependency. Just HTTP GET /api/derivatives. """ from datetime import date as Date from typing import Optional import requests from .base import BaseFetcher from config import config class DerivativesFetcher(BaseFetcher): """Fetches derivatives snapshot from data_provider /api/derivatives.""" def __init__(self, provider_url: Optional[str] = None): super().__init__(timeout=15, max_retries=3) self.provider_url = provider_url or config.provider_url def fetch(self, target_date: Optional[Date] = None) -> list[dict]: """Fetch derivatives data. Returns list with one record dict.""" url = f"{self.provider_url}/api/derivatives" params = {"symbol": config.btc_symbol} try: data = self._get(url, params=params) record = { "date": str(target_date or Date.today()), "symbol": config.btc_symbol, "funding_rate": data.get("funding_rate"), "open_interest": data.get("open_interest"), "oi_24h_change_pct": data.get("oi_change_pct"), "basis_annualised_pct": data.get("basis"), "source": "data_provider", } return [record] except Exception: return [] def store(self, db_path: Optional[str] = None, records: Optional[list[dict]] = None) -> int: """Store derivatives records into SQLite.""" import sqlite3 db_path = db_path or config.db_path records = records or [] conn = sqlite3.connect(db_path) count = 0 for r in records: try: conn.execute(""" INSERT OR REPLACE INTO derivatives (date, symbol, funding_rate, open_interest, oi_24h_change_pct, long_liquidations, short_liquidations, basis_annualised_pct) VALUES (?, ?, ?, ?, ?, NULL, NULL, ?) """, ( r["date"], r.get("symbol", config.btc_symbol), r.get("funding_rate"), r.get("open_interest"), r.get("oi_24h_change_pct"), r.get("basis_annualised_pct"), )) count += 1 except Exception: continue conn.commit() conn.close() return count