From 02a769f513222339b89c2f7f2306c08786c3e082 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 2 Mar 2026 04:22:12 +0000 Subject: [PATCH] fix: FR collector use premiumIndex API for real-time 5min data - Changed from /fapi/v1/fundingRate (8h settlement only) to /fapi/v1/premiumIndex (real-time) - Each 5-min poll now stores a new row with current timestamp - Payload includes both fundingRate and lastFundingRate for compat - Fixes: FR data was only 6 rows per 4 days, now ~288/day per coin --- backend/market_data_collector.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/backend/market_data_collector.py b/backend/market_data_collector.py index d808cd7..33a3a43 100644 --- a/backend/market_data_collector.py +++ b/backend/market_data_collector.py @@ -136,13 +136,25 @@ class MarketDataCollector: self.save_indicator(symbol, "coinbase_premium", ts, payload) async def collect_funding_rate(self, session: aiohttp.ClientSession, symbol: str) -> None: - endpoint = "https://fapi.binance.com/fapi/v1/fundingRate" - data = await self.fetch_json(session, endpoint, {"symbol": symbol, "limit": 1}) + endpoint = "https://fapi.binance.com/fapi/v1/premiumIndex" + data = await self.fetch_json(session, endpoint, {"symbol": symbol}) if not data: raise RuntimeError("empty response") - item = data[0] - ts = int(item.get("fundingTime") or int(time.time() * 1000)) - self.save_indicator(symbol, "funding_rate", ts, item) + # premiumIndex returns a single object (not array) + item = data if isinstance(data, dict) else data[0] + # Use current time as timestamp so every 5-min poll stores a new row + ts = int(time.time() * 1000) + payload = { + "symbol": item.get("symbol"), + "markPrice": item.get("markPrice"), + "indexPrice": item.get("indexPrice"), + "lastFundingRate": item.get("lastFundingRate"), + "nextFundingTime": item.get("nextFundingTime"), + "interestRate": item.get("interestRate"), + "fundingRate": item.get("lastFundingRate"), # compat: signal_engine reads 'fundingRate' + "time": ts, + } + self.save_indicator(symbol, "funding_rate", ts, payload) async def collect_symbol(self, session: aiohttp.ClientSession, symbol: str) -> None: tasks = [