New-b question

Hello all,

I am a ruby novice who would really appreciate some guidance with the
following:

I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.

n=5
dataset=[
25.0000,24.8750,24.7813,24.5938,24.5000,24.6250,25.2188,27.2500,26.2500,26.5938]

n.times do |period|
a = period+1
b = dataset[period]
c = a*b
puts c

end

output:

25.0
49.75
74.3439
98.3752
122.5

but what I now want it to do is add up the output and / 15, to give me
one number, approx 26.6646

Then using a loop, do the same again starting with the next number,
24.8750, and so on until it has gobe through the data series?

Many thanks for your time,

David

David N. wrote:

I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.

Does this help? You will need to handle the edge cases somehow…

$ ri Enumerable#each_cons | cat
--------------------------------------------------- Enumerable#each_cons
each_cons(n) {…}

  From Ruby 1.8

  Iterates the given block for each array of consecutive <n>
  elements.

  e.g.:

      (1..10).each_cons(3) {|a| p a}
      # outputs below
      [1, 2, 3]
      [2, 3, 4]
      [3, 4, 5]
      [4, 5, 6]
      [5, 6, 7]
      [6, 7, 8]
      [7, 8, 9]
      [8, 9, 10]

On Wed, Jun 17, 2009 at 3:33 PM, David N.
[email protected]wrote:

Hello all,

I am a ruby novice who would really appreciate some guidance with the
following:

I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.

This should do the trick for you

John

thanks very much for the replies,

How would I do that using and amending the original code?

cheers

John W Higgins wrote:

On Wed, Jun 17, 2009 at 3:33 PM, David N.
[email protected]wrote:

Hello all,

I am a ruby novice who would really appreciate some guidance with the
following:

I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.

This should do the trick for you

Weighted Average · GitHub

John

2009/6/18 John W Higgins [email protected]:

next * 4 etc etc. with the oldest (the 5th number) * 1.

This should do the trick for you

Weighted Average · GitHub

Here’s my suggestion

weights = (1…5).to_a
div = weights.inject(0){|s,x| s + x}.to_f

data = [
25.0000,
24.8750,
24.7813,
24.5938,
24.5000,
24.6250,
25.2188,
27.2500,
26.2500,
26.5938,
]

data.each_cons(weights.size).each_with_index do |c,i|
num = 0
c.zip(weights) {|a,b| num += a * b}
printf “period %2d: %8.3f\n”, i, num / div
end

You only need to change ‘weights’ and the calculation will still.

Kind regards

robert

On Thu, Jun 18, 2009 at 1:23 AM, David N.
[email protected]wrote:

thanks very much for the replies,

How would I do that using and amending the original code?

cheers

Are you still wishing to see all the intermediate steps (i.e. the value
of
255, 24.8574 etc etc etc)?

John

On Thu, Jun 18, 2009 at 4:24 PM, David N.
[email protected]wrote:


Hi John,

thanks for your patience.

In terms of the main objective, then no, they do not have to be there -
but I think it would help my understanding of what is happening if they
were there…

Ok then lets remove some of the ruby tricks and just make the code work
because as most programmers do I’ve pushed you into the deep end and you
are
looking to keep your feet solidly on the bottom of the pool while still
being able to breathe :slight_smile:

Lets try this gist:132285 · GitHub - a little more output at
each
step. It’s different then the first shot I took at it but it’s also much
easier to digest each piece and see what it’s doing.

John

John W Higgins wrote:

On Thu, Jun 18, 2009 at 1:23 AM, David N.
[email protected]wrote:

thanks very much for the replies,

How would I do that using and amending the original code?

cheers

Are you still wishing to see all the intermediate steps (i.e. the value
of
255, 24.8574 etc etc etc)?

John

Hi John,

thanks for your patience.

In terms of the main objective, then no, they do not have to be there -
but I think it would help my understanding of what is happening if they
were there…

2009/6/23 David N. [email protected]:

Thanks very much for that. It is very helpful. I think your summary is
pretty accurate of where I am right now - but I will get there!

If it helps you I can also provide some commenting of the code I
posted. Just let me know.

Kind regards

robert

Robert K. wrote:

2009/6/23 David N. [email protected]:

Thanks very much for that. It is very helpful. I think your summary is
pretty accurate of where I am right now - but I will get there!

If it helps you I can also provide some commenting of the code I
posted. Just let me know.

Kind regards

robert

Hi Again Robert,

I think I would find some comments on the code very helpful.

cheers

David

John W Higgins wrote:

On Thu, Jun 18, 2009 at 4:24 PM, David N.
[email protected]wrote:


Hi John,

thanks for your patience.

In terms of the main objective, then no, they do not have to be there -
but I think it would help my understanding of what is happening if they
were there…

Ok then lets remove some of the ruby tricks and just make the code work
because as most programmers do I’ve pushed you into the deep end and you
are
looking to keep your feet solidly on the bottom of the pool while still
being able to breathe :slight_smile:

Lets try this gist:132285 · GitHub - a little more output at
each
step. It’s different then the first shot I took at it but it’s also much
easier to digest each piece and see what it’s doing.

John

Hi John,

Thanks very much for that. It is very helpful. I think your summary is
pretty accurate of where I am right now - but I will get there!

2009/6/25 David N. [email protected]:

Robert K. wrote:

2009/6/23 David N. [email protected]:

I think I would find some comments on the code very helpful.

Ok, here we go. The basic idea is to have a single definition of the
weight handling and separate the algorithm from that. That way we can
use the algorithm for whatever weighting schemes we want to apply. I
have “repackaged” the code into a method of module Enumerable which
seems appropriate considering the genericity of the approach.

Basically we have two inputs for the algorithm:

  • enum of data
  • weighting scheme

module Enumerable

def weighting(weights)
if block_given?
# input: weights
weights = weights.to_a

  # derive the divisor once from the weights because
  # it depends on the weights and does not change
  # otherwise
  div = weights.inject(0){|s,x| s + x}.to_f

  # Now iterate through self using a sliding window
  # of weights.size elements (this is done by each_cons)
  # for each window we calculate the weighted average
  # and yield it to the block passed to this method
  # Array#zip is used to iterate the weights and the
  # sliding window in lock step.
  each_cons weights.size do |elements|
   sum = 0
   elements.zip(weights) {|n,w| sum += n * w}
   yield sum / div
  end

  self
else
  # create an Enumerator to allow for chaining.
  enum_for(:weighting, weights)
end

end

end

input to the calculation, weighting scheme:

weights = 1…5

second input, our data

data = [
25.0000,
24.8750,
24.7813,
24.5938,
24.5000,
24.6250,
25.2188,
27.2500,
26.2500,
26.5938,
]

data.weighting(weights).each_with_index do |avg, i|
printf “period %2d: %8.3f\n”, i, avg
end

Kind regards

robert