moving_average 0.0.4 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -67,6 +67,47 @@ class Array
67
67
  end
68
68
  alias_method :sma, :simple_moving_average
69
69
 
70
+ # Compute the smoothed moving average of the values of an Array.
71
+ #
72
+ # Formally, given that the first value for the SMMA is the SMA, subsequent
73
+ # values can be computed as
74
+ #
75
+ # (sma – smma_i-1 + a[i])
76
+ # -----------------------
77
+ # n
78
+ #
79
+ # where
80
+ #
81
+ # smma_i-1
82
+ #
83
+ # is the smoothed moving average of the previous index.
84
+ #
85
+ # Formula taken from
86
+ # https://mahifx.com/indicators/smoothed-moving-average-smma
87
+ #
88
+ # ==== Parameters
89
+ #
90
+ # * +idx+ - Optional, the index of the last datum to consider.
91
+ # * +tail+ - Optional, the number of data to consider.
92
+ def smoothed_moving_average(idx=nil, tail=nil)
93
+ # Set these manually here since we need the leading SMA.
94
+ if tail.nil?
95
+ idx = self.size - 1 if idx.nil?
96
+ tail = idx / 2
97
+ tail += 1 if idx.odd?
98
+ end
99
+ idx, tail = idx_and_tail_or_defaults(idx, tail)
100
+ valid_for_ma(idx, tail)
101
+ valid_for_ma(idx - tail, tail)
102
+ smma1 = self[idx - 2 * tail + 1..idx - tail].sma
103
+ (idx - tail + 1..idx).to_a.each do |tidx|
104
+ prevsum = self[tidx - tail + 1..tidx].sum
105
+ smma1 = (prevsum - smma1 + self[idx - (idx - tidx)]) / tail
106
+ end
107
+ smma1
108
+ end
109
+ alias_method :smma, :smoothed_moving_average
110
+
70
111
  # Compute the weighted moving average of the values of an Array.
71
112
  #
72
113
  # Formally, the WMA can be computed as n / d, where
@@ -1,3 +1,3 @@
1
1
  module MovingAverage
2
- VERSION = '0.0.4'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -52,6 +52,33 @@ describe MovingAverage do
52
52
  expect { [1, 2, 3].simple_moving_average(1, -1) }.to raise_exception(MovingAverage::Errors::InvalidTailError, "Given tail is <= 0.")
53
53
  expect { [1, 2, 3].simple_moving_average(1, 3) }.to raise_exception(MovingAverage::Errors::NotEnoughDataError, "Given tail is too large for idx.")
54
54
  end
55
+
56
+ end
57
+
58
+ describe "smoothed moving average" do
59
+
60
+ SMMA_DATA = (1..10).to_a.freeze
61
+ SMMA = 8.5
62
+
63
+ it "should work for missing arguments" do
64
+ SMMA_DATA.smoothed_moving_average.round(1).should ==(SMMA)
65
+ SMMA_DATA.smma.round(1).should ==(SMMA)
66
+ SMMA_DATA.smoothed_moving_average(9).round(1).should ==(SMMA)
67
+ SMMA_DATA.smma(9).round(1).should ==(SMMA)
68
+ end
69
+
70
+ it "should work for valid arguments" do
71
+ SMMA_DATA.smoothed_moving_average(9, 5).round(1).should ==(SMMA)
72
+ SMMA_DATA.smma(9, 5).round(1).should ==(SMMA)
73
+ end
74
+
75
+ it "should raise proper errors for invalid arguments" do
76
+ expect { [1, 2, 3].smoothed_moving_average(-1, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
77
+ expect { [1, 2, 3].smoothed_moving_average(3, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
78
+ expect { [1, 2, 3].smoothed_moving_average(1, -1) }.to raise_exception(MovingAverage::Errors::InvalidTailError, "Given tail is <= 0.")
79
+ expect { [1, 2, 3].smoothed_moving_average(1, 3) }.to raise_exception(MovingAverage::Errors::NotEnoughDataError, "Given tail is too large for idx.")
80
+ end
81
+
55
82
  end
56
83
 
57
84
  describe "weighted moving average" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moving_average
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-17 00:00:00.000000000 Z
12
+ date: 2013-03-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec