查找股票图表的最小最大值

时间:2011-08-15 01:57:55

标签: algorithm finance stocks

stock

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

我有文本格式的数据,所以我不需要在图片中找到它。股票的问题在于他们拥有如此多的本地仓位和最大限度的简单衍生品将无法运作。

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

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

编辑:

我阅读了一些评论,但我没有意外地圈出一些最小值和最大值。

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

9 个答案:

答案 0 :(得分:13)

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

enter image description here

修改

如果它对某人有用,这是我的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]
  ]

答案 1 :(得分:4)

我不知道你的意思是简单的衍生物&#34;。我理解这意味着你已经测试了gradient descent,并且由于局部极值丰富而发现它不能令人满意。如果是这样,您想查看simulated annealing

  

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

     

(...)   然而,为了逃避局部最优,该算法将有可能向坏方向迈出一步:换句话说,采取增加最小化问题的值或减少的步骤最大化问题的价值。为了模拟退火过程,这个概率部分取决于温度&#34;算法中的参数,它以高值初始化并在每次迭代时减小。因此,算法最初很有可能远离附近(可能是本地的)最优。在迭代中,概率将减小,算法将收敛于(希望全局)最优,它没有机会逃脱。 (source,削减&amp;,强调我的)

知道,本地最佳值恰好是图形中的圆圈代表的,上面的,以及您想要找到的内容。但是,当我解释引用&#34; 如此多的本地分钟和最大的简单衍生物不会起作用。&#34;,这也正是你发现的太多。我认为你所有的&#34; zig-zag&#34;都有问题。你曲线使两个圆圈点之间。

所有这些似乎将你圈出的最佳点与曲线的其余点区分开来的是全局性,正是:找到比第一点更低的点你在左边圈你必须在x坐标中以进一步远离,而不是你需要为它的近邻做同样的事。这就是退火给你的东西:根据温度参数,你可以控制自己允许的跳跃大小。 是一个值,你可以抓住&#34; big&#34;当地的最佳,但却错过了&#34;小&#34;那些。我所暗示的并不是革命性的:有几个例子(例如1 2),人们从这些嘈杂的数据中获得了很好的结果。

答案 2 :(得分:3)

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

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

原因:高斯滤波器是唯一不会产生“伪”最大值的滤波器;最大的不是开始的。这在理论上已经证明了连续和离散数据(确保你使用离散高斯来表示离散数据!)。当您增加高斯西格玛时,局部最大值和最小值将以最直观的方式合并。因此,如果您希望每天不超过一个局部最大值,则将sigma设置为1,ET cetera。

答案 3 :(得分:2)

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

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

使用可调算法后,您可以调整它直到看起来正确。

答案 4 :(得分:2)

您可以使用Spline method为原始功能[具有所需程度]创建一个有争议的approximation polynom。拥有此多项式后,在其上查找[使用基本微积分]的局部最小值/最大值[生成的多项式]。

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

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

答案 5 :(得分:1)

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

  1. 执行FFT
  2. 在频率空间中进行带通。根据您希望极值看起来很好的数据范围,即感兴趣的时间刻度,选择带通'参数。
  3. 执行逆FFT。
  4. 选择生成曲线的局部最大值。
  5. 第二步的参数似乎很主观,但同样,主观性是股票图表分析的本质。

答案 6 :(得分:0)

正如belisarius所提到的,最好的方法似乎涉及平滑过滤数据。通过足够的平滑,寻找斜率的变化应该精确定位局部的分钟和最大值(导数将在这里有所帮助)。我会使用居中的滑动窗口来表示正在运行的中值/平均值,或者正在进行的EMA(或类似的IIR滤波器)。

答案 7 :(得分: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 | False}

答案 8 :(得分:-2)

Fermat's Theorem将帮助您找到本地最小值和最大值。