PowerBI运行Python脚本报错:ValueError: No objects to concatenate
问题
- 在PowerBI中运行Python脚本时触发
ValueError: No objects to concatenate错误 - 脚本在Spyder环境中可正常运行并输出结果,在PowerBI编写脚本时能预览输出表,但点击加载数据时失败
- 使用其他经纪商API的同类代码可在PowerBI正常运行,仅调用IB API时出现此问题
相关代码:
import pandas as pd import datetime as dt from datetime import datetime, timedelta today_date = dt.date.today() + timedelta(1) #today_date = today_date.strftime("20%y-%m-%d") import yfinance as yf import sys sys.path.append(r'F:\Projects\!!!Python Data\Quants Strategies\!Interactive Broker') import IB_API print("Testing IB's API as an imported library:") US_Stock_Portfolio = IB_API.read_positions() US_Stock_Portfolio = US_Stock_Portfolio.reset_index() US_Stock_Portfolio = US_Stock_Portfolio[['Symbol', 'Quantity']] US_Stock_Ticker = [] for ticker in US_Stock_Portfolio['Symbol']: US_Stock_Ticker.append(ticker) # Performance 5 Years Start_date_Perf = today_date - timedelta(365*5) End_date_Perf = today_date #VaR_Date 1 year Start_date_Var = today_date - timedelta(365) End_date_Var = today_date #SVaR date 2019-2020 Start_date_SVar = '2020-1-1' End_date_SVar = '2020-12-31' Name = ['Performance', 'VaR', 'SVaR'] S_date_list = [Start_date_Perf, Start_date_Var, Start_date_SVar ] E_date_list = [End_date_Perf, End_date_Var, End_date_SVar ] for i in range(0,3): US_Stock_Data = yf.download(US_Stock_Ticker, S_date_list[i] , E_date_list[i], period='1d', progress=False)['Adj Close'] US_Stock_Data = pd.DataFrame(US_Stock_Data) US_Stock_Data.index = US_Stock_Data.index.tz_localize(None) US_Stock_Data = US_Stock_Data.reset_index() US_Stock_Data.sort_values(by='Date', ascending = True, inplace = True) US_Stock_Data = US_Stock_Data.replace("", None).bfill() US_Stock_Data = US_Stock_Data.replace("", None).ffill() US_Stock_Data[['Date','Time']] = US_Stock_Data['Date'].apply(str).str.split(' ', expand = True) US_Stock_Data = US_Stock_Data.drop('Time', axis=1) US_Stock_Data = US_Stock_Data.drop_duplicates(subset=['Date']) #bm_data.to_excel(r"F:\Projects\Company analysis\Stock Data\BM_data.xlsx",index=False) """ if Name[i] == 'Performance': US_Stock_Data_Perf = US_Stock_Data.copy() elif Name[i] == 'VaR': US_Stock_Data_VaR = US_Stock_Data.copy() elif Name[i] == 'SVaR': US_Stock_Data_SVaR = US_Stock_Data.copy() """ ### Calculating new dfs for Portfolio Market Value US_Stock_Data_new = US_Stock_Data.copy() #IN_Stock_Data_new.rename(columns = {'Ticker':'Yahoo Ticker'}, inplace = True) for j in US_Stock_Portfolio['Symbol']: US_Stock_Data_new[j] = US_Stock_Data_new[j] * float(US_Stock_Portfolio.loc[US_Stock_Portfolio['Symbol'] == j]['Quantity'].iloc[0]) #US_Stock_Data_new[j] = US_Stock_Data_new[j] * float(US_Stock_Portfolio.loc[US_Stock_Portfolio['Symbol'] == j]['Quantity']) Date = [] for k in US_Stock_Data_new['Date']: Date.append(k) US_Stock_Data_new = US_Stock_Data_new.drop(['Date'], axis=1) Port_Value = [] for l in range(0, len(US_Stock_Data_new)): Port_Value.append(US_Stock_Data_new.loc[l].sum()) US_Stock_Data_new_perf = pd.DataFrame(list(zip(Date, Port_Value)), columns = ['Date', 'Market Value']) US_Stock_Data_new_perf['Market Value %'] = US_Stock_Data_new_perf['Market Value'].pct_change() US_Stock_Data_new_perf['Market Value % Cumsum'] = US_Stock_Data_new_perf['Market Value %'].cumsum() print('downloaded data for '+ Name[0]) if Name[i] == 'Performance': US_Port_Perf = US_Stock_Data_new_perf.copy() elif Name[i] == 'VaR': US_Port_VaR = US_Stock_Data_new_perf.copy() elif Name[i] == 'SVaR': US_Port_SVaR = US_Stock_Data_new_perf.copy() VaR_01 = [] SVaR_01= [] VaR_05 = [] SVaR_05 = [] Temp = [] Var_df = pd.DataFrame(Temp) Var_df['ascending'] = US_Port_VaR['Market Value %'].sort_values(ascending=True) VaR_01.append(Var_df.quantile(0.01).iloc[0]) VaR_05.append(Var_df.quantile(0.05).iloc[0]) Temp = [] Var_df = pd.DataFrame(Temp) Var_df['ascending'] = US_Port_SVaR['Market Value %'].sort_values(ascending=True) SVaR_01.append(Var_df.quantile(0.01).iloc[0]) SVaR_05.append(Var_df.quantile(0.05).iloc[0]) US_Port_Var_Data = pd.DataFrame(list(zip(VaR_01, VaR_05, SVaR_01,SVaR_05)), columns = ['1D VaR @99%', '1D VaR @95%','1D SVaR @99%', '1D SVaR @95%']) US_Port_Var_Data = US_Port_Var_Data.T US_Port_Var_Data.rename(columns = {0:'US Portfolio'}, inplace = True) US_Port_Var_Data = US_Port_Var_Data.reset_index() #US_Stock_Portfolio.to_excel(r'F:\Projects\Company Analysis\Holdings\US_Stock_Portfolio.xlsx') del US_Stock_Data del US_Stock_Data_new del US_Stock_Data_new_perf del US_Stock_Portfolio del Var_df
错误详情:
1 query is blocked by the following errors: US_Port_VaR ADO.NET: Python script error. ValueError: No objects to concatenate During handling of the above exception, another exception occurred: ValueError: No objects to concatenate US_Port_Var_Data ADO.NET: Python script error. ValueError: No objects to concatenate During handling of the above exception, another exception occurred: ValueError: No objects to concatenate US_Port_SVaR ADO.NET: Python script error. ValueError: No objects to concatenate During handling of the above exception, another exception occurred: ValueError: No objects to concatenate
解决方案
检查IB API返回的持仓数据是否为空
脚本依赖IB_API.read_positions()获取持仓数据,如果PowerBI环境中该接口返回空DataFrame,后续基于ticker的yfinance下载会得到空数据,最终触发拼接错误。在调用IB API后加验证代码:print("持仓数据行数:", len(US_Stock_Portfolio))若输出为0,说明IB API在PowerBI环境中未正确获取数据,需检查IB连接状态、权限或PowerBI的Python环境是否能正常访问IB API。
确保循环中生成的DataFrame不为空
循环处理三个时段数据时,若某一时段下载的US_Stock_Data为空,后续生成的US_Port_VaR/US_Port_SVaR也会是空DataFrame,计算涨跌后全为NaN,导致拼接失败。在循环内添加空值检查:if US_Stock_Data.empty: print(f"{Name[i]}时段无数据,跳过") continue移除末尾的变量删除语句
脚本末尾的del语句会删除PowerBI需要加载的目标DataFrame(如US_Port_VaR、US_Port_Var_Data),导致加载时找不到变量,直接删掉所有del语句即可。统一日期格式
代码中Start_date_SVar是字符串格式,另外两个起始日期是date对象,yfinance对不同格式日期的处理可能存在差异,统一转为字符串:Start_date_Perf = (today_date - timedelta(365*5)).strftime("%Y-%m-%d") Start_date_Var = (today_date - timedelta(365)).strftime("%Y-%m-%d")检查PowerBI的Python环境依赖
确认PowerBI使用的Python环境中已安装pandas、yfinance及IB API相关依赖,版本与Spyder环境一致。可在脚本开头添加版本检查:print("pandas版本:", pd.__version__) print("yfinance版本:", yf.__version__)
内容的提问来源于stack exchange,提问作者its Deejay
相关产品推荐
相关产品推荐

