vensentzhou 发布于2022-08-07
回复 23
浏览 5715
46
昨天在知乎上看到一位医学博士的文章[《推荐一个非常实用的峰值查找算法(peak detection)》](https://zhuanlan.zhihu.com/p/549588865)
在数字信号处理中,经常涉及到波峰(或波谷)查找算法,比如心率测量、步数计数等。对于周期信号或者准周期信号,有一种称之为Automatic multiscale-based peak detection (AMPD),即自动多尺度峰值查找算法。
其优势是:
(1)算法本身(几乎)没有超参数,无需调参,对信号具有良好的自适应性,唯一的假设是信号是周期的或者准周期的;
(2)抗噪能力强,后面可以看到,对周期性的要求也不是很高。
就是用一个多尺度的滑动窗口去两侧进行比较,寻找局部最大值。
```
import numpy as np
def AMPD(data):
"""
实现AMPD算法
:param data: 1-D numpy.ndarray
:return: 波峰所在索引值的列表
"""
p_data = np.zeros_like(data, dtype=np.int32)
count = data.shape[0]
arr_rowsum = []
for k in range(1, count // 2 + 1):
row_sum = 0
for i in range(k, count - k):
if data[i] > data[i - k] and data[i] > data[i + k]:
row_sum -= 1
arr_rowsum.append(row_sum)
min_index = np.argmin(arr_rowsum)
max_window_length = min_index
for k in range(1, max_window_length + 1):
for i in range(k, count - k):
if data[i] > data[i - k] and data[i] > data[i + k]:
p_data[i] += 1
return np.where(p_data == max_window_length)[0]
```
我们先来合成一段数据看看效果:
```
import matplotlib.pyplot as plt
def sim_data():
N = 1000
x = np.linspace(0, 200, N)
y = 2 * np.cos(2 * np.pi * 300 * x) \
+ 5 * np.sin(2 * np.pi * 100 * x) \
+ 4 * np.random.randn(N)
return y
def vis():
y = sim_data()
plt.plot(range(len(y)), y)
px = AMPD(y)
plt.scatter(px, y[px], color="red")
plt.show()
vis()
```

效果还不错,那么对于股票数据效果怎样呢?
```
data=get_price('600887.XSHG',start_date='2021-07-30',end_date='2022-08-05')
y = data['close']
plt.plot(range(len(y)), y)
px = AMPD(y)
plt.scatter(px, y[px], color="red")
```

好像也还不错。
指数好像效果就比较差了:
```
data=get_price('000300.XSHG',start_date='2021-07-30',end_date='2022-08-05')
y = data['close']
plt.plot(range(len(y)), y)
px = AMPD(y)
plt.scatter(px, y[px], color="red")
```

波谷的计算方式只需要把数据乘以-1反转一下就可以了。
抛砖引玉,欢迎有兴趣的大佬优化股票市场的应用。
评论
非常不错,谢谢。期待你用它出来的策略,关注和点赞。
2022-08-09
有意思的算法,值得研究一下,多谢
2022-08-09
感谢分享,用这个做压力支撑是不是会更有效
2022-08-09
@智习 希望大佬优化股市应用
2022-08-09
@引力弹弓 如果做技术分析,压力支撑线的前置条件是极值点
2022-08-09
为什么在指数上的效果不好呢,是不是选的时间跨度太大了?
2022-08-09
@nkxiaoqi 金融市场的优化,还仰仗各位大佬
2022-08-09