""" fetcher.py - 从 data_provider HTTP API 拉取 K 线数据。 """ from typing import List, Optional import requests import pandas as pd import logging logger = logging.getLogger(__name__) PROVIDER_URL = "http://103.179.242.166" PROVIDER_URL = "http://127.0.0.1" FETCH_LIMIT = 1000 _symbols_cache: Optional[List[str]] = None # 只推送 BTC,其他币对暂不监控 _SYMBOL_WHITELIST = {"BTC/USDT:USDT", "ETH/USDT:USDT", "SOL/USDT:USDT"} def get_symbols() -> list[str]: """获取要监控的币对列表(目前只监控 BTC)。""" global _symbols_cache if _symbols_cache is not None: return _symbols_cache try: resp = requests.get(f"{PROVIDER_URL}/health", timeout=10) resp.raise_for_status() all_symbols = resp.json().get("symbols", []) _symbols_cache = [s for s in all_symbols if s in _SYMBOL_WHITELIST] logger.info(f"获取到 {len(all_symbols)} 个币对,过滤后监控 {len(_symbols_cache)} 个: {_symbols_cache}") except Exception as e: logger.error(f"获取币对列表失败: {e}") _symbols_cache = ["BTC/USDT:USDT"] return _symbols_cache def fetch_ohlcv(symbol: str, tf: str = "1m") -> pd.DataFrame: """从 data_provider API 拉取某个币对最近 FETCH_LIMIT 根 K 线。""" url = f"{PROVIDER_URL}/api/candles" params = { "symbol": symbol, "tf": tf, "limit": FETCH_LIMIT, } resp = requests.get(url, params=params, timeout=30) resp.raise_for_status() data = resp.json() if not data: logger.warning(f"{symbol}: API 返回空数据") return pd.DataFrame() df = pd.DataFrame(data) df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms", utc=True) df["date"] = df["timestamp"] df = df.drop_duplicates(subset="timestamp").sort_values("timestamp").reset_index(drop=True) return df