In GNU Octave, would like to calculate an n-day exponential moving average of a vector without using a for-loop.
I am able to do this with a for loop but it is inefficient. I would like to use the filter function, however I am unsure how to get this to work correctly.
Reinventing the wheel on octave exponential moving average for a vector is silly. Just copy and paste movavg.m
function defined in the octave financial package here: 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
And invoke thustly:
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')
Which prints:
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