基于OHLC数据与上下边界识别做多入场点的Pandas实现求助
问题排查与解决方案:金融数据循环分析的无限循环问题
场景与需求
现有场景:
- 包含某金融资产OHLC(开盘价、最高价、最低价、收盘价)数据的Pandas DataFrame(
df) - 两个与
df同索引的序列:upper_bound(价格高于收盘价)、lower_bound(价格低于收盘价)
需求目标:
- 找到
df中Low Price≤lower_bound的索引 - 找到该索引之后第一个
df中High Price≥upper_bound的索引 - 计算这两个索引对应的
lower_bound到upper_bound的涨跌幅 - 将涨跌幅、起始索引、结束索引存入
possible_long_entriesDataFrame - 循环执行直至无数据可分析
问题现象
编写的Python代码在i=407时陷入无限循环,仅提取了部分有效数据(已提取数据对应的字典见下文)。
原代码
# Find all the possible long entries that could have been made considering the information above possible_long_entries = pd.DataFrame(columns=['Actual Percentage Change', 'Start Index', 'End Index']) i=0 while i < (len(df)-1): if df['Low Price'][i] <= lower_bound[i]: lower_index = i j = i + 1 while j < (len(df)-1): if df['High Price'][j] >= upper_bound[j]: upper_index = j percentage_change = (upper_bound.iat[upper_index] - lower_bound.iat[lower_index]) / lower_bound.iat[lower_index] * 100 possible_long_entries = possible_long_entries.append({'Actual Percentage Change':percentage_change,'Start Index': lower_index, 'End Index':upper_index},ignore_index=True) i = j + 1 print(i) break else: j += 1 else: i += 1
已提取的部分数据
final_dict = {'Actual Percentage Change': {0: 3.694220620875114, 1: 2.4230128905797654, 2: 2.1254433367789014, 3: 2.9138599524587625, 4: 3.177040784650736, 5: 1.0867515559002843, 6: 0.08567173253550972, 7: 0.19999498819328332, 8: 3.069342080456284, 9: 1.467935498997383, 10: -0.6867540630203672, 11: 2.019389675661748, 12: 3.1057216745256353, 13: 1.758775161828502}, 'Start Index': {0: 17.0, 1: 50.0, 2: 89.0, 3: 106.0, 4: 113.0, 5: 132.0, 6: 169.0, 7: 193.0, 8: 237.0, 9: 271.0, 10: 285.0, 11: 345.0, 12: 374.0, 13: 401.0}, 'End Index': {0: 38.0, 1: 62.0, 2: 101.0, 3: 109.0, 4: 118.0, 5: 146.0, 6: 185.0, 7: 206.0, 8: 251.0, 9: 281.0, 10: 322.0, 11: 361.0, 12: 396.0, 13: 406.0}} possible_long_entries = pd.DataFrame(final_dict)
问题排查
- 无限循环触发原因:当
i=407时,df['Low Price'][i] <= lower_bound[i]条件成立,但从j=408到len(df)-1的所有位置,df['High Price'][j] >= upper_bound[j]始终不满足。此时内层while循环会一直执行j +=1直到j达到len(df)-1,但内层循环结束后没有更新i的值,外层循环的i仍然是407,导致外层循环无限重复执行。 - 逻辑漏洞:原代码只在找到符合条件的
j时才更新i,如果找不到符合条件的j,i不会递增,永远停留在当前值,触发无限循环。
解决方案
修复后的代码
import pandas as pd # 初始化结果DataFrame possible_long_entries = pd.DataFrame(columns=['Actual Percentage Change', 'Start Index', 'End Index']) i = 0 df_len = len(df) while i < df_len - 1: if df['Low Price'].iloc[i] <= lower_bound.iloc[i]: lower_index = i j = i + 1 found = False # 遍历寻找后续第一个符合条件的j while j < df_len - 1: if df['High Price'].iloc[j] >= upper_bound.iloc[j]: upper_index = j # 计算涨跌幅 pct_change = (upper_bound.iloc[upper_index] - lower_bound.iloc[lower_index]) / lower_bound.iloc[lower_index] * 100 # 使用concat替代append(append已被弃用) new_row = pd.DataFrame({ 'Actual Percentage Change': [pct_change], 'Start Index': [lower_index], 'End Index': [upper_index] }) possible_long_entries = pd.concat([possible_long_entries, new_row], ignore_index=True) i = j + 1 found = True print(i) break j += 1 # 如果没找到符合条件的j,i直接递增,避免死循环 if not found: i += 1 else: i += 1
关键优化点
- 添加
found标记:追踪内层循环是否找到符合条件的j,如果没找到,强制递增i,避免无限循环。 - 替换
append为concat:append方法已被Pandas弃用,concat是更高效且推荐的方式。 - 使用
iloc替代直接索引:对于位置索引,iloc更清晰且性能更优,避免潜在的索引混淆问题。 - 提取
len(df)为变量:避免重复计算,提升代码效率。
额外建议
- 边界条件处理:可以考虑当
j遍历到末尾仍未找到符合条件的记录时,是否需要记录该起始索引(标记为未完成),根据业务需求调整逻辑。 - 性能优化:对于大规模数据,嵌套循环效率较低,可考虑使用向量化操作或
shift、cumsum等Pandas函数实现逻辑,提升运行速度。
内容的提问来源于stack exchange,提问作者NoahVerner
相关产品推荐
相关产品推荐

