如何在Pandas DataFrame中高效筛选未被突破的Tsph标记K线?
高效提取未被突破的Tsph/Tspl K线方案
核心逻辑
要找每个时间点下,满足Tsph=True且高点未被后续K线突破的行,本质是筛选出:标记了Tsph的K线中,其高点在自身出现后到当前时间点的区间内始终是最大值的记录。同理Tspl对应低点始终是最小值的记录。
直接循环遍历每个Tsph点并计算区间极值的效率极低,尤其数据量大时。我们可以通过预处理每个标记点的有效截止时间,实现后续高效查询。
实现步骤
1. 预处理标记点的有效截止时间
对每个Tsph/Tspl标记点,计算它的“有效截止点”——即后续第一个突破其高点(或低点)的K线索引。如果没有突破点,有效截止点就是最后一根K线的索引。
2. 快速查询当前时间的有效标记点
对于任意当前索引,只需筛选出“标记时间≤当前索引”且“有效截止时间≥当前索引”的记录,这些就是未被突破的有效K线。
完整代码
import pandas as pd import numpy as np def preprocess_pivot_points(df, pivot_col, price_col, is_high=True): # 提取所有标记为True的K线 pivot_points = df[df[pivot_col]][[price_col]].reset_index().rename(columns={'index': 'datetime'}) price_array = df[price_col].values # 获取每个标记点在原数据中的位置索引 pivot_positions = df.index.get_indexer(pivot_points['datetime']) valid_until_list = [] for pos, price in zip(pivot_positions, pivot_points[price_col].values): # 查找后续第一个突破当前价格的位置 if is_high: # 找第一个比当前高点更高的K线 break_mask = price_array[pos+1:] > price else: # 找第一个比当前低点更低的K线 break_mask = price_array[pos+1:] < price if break_mask.any(): # 计算突破点的索引 first_break_pos = pos + 1 + np.argmax(break_mask) valid_until_list.append(df.index[first_break_pos]) else: # 没有突破点,有效到最后一根K线 valid_until_list.append(df.index[-1]) pivot_points['valid_until'] = valid_until_list return pivot_points # 假设df_resampled是你的K线DataFrame,包含datetime索引、High、Low、Tsph、Tspl列 # 预处理Tsph和Tspl标记点 tsph_valid = preprocess_pivot_points(df_resampled, 'Tsph', 'High', is_high=True) tspl_valid = preprocess_pivot_points(df_resampled, 'Tspl', 'Low', is_high=False) # 示例:查询当前时间点的有效标记K线 current_time = pd.to_datetime('2023-10-10 15:00:00') valid_tsph_now = tsph_valid[(tsph_valid['datetime'] <= current_time) & (tsph_valid['valid_until'] >= current_time)] valid_tspl_now = tspl_valid[(tspl_valid['datetime'] <= current_time) & (tspl_valid['valid_until'] >= current_time)]
效率优势
- 预处理阶段仅遍历所有标记点(数量远小于总K线数),时间复杂度为O(M)(M是标记点数量)
- 后续每次查询仅需布尔筛选,时间复杂度为O(K)(K是当前有效标记点数量),相比原循环方案的O(N)(N是区间K线数),在数据量较大时效率提升显著。
内容的提问来源于stack exchange,提问作者AAM
相关产品推荐
相关产品推荐

