Python获取NSE股票历史数据时触发IndexError: single positional indexer is out-of-bounds错误求助
Hey there! 看起来你在使用Upstox API批量拉取NSE印度1700多家企业近120天股票数据时,遇到了IndexError: single positional indexer is out-of-bounds错误,结合你的代码片段和Python 3.13的环境,我来帮你分析下可能的问题和解决思路:
先理清楚你的场景
- 需求:获取1700+家NSE上市公司近120天的日线数据
- 环境:Python 3.13
- 核心错误:
IndexError: single positional indexer is out-of-bounds - 你的核心代码片段(补全了合理的未写完部分):
def getHistoricalData(symInfo): res = None try: parseInstrument = urllib.parse.quote(symInfo.instrument_key) fromDate = (datetime.now(TIME_ZONE) - timedelta(days=120)).strftime("%Y-%m-%d") todate = datetime.now(TIME_ZONE).strftime("%Y-%m-%d") url = f'https://api.upstox.com/v2/historical-candle/{parseInstrument}/day/{todate}/{fromDate}' res = requests.get(url, headers=YOUR_AUTH_HEADERS) # 推测你这里有授权头信息 # 推测你后续有解析响应为DataFrame的操作,这一步触发了错误 response_data = res.json() candles = response_data['data']['candles'] df = pd.DataFrame(candles) # 比如用df.iloc[:, 0]这类位置索引操作时触发了错误 except IndexError as e: print(f"Error for {symInfo.instrument_key}: {e}")
错误的常见原因
这个错误本质是你尝试用位置索引(比如pandas的iloc/iat,或者列表的下标访问)去一个不存在的位置,结合你的场景,大概率是以下几种情况:
1. API返回的内容不符合预期(空数据或错误响应)
有些上市企业可能近120天没有交易数据,或者你的instrument_key无效、权限不足,导致API返回的candles列表是空的,甚至直接返回错误信息。这时候你强行转成DataFrame再做索引操作,就会触发越界错误。2. API的日期参数顺序搞反了
看你构造的URL:day/{todate}/{fromDate},Upstox的历史K线API通常要求日期参数是起始日期在前,结束日期在后,你这里把todate和fromDate的顺序写反了,可能导致API返回空的蜡烛图数据,后续解析时触发错误。3. 处理DataFrame时的索引操作无数据可访问
比如你假设返回的蜡烛图数据有固定列数,直接用df.iloc[:, 1]去访问第二列,但如果DataFrame是空的(没有行/列),就会触发这个索引错误。
具体的解决步骤
步骤1:先验证API的返回内容
在请求API后,先不要急着解析数据,先打印响应状态码和返回内容,确认数据结构是否正确:
res = requests.get(url, headers=YOUR_AUTH_HEADERS) # 先检查请求是否成功 if res.status_code != 200: print(f"Request failed for {symInfo.instrument_key}, status code: {res.status_code}") print(f"Error message: {res.json()}") return None # 再检查返回的数据结构是否符合预期 response_data = res.json() if not response_data.get('data') or not response_data['data'].get('candles') or len(response_data['data']['candles']) == 0: print(f"No historical data found for {symInfo.instrument_key}") return None
步骤2:修正日期参数的顺序
把URL里的todate和fromDate调换位置,符合API的参数要求:
# 修正后的URL,起始日期在前,结束日期在后 url = f'https://api.upstox.com/v2/historical-candle/{parseInstrument}/day/{fromDate}/{todate}'
步骤3:给DataFrame操作加安全判断
在对DataFrame做索引操作前,先确认DataFrame非空,有足够的行/列:
candles = response_data['data']['candles'] df = pd.DataFrame(candles) # 比如要访问第一列,先判断列数足够 if len(df.columns) > 0: first_column = df.iloc[:, 0] else: print(f"DataFrame has no columns for {symInfo.instrument_key}") return None
步骤4:批量处理时隔离单个错误
因为你要处理1700多家企业,单个企业的错误不应该中断整个批量任务,所以在循环调用getHistoricalData时也要加异常捕获:
# 假设你有一个所有标的的列表all_symbols for sym in all_symbols: try: getHistoricalData(sym) except Exception as e: print(f"Failed to fetch data for {sym.instrument_key}: {str(e)}") continue # 跳过错误的标的,继续处理下一个
备注:内容来源于stack exchange,提问作者NeedBasedLearner

