28

股票

是否有任何特定的算法可以让我找到上图中的最小值和最大值?

我有文本格式的数据,所以我不需要在图片中找到它。股票的问题在于它们有这么多的局部最小值和最大值,简单的衍生品将不起作用。

我正在考虑使用数字滤波器(z 域)并平滑图形,但我仍然有太多的局部最小值和最大值。

我也尝试使用移动平均线来平滑图表,但我的最大值和最小值也太多了。

编辑:

我阅读了一些评论,我只是没有偶然圈出一些最小值和最大值。

我想我想出了一个可行的算法。首先找到最小和最大点(当天的最高点和当天的最低点)。然后画三条线,从开盘到高点或低点,以先到者为准,然后画一条从低点到高点或从高点到低点的线,最后到收盘价。然后在这三个区域中的每一个中找到离线最远的点作为我的高点和低点,然后重复循环。

4

9 回答 9

15

我通常使用移动平均线和指数移动平均线的组合。它(根据经验)证明非常适合这项任务(至少足以满足我的需要)。结果仅使用两个参数进行调整。这是一个示例:

在此处输入图像描述

编辑

如果它对某人有用,这是我的 Mathematica 代码:

f[sym_] := Module[{l},
  (*get data*)
  l = FinancialData[sym, "Jan. 1, 2010"][[All, 2]];
  (*perform averages*)
  l1 = ExponentialMovingAverage[MovingAverage[l, 10], .2];
  (*calculate ma and min positions in the averaged list*)
  l2 = {#[[1]], l1[[#[[1]]]]} & /@ 
    MapIndexed[If[#1[[1]] < #1[[2]] > #1[[3]], #2, Sequence @@ {}] &, 
     Partition[l1, 3, 1]];
  l3 = {#[[1]], l1[[#[[1]]]]} & /@ 
    MapIndexed[If[#1[[1]] > #1[[2]] < #1[[3]], #2, Sequence @@ {}] &, 
     Partition[l1, 3, 1]];
  (*correlate with max and mins positions in the original list*)
  maxs = First /@ (Ordering[-l[[#[[1]] ;; #[[2]]]]] + #[[1]] - 
        1 & /@ ({4 + #[[1]] - 5, 4 + #[[1]] + 5} & /@ l2));
  mins = Last /@ (Ordering[-l[[#[[1]] ;; #[[2]]]]] + #[[1]] - 
        1 & /@ ({4 + #[[1]] - 5, 4 + #[[1]] + 5} & /@ l3));
  (*Show the plots*)
  Show[{
    ListPlot[l, Joined -> True, PlotRange -> All, 
     PlotLabel -> 
      Style[Framed[sym], 16, Blue, Background -> Lighter[Yellow]]],
    ListLinePlot[ExponentialMovingAverage[MovingAverage[l, 10], .2]], 
    ListPlot[{#, l[[#]]} & /@ maxs, 
     PlotStyle -> Directive[PointSize[Large], Red]],
    ListPlot[{#, l[[#]]} & /@ mins, 
     PlotStyle -> Directive[PointSize[Large], Black]]}, 
   ImageSize -> 400]
  ]
于 2011-09-19T20:41:10.640 回答
5

您会注意到很多答案都适用于带有某种低通滤波的导数。某种移动平均线,如果你愿意的话。fft、方窗移动平均线和指数移动平均线在基本层面上都非常相似。但是,考虑到所有移动平均线的选择,哪一个是最好的?

答案:高斯移动平均线;你知道的正态分布。

原因:高斯滤波器是唯一永远不会产生“假”最大值的滤波器;一开始就不存在的最大值。这在理论上已被证明适用于连续数据和离散数据(但请确保将离散高斯用于离散数据!)。随着您增加高斯 sigma,局部最大值和最小值将以最直观的方式合并。因此,如果您希望每天不超过一个局部最大值,您可以将 sigma 设置为 1,ET 等等。

于 2011-09-23T16:16:13.183 回答
4

我不知道您所说的“简单导数”是什么意思。我理解这意味着您已经测试了梯度下降并发现它由于局部极值的丰富而不能令人满意。如果是这样,你想看看模拟退火

退火是一种冶金工艺,用于通过加热和冷却处理来回火金属。(...)。这些不规则性是由于原子被卡在结构的错误位置。在退火过程中,金属被加热,然后慢慢冷却。加热为原子提供了它们脱离卡住所需的能量,而缓慢的冷却期使它们能够移动到结构中的正确位置。

(...)但是,为了逃避局部最优,算法将有可能朝着错误的方向迈出一步:换句话说,采取增加最小化问题值或降低值的步骤对于最大化问题。为了模拟退火过程,该概率将部分取决于算法中的“温度”参数,该参数以高值初始化并在每次迭代时降低。因此,该算法最初将很有可能远离附近的(可能是局部的)最优值。在迭代过程中,概率会降低,算法将收敛于(希望是全局的)最优值,它没有机会逃脱。(来源,削减和强调我的)

知道局部最优值正是您绘图中的圆圈所代表的内容,因此也是您想要找到的内容。但是,正如我解释这句话“这么多的局部最小值和最大值简单的导数不起作用。 ”,这也正是你发现的太多。我假设你对曲线在两个圆圈点之间形成的所有“之字形”都有问题。

似乎将您圈出的最佳点与曲线的其余点区分开来的所有因素都是它们的全局性,确切地说:要找到比您在左侧圈出的第一个点更低的点,您必须在 x 坐标中以任何一种方式走得更远比你需要为它的近邻做同样的事情。这就是退火给你的:根据温度参数,你可以控制你允许自己做出的跳跃的大小。必须有一个值,您可以捕捉到“大”局部最优值,但又错过了“小”值。我的建议不是革命性的:有几个例子(例如1 2) 人们从这些嘈杂的数据中获得了不错的结果。

于 2011-08-15T02:55:10.173 回答
2

只需以精确但可调的方式定义最小值和最大值的含义,然后对其进行调整,直到找到正确的最小值和最大值。例如,您可以首先通过将每个值替换为该值的平均值及其左右 N 个值来平滑图形。通过增加 N,您可以减少找到的最小值和最大值的数量。

然后,您可以将最小值定义为一个点,如果您左右跳过 A 值,则接下来的 B 值都显示出一致的增加趋势。通过增加 B,您可以找到更少的最小值和最大值。通过调整 A,您可以调整允许的最小值或最大值的“平坦”程度。

一旦你使用了一个可调算法,你就可以调整它直到它看起来正确。

于 2011-08-15T09:11:16.900 回答
2

您可以使用Spline 方法为您的原始函数创建一个连续逼近多项式[具有所需的度数]。在你有了这个多项式之后,在它[生成的多项式]上寻找一个局部最小值/最大值[使用基本微积分]。

请注意,样条方法为您提供了一个“平滑”的近似多项式 - 因此很容易找到局部最小值/最大值,并且都尽可能接近原始函数,因此局部最小值/最大值应该非常接近原始函数中的真实值。

为了提高准确性,在生成的多项式中找到局部最小值/最大值后,对于x0代表局部最小值/最大值的每个,您应该查看所有 x 使得 x0-delta < x < x0 + delta,以找到该点表示的实际最小值/最大值。

于 2011-09-20T12:14:54.090 回答
1

我经常发现人类主观感知的极值(阅读:股票图表中唯一的极值,主要是随机噪声)通常是在傅立叶带通滤波之后找到的。你可以试试这个算法:

  1. 执行 FFT
  2. 在频率空间中做一个带通。根据您希望极值看起来不错的数据范围,即感兴趣的时间尺度,选择带通参数。
  3. 执行逆 FFT。
  4. 选择结果曲线的局部最大值。

第二步的参数看起来很主观,但同样,主观性是股票图表分析的本质。

于 2011-09-18T00:51:55.003 回答
0

正如 belisarius 所提到的,最好的方法似乎是平滑地过滤数据。通过足够的平滑,寻找斜率的变化应该查明当地的最小值和最大值(导数在这里会有所帮助)。我会使用居中的滑动窗口来运行中值/平均值,或正在进行的 EMA(或类似的 IIR 滤波器)。

于 2011-09-23T17:22:41.300 回答
0

此 python 代码检测范围 5 中的局部极值。df 应包含 OHLC 列

df['H_5'], df['L_5'] =  df['H'].shift(-5), df['L'].shift(-5)
df['MAXH5'] = df['H'].rolling(window=5).max()
df['MINL5'] = df['L'].rolling(window=5).min()
df['MAXH_5'] = df['H_5'].rolling(window=5).max()
df['MINL_5'] = df['L_5'].rolling(window=5).min()
df.eval(" maximum5 = (MAXH5==H) & (MAXH_5==H)   ")
df.eval(" minimum5 = (MINL5==L) & (MINL_5==L)   ")
df.eval(" is_extremum_range5 = maximum5 | minimum5  ")

结果在列is_extremum_range5= {True| 错误的}

于 2019-11-20T11:06:45.867 回答
-2

费马定理将帮助您找到局部最小值和最大值。

于 2011-08-15T02:10:10.727 回答