
本文介绍如何使用 pandas 的 rolling 窗口与条件判断,仅标记每个枢轴高点(pivot=2)或低点(pivot=1)首次被突破的后续k线,避免重复触发,适用于量化交易中的关键位突破信号提取。
在技术分析中,枢轴点(Pivot Point)常用于识别局部极值——例如,某根K线的 high 是其前后各两根(共5根)K线中的最高值,则标记为“潜在高点”(通常赋值为 2);若 low 是5根K线中的最低值,则标记为“潜在低点”(赋值为 1)。但问题核心不在于识别枢轴本身,而在于:找出此后首个真正“突破”该枢轴位的K线——即:
- 对于 pivot=2(高点),找第一个 high > 枢轴所在行的 high 的后续K线;
- 对于 pivot=1(低点),找第一个 low 且每个枢轴仅触发一次,后续即使再突破也不重复标记。
以下是完整、可复现的解决方案:
✅ 步骤一:构建枢轴列(确认局部极值)
import pandas as pd
import numpy as np
# 示例数据(已按时间顺序排列)
data = {
'date': ['01.01.2020', '02.01.2020', '03.01.2020', '04.01.2020', '05.01.2020',
'06.01.2020', '07.01.2020', '08.01.2020', '09.01.2020', '10.01.2020',
'11.01.2020', '12.01.2020', '13.01.2020', '14.01.2020', '15.01.2020',
'16.01.2020', '17.01.2020'],
'high': [207, 208, 209, 207, 206, 205, 204, 206, 207, 208, 210, 212, 214, 207, 203, 201, 199],
'low': [204, 205, 205, 203, 202, 200, 199, 201, 202, 205, 207, 209, 210, 204, 202, 198, 196]
}
df = pd.DataFrame(data)
# 使用中心滚动窗口(window=5, center=True)识别局部极值
cond_high = df['high'].rolling(5, center=True).max().eq(df['high'])
cond_low = df['low'].rolling(5, center=True).min().eq(df['low'])
df['pivot'] = np.select([cond_high, cond_low], [2, 1], default=0)⚠️ 注意:center=True 确保窗口以当前行为中心(即前后各2行),更符合“围绕当前K线判断”的业务逻辑;需确保 DataFrame 索引连续且无缺失,否则 rolling 可能产生 NaN。
✅ 步骤二:标记「首次突破」K线(核心逻辑)
我们不使用循环,而是借助 cummax / cummin 和布尔索引实现向量化高效处理:
# 初始化标记列
df['takes_pivot'] = 0
# 获取所有 pivot=2(高点)的位置及对应 high 值
pivot_highs = df[df['pivot'] == 2].copy()
pivot_highs['break_level'] = pivot_highs['high']
# 获取所有 pivot=1(低点)的位置及对应 low 值
pivot_lows = df[df['pivot'] == 1].copy()
pivot_lows['break_level'] = pivot_lows['low']
# 对每个高点,向后查找首个 high > break_level 的行(且该行索引 > 高点索引)
for idx, row in pivot_highs.iterrows():
mask = (df.index > idx) & (df['high'] > row['break_level'])
hit = df[mask].head(1)
if not hit.empty:
df.loc[hit.index[0], 'takes_pivot'] = 2 # 标记为“突破高点”
# 对每个低点,向后查找首个 low < break_level 的行
for idx, row in pivot_lows.iterrows():
mask = (df.index > idx) & (df['low'] < row['break_level'])
hit = df[mask].head(1)
if not hit.empty:
df.loc[hit.index[0], 'takes_pivot'] = 1 # 标记为“突破低点”执行后,takes_pivot 列将仅在每个枢轴首次被有效突破时填入 1 或 2,其余为 0。例如:
- 03.01.2020 处 pivot=2(high=209),后续首个 high > 209 出现在 11.01.2020(high=210)→ takes_pivot=2;
- 07.01.2020 处 pivot=1(low=199),后续首个 low
✅ 优化建议(避免显式循环)
若数据量极大(>10万行),可用 numba 或分组向量化加速;但对常规行情数据(日线/小时线),上述双循环因配合 .head(1) 提前终止,实际性能优异且逻辑清晰、易于调试。
? 总结
- 枢轴识别依赖 rolling(..., center=True) + eq() 判断局部极值;
- “首次突破”本质是带索引约束的前向搜索,用 df.index > pivot_idx 保证时序性;
- 每个枢轴独立触发、互不干扰,天然满足“only once”要求;
- 最终 takes_pivot 可直接用于策略信号生成(如:if takes_pivot == 2: enter_long())。
此方法兼顾准确性、可读性与工程实用性,是量化择时中处理枢轴突破逻辑的推荐范式。










