1

在 GNU Octave 中,想在不使用 for 循环的情况下计算向量的 n 天指数移动平均值。

我可以使用 for 循环来做到这一点,但效率低下。我想使用过滤器功能,但是我不确定如何让它正常工作。

4

2 回答 2

1

将这个线程的位拼凑在一起后

http://octave.1599824.n4.nabble.com/vectorized-moving-average-td2132090.html

我使用 Octave 的过滤器功能构建了这个功能。

function meanV = movingEMean(V, window)
  simpleAvg = mean(V(1:window));
  alpha = 1/window;
  X = V(window:end);
  X(1) = simpleAvg;
  meanV = filter(alpha, [1 alpha-1], X, simpleAvg*(1-alpha));
end

它以简单的移动平均线为基础开始。V是用于计算指数移动平均线的数字的列向量。 window是天数的整数。我用了12。

这是这个函数的数学解释。

http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average

请注意,页面使用2/(n+1)(where niswindow或天数) as alpha,但我使用1/n该值是因为该值alpha符合我的需要。alpha根据需要进行调整。

或者,我有时需要我的输入和输出向量的尺寸来匹配。NaN我通过添加meanV = [NaN(window-1,1); meanV];作为函数的最后一行来填充无效值movingEMeansimpleAvg如果你想要一个粗略的估计,你也可以填写它。

于 2012-12-09T01:15:29.323 回答
0

在向量的倍频程指数移动平均线上重新发明轮子是愚蠢的。只需在此处复制和粘贴movavg.moctave 财务包中定义的功能:https ://octave.sourceforge.io/financial :

function [varargout] = movavg(asset, lead, lag, alpha = 0) 
  if nargin < 3 || nargin > 4 
    print_usage (); 
  endif 
  if lead > lag 
    error ("lead must be <= lag") 
  elseif ischar (alpha) 
    if ! strcmpi (alpha, "e") 
      error ("alpha must be 'e' if it is a char"); 
    endif 
  elseif ! isnumeric (alpha) 
    error ("alpha must be numeric or 'e'") 
  endif 
  ## Compute the weights 
  if ischar (alpha) 
    lead = exp(1:lead); 
    lag  = exp(1:lag); 
  else 
    lead = (1:lead).^alpha; 
    lag  = (1:lag).^alpha; 
  endif 
  ## Adjust the weights to equal 1 
  lead = lead / sum (lead); 
  lag  = lag / sum (lag); 
  short = asset; 
  long  = asset; 
  for i = 1:length (asset) 
    if i < length (lead) 
      ## Compute the run-in period 
      r        = length (lead) - i + 1:length(lead); 
      short(i) = dot (asset(1:i), lead(r))./sum (lead(r)); 
    else 
      short(i) = dot (asset(i - length(lead) + 1:i), lead); 
    endif 
    if i < length (lag) 
      r       = length (lag) - i + 1:length(lag); 
      long(i) = dot (asset(1:i), lag(r))./sum (lag(r)); 
    else 
      long(i) = dot (asset(i - length(lag) + 1:i), lag); 
    endif 
  endfor 
  if nargout > 0 
    varargout{1} = short; 
  else 
    plot((1:length(asset))', [asset(:), long(:), short(:)]); 
  endif 
  if nargout > 1 
    varargout{2} = long; 
  endif 
endfunction 

并如此调用:

foo = [NaN; 1;4;8;10;-3;3;4;0;0;3;4;5;6;7;8;9];     
lead = 7 
lag = 7
alpha = 'e' 
movavg(foo, lead, lag, 'e')

哪个打印:

       NaN
       NaN
       NaN
       NaN
       NaN
       NaN
       NaN
   3.39851
   1.24966
   0.45742
   2.06175
   3.28350
   4.37315
   5.40325
   6.41432
   7.42128
   8.42441
于 2022-01-06T22:14:42.297 回答