这是我之前关于定位高峰和低谷问题的更新。上一个问题是:
peaks and troughs in MATLAB (but with corresponding definition of a peak and trough)
这一次,我做了建议的答案,但我认为最终算法仍有问题。你能告诉我在我的代码中我做错了什么吗?感谢。
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
答案 0 :(得分: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;
答案 1 :(得分:0)
我认为找到峰值和谷值的技术比上面给出的百分比阈值技术更好。将最小二乘拟合抛物线拟合到数据集中,这样做的技术在1946年弗兰克彼得斯论文中,“抛物线相关,一种新的描述性统计”。如彼得斯所定义的那样,拟合的抛物线可能具有曲率指数。通过测试哪些点在消除时最小化抛物线曲率指数的绝对值来找到峰和谷。一旦发现这些点,通过考虑当排除该点时曲率指数如何变化来测试其峰值和谷值,这将取决于原始抛物线是否具有正曲率或负曲率指数。如果您担心连续点的消除达到最小绝对值曲率,则通过设置最小距离来约束所识别的点必须彼此相同。另一个限制因素必须是确定的点数。如果没有这个约束,该算法将除去除了两个点之外的所有点,即没有曲率的直线。 有时候,连续点之间会有很大的变化,两者都应该包含在极端点中。对覆盖最小距离约束的连续点的百分比阈值测试可能是有用的。 另一种解决方案可能是计算该系列的快速傅里叶变换并去除最小化较低光谱的点。 FFT函数比找到最小二乘拟合抛物线的代码更容易获得。有一种矩阵操作技术可用于确定比Peter的方法更易于管理的最小二乘拟合抛物线。我在某个地方看到它记录在网上,但丢失了链接。任何能够使用矩阵向量符号得出最小二乘拟合抛物线的人的建议将不胜感激。