moving_average 0.0.2 → 0.0.3
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.
- data/lib/moving_average/moving_average.rb +16 -3
- data/lib/moving_average/version.rb +1 -1
- data/spec/moving_average_spec.rb +67 -29
- metadata +38 -55
@@ -1,5 +1,15 @@
|
|
1
1
|
class Array
|
2
2
|
|
3
|
+
def idx_and_tail_or_defaults(idx, tail)
|
4
|
+
if tail.nil?
|
5
|
+
tail = self.size
|
6
|
+
if idx.nil?
|
7
|
+
idx = self.size - 1
|
8
|
+
end
|
9
|
+
end
|
10
|
+
[idx, tail]
|
11
|
+
end; private :idx_and_tail_or_defaults
|
12
|
+
|
3
13
|
def valid_for_ma(idx, tail)
|
4
14
|
unless idx >= 0 && idx < self.size
|
5
15
|
raise MovingAverage::Errors::InvalidIndexError
|
@@ -13,7 +23,8 @@ class Array
|
|
13
23
|
true
|
14
24
|
end; private :valid_for_ma
|
15
25
|
|
16
|
-
def exponential_moving_average(idx, tail)
|
26
|
+
def exponential_moving_average(idx=nil, tail=nil)
|
27
|
+
idx, tail = idx_and_tail_or_defaults(idx, tail)
|
17
28
|
valid_for_ma(idx, tail)
|
18
29
|
# Taken from
|
19
30
|
# http://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
|
@@ -27,13 +38,15 @@ class Array
|
|
27
38
|
end
|
28
39
|
alias_method :ema, :exponential_moving_average
|
29
40
|
|
30
|
-
def simple_moving_average(idx, tail)
|
41
|
+
def simple_moving_average(idx=nil, tail=nil)
|
42
|
+
idx, tail = idx_and_tail_or_defaults(idx, tail)
|
31
43
|
valid_for_ma(idx, tail)
|
32
44
|
self[idx-tail+1..idx].sum.to_f / tail
|
33
45
|
end
|
34
46
|
alias_method :sma, :simple_moving_average
|
35
47
|
|
36
|
-
def weighted_moving_average(idx, tail)
|
48
|
+
def weighted_moving_average(idx=nil, tail=nil)
|
49
|
+
idx, tail = idx_and_tail_or_defaults(idx, tail)
|
37
50
|
valid_for_ma(idx, tail)
|
38
51
|
# Taken from
|
39
52
|
# http://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average
|
data/spec/moving_average_spec.rb
CHANGED
@@ -2,46 +2,84 @@ require 'moving_average'
|
|
2
2
|
|
3
3
|
describe MovingAverage do
|
4
4
|
|
5
|
-
|
5
|
+
describe "exponential moving average" do
|
6
|
+
|
6
7
|
# Example taken from
|
7
8
|
# http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
|
8
|
-
|
9
|
-
|
10
|
-
a.ema(9, 10).round(3).should eql(22.247)
|
11
|
-
end
|
9
|
+
EMA_DATA = [22.27, 22.19, 22.08, 22.17, 22.18, 22.13, 22.23, 22.43, 22.24, 22.29].freeze
|
10
|
+
EMA = 22.247
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
it "should work for missing arguments" do
|
13
|
+
EMA_DATA.exponential_moving_average.round(3).should eql(EMA)
|
14
|
+
EMA_DATA.ema.round(3).should eql(EMA)
|
15
|
+
EMA_DATA.exponential_moving_average(9).round(3).should eql(EMA)
|
16
|
+
EMA_DATA.ema(9).round(3).should eql(EMA)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should work for valid arguments" do
|
20
|
+
# Example taken from
|
21
|
+
# http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
|
22
|
+
EMA_DATA.exponential_moving_average(9, 10).round(3).should eql(EMA)
|
23
|
+
EMA_DATA.ema(9, 10).round(3).should eql(EMA)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise proper errors for invalid arguments" do
|
27
|
+
expect { [1, 2, 3].exponential_moving_average(-1, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
28
|
+
expect { [1, 2, 3].exponential_moving_average(3, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
29
|
+
expect { [1, 2, 3].exponential_moving_average(1, -1) }.to raise_exception(MovingAverage::Errors::InvalidTailError, "Given tail is <= 0.")
|
30
|
+
expect { [1, 2, 3].exponential_moving_average(1, 3) }.to raise_exception(MovingAverage::Errors::NotEnoughDataError, "Given tail is too large for idx.")
|
31
|
+
end
|
19
32
|
|
20
|
-
it "simple moving average should work" do
|
21
|
-
(1..5).to_a.simple_moving_average(4, 5).should ==(3)
|
22
|
-
(1..5).to_a.sma(4, 5).should ==(3)
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
35
|
+
describe "simple moving average" do
|
36
|
+
|
37
|
+
it "should work for missing arguments" do
|
38
|
+
(1..5).to_a.simple_moving_average.should ==(3)
|
39
|
+
(1..5).to_a.sma.should ==(3)
|
40
|
+
(1..5).to_a.simple_moving_average(4).should ==(3)
|
41
|
+
(1..5).to_a.sma(4).should ==(3)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should work for valid arguments" do
|
45
|
+
(1..5).to_a.simple_moving_average(4, 5).should ==(3)
|
46
|
+
(1..5).to_a.sma(4, 5).should ==(3)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should raise proper errors for invalid arguments" do
|
50
|
+
expect { [1, 2, 3].simple_moving_average(-1, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
51
|
+
expect { [1, 2, 3].simple_moving_average(3, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
52
|
+
expect { [1, 2, 3].simple_moving_average(1, -1) }.to raise_exception(MovingAverage::Errors::InvalidTailError, "Given tail is <= 0.")
|
53
|
+
expect { [1, 2, 3].simple_moving_average(1, 3) }.to raise_exception(MovingAverage::Errors::NotEnoughDataError, "Given tail is too large for idx.")
|
54
|
+
end
|
30
55
|
end
|
31
56
|
|
32
|
-
|
57
|
+
describe "weighted moving average" do
|
58
|
+
|
33
59
|
# Example taken from
|
34
60
|
# http://daytrading.about.com/od/indicators/a/MovingAverages.htm
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
61
|
+
WMA_DATA = [1.2900, 1.2900, 1.2903, 1.2904].freeze
|
62
|
+
WMA = 1.29025
|
63
|
+
|
64
|
+
it "should work for missing arguments" do
|
65
|
+
WMA_DATA.weighted_moving_average.should eql(WMA)
|
66
|
+
WMA_DATA.wma.should eql(WMA)
|
67
|
+
WMA_DATA.weighted_moving_average(3).should eql(WMA)
|
68
|
+
WMA_DATA.wma(3).should eql(WMA)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should work for valid arguments" do
|
72
|
+
WMA_DATA.weighted_moving_average(3, 4).should eql(WMA)
|
73
|
+
WMA_DATA.wma(3, 4).should eql(WMA)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should raise proper errors for invalid arguments" do
|
77
|
+
expect { [1, 2, 3].weighted_moving_average(-1, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
78
|
+
expect { [1, 2, 3].weighted_moving_average(3, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
79
|
+
expect { [1, 2, 3].weighted_moving_average(1, -1) }.to raise_exception(MovingAverage::Errors::InvalidTailError, "Given tail is <= 0.")
|
80
|
+
expect { [1, 2, 3].weighted_moving_average(1, 3) }.to raise_exception(MovingAverage::Errors::NotEnoughDataError, "Given tail is too large for idx.")
|
81
|
+
end
|
39
82
|
|
40
|
-
it "weighted moving average should raise proper errors for invalid arguments" do
|
41
|
-
expect { [1, 2, 3].weighted_moving_average(-1, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
42
|
-
expect { [1, 2, 3].weighted_moving_average(3, 3) }.to raise_exception(MovingAverage::Errors::InvalidIndexError, "Given idx is outside the Array.")
|
43
|
-
expect { [1, 2, 3].weighted_moving_average(1, -1) }.to raise_exception(MovingAverage::Errors::InvalidTailError, "Given tail is <= 0.")
|
44
|
-
expect { [1, 2, 3].weighted_moving_average(1, 3) }.to raise_exception(MovingAverage::Errors::NotEnoughDataError, "Given tail is too large for idx.")
|
45
83
|
end
|
46
84
|
|
47
85
|
end
|
metadata
CHANGED
@@ -1,48 +1,40 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: moving_average
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 2
|
10
|
-
version: 0.0.2
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Brad Cater
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-03-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: rspec
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
18
|
+
requirements:
|
27
19
|
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 2
|
32
|
-
- 13
|
33
|
-
version: "2.13"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '2.13'
|
34
22
|
type: :development
|
35
|
-
|
36
|
-
|
37
|
-
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.13'
|
30
|
+
description: This gem adds methods to the Array class to compute different types of
|
31
|
+
moving averages.
|
32
|
+
email:
|
38
33
|
- bradcater@gmail.com
|
39
34
|
executables: []
|
40
|
-
|
41
35
|
extensions: []
|
42
|
-
|
43
36
|
extra_rdoc_files: []
|
44
|
-
|
45
|
-
files:
|
37
|
+
files:
|
46
38
|
- .gitignore
|
47
39
|
- Gemfile
|
48
40
|
- LICENSE
|
@@ -54,39 +46,30 @@ files:
|
|
54
46
|
- lib/moving_average/version.rb
|
55
47
|
- moving_average.gemspec
|
56
48
|
- spec/moving_average_spec.rb
|
57
|
-
|
58
|
-
homepage: ""
|
49
|
+
homepage: ''
|
59
50
|
licenses: []
|
60
|
-
|
61
51
|
post_install_message:
|
62
52
|
rdoc_options: []
|
63
|
-
|
64
|
-
require_paths:
|
53
|
+
require_paths:
|
65
54
|
- lib
|
66
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
56
|
none: false
|
68
|
-
requirements:
|
69
|
-
- -
|
70
|
-
- !ruby/object:Gem::Version
|
71
|
-
|
72
|
-
|
73
|
-
- 0
|
74
|
-
version: "0"
|
75
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
62
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
81
|
-
segments:
|
82
|
-
- 0
|
83
|
-
version: "0"
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
84
67
|
requirements: []
|
85
|
-
|
86
68
|
rubyforge_project:
|
87
|
-
rubygems_version: 1.
|
69
|
+
rubygems_version: 1.8.23
|
88
70
|
signing_key:
|
89
71
|
specification_version: 3
|
90
|
-
summary: This gem adds methods to the Array class to compute different types of moving
|
91
|
-
|
72
|
+
summary: This gem adds methods to the Array class to compute different types of moving
|
73
|
+
averages.
|
74
|
+
test_files:
|
92
75
|
- spec/moving_average_spec.rb
|