如何精准识别并标记唯一有效的高低点枢轴(Pivot)信号

8次阅读

如何精准识别并标记唯一有效的高低点枢轴(Pivot)信号

本文介绍如何使用 pandas 的滚动窗口与条件选择,仅标记每个局部极值首次出现的枢轴点(1 表示局部低点,2 表示局部高点),避免重复触发,适用于技术分析中的有效突破信号识别。

在量化交易与技术分析中,枢轴点(Pivot Points)常用于识别价格趋势转折的关键位置。但原始的局部极值检测(如 rolling(5, center=True).max() == high)容易在平台或窄幅震荡区间内连续多日触发相同信号(例如连续3天都是局部高点),导致“信号漂移”——即同一波段内多次标记,丧失交易意义。

核心目标:对每个已识别的枢轴类型(高点=2 / 低点=1),仅保留该极值序列中首个出现且未被后续更强极值覆盖的独立信号。换言之:一旦某日被标记为 pivot=2(局部高点),则在其后直到下一个更高 pivot=2 出现前,中间所有“伪高点”均应忽略;pivot=1 同理。

✅ 正确实现:基于滚动窗口 + np.select 构建基础枢轴列

首先,使用中心对称的 5 窗口(含自身及上下各 2 行)检测局部极值:

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)  # 构建基础 pivot 列:2=局部高点,1=局部低点,0=非枢轴 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)

⚠️ 注意:rolling(…, center=True) 要求窗口大小为奇数(此处为 5),且首尾两行因无法满足中心对称而返回 NaN —— 需填充或截断。推荐用 min_periods=3 或直接 dropna() 处理边界。

✅ 进阶去重:确保每个 pivot 类型“仅触发一次”,直到新极值出现

上述代码生成的是所有局部极值点,但题目要求“only once”——即每个方向(高/低)只取第一个有效突破,后续同向信号需抑制,直至反向或更强信号重置。

实现逻辑如下:

  • 对 pivot == 2 序列,从前向后扫描,仅保留首次出现且之后未被更高高点替代的点;
  • 更实用的做法是:按时间顺序遍历,维护当前“已确认的最高高点”和“最低低点”,仅当新高 > 当前最高 或 新低
# 初始化状态变量 last_high = -np.inf last_low  = np.inf takes_pivot = np.zeros(len(df), dtype=int)  for i in range(len(df)):     h, l = df.iloc[i]['high'], df.iloc[i]['low']     if h > last_high and df.iloc[i]['pivot'] == 2:         takes_pivot[i] = 2         last_high = h     elif l < last_low and df.iloc[i]['pivot'] == 1:         takes_pivot[i] = 1         last_low = l  df['takes_pivot'] = takes_pivot

运行后,takes_pivot 列将严格满足题意:

  • 2 仅出现在 13.01.2020(214,突破此前所有高点);
  • 1 仅出现在 07.01.2020(199,跌破此前所有低点);
    → 完全匹配用户期望的“only once”行为。

? 关键注意事项

  • 窗口大小选择:5 是常见设定(2+1+2),但可根据周期调整(如日线用 9,小时线用 5);
  • 边界处理:center=True 导致首尾 NaN,建议 df.dropna(subset=['pivot']) 或用 min_periods=3 缓解;
  • 性能优化循环大数据集上较慢,可改用 numba 加速或向量化状态传播(如 cummax/cummin 辅助判断);
  • 业务语义:takes_pivot 不是数学极值,而是交易意义上首次达成的新高/新低枢轴,具备明确的策略触发价值。

通过此方法,你不仅能准确识别枢轴点,更能将其转化为稳健、去噪、可直接对接交易系统的信号列。

text=ZqhQzanResources