
本文介绍如何应对 tvDatafeed 库中偶发的 Connection to remote host was lost 和 no data, please check the exchange and symbol 错误,通过可控重试机制提升数据获取稳定性。
本文介绍如何应对 tvdatafeed 库中偶发的 `connection to remote host was lost` 和 `no data, please check the exchange and symbol` 错误,通过可控重试机制提升数据获取稳定性。
在使用 tvDatafeed(如 tvdatafeed 或 tvDatafeed 第三方封装库)获取 TradingView 历史行情时,开发者常遇到一种非确定性报错:
ERROR:tvDatafeed.main:Connection to remote host was lost. ERROR:tvDatafeed.main:no data, please check the exchange and symbol
值得注意的是:该错误并非总由参数错误引起——即使 exchange(如 'BINANCE')和 symbol(如 'BTCUSDT')完全正确、且同一请求在稍后重试即可成功,仍可能触发此提示。根本原因通常是网络抖动、TradingView 后端限流、或 tvDatafeed 内部会话超时导致的临时连接中断,而非用户配置问题。
✅ 推荐解决方案:带退避机制的智能重试
避免简单粗暴的无限 while True 循环(易阻塞、无超时、难调试),应采用有限次数 + 指数退避 + 异常分类处理的稳健策略。以下为生产就绪示例(基于 tvDatafeed v0.2.0+):
import time
import logging
from tvDatafeed import TvDatafeed, Interval
def fetch_ohlcv_safely(
tv: TvDatafeed,
symbol: str,
exchange: str,
interval: Interval = Interval.in_daily,
n_bars: int = 100,
max_retries: int = 5,
base_delay: float = 1.0
) -> pd.DataFrame:
"""
安全获取K线数据,自动重试临时网络错误
"""
for attempt in range(1, max_retries + 1):
try:
logging.info(f"Fetching {exchange}:{symbol} (attempt {attempt}/{max_retries})...")
df = tv.get_hist(
symbol=symbol,
exchange=exchange,
interval=interval,
n_bars=n_bars
)
if df is not None and not df.empty:
logging.info("✅ Data fetched successfully.")
return df
else:
raise ValueError("Empty response received")
except Exception as e:
error_msg = str(e).lower()
# 仅对已知瞬态错误重试(可按需扩展)
if "connection" in error_msg or "no data" in error_msg or "timeout" in error_msg:
if attempt < max_retries:
delay = min(base_delay * (2 ** (attempt - 1)), 30.0) # 最大延迟30s
logging.warning(f"⚠️ Transient error: {e}. Retrying in {delay:.1f}s...")
time.sleep(delay)
else:
raise RuntimeError(f"All {max_retries} attempts failed: {e}")
else:
# 非瞬态错误(如symbol不存在),立即抛出
raise
raise RuntimeError("Unexpected fall-through in retry loop")
# 使用示例
tv = TvDatafeed() # 默认使用 public session
df = fetch_ohlcv_safely(
tv=tv,
symbol='BTCUSDT',
exchange='BINANCE',
interval=Interval.in_1_hour,
max_retries=3
)
print(df.tail())⚠️ 关键注意事项
- 不要忽略日志级别:将 tvDatafeed 日志设为 WARNING 或更低,便于捕获底层错误(logging.getLogger('tvDatafeed.main').setLevel(logging.WARNING));
- 区分错误类型:"no data" 在重试场景下大概率是连接问题,但若持续失败,需人工验证 symbol/exchange 是否真实存在于 TradingView(例如 BINANCE:ETHUSDT 正确,而 BINANCE:ETH/USDT 可能失败);
- 避免高频请求:TradingView 对未登录会话有严格速率限制(通常 ≤ 10–20 请求/分钟),建议单次 get_hist() 覆盖足够长周期,而非频繁拉取小窗口;
- 考虑会话复用:TvDatafeed() 实例应全局复用,避免重复创建会话导致 Cookie 失效;
- 升级依赖:确保使用 tvDatafeed>=0.2.0,旧版本存在已修复的会话管理缺陷。
通过上述结构化重试方案,可将 tvDatafeed 的可用性从“偶发失败”提升至“生产级稳定”,同时保持代码清晰、可观测、易维护。










