5

我需要一种方法来识别Mathematica中时间序列数据中的局部最小值和最大值。这看起来应该是一件容易的事,但它会变得棘手。我在MathForum上发布了这篇文章,但是我想这里可能会有更多的关注。识别时间序列中重要的最小值和最大值w/Mathematica

你可以找到一个文件,在讨论这个问题:http://www.cs.cmu.edu/~eugene/research/full/compress-series.pdf

到目前为止,我已经试过这...

获取和格式化的一些数据:

data = FinancialData["SPY", {"May 1, 2006", "Jan. 21, 2011"}][[All, 2]]; 
data = data/[email protected]; 
data = Transpose[{Range[[email protected]], data}]; 

定义2个功能:

第一种方法:

findMinimaMaxima[data_, window_] := With[{k = window}, 
    data[[k + [email protected][Partition[data[[All, 2]], 2 k + 1, 1], x_List /; x[[k + 1]] < Min[Delete[x, k + 1]] || x[[k + 1]] > Max[Delete[x, k + 1]]]]]] 

现在另一种方法,虽然不够灵活:

findMinimaMaxima2[data_] := data[[[email protected](Length[#] & /@ Split[Prepend[Sign[[email protected][[All, 2]] - [email protected][[All, 2]]], 0]])]] 

看看每个功能做什么。第一findMinimaMaxima2 []:

minmax = findMinimaMaxima2[data]; 
{[email protected], [email protected]} 
[email protected] 

这将选择在大约49%的数据压缩所有的最大值和最小值和结果(在这种情况下),但它不具有扩大窗口的灵活性。 另一种方法。 2窗口,产生较少的,可以说是更重要的极值:

minmax2 = findMinimaMaxima[data, 2]; 
{[email protected], [email protected]} 
[email protected] 

但看看我们的窗口扩大到60会发生什么:

minmax2 = findMinimaMaxima[data, 60]; 
ListLinePlot[{data, minmax2}] 

一些不再交替的最小值和最大值的。 应用findMinimaMaxima2 []以findMinimaMaxima []的输出提供了一个解决办法...

minmax3 = findMinimaMaxima2[minmax2]; 
ListLinePlot[{data, minmax2, minmax3}] 

,但是这似乎是一个笨拙的方式来解决这个问题。

因此,使用固定窗口来查看左侧和右侧的想法并不完全符合人们的想法。我开始考虑另一种可以使用范围值R(例如向上或向下移动百分比)的函数来满足或超过该函数来设置下一个最小值或最大值的选项。这是我第一次尝试:

findMinimaMaxima3[data_, R_] := Module[{d, n, positions}, 
    d = data[[All, 2]]; 
    n = Transpose[{data[[All, 1]], [email protected][If[(#2 <= #1 + #1*R && #2 >= #1) || (#2 >= #1 - #1* R && #2 <= #1), #1, #2] &, d[[1]], d]}]; 
    n = Sign[[email protected][[All, 2]] - [email protected][[All, 2]]]; 
    positions = [email protected][Most[Position[n, Except[0]]]]; 
    data[[positions]] 
    ] 

minmax4 = findMinimaMaxima3[data, 0.1]; 
ListLinePlot[{data, minmax4}] 

这也与后处理的好处findMinimaMaxima2 []

ListLinePlot[{data, findMinimaMaxima2[minmax4]}] 

但是,如果你仔细观察,你会发现,如果他们超越的R值忽略了极端几个职位 - 包括图表的绝对最小值和最大值以及沿着上下的大动作。更改R值显示它如何错过顶部和底部甚至更多:

minmax4 = findMinimaMaxima3[data, 0.15]; 
ListLinePlot[{data, minmax4}] 

所以,我需要重新考虑。任何人都可以查看数据图并轻松识别重要的最小值和最大值。看起来很难得到一个算法来做到这一点。窗口和/或R值对解决方案看起来很重要,但它们本身似乎都不够(至少在以上方法中不是这样)。

任何人都可以扩展任何显示的方法或建议一个替代品来识别重要的最小值和最大值?

高兴地转发一个笔记本的所有代码和讨论。让我知道是否有人需要它。

谢谢 Jagra

+0

交替最大值和最小值标准在价格变化中并不总是很重要。像这里http://i.imgur.com/nsIK7.png – 2011-01-29 21:23:34

+0

请允许我欢迎您来到StackOverflow并提醒我们通常在这里做的三件事:1)当您获得帮助时,尝试给予它**回答问题**在您的专业领域2)[`阅读常见问题](http://tinyurl.com/2vycnvr)3)当您看到好的问答时,将它们投票[`使用灰色三角形](http:// i .imgur.com/kygEP.png),因为系统的可信度基于用户通过分享知识获得的声誉。还请记住接受更好地解决您的问题的答案,如果有的话['通过按复选标记符号](http://i.imgur.com/uqJeW.png) – 2011-02-12 02:12:54

回答

8

我建议使用迭代的方法。下面的函数从this post拍摄,虽然他们可以更简明地写,而不编译,他们会做的工作:

localMinPositionsC = 
Compile[{{pts, _Real, 1}}, 
    Module[{result = Table[0, {Length[pts]}], i = 1, ctr = 0}, 
    For[i = 2, i < Length[pts], i++, 
    If[pts[[i - 1]] > pts[[i]] && pts[[i + 1]] > pts[[i]], 
     result[[++ctr]] = i]]; 
    Take[result, ctr]]]; 

localMaxPositionsC = 
    Compile[{{pts, _Real, 1}}, 
    Module[{result = Table[0, {Length[pts]}], i = 1, ctr = 0}, 
     For[i = 2, i < Length[pts], i++, 
     If[pts[[i - 1]] < pts[[i]] && pts[[i + 1]] < pts[[i]], 
      result[[++ctr]] = i]]; 
     Take[result, ctr]]]; 

这里是你的数据图:

dplot = ListLinePlot[data] 

在这里,我们绘制分钟,其后3次迭代获得的:

mins = ListPlot[Nest[#[[localMinPositionsC[#[[All, 2]]]]] &, data, 3], 
    PlotStyle -> Directive[PointSize[0.015], Red]] 

同为最大值:

maxs = ListPlot[Nest[#[[localMaxPositionsC[#[[All, 2]]]]] &, data, 3], 
    PlotStyle -> Directive[PointSize[0.015], Green]] 

,并将所得的情节:

Show[{dplot, mins, maxs}] 

enter image description here

您可能会有所不同迭代次数,以获得更多的粗粒度或更细的最小值/最大值。

编辑:

其实,我只注意到了几个点仍用这种方法错过了,既为 最小值和最大值。所以,我建议它作为一个起点,而不是一个完整的解决方案。也许,你可以分析来自不同迭代的最小值/最大值,有时包括来自“前一个”,更细粒度的最小值/最大值。此外,这种类型的工作唯一的“物理原因”是,财务数据的性质似乎是分形的,有几个截然不同的尺度。上述Nest-s中的每次迭代都以特定比例为目标。这对于任意信号来说效果不佳。

相关问题