- import yfinance as yf
- import pandas as pd # 通常会用到 pandas
1 创建 Tickers 对象
- tickers_list = ["AAPL", "MSFT", "GOOG", "AMZN"]
- tickers = yf.Tickers(" ".join(tickers_list)) # 或者直接 yf.Tickers("AAPL MSFT GOOG AMZN")
- print(tickers)
- # 批量获取过去一个月的数据
- multi_hist = tickers.history(period="1mo")
- print("\n批量获取的历史数据 (部分):")
- print(multi_hist.head())
- # 查看列索引结构
- print("\n多层列索引:")
- print(multi_hist.columns)
- # 访问特定股票的特定列数据
- print("\n访问 AAPL 的收盘价:")
- print(multi_hist['AAPL']['Close'].head())
- # 或者使用 stack() 方法转换数据结构,更方便按 Ticker 分组处理
- # stacked_hist = multi_hist.stack(level=0).reset_index().rename(columns={'level_1': 'Ticker'})
- # print("\n转换后的数据结构:")
- # print(stacked_hist.head())
- # 访问 Tickers 对象中的 Google (GOOG) Ticker 对象
- goog_ticker = tickers.tickers['GOOG']
- # 获取 Google 的 info
- goog_info = goog_ticker.info
- print(f"\nGoogle 的公司名称: {goog_info.get('longName')}")
- # 获取 Google 的财务数据
- goog_financials = goog_ticker.financials
- print("\nGoogle 的年度损益表 (部分):")
- print(goog_financials.head())
- # 使用 yf.download() 批量下载历史数据
- data = yf.download("NVDA TSLA NFLX", start="2024-01-01", end="2024-04-01")
- print("\n使用 yf.download() 获取的数据 (部分):")
- print(data.head())
- # download 返回的 DataFrame 默认按数据字段分组 (Open, High, Low, Close, Adj Close, Volume)
- print("\nyf.download() 返回的列索引:")
- print(data.columns)
- # 访问特定字段的所有股票数据
- print("\n所有股票的收盘价:")
- print(data['Close'].head())
- # 访问特定股票的所有数据
- print("\nTSLA 的所有数据:")
- print(data.xs('TSLA', level=1, axis=1).head()) # 使用 xs 进行跨层级选择
- # 也可以设置 group_by='ticker' 使列索引先按 Ticker 分组
- data_grouped_by_ticker = yf.download("NVDA TSLA NFLX", start="2024-01-01", end="2024-04-01", group_by='ticker')
- print("\n按 Ticker 分组的数据 (部分):")
- print(data_grouped_by_ticker.head())
- print("\n按 Ticker 分组的列索引:")
- print(data_grouped_by_ticker.columns)
- print("\n访问 TSLA 的收盘价 (按 Ticker 分组):")
- print(data_grouped_by_ticker['TSLA']['Close'].head())
Yahoo Finance 并未公开其确切的请求频率限制,但过于频繁的请求(尤其是在短时间内大量请求不同 Ticker 的多种数据)可能导致 IP 被暂时封禁(通常返回 HTTP 403 或 429 错误)。
策略:
尽量使用 Tickers 对象或 yf.download() 进行批量操作,而不是在循环中单独请求每个 Ticker。
如果在循环中进行请求,请在每次请求后加入适当的延迟(例如 time.sleep(1))。
避免不必要的数据请求。
如果需要大量数据,考虑分批次、在不同时间进行。