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

如何在Scipy峰值检测中偏向负峰值(谷值)左侧?

偏向左侧的负峰值(谷值)检测方案

一、Scipy库的适配调整

Scipy的find_peaks本身不支持直接给prominence的左右侧加权,但可以通过以下两种方式实现偏向左侧的谷值检测:

1. 限制右侧评估窗口长度(wlen参数)

检测谷值时(通过取反数据调用find_peaks),可以设置wlen参数让右侧的评估窗口比左侧短,这样计算突出度时会更侧重左侧的高度差。该参数支持设置元组来分别指定左右窗口长度(需Scipy 1.7+版本),左侧窗口设大、右侧设小,就能让算法更倾向于认可左侧满足条件的谷值。

示例代码:

import matplotlib.pyplot as plt
import scipy.signal as signal

# 取反数据找谷值,设置wlen让右侧窗口更短,偏向左侧检测
peaks, properties = signal.find_peaks(-df['RSI_MA14'], prominence=10, wlen=(20, 5))
local_minima = df.iloc[peaks]

# 筛选x=200附近的最后一个负峰值(这里设±20为"附近"范围,可自行调整)
target_peaks = [p for p in peaks if abs(p - 200) <= 20]
last_peak = max(target_peaks) if target_peaks else None

# 绘图展示
plt.plot(df.index, df['RSI_MA14'])
plt.scatter(peaks, df['RSI_MA14'].iloc[peaks], color='red', label='检测到的谷值')
if last_peak:
    plt.scatter(last_peak, df['RSI_MA14'].iloc[last_peak], color='blue', label='接近200的最后谷值')
plt.legend()
plt.show()

2. 自定义左侧优先的筛选逻辑

先通过find_peaks获取所有候选谷值,再手动筛选出左侧突出度达标、右侧要求放宽的点,以此实现偏向左侧的效果。比如要求左侧的下降幅度≥10,右侧上升幅度≥5即可。

示例代码:

import matplotlib.pyplot as plt
import scipy.signal as signal
import numpy as np

# 先获取所有候选谷值(放宽初始prominence阈值)
peaks, properties = signal.find_peaks(-df['RSI_MA14'], prominence=5)
rsi_data = df['RSI_MA14'].values

# 自定义筛选规则:左侧深度≥10,右侧深度≥5
filtered_peaks = []
left_win = 15  # 左侧计算窗口长度
right_win = 5  # 右侧计算窗口长度
for p in peaks:
    # 计算左侧最大差值(谷值左侧最高点与谷值的差)
    left_start = max(0, p - left_win)
    left_max = np.max(rsi_data[left_start:p])
    left_prom = left_max - rsi_data[p]
    # 计算右侧差值(谷值右侧最高点与谷值的差)
    right_end = min(len(rsi_data)-1, p + right_win)
    right_max = np.max(rsi_data[p+1:right_end+1])
    right_prom = right_max - rsi_data[p]
    # 满足左侧优先的条件则保留
    if left_prom >= 10 and right_prom >= 5:
        filtered_peaks.append(p)

# 筛选x=200附近的最后一个谷值
target_peaks = [p for p in filtered_peaks if abs(p - 200) <= 20]
last_peak = max(target_peaks) if target_peaks else None

# 绘图展示
plt.plot(df.index, rsi_data)
plt.scatter(filtered_peaks, rsi_data[filtered_peaks], color='red', label='偏向左侧的谷值')
if last_peak:
    plt.scatter(last_peak, rsi_data[last_peak], color='blue', label='接近200的最后谷值')
plt.legend()
plt.show()

二、实时数据处理的专属策略

针对实时新增数据的场景,偏向左侧检测意味着不需要等待右侧足够多的数据就能判定谷值,推荐采用滑动窗口+阈值判定的方式:

1. 核心逻辑

  • 维护一个滑动窗口,实时跟踪当前数据点和左侧窗口内的最大值
  • 当当前数据点比左侧窗口最大值低出设定阈值(比如10),且后续连续几个点开始上升时,立即判定该点为谷值
  • 这种方式无需等待右侧大量数据,完全适配实时数据流场景

2. 示例代码

import matplotlib.pyplot as plt
import numpy as np

rsi_data = df['RSI_MA14'].values
left_win_size = 15  # 左侧参考窗口大小
prominence_thresh = 10  # 左侧深度阈值
post_rising_count = 3  # 连续上升的点数,用于确认谷值

realtime_minima = []
# 模拟实时数据流入的遍历过程
for i in range(left_win_size, len(rsi_data)):
    left_max = np.max(rsi_data[i-left_win_size:i])
    # 检查当前点是否满足左侧深度要求
    if left_max - rsi_data[i] >= prominence_thresh:
        # 检查后续点是否连续上升,确认谷值
        if i + post_rising_count < len(rsi_data):
            post_data = rsi_data[i+1:i+post_rising_count+1]
            if all(post_data[j] > post_data[j-1] for j in range(1, len(post_data))):
                realtime_minima.append(i)
                # 跳过后续点,避免重复检测
                i += post_rising_count

# 筛选x=200附近的最后一个谷值
target_peaks = [p for p in realtime_minima if abs(p - 200) <= 20]
last_peak = max(target_peaks) if target_peaks else None

# 绘图展示
plt.plot(df.index, rsi_data)
plt.scatter(realtime_minima, rsi_data[realtime_minima], color='red', label='实时检测的偏向左侧谷值')
if last_peak:
    plt.scatter(last_peak, rsi_data[last_peak], color='blue', label='接近200的最后谷值')
plt.legend()
plt.show()

三、其他可选工具

如果不想用Scipy,还可以考虑:

  • Pandas Rolling窗口:结合滚动窗口计算最大值,自定义谷值判定逻辑,适合DataFrame操作
  • TA-Lib库:专门用于技术分析,内置谷值/峰值检测函数,部分参数可调整检测偏向性(需额外安装)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:23:11