yFinance拉取股票5年历史数据存CSV报错:需传入二维输入
解决yFinance数据保存CSV时的ValueError问题
问题场景
需要拉取多只股票的5年历史数据(如适用)并保存为CSV,后续仅需每日更新本地数据,但测试代码在写入环节报错,错误提示为ValueError: Must pass 2-d input. shape=(1, 561, 7)。原因是将yFinance返回的DataFrame放入列表再转为新DataFrame,导致数据结构异常。
原测试代码:
import yfinance as yf import pandas as pd data = pd.DataFrame() foo = yf.Ticker('GRAB') temp = pd.DataFrame([foo.history('5y')]) temp.to_csv('out.csv')
报错信息:
Traceback (most recent call last): File "C:\Users\jmshe\AppData\Local\Programs\Python\Python310\stock 2.py", line 10, in temp = pd.DataFrame([foo.history('5y')]) File "C:\Users\jmshe\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\frame.py", line 762, in __init__ mgr = ndarray_to_mgr( File "C:\Users\jmshe\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py", line 329, in ndarray_to_mgr values = _prep_ndarraylike(values, copy=copy_on_sanitize) File "C:\Users\jmshe\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\internals\construction.py", line 583, in _prep_ndarraylike raise ValueError(f"Must pass 2-d input. shape={values.shape}") ValueError: Must pass 2-d input. shape=(1, 561, 7)
解决方案
1. 单只股票数据修正
yf.Ticker.history()本身返回的就是标准2维DataFrame,不需要用列表包裹再转DataFrame,直接使用返回结果即可:
import yfinance as yf import pandas as pd foo = yf.Ticker('GRAB') # 直接获取历史数据DataFrame temp = foo.history('5y') # 保存为CSV temp.to_csv('grab_stock_data.csv')
2. 多只股票数据批量处理
遍历股票代码列表,为每个股票的DataFrame添加股票标识列,再合并成一个大DataFrame保存:
import yfinance as yf import pandas as pd # 待拉取的股票代码列表 stock_symbols = ['GRAB', 'AAPL', 'MSFT'] all_data = [] for symbol in stock_symbols: ticker = yf.Ticker(symbol) df = ticker.history('5y') # 添加股票代码列,方便区分不同股票 df['Symbol'] = symbol all_data.append(df) # 合并所有股票数据 combined_df = pd.concat(all_data) # 保存为CSV combined_df.to_csv('multi_stock_data.csv')
3. 每日更新本地数据
读取本地已保存的CSV,获取最新日期,拉取该日期之后的增量数据并追加:
import yfinance as yf import pandas as pd from datetime import datetime csv_path = 'multi_stock_data.csv' # 读取本地已有数据 existing_df = pd.read_csv(csv_path, index_col=0, parse_dates=True) # 获取最新日期 latest_date = existing_df.index.max() # 遍历股票代码,拉取增量数据 stock_symbols = existing_df['Symbol'].unique() update_data = [] for symbol in stock_symbols: ticker = yf.Ticker(symbol) # 拉取最新日期之后的数据(注意yfinance的start参数是左闭右开) df_update = ticker.history(start=latest_date + pd.Timedelta(days=1)) if not df_update.empty: df_update['Symbol'] = symbol update_data.append(df_update) if update_data: # 合并增量数据并追加到本地文件 update_df = pd.concat(update_data) combined_df = pd.concat([existing_df, update_df]) combined_df.to_csv(csv_path) print(f"已更新{len(update_df)}条数据") else: print("当前数据已是最新,无需更新")
内容的提问来源于stack exchange,提问作者James Herndon
相关产品推荐
相关产品推荐

