I implemented your suggestions below, and, at least
for my few test cases so far, it works great, and I'm now starting to
understand the filter() arguments. It doesn't match movavg() from the
financial package perfectly for the first n days but I think that's because I
assume the negative time values of the asset are all equal to asset(1).
The reason why I like filter() better than movavg() is because filter() is
vectorized (movavg() has a for loop). Plus, movavg() is broken for
exponential cases. Thanks James!
FWIW, here's my moving average function (with no for
loops):
function [ma] = mafilter(asset, ma_alphatype,
ma_days, ma_alpha)
if ma_alphatype ==
"e"
# calculate exponential moving averages (don't use movavg() here cuz it's
broken)
alpha = 2 /
(ma_days+1);
ma =
filter(alpha, [1 alpha-1], asset,
asset(1)*(1-alpha));
else
coef_v =
(ma_days:-1:1).^ma_alpha; #
determine vector
coefficients
coef_v
=
coef_v/sum(coef_v); #
sum vector coefficients to equal
1
si =
repmat(asset(1), 1, ma_days-1); #
begin building initial cond by repeating first
value
si =
conv(si,coef_v);
# convolve initial cond with
coefficients
si =
si(ma_days :
end);
# keep only the last part as the true initial
condition
ma =
filter(coef_v, 1, asset,
si);
# run the filter
endif;
endfunction
Hi Tim,
Someone a few months ago had a similar problem with the
filter function. The problem is that the 4th argument to the filter
function (the initial conditions of the filter, SI it is called) don't
specify x(n) for n < 0, like you would intuitively think so. They
represent the internal states of the filter, which are less than intuitive
to say the least. (And isn't documented in the help text of the filter
function).
Anyway, the essence is that to make a "more" efficient filter
you can implement a filter where there are these internal states. And
you need to do a precomputing step if you want to find the initial states.
These are just back of the envelope calculations, so I provide no
guarantees. I also assume that a = 1 (i.e. no feedback) which is true
for a moving average filter as you have in your example.
Let, b be the vectors of coefficients in your filter be of length n and
initial_x be a vector of the values from t = -n+1 to t=-1. Then, I
did
tmp_var = conv(initial_x, b);
si = tmp_var(n:end);
Then,
z = filter(b, 1, x, si);
I think should give you want you want. I just tested this in the
corner case where I set all the initial_x variables were constant (so I'd
know that the moving average of them should be that constant) and it behaved
as expected. But like I said before, I'd use with caution till you try
it out a bit. I make no guarantees.
It should be possible (and probably pretty easy, but I'm just not
seeing it now) to allow an a coefficient vector thats not equal to 1 and
still solve for the si variable, but it just hit midnight here and I need
some sleep.
I hope this helps.
On Thu, Sep 16, 2010 at 2:41 PM, Tim Rueth
<address@hidden> wrote:
Octave experts:
I have been using filter() to compute a
weighted moving average, ma1, of a vector, cls_v, with a weighting
factor, alpha. I just found out that the first num_days-1 of the
moving average are not correct. I'm assuming I don't have a
filter coefficient quite correct or something, but I'm stuck. I
tried to understand the formula in help, but got lost. Any
takers?
Here's my current
code:
coef_v =
(num_days : -1 : 1).^alpha;
coef_v =
coef_v/sum(coef_v);
# sum vector coefficients to equal 1
si =
repmat(cls_v(1), 1, num_days - 1);
ma1 =
filter(coef_v, 1, cls_v, si);
Thanks,
--Tim
_______________________________________________
Help-octave
mailing list
address@hidden
https://www-old.cae.wisc.edu/mailman/listinfo/help-octave