关于寻找顶和底的一些研究
Table of Content
scipy当中有一些信号处理函数,可以用来发现顶和底,比如argrelextrema
。
比函数名上看,这是一个寻找相对极值点坐标的函数。我们来看一下它的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
argrelextrema
来查找均线的顶和底。这里使用均线,是因为均线相对平滑,去除了一些噪音。这里的moving_average
定义为:
1 2 3 |
|
move_mean
,最高可以快6000多倍(取自官方文档,不一定是和np.convolve方法比较)。
通过给argrelextrem
传入不同的比较函数(例子中是np.less
和np.greater
),我们可以分别查找极大值和极小值,记为peaks和valleys。
然后我们把均线、收盘价线和极值点画在同一个图上。最后,我们假设在低点买入,在高点卖出,就可以计算出策略的收益。
下图是我们以东方电气2021年11月2日为止点,对60个交易日内进行信号发现的结果:
可以看出,仅仅使用默认参数,argrelextrem
就能较好地发现顶和底。我们得到的最终收益是35%,而同期该股实际上是不涨不跌。
非常惊人,just too good to be true.
那么倒底哪里错了?
原因出在argrelextrem
的工作方式。它只有在股价已经向下走时,才能检测出一个顶点已经存在。这是一个未来函数。它意味着,只有在明天才可能识别出今天应该发出的信号。但我们不可能返回昨天来完成交易。
为了进一步验证上述观点,我们取2021年9月3日前后的两张图来对比:
上图是截止9月3日的图。从后面的结果来看,argrelextrem
应该在这一天标注出一个底点。但是它并没有。
上图的时间是9月6日,这次它标注出来一个底点,但是标注在前一天。
由于均值线使用的是收盘价,这意味着,只有在9月6日收盘后,我们才能识别9月3日是一个低点。如果这时我们按9月6日的收盘价(实际交易还要晚一点,只能使用第二天的开盘价)来买入,情况会如何?
我们把上面的方法中,买卖价都顺延一天,得到的收益率是-13%。如果我们在起点时,以开盘价买入,在终点以收盘价卖出,则还可以收益8.4%。在动用高大上的数学方法后,成功地亏掉了21%。这里我们取得是5日均线。取10日、或者3日,都逃不掉亏损的命运。
理想是美好的,现实是残酷的。
然而。。。
老股民很容易观察到,在位置5附近,股价已经滞涨好几天了,均线也在走平。有句股谚,三天不创新高就要抛(这是对运做强势股而言)。这是因为,如果三天不创新高,则均线就会象上图中位置5附近一样走平,接下来既可能突破平台开启第二浪,也可能下跌。因此,我们的策略可以是这样,通过算法检测到均线走平,发出预警(此时可以部分减仓),等待明确的信号再决定是否清仓(反之则是买入)。
假设我们能在argrelextrem
前一天发现走平的信号。如果此时处于高位,则卖出一半,待argrelextrem
报出信号后,再卖出全部仓位。这样,上面函数的开仓、平仓部分就改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
现在,问题就变成了,如何检测均线走平?这个问题回答起来也并不那么容易。不过我们先来看看这里的检测峰和谷的方法的实际作用。
从上面的分析可以看出,峰和谷的检测是后验的,即只有当峰和谷已经走出来,上面的算法才能检测到。虽然它对投资可能没有直接的指导意义,但我们也可以用它来标注数据,以供机器学习使用。
下图显示了使用上述方法,对上证指数一段时间的峰和谷进行标注的结果:
我们先是使用均线对波动进行平滑,然后通过argrelextrem进行峰和谷的检测,然后在此基础上,对峰和谷进行一些小的修正,使之与股价、而不是均线对齐。我们采用沪指过去6年的30分钟线,共发现734个顶点和738个底点,制作成为标注数据。
有了这些标注数据,我们就可以训练和检验自己的机器学习模型了。出人意料的是,数据量并不大。这也说明在A股市场上,趋势一旦形成,往往还能持续一段时间。这也是量化模型能够有用武之地的一个注脚。