0

这是对上一个关于定位波峰和波谷的问题的更新。上一个问题是这样的:

MATLAB 中的波峰和波谷(但有相应的波峰和波谷定义)

这一次,我做了建议的答案,但我认为最终算法仍然存在问题。你能告诉我我的代码做错了什么吗?谢谢。

function [vectpeak, vecttrough]=peaktroughmodified(x,cutoff)

% This function is a modified version of the algorithm used to identify
% peaks and troughs in a series of prices. This will be used to identify
% the head and shoulders algorithm. The function gives you two vectors:
% PEAKS - an indicator vector that identifies the peaks in the function,
% and TROUGHS - an indicator vector that identifies the troughs of the
% function. The input is the vector of exchange rate series, and the cutoff
% used for refining possible peaks and troughs.

% Finding all possible peaks and troughs of our vector.
[posspeak,possploc]=findpeaks(x);
[posstrough,posstloc]=findpeaks(-x);
posspeak=posspeak';
posstrough=posstrough';

% Initialize vector of peaks and troughs.
numobs=length(x);
prelimpeaks=zeros(numobs,1); 
prelimtroughs=zeros(numobs,1);
numpeaks=numel(possploc);
numtroughs=numel(posstloc);

% Indicator for possible peaks and troughs.
for i=1:numobs
    for j=1:numpeaks
        if i==possploc(j);
            prelimpeaks(i)=1;
        end
    end
end

for i=1:numobs
    for j=1:numtroughs
       if i==posstloc(j);
            prelimtroughs(i)=1;
       end
    end
end

% Vector that gives location.
location=1:1:numobs;
location=location';

% From the list of possible peaks and troughs, find the peaks and troughs
% that fit Chang and Osler [1999] definition.
% "A peak is a local minimum at least x percent higher than the preceding
% trough, and a trough is a local minimum at least x percent lower than the
% preceding peak." [Chang and Osler, p.640]

% cutoffs
peakcutoff=1.0+cutoff; % cutoff for peaks
troughcutoff=1.0-cutoff; % cutoff for troughs


% First peak and first trough are initialized as previous peaks/troughs.

prevpeakloc=possploc(1);
prevtroughloc=posstloc(1);

% Initialize vectors of final peaks and troughs.
vectpeak=zeros(numobs,1);
vecttrough=zeros(numobs,1);

% We first check whether we start looking for peaks and troughs.
for i=1:numobs
    if prelimpeaks(i)==1;
       if i>prevtroughloc;
           ratio=x(i)/x(prevtroughloc);
           if ratio>peakcutoff;
               vectpeak(i)=1;
               prevpeakloc=location(i);
           else vectpeak(i)=0;
           end
       end
    elseif prelimtroughs(i)==1;
        if i>prevpeakloc;
            ratio=x(i)/x(prevpeakloc);
            if ratio<troughcutoff;
                vecttrough(i)=1;
                prevtroughloc=location(i);
            else vecttrough(i)=0;
            end
        end
    else
        vectpeak(i)=0;
        vecttrough(i)=0;
    end
end        
end
4

2 回答 2

0

我刚刚运行它,如果您进行此更改,它似乎可以工作:

peakcutoff= 1/cutoff; % cutoff for peaks
troughcutoff= cutoff; % cutoff for troughs

我用下面的代码对其进行了测试,截止值为 0.1(峰必须比谷大 10 倍),看起来很合理

x = randn(1,100).^2;
[vectpeak,vecttrough] = peaktroughmodified(x,0.1);
peaks = find(vectpeak);
troughs = find(vecttrough);
plot(1:100,x,peaks,x(peaks),'o',troughs,x(troughs),'o')

我强烈建议您阅读 matlab 中的矢量化。您的程序中有许多浪费的行,这使得它难以阅读,并且在大数据集时也会使其非常慢。例如,prelimpeaks 和 prelimtroughs 可以在没有循环的情况下完全定义,每个都在一行中:

prelimpeaks(possploc) = 1;
prelimtroughs(posstloc) = 1;
于 2012-09-19T19:23:50.263 回答
0

我认为找到峰值和谷值的技术比上面给出的百分比阈值技术更好。将最小二乘拟合抛物线拟合到数据集,实现这一点的技术在 1946 年 Frank Peters 的论文“抛物线相关性,一种新的描述性统计”中。正如彼得斯定义的那样,拟合的抛物线可能具有曲率指数。通过测试哪些点在消除时使抛物线曲率指数的绝对值最小化,从而找到峰和谷。一旦发现这些点,通过考虑在排除该点时曲率指数如何变化来测试哪些是峰,哪些是谷,这将取决于原始抛物线的曲率指数是正数还是负数。如果您担心连续点的消除会实现最小绝对值曲率,请通过设置识别点彼此之间的最小距离来进行约束。另一个约束必须是识别的点数。如果没有这个约束,这个算法将删除除两个点之外的所有点,一条没有曲率的直线。有时连续点之间存在急剧变化,两者都应包含在极值点中。也许覆盖最小距离约束的连续点的百分比阈值测试会很有用。另一种解决方案可能是计算级数的快速傅立叶变换并删除使较低光谱最小化的点。FFT 函数比找到最小二乘拟合抛物线的代码更容易获得。有一种用于确定最小二乘拟合抛物线的矩阵操作技术,它比 Peter 的方法更易于管理。我在某个地方看到它记录在网络上,但丢失了链接。任何能够使用矩阵向量表示法得出最小二乘拟合抛物线的人的建议将不胜感激。

于 2013-06-08T09:00:32.300 回答