You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OHLC数据与上下边界识别做多入场点的Pandas实现求助

问题排查与解决方案:金融数据循环分析的无限循环问题

场景与需求

现有场景:

  • 包含某金融资产OHLC(开盘价、最高价、最低价、收盘价)数据的Pandas DataFrame(df)
  • 两个与df同索引的序列:upper_bound(价格高于收盘价)、lower_bound(价格低于收盘价)

需求目标:

  1. 找到df中Low Price ≤ lower_bound的索引
  2. 找到该索引之后第一个df中High Price ≥ upper_bound的索引
  3. 计算这两个索引对应的lower_bound到upper_bound的涨跌幅
  4. 将涨跌幅、起始索引、结束索引存入possible_long_entries DataFrame
  5. 循环执行直至无数据可分析

问题现象

编写的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)

问题排查

  1. 无限循环触发原因:当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,导致外层循环无限重复执行。
  2. 逻辑漏洞:原代码只在找到符合条件的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)为变量:避免重复计算,提升代码效率。

额外建议

  1. 边界条件处理:可以考虑当j遍历到末尾仍未找到符合条件的记录时,是否需要记录该起始索引(标记为未完成),根据业务需求调整逻辑。
  2. 性能优化:对于大规模数据,嵌套循环效率较低,可考虑使用向量化操作或shift、cumsum等Pandas函数实现逻辑,提升运行速度。

内容的提问来源于stack exchange,提问作者NoahVerner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:45:53