基于FMP API用Pandas生成历史价格CSV报df未定义错误求解
问题根因
NameError: name 'df' is not defined报错由变量未赋值就直接引用导致,和猜测的merge、replace逻辑无关,核心问题点有两个:
prepare_data函数内完成行情数据清洗的变量是prices_df,后续操作的df从未在当前函数作用域内赋值,直接调用就会触发未定义错误- 代码附带存在几个隐性运行bug:接口请求失败时无兜底返回、Pandas 1.4.0以上版本已废弃
DataFrame.append()方法、日期索引类型不匹配容易触发取值报错。
修复方案
核心改动说明
- 在
prepare_data函数内将清洗完成的prices_df赋值给df后再做索引重命名、标的列添加操作,从根源解决未定义报错 - 给
get_symbol_prices增加请求失败、返回格式异常的兜底逻辑,返回空DataFrame避免后续链式调用报错 - 替换已废弃的
append拼接逻辑,改用列表收集单标的数据后一次性pd.concat,性能更好且兼容所有Pandas版本 - 统一日期索引格式,避免字符串日期和datetime类型索引不匹配导致的取值失败
修复后可直接运行的完整代码:
import os from datetime import date, timedelta import requests import pandas as pd TICKERS = ['A', 'AA', 'AAPL', 'ABNB', 'ADBE','AMAT', 'AMD', 'AMC', 'AMGN', 'AMZN'] LOOK_BACK_PERIOD = 100 def last_business_day(): test_date = date.today() diff = 1 if test_date.weekday() == 0: diff = 3 elif test_date.weekday() == 6: diff = 2 else: diff = 1 res = test_date - timedelta(days=diff) return pd.to_datetime(res) def get_symbol_prices(symbol, start_date, end_date): session = requests.Session() request = f"https://financialmodelingprep.com/api/v3/historical-price-full/{symbol}\ ?apikey=YOURAPI\ &from={start_date}&to={end_date}".replace(" ", "") r = session.get(request) if r.status_code == requests.codes.ok: df = pd.io.json.read_json(r.text) if not df.empty and 'historical' in df.columns: df = pd.DataFrame(df['historical'].to_list()) df['date'] = pd.to_datetime(df['date']) df = df.set_index('date').sort_index() return df # 接口异常时返回空DataFrame兜底 return pd.DataFrame() def prepare_data(symbol, look_back_period): start_date = date.today() - timedelta(days=look_back_period) end_date = date.today() prices_df = get_symbol_prices(symbol=symbol, start_date=start_date, end_date=end_date) if prices_df.empty: return pd.DataFrame() prices_df = prices_df[['open', 'high', 'low', 'close', 'volume']] # 无需额外merge逻辑,直接赋值即可 df = prices_df.copy() df.index.name = 'datetime' df['symbol'] = symbol return df def get_final_df(tickers, look_back_period): df_list = [] for symbol in tickers: symbol_df = prepare_data(symbol=symbol, look_back_period=look_back_period) if not symbol_df.empty: df_list.append(symbol_df) total_df = pd.concat(df_list) # 仅返回最近一个交易日的标的数据 return total_df.loc[last_business_day()] def main(): historical_df = get_final_df(tickers=TICKERS, look_back_period=LOOK_BACK_PERIOD) output_folder = 'E:/' file_name = 'HISTORICALPORTFOLIO.csv' historical_df.to_csv(os.path.join(output_folder, file_name)) if __name__ == '__main__': main()
运行注意事项
- 运行前将代码中
YOURAPI替换为你在金融数据平台申请的有效API Key,否则会触发接口权限错误 - 提前安装依赖库:执行命令
pip install pandas requests - 如果需要导出全周期历史数据而非仅最近一个交易日的数据,将
get_final_df函数最后一行返回语句改为return total_df即可
内容的提问来源于stack exchange,提问作者steeltoaster
相关产品推荐
相关产品推荐

