ruby-technical-analysis 0.1.1 → 1.0.4
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.
- checksums.yaml +4 -4
- data/lib/ruby-technical-analysis.rb +1 -0
- data/lib/ruby_technical_analysis/indicator.rb +41 -0
- data/lib/ruby_technical_analysis/indicators/bollinger_bands.rb +50 -0
- data/lib/ruby_technical_analysis/indicators/chaikin_money_flow.rb +47 -0
- data/lib/ruby_technical_analysis/indicators/chande_momentum_oscillator.rb +56 -0
- data/lib/ruby_technical_analysis/indicators/commodity_channel_index.rb +70 -0
- data/lib/ruby_technical_analysis/indicators/envelopes_ema.rb +48 -0
- data/lib/ruby_technical_analysis/indicators/intraday_momentum_index.rb +45 -0
- data/lib/ruby_technical_analysis/indicators/macd.rb +86 -0
- data/lib/ruby_technical_analysis/indicators/mass_index.rb +70 -0
- data/lib/ruby_technical_analysis/indicators/moving_averages.rb +71 -0
- data/lib/ruby_technical_analysis/indicators/pivot_points.rb +75 -0
- data/lib/ruby_technical_analysis/indicators/price_channel.rb +48 -0
- data/lib/ruby_technical_analysis/indicators/qstick.rb +44 -0
- data/lib/ruby_technical_analysis/indicators/rate_of_change.rb +40 -0
- data/lib/ruby_technical_analysis/indicators/relative_momentum_index.rb +79 -0
- data/lib/ruby_technical_analysis/indicators/relative_strength_index.rb +74 -0
- data/lib/ruby_technical_analysis/indicators/statistical_methods.rb +40 -0
- data/lib/ruby_technical_analysis/indicators/stochastic_oscillator.rb +99 -0
- data/lib/ruby_technical_analysis/indicators/volume_oscillator.rb +50 -0
- data/lib/ruby_technical_analysis/indicators/volume_rate_of_change.rb +48 -0
- data/lib/ruby_technical_analysis/indicators/wilders_smoothing.rb +47 -0
- data/lib/ruby_technical_analysis/indicators/williams_percent_r.rb +69 -0
- data/lib/ruby_technical_analysis.rb +24 -7
- data/spec/ruby_technical_analysis/indicator_spec.rb +76 -0
- data/spec/ruby_technical_analysis/indicators/bollinger_bands_spec.rb +67 -0
- data/spec/ruby_technical_analysis/indicators/chaikin_money_flow_spec.rb +63 -0
- data/spec/ruby_technical_analysis/indicators/chande_momentum_oscillator_spec.rb +59 -0
- data/spec/ruby_technical_analysis/indicators/commodity_channel_index_spec.rb +66 -0
- data/spec/ruby_technical_analysis/indicators/envelopes_ema_spec.rb +69 -0
- data/spec/ruby_technical_analysis/indicators/intraday_momentum_spec.rb +63 -0
- data/spec/ruby_technical_analysis/indicators/macd_spec.rb +61 -0
- data/spec/ruby_technical_analysis/indicators/mass_index_spec.rb +67 -0
- data/spec/ruby_technical_analysis/indicators/moving_averages_spec.rb +81 -0
- data/spec/ruby_technical_analysis/indicators/pivot_points_spec.rb +43 -0
- data/spec/ruby_technical_analysis/indicators/price_channel_spec.rb +64 -0
- data/spec/ruby_technical_analysis/indicators/qstick_spec.rb +59 -0
- data/spec/ruby_technical_analysis/indicators/rate_of_change_spec.rb +59 -0
- data/spec/ruby_technical_analysis/indicators/relative_momentum_index_spec.rb +67 -0
- data/spec/ruby_technical_analysis/indicators/relative_strength_index_spec.rb +59 -0
- data/spec/ruby_technical_analysis/indicators/statistical_methods_spec.rb +91 -0
- data/spec/ruby_technical_analysis/indicators/stochastic_oscillator_spec.rb +106 -0
- data/spec/ruby_technical_analysis/indicators/volume_oscillator_spec.rb +98 -0
- data/spec/ruby_technical_analysis/indicators/volume_rate_of_change_spec.rb +67 -0
- data/spec/ruby_technical_analysis/indicators/wiilders_smoothing_spec.rb +67 -0
- data/spec/ruby_technical_analysis/indicators/williams_percent_r_spec.rb +71 -0
- data/spec/spec_helper.rb +1 -0
- metadata +100 -40
- data/.rubocop.yml +0 -34
- data/CHANGELOG.md +0 -5
- data/CODE_OF_CONDUCT.md +0 -84
- data/Gemfile +0 -12
- data/LICENSE.txt +0 -21
- data/README.md +0 -36
- data/Rakefile +0 -16
- data/lib/ruby-technical-analysis/indicators/bollinger_bands.rb +0 -25
- data/lib/ruby-technical-analysis/indicators/chaikin_money_flow.rb +0 -70
- data/lib/ruby-technical-analysis/indicators/chande_momentum_oscillator.rb +0 -34
- data/lib/ruby-technical-analysis/indicators/commodity_channel_index.rb +0 -64
- data/lib/ruby-technical-analysis/indicators/envelopes_ema.rb +0 -24
- data/lib/ruby-technical-analysis/indicators/intraday_momentum_index.rb +0 -48
- data/lib/ruby-technical-analysis/indicators/macd.rb +0 -47
- data/lib/ruby-technical-analysis/indicators/mass_index.rb +0 -73
- data/lib/ruby-technical-analysis/indicators/pivot_points.rb +0 -23
- data/lib/ruby-technical-analysis/indicators/price_channel.rb +0 -37
- data/lib/ruby-technical-analysis/indicators/qstick.rb +0 -40
- data/lib/ruby-technical-analysis/indicators/rate_of_change.rb +0 -18
- data/lib/ruby-technical-analysis/indicators/relative_momentum_index.rb +0 -66
- data/lib/ruby-technical-analysis/indicators/relative_strength_index.rb +0 -63
- data/lib/ruby-technical-analysis/indicators/stochastic_oscillator.rb +0 -65
- data/lib/ruby-technical-analysis/indicators/volume_oscillator.rb +0 -38
- data/lib/ruby-technical-analysis/indicators/volume_rate_of_change.rb +0 -26
- data/lib/ruby-technical-analysis/indicators/wilders_smoothing.rb +0 -27
- data/lib/ruby-technical-analysis/indicators/williams_percent_r.rb +0 -52
- data/lib/ruby-technical-analysis/moving_averages.rb +0 -85
- data/lib/ruby-technical-analysis/statistical_methods.rb +0 -24
- data/lib/ruby-technical-analysis/version.rb +0 -5
- data/sig/ruby-technical-analysis.rbs +0 -4
@@ -0,0 +1,76 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe Indicator do
|
5
|
+
describe "#initialize" do
|
6
|
+
series = [10, 20, 30, 40, 50]
|
7
|
+
indicator = described_class.new(series: series)
|
8
|
+
|
9
|
+
it "initializes with a series of series" do
|
10
|
+
expect(indicator.series).to eq(series)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#call" do
|
15
|
+
it "is a class method" do
|
16
|
+
expect(described_class).to respond_to(:call)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Private methods only tested for base class
|
21
|
+
|
22
|
+
describe "#extract_series" do
|
23
|
+
series = [10, 20, 30, 40, 50]
|
24
|
+
indicator = described_class.new(series: series)
|
25
|
+
|
26
|
+
it "extracts the series from the series" do
|
27
|
+
expect(indicator.send(:extract_series)).to eq(series)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#extract_highs_lows_closes_volumes" do
|
32
|
+
highs = [1, 2, 3, 4, 5]
|
33
|
+
lows = [6, 7, 8, 9, 10]
|
34
|
+
closes = [11, 12, 13, 14, 15]
|
35
|
+
volumes = [100, 200, 300, 400, 500]
|
36
|
+
|
37
|
+
series = highs.zip(lows, closes, volumes)
|
38
|
+
indicator = described_class.new(series: series)
|
39
|
+
|
40
|
+
it "extracts the highs, lows, closes, and volumes from the series" do
|
41
|
+
expect(indicator.send(:extract_highs_lows_closes_volumes)).to eq([highs, lows, closes, volumes])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#extract_highs_lows_closes" do
|
46
|
+
highs = [1, 2, 3, 4, 5]
|
47
|
+
lows = [6, 7, 8, 9, 10]
|
48
|
+
closes = [11, 12, 13, 14, 15]
|
49
|
+
|
50
|
+
series = highs.zip(lows, closes)
|
51
|
+
indicator = described_class.new(series: series)
|
52
|
+
|
53
|
+
it "extracts the highs, lows, and closes from the series" do
|
54
|
+
expect(indicator.send(:extract_highs_lows_closes)).to eq([highs, lows, closes])
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#moving_averages" do
|
59
|
+
series = [10, 20, 30, 40, 50]
|
60
|
+
indicator = described_class.new(series: series)
|
61
|
+
|
62
|
+
it "calculates moving averages" do
|
63
|
+
expect(indicator.send(:moving_averages, period: 3)).to be_a(RubyTechnicalAnalysis::MovingAverages)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#statistical_methods" do
|
68
|
+
series = [10, 20, 30, 40, 50]
|
69
|
+
indicator = described_class.new(series: series)
|
70
|
+
|
71
|
+
it "performs statistical calculations" do
|
72
|
+
expect(indicator.send(:statistical_methods)).to be_a(RubyTechnicalAnalysis::StatisticalMethods)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe BollingerBands do
|
5
|
+
let(:series) { [31.875, 32.125, 32.3125, 32.125, 31.875] }
|
6
|
+
let(:period) { 5 }
|
7
|
+
|
8
|
+
let(:bollinger_bands) { described_class.new(series: series, period: period) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "initializes the BollingerBands object" do
|
12
|
+
expect(bollinger_bands).to be_an_instance_of(described_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "initializes with default period of 20" do
|
16
|
+
expect(described_class.new(series: series).period).to eq(20)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "initializes with default standard deviations of 2" do
|
20
|
+
expect(described_class.new(series: series).standard_deviations).to eq(2)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "class methods" do
|
25
|
+
describe "#call" do
|
26
|
+
let(:bollinger_bands) { described_class.call(series: series, period: period) }
|
27
|
+
|
28
|
+
it "returns an array containing the current upper, middle, and lower bands of the series" do
|
29
|
+
expect(bollinger_bands).to eq([32.397, 32.062, 31.727])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "instance methods" do
|
35
|
+
describe "#call" do
|
36
|
+
it "returns an array containing the current upper, middle, and lower bands of the series" do
|
37
|
+
expect(bollinger_bands.call).to eq([32.397, 32.062, 31.727])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#valid?" do
|
42
|
+
it "returns true when the period is less than or equal to the series length" do
|
43
|
+
expect(bollinger_bands.valid?).to be(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns false when the period is greater than the series length" do
|
47
|
+
expect(described_class.new(series: series, period: 6).valid?).to be(false)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "returns false when the standard deviations is less than or equal to 0" do
|
51
|
+
expect(described_class.new(series: series, standard_deviations: 0).valid?).to be(false)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "secondary series" do
|
57
|
+
series = [31.875, 32.125, 32.3125, 32.125, 31.875, 32.3125]
|
58
|
+
period = 5
|
59
|
+
|
60
|
+
expected_values = [32.508, 32.15, 31.791]
|
61
|
+
|
62
|
+
it "returns the expected values" do
|
63
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_values)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe ChaikinMoneyFlow do
|
5
|
+
let(:series) {
|
6
|
+
[[8.625, 8.3125, 8.625, 4494], [8.625, 8.4375, 8.5, 2090], [8.625, 8.4375, 8.625, 1306],
|
7
|
+
[8.75, 8.625, 8.75, 4242], [8.75, 8.4375, 8.5, 2874]]
|
8
|
+
}
|
9
|
+
let(:period) { 5 }
|
10
|
+
|
11
|
+
let(:cmf) { described_class.new(series: series, period: period) }
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "initializes the ChaikinMoneyFlow object" do
|
15
|
+
expect(cmf).to be_an_instance_of(described_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "initializes with default period of 21" do
|
19
|
+
expect(described_class.new(series: series).period).to eq(21)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "class methods" do
|
24
|
+
describe "#call" do
|
25
|
+
let(:cmf) { described_class.call(series: series, period: period) }
|
26
|
+
|
27
|
+
it "returns the ChaikinMoneyFlow value" do
|
28
|
+
expect(cmf.truncate(5)).to eq(0.50786)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "instance methods" do
|
34
|
+
describe "#call" do
|
35
|
+
it "returns the ChaikinMoneyFlow value" do
|
36
|
+
expect(cmf.call.truncate(5)).to eq(0.50786)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#valid?" do
|
41
|
+
it "returns true when the period is less than or equal to the series length" do
|
42
|
+
expect(cmf.valid?).to be(true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns false when the period is greater than the series length" do
|
46
|
+
expect(described_class.new(series: series, period: 6).valid?).to be(false)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "secondary series" do
|
52
|
+
series = [[8.625, 8.3125, 8.625, 4494], [8.625, 8.4375, 8.5, 2090], [8.625, 8.4375, 8.625, 1306],
|
53
|
+
[8.75, 8.625, 8.75, 4242], [8.75, 8.4375, 8.5, 2874], [8.5625, 8.5, 8.5, 598]]
|
54
|
+
period = 5
|
55
|
+
|
56
|
+
expected_value = 0.22763
|
57
|
+
|
58
|
+
it "returns the expected value" do
|
59
|
+
expect(described_class.new(series: series, period: period).call.truncate(5)).to eq(expected_value)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe ChandeMomentumOscillator do
|
5
|
+
let(:series) { [51.0625, 50.125, 52.3125, 52.1875, 53.1875, 53.0625] }
|
6
|
+
let(:period) { 5 }
|
7
|
+
|
8
|
+
let(:oscillator) { described_class.new(series: series, period: period) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "initializes the ChandeMomentumOscillator object" do
|
12
|
+
expect(oscillator).to be_an_instance_of(described_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "initializes with default period of 20" do
|
16
|
+
expect(described_class.new(series: series).period).to eq(20)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "class methods" do
|
21
|
+
describe "#call" do
|
22
|
+
let(:oscillator) { described_class.call(series: series, period: period) }
|
23
|
+
|
24
|
+
it "returns the ChandeMomentumOscillator value" do
|
25
|
+
expect(oscillator.truncate(4)).to eq(45.7143)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "instance methods" do
|
31
|
+
describe "#call" do
|
32
|
+
it "returns the ChandeMomentumOscillator value" do
|
33
|
+
expect(oscillator.call.truncate(4)).to eq(45.7143)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#valid?" do
|
38
|
+
it "returns true when the period is less than or equal to the series length" do
|
39
|
+
expect(oscillator.valid?).to be(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns false when the period is greater than the series length" do
|
43
|
+
expect(described_class.new(series: series, period: 6).valid?).to be(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "secondary series" do
|
49
|
+
series = [51.0625, 50.125, 52.3125, 52.1875, 53.1875, 53.0625, 54.0625]
|
50
|
+
period = 5
|
51
|
+
|
52
|
+
expected_value = 88.7324
|
53
|
+
|
54
|
+
it "returns the expected value" do
|
55
|
+
expect(described_class.new(series: series, period: period).call.truncate(4)).to eq(expected_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe CommodityChannelIndex do
|
5
|
+
let(:series) {
|
6
|
+
[[15.125, 14.936, 14.936], [15.052, 14.6267, 14.752], [14.8173, 14.5557, 14.5857],
|
7
|
+
[14.69, 14.46, 14.6], [14.7967, 14.5483, 14.6983], [14.7940, 13.9347, 13.946],
|
8
|
+
[14.093, 13.8223, 13.9827], [14.7, 14.02, 14.45], [14.5255, 14.2652, 14.3452]]
|
9
|
+
}
|
10
|
+
let(:period) { 5 }
|
11
|
+
|
12
|
+
let(:cci) { described_class.new(series: series, period: period) }
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "initializes the CommodityChannelIndex object" do
|
16
|
+
expect(cci).to be_an_instance_of(described_class)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "initializes with default period of 20" do
|
20
|
+
expect(described_class.new(series: series).period).to eq(20)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "class methods" do
|
25
|
+
describe "#call" do
|
26
|
+
let(:cci) { described_class.call(series: series, period: period) }
|
27
|
+
|
28
|
+
it "returns the CommodityChannelIndex value" do
|
29
|
+
expect(cci.truncate(4)).to eq(18.089)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "instance methods" do
|
35
|
+
describe "#call" do
|
36
|
+
it "returns the CommodityChannelIndex value" do
|
37
|
+
expect(cci.call.truncate(4)).to eq(18.089)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#valid?" do
|
42
|
+
it "returns true when the series is valid" do
|
43
|
+
expect(cci.valid?).to be_truthy
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns false when the series is not valid" do
|
47
|
+
expect(described_class.new(series: [], period: period).valid?).to be(false)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "secondary series" do
|
53
|
+
series = [[15.125, 14.936, 14.936], [15.052, 14.6267, 14.752], [14.8173, 14.5557, 14.5857],
|
54
|
+
[14.69, 14.46, 14.6], [14.7967, 14.5483, 14.6983], [14.794, 13.9347, 13.946],
|
55
|
+
[14.093, 13.8223, 13.9827], [14.7, 14.02, 14.45], [14.5255, 14.2652, 14.3452],
|
56
|
+
[14.6579, 14.3773, 14.4197]]
|
57
|
+
period = 5
|
58
|
+
|
59
|
+
expected_value = 84.4605
|
60
|
+
|
61
|
+
it "returns the expected value" do
|
62
|
+
expect(described_class.new(series: series, period: period).call.truncate(4)).to eq(expected_value)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe EnvelopesEma do
|
5
|
+
let(:series) { [25, 24.875, 24.781, 24.594, 24.5] }
|
6
|
+
let(:period) { 5 }
|
7
|
+
let(:percent) { 20 }
|
8
|
+
|
9
|
+
let(:envelopes_ema) { described_class.new(series: series, period: period, percent: 20) }
|
10
|
+
|
11
|
+
describe "#initialize" do
|
12
|
+
it "initializes the EnvelopesEma object" do
|
13
|
+
expect(envelopes_ema).to be_an_instance_of(described_class)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "initializes with default period of 20" do
|
17
|
+
expect(described_class.new(series: series).period).to eq(20)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes with default percent of 5" do
|
21
|
+
expect(described_class.new(series: series).percent).to eq(5)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "class methods" do
|
26
|
+
describe "#call" do
|
27
|
+
let(:envelopes_ema) { described_class.call(series: series, period: period, percent: 20) }
|
28
|
+
|
29
|
+
it "returns an array containing the current upper, middle, and lower bands of the series" do
|
30
|
+
expect(envelopes_ema).to eq([29.637, 24.698, 19.758])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "instance methods" do
|
36
|
+
describe "#call" do
|
37
|
+
it "returns an array containing the current upper, middle, and lower bands of the series" do
|
38
|
+
expect(envelopes_ema.call).to eq([29.637, 24.698, 19.758])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#valid?" do
|
43
|
+
it "returns true when the series is valid" do
|
44
|
+
expect(envelopes_ema.valid?).to be(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns false when the series is not valid" do
|
48
|
+
expect(described_class.new(series: [], period: period, percent: percent).valid?).to be(false)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns false when the percent is greater than 100" do
|
52
|
+
expect(described_class.new(series: series, period: period, percent: 101).valid?).to be(false)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "secondary series" do
|
58
|
+
series = [25, 24.875, 24.781, 24.594, 24.5, 24.625]
|
59
|
+
period = 5
|
60
|
+
percent = 20
|
61
|
+
|
62
|
+
expected_values = [29.588, 24.657, 19.725]
|
63
|
+
|
64
|
+
it "returns the expected values" do
|
65
|
+
expect(described_class.new(series: series, period: period, percent: percent).call).to eq(expected_values)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe IntradayMomentumIndex do
|
5
|
+
let(:series) {
|
6
|
+
[[18.4833, 18.5], [18.5417, 18.4167], [18.4167, 18.1667], [18.1667, 18.125], [18.1667, 17.9583],
|
7
|
+
[18.0417, 18], [18, 17.9583], [17.9167, 17.8333], [17.7917, 17.9583]]
|
8
|
+
}
|
9
|
+
let(:period) { 7 }
|
10
|
+
|
11
|
+
let(:imi) { described_class.new(series: series, period: period) }
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "initializes the IntradayMomentumIndex object" do
|
15
|
+
expect(imi).to be_an_instance_of(described_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "initializes with default period of 14" do
|
19
|
+
expect(described_class.new(series: series).period).to eq(14)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "class methods" do
|
24
|
+
describe "#call" do
|
25
|
+
let(:imi) { described_class.call(series: series, period: period) }
|
26
|
+
|
27
|
+
it "returns the IntradayMomentumIndex value" do
|
28
|
+
expect(imi).to eq(19.988)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "instance methods" do
|
34
|
+
describe "#call" do
|
35
|
+
it "returns the IntradayMomentumIndex value" do
|
36
|
+
expect(imi.call).to eq(19.988)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#valid?" do
|
41
|
+
it "returns true when the series is valid" do
|
42
|
+
expect(imi.valid?).to be(true)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns false when the series is not valid" do
|
46
|
+
expect(described_class.new(series: [], period: period).valid?).to be(false)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "secondary series" do
|
52
|
+
series = [[18.4833, 18.5], [18.5417, 18.4167], [18.4167, 18.1667], [18.1667, 18.125], [18.1667, 17.9583],
|
53
|
+
[18.0417, 18], [18, 17.9583], [17.9167, 17.8333], [17.7917, 17.9583], [18.0417, 18.5417]]
|
54
|
+
period = 7
|
55
|
+
|
56
|
+
expected_value = 61.5228
|
57
|
+
|
58
|
+
it "returns the expected value" do
|
59
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_value)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe Macd do
|
5
|
+
let(:series) {
|
6
|
+
[166.23, 164.51, 162.41, 161.62, 159.78, 159.69, 159.22, 170.33,
|
7
|
+
174.78, 174.61, 175.84, 172.9, 172.39, 171.66, 174.83, 176.28,
|
8
|
+
172.12, 168.64, 168.88, 172.79, 172.55, 168.88, 167.3, 164.32,
|
9
|
+
160.07, 162.74, 164.85, 165.12, 163.2, 166.56, 166.23, 163.17,
|
10
|
+
159.3, 157.44, 162.95]
|
11
|
+
}
|
12
|
+
|
13
|
+
let(:macd) { described_class.new(series: series) }
|
14
|
+
|
15
|
+
describe "#initialize" do
|
16
|
+
it "initializes the Macd object" do
|
17
|
+
expect(macd).to be_an_instance_of(described_class)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes with default fast_period of 12" do
|
21
|
+
expect(described_class.new(series: series).fast_period).to eq(12)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "initializes with default slow_period of 26" do
|
25
|
+
expect(described_class.new(series: series).slow_period).to eq(26)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "initializes with default signal_period of 9" do
|
29
|
+
expect(described_class.new(series: series).signal_period).to eq(9)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "class methods" do
|
34
|
+
describe "#call" do
|
35
|
+
let(:macd) { described_class.call(series: series) }
|
36
|
+
|
37
|
+
it "returns an array containing the current upper, middle, and lower bands of the series" do
|
38
|
+
expect(macd).to eq([-1.934, -1.664, -0.27])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "instance methods" do
|
44
|
+
describe "#call" do
|
45
|
+
it "returns an array containing the current upper, middle, and lower bands of the series" do
|
46
|
+
expect(macd.call).to eq([-1.934, -1.664, -0.27])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#valid?" do
|
51
|
+
it "returns true when the series is valid" do
|
52
|
+
expect(macd.valid?).to be(true)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns false when the series is not valid" do
|
56
|
+
expect(described_class.new(series: [], fast_period: 12, slow_period: 26, signal_period: 9).valid?).to be(false)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe MassIndex do
|
5
|
+
let(:series) {
|
6
|
+
[[38.125, 37.75], [38, 37.75], [37.9375, 37.8125], [37.875, 37.625], [38.125, 37.5],
|
7
|
+
[38.125, 37.5], [37.75, 37.5], [37.625, 37.4375], [37.6875, 37.375], [37.5, 37.375],
|
8
|
+
[37.5625, 37.375], [37.625, 36.8125], [36.6875, 36.3125], [36.875, 36.25], [36.9375, 36.5],
|
9
|
+
[36.5, 36.25], [36.9375, 36.3125], [37, 36.625], [36.875, 36.5625]]
|
10
|
+
}
|
11
|
+
let(:period) { 9 }
|
12
|
+
|
13
|
+
let(:mass_index) { described_class.new(series: series, period: period) }
|
14
|
+
|
15
|
+
describe "#initialize" do
|
16
|
+
it "initializes the MassIndex object" do
|
17
|
+
expect(mass_index).to be_an_instance_of(described_class)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes with default period of 9" do
|
21
|
+
expect(described_class.new(series: series).period).to eq(9)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "class methods" do
|
26
|
+
describe "#call" do
|
27
|
+
let(:mass_index) { described_class.call(series: series, period: period) }
|
28
|
+
|
29
|
+
it "returns the MassIndex value" do
|
30
|
+
expect(mass_index).to eq(3.2236)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "instance methods" do
|
36
|
+
describe "#call" do
|
37
|
+
it "returns the MassIndex value" do
|
38
|
+
expect(mass_index.call).to eq(3.2236)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#valid?" do
|
43
|
+
it "returns true when the series is valid" do
|
44
|
+
expect(mass_index.valid?).to be(true)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns false when the series is not valid" do
|
48
|
+
expect(described_class.new(series: [], period: period).valid?).to be(false)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "secondary series" do
|
54
|
+
series = [[38.125, 37.75], [38, 37.75], [37.9375, 37.8125], [37.875, 37.625], [38.125, 37.5],
|
55
|
+
[38.125, 37.5], [37.75, 37.75], [37.625, 37.4375], [37.6875, 37.375], [37.75, 37.375],
|
56
|
+
[37.5625, 37.375], [37.625, 36.8125], [36.6875, 36.3125], [36.875, 36.25], [36.9375, 36.5],
|
57
|
+
[36.5, 36.25], [36.9375, 36.3125], [37, 36.625], [36.875, 36.5625], [36.8125, 36.375]]
|
58
|
+
period = 9
|
59
|
+
|
60
|
+
expected_value = 3.1387
|
61
|
+
|
62
|
+
it "returns the expected value" do
|
63
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe MovingAverages do
|
5
|
+
let(:series) { [25, 24.875, 24.781, 24.594, 24.5] }
|
6
|
+
let(:period) { 5 }
|
7
|
+
|
8
|
+
let(:moving_averages) { described_class.new(series: series, period: period) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "initializes the MovingAverages object" do
|
12
|
+
expect(moving_averages).to be_an_instance_of(described_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "initializes with default period of 20" do
|
16
|
+
expect(described_class.new(series: series).period).to eq(20)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#sma" do
|
21
|
+
it "returns the simple moving average value" do
|
22
|
+
expect(moving_averages.sma.round(3)).to eq(24.75)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "secondary series" do
|
26
|
+
series = [25, 24.875, 24.781, 24.594, 24.5, 24.625]
|
27
|
+
period = 5
|
28
|
+
|
29
|
+
expected_value = 24.675
|
30
|
+
|
31
|
+
it "returns the expected value" do
|
32
|
+
expect(described_class.new(series: series, period: period).sma).to eq(expected_value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#ema" do
|
38
|
+
it "returns the exponential moving average value" do
|
39
|
+
expect(moving_averages.ema.round(3)).to eq(24.698)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "secondary series" do
|
43
|
+
series = [25, 24.875, 24.781, 24.594, 24.5, 24.625]
|
44
|
+
period = 5
|
45
|
+
|
46
|
+
expected_value = 24.657
|
47
|
+
|
48
|
+
it "returns the expected value" do
|
49
|
+
expect(described_class.new(series: series, period: period).ema.round(3)).to eq(expected_value)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#wma" do
|
55
|
+
it "returns the weighted moving average value" do
|
56
|
+
expect(moving_averages.wma.round(3)).to eq(24.665)
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "secondary series" do
|
60
|
+
series = [25, 24.875, 24.781, 24.594, 24.5, 24.625]
|
61
|
+
period = 5
|
62
|
+
|
63
|
+
expected_value = 24.623
|
64
|
+
|
65
|
+
it "returns the expected value" do
|
66
|
+
expect(described_class.new(series: series, period: period).wma.round(3)).to eq(expected_value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#valid?" do
|
72
|
+
it "returns true when the series is valid" do
|
73
|
+
expect(moving_averages.valid?).to be(true)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns false when the series is not valid" do
|
77
|
+
expect(described_class.new(series: [], period: period).valid?).to be(false)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|