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,43 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe PivotPoints do
|
5
|
+
let(:series) { [176.65, 152, 165.12] }
|
6
|
+
|
7
|
+
let(:pivot_points) { described_class.new(series: series) }
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
it "initializes the PivotPoints object" do
|
11
|
+
expect(pivot_points).to be_an_instance_of(described_class)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "class methods" do
|
16
|
+
describe "#call" do
|
17
|
+
let(:pivot_points) { described_class.call(series: series) }
|
18
|
+
|
19
|
+
it "returns an array containing the current support levels, pivot, and resistance levels" do
|
20
|
+
expect(pivot_points).to eq([127.88, 139.94, 152.53, 164.59, 177.18, 189.24, 201.83])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "instance methods" do
|
26
|
+
describe "#call" do
|
27
|
+
it "returns an array containing the current support levels, pivot, and resistance levels" do
|
28
|
+
expect(pivot_points.call).to eq([127.88, 139.94, 152.53, 164.59, 177.18, 189.24, 201.83])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#valid?" do
|
33
|
+
it "returns true if the object is valid" do
|
34
|
+
expect(pivot_points.valid?).to eq(true)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "returns false if the object is invalid" do
|
38
|
+
expect(described_class.new(series: []).valid?).to eq(false)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe PriceChannel do
|
5
|
+
let(:series) {
|
6
|
+
[[2.8097, 2.8437], [2.9063, 2.8543], [2.875, 2.8333], [2.8543, 2.8127], [2.974, 2.8647],
|
7
|
+
[3.073, 2.9793]]
|
8
|
+
}
|
9
|
+
|
10
|
+
let(:period) { 5 }
|
11
|
+
|
12
|
+
let(:price_channel) { described_class.new(series: series, period: period) }
|
13
|
+
|
14
|
+
describe "#initialize" do
|
15
|
+
it "initializes the PriceChannel object" do
|
16
|
+
expect(price_channel).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(:price_channel) { described_class.call(series: series, period: period) }
|
27
|
+
|
28
|
+
it "returns an array containing the upper and lower levels" do
|
29
|
+
expect(price_channel).to eq([2.974, 2.8127])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "instance methods" do
|
35
|
+
describe "#call" do
|
36
|
+
it "returns an array containing the upper and lower levels" do
|
37
|
+
expect(price_channel.call).to eq([2.974, 2.8127])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#valid?" do
|
42
|
+
it "returns true if the object is valid" do
|
43
|
+
expect(price_channel.valid?).to eq(true)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns false if the object is invalid" do
|
47
|
+
expect(described_class.new(series: []).valid?).to eq(false)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "secondary series" do
|
53
|
+
series = [[2.8097, 2.8437], [2.9063, 2.8543], [2.875, 2.8333], [2.8543, 2.8127], [2.974, 2.8647],
|
54
|
+
[3.073, 2.9793], [3.1563, 3.0937]]
|
55
|
+
period = 5
|
56
|
+
|
57
|
+
expected_values = [3.073, 2.8127]
|
58
|
+
|
59
|
+
it "returns the expected values" do
|
60
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_values)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe QStick do
|
5
|
+
let(:series) { [[62.5625, 64.5625], [64.625, 64.125], [63.5625, 64.3125], [63.9375, 64.875]] }
|
6
|
+
let(:period) { 4 }
|
7
|
+
|
8
|
+
let(:q_stick) { described_class.new(series: series, period: period) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "initializes the QStick object" do
|
12
|
+
expect(q_stick).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(:q_stick) { described_class.call(series: series, period: period) }
|
23
|
+
|
24
|
+
it "returns the QStick value" do
|
25
|
+
expect(q_stick).to eq(0.7969)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "instance methods" do
|
31
|
+
describe "#call" do
|
32
|
+
it "returns the QStick value" do
|
33
|
+
expect(q_stick.call).to eq(0.7969)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#valid?" do
|
38
|
+
it "returns true when the series is valid" do
|
39
|
+
expect(q_stick.valid?).to be(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns false when the series is not valid" do
|
43
|
+
expect(described_class.new(series: [], period: period).valid?).to be(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "secondary series" do
|
49
|
+
series = [[62.5625, 64.5625], [64.625, 64.125], [63.5625, 64.3125], [63.9375, 64.875], [64.5, 65.1875]]
|
50
|
+
period = 4
|
51
|
+
|
52
|
+
expected_value = 0.4688
|
53
|
+
|
54
|
+
it "returns the expected value" do
|
55
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe RateOfChange do
|
5
|
+
let(:series) { [5.5625, 5.375, 5.375, 5.0625] }
|
6
|
+
let(:period) { 3 }
|
7
|
+
|
8
|
+
let(:roc) { described_class.new(series: series, period: period) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "initializes the RateOfChange object" do
|
12
|
+
expect(roc).to be_an_instance_of(described_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "initializes with default period of 30" do
|
16
|
+
expect(described_class.new(series: series).period).to eq(30)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "class methods" do
|
21
|
+
describe "#call" do
|
22
|
+
let(:roc) { described_class.call(series: series, period: period) }
|
23
|
+
|
24
|
+
it "returns the RateOfChange value" do
|
25
|
+
expect(roc).to eq(-8.99)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "instance methods" do
|
31
|
+
describe "#call" do
|
32
|
+
it "returns the RateOfChange value" do
|
33
|
+
expect(roc.call).to eq(-8.99)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#valid?" do
|
38
|
+
it "returns true when the series is valid" do
|
39
|
+
expect(roc.valid?).to be(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns false when the series is not valid" do
|
43
|
+
expect(described_class.new(series: [1, 2, 3], period: period).valid?).to be(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "secondary series" do
|
49
|
+
series = [5.5625, 5.375, 5.375, 5.0625, 5.1094]
|
50
|
+
period = 3
|
51
|
+
|
52
|
+
expected_value = -4.94
|
53
|
+
|
54
|
+
it "returns the expected value" do
|
55
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe RelativeMomentumIndex do
|
5
|
+
let(:series) {
|
6
|
+
[6.875, 6.9375, 6.8125, 6.6095, 6.7345, 6.672, 6.625, 6.6875, 6.547, 6.6563, 6.672, 6.6563]
|
7
|
+
}
|
8
|
+
let(:period_mom) { 4 }
|
9
|
+
let(:period_rmi) { 8 }
|
10
|
+
|
11
|
+
let(:rmi) { described_class.new(series: series, period_mom: period_mom, period_rmi: period_rmi) }
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it "initializes the RelativeMomentumIndex object" do
|
15
|
+
expect(rmi).to be_an_instance_of(described_class)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "initializes with default period_mom of 14" do
|
19
|
+
expect(described_class.new(series: series).period_mom).to eq(14)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "initializes with default period_rmi of 20" do
|
23
|
+
expect(described_class.new(series: series).period_rmi).to eq(20)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "class methods" do
|
28
|
+
describe "#call" do
|
29
|
+
let(:rmi) { described_class.call(series: series, period_mom: period_mom, period_rmi: period_rmi) }
|
30
|
+
|
31
|
+
it "returns the RelativeMomentumIndex value" do
|
32
|
+
expect(rmi).to eq(13.1179)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "instance methods" do
|
38
|
+
describe "#call" do
|
39
|
+
it "returns the RelativeMomentumIndex value" do
|
40
|
+
expect(rmi.call).to eq(13.1179)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#valid?" do
|
45
|
+
it "returns true when the series is valid" do
|
46
|
+
expect(rmi.valid?).to be(true)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns false when the series is not valid" do
|
50
|
+
expect(described_class.new(series: [*1..11], period_mom: period_mom, period_rmi: period_rmi).valid?).to be(false)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "secondary series" do
|
56
|
+
series = [6.875, 6.9375, 6.8125, 6.6095, 6.7345, 6.672, 6.625, 6.6875, 6.547, 6.6563, 6.672, 6.6563, 6.5938]
|
57
|
+
period_mom = 4
|
58
|
+
period_rmi = 8
|
59
|
+
|
60
|
+
expected_value = 17.7112
|
61
|
+
|
62
|
+
it "returns the expected value" do
|
63
|
+
expect(described_class.new(series: series, period_mom: period_mom, period_rmi: period_rmi).call).to eq(expected_value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe RelativeStrengthIndex do
|
5
|
+
let(:series) { [37.875, 39.5, 38.75, 39.8125, 40, 39.875] }
|
6
|
+
let(:period) { 5 }
|
7
|
+
|
8
|
+
let(:rsi) { described_class.new(series: series, period: period) }
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
it "initializes the RelativeStrengthIndex object" do
|
12
|
+
expect(rsi).to be_an_instance_of(described_class)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "initializes with default period of 14" do
|
16
|
+
expect(described_class.new(series: series).period).to eq(14)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "class methods" do
|
21
|
+
describe "#call" do
|
22
|
+
let(:rsi) { described_class.call(series: series, period: period) }
|
23
|
+
|
24
|
+
it "returns the RelativeStrengthIndex value" do
|
25
|
+
expect(rsi).to eq(76.6667)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "instance methods" do
|
31
|
+
describe "#call" do
|
32
|
+
it "returns the RelativeStrengthIndex value" do
|
33
|
+
expect(rsi.call).to eq(76.6667)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#valid?" do
|
38
|
+
it "returns true when the series is valid" do
|
39
|
+
expect(rsi.valid?).to be(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns false when the series is not valid" do
|
43
|
+
expect(described_class.new(series: [*1..5], period: period).valid?).to be(false)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "secondary series" do
|
49
|
+
series = [37.875, 39.5, 38.75, 39.8125, 40, 39.875, 40.1875]
|
50
|
+
period = 5
|
51
|
+
|
52
|
+
expected_value = 78.8679
|
53
|
+
|
54
|
+
it "returns the expected value" do
|
55
|
+
expect(described_class.new(series: series, period: period).call).to eq(expected_value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe StatisticalMethods do
|
5
|
+
let(:series) { [0, 1, 2, 3] }
|
6
|
+
|
7
|
+
let(:stats) { described_class.new(series: series) }
|
8
|
+
|
9
|
+
describe "#initialize" do
|
10
|
+
it "initializes the StatisticalMethods object" do
|
11
|
+
expect(stats).to be_an_instance_of(described_class)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#mean" do
|
16
|
+
it "returns the mean value" do
|
17
|
+
expect(stats.mean).to eq(1.5)
|
18
|
+
end
|
19
|
+
|
20
|
+
context "secondary series" do
|
21
|
+
series = [-1, 1, 2, -2]
|
22
|
+
|
23
|
+
it "returns the expected value" do
|
24
|
+
expect(described_class.new(series: series).mean).to eq(0)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when the series is all zeros" do
|
29
|
+
series = [0, 0, 0, 0]
|
30
|
+
|
31
|
+
it "returns 0" do
|
32
|
+
expect(described_class.new(series: series).mean).to eq(0)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#variance" do
|
38
|
+
it "returns the variance value" do
|
39
|
+
expect(stats.variance).to eq(1.25)
|
40
|
+
end
|
41
|
+
|
42
|
+
context "secondary series" do
|
43
|
+
series = [-1, 1, 2, -2]
|
44
|
+
|
45
|
+
it "returns the expected value" do
|
46
|
+
expect(described_class.new(series: series).variance).to eq(2.5)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when the series is all zeros" do
|
51
|
+
series = [0, 0, 0, 0]
|
52
|
+
|
53
|
+
it "returns 0" do
|
54
|
+
expect(described_class.new(series: series).variance).to eq(0)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#standard_deviation" do
|
60
|
+
it "returns the standard_deviation value" do
|
61
|
+
expect(stats.standard_deviation.truncate(5)).to eq(1.11803)
|
62
|
+
end
|
63
|
+
|
64
|
+
context "secondary series" do
|
65
|
+
series = [-1, 1, 2, -2]
|
66
|
+
|
67
|
+
it "returns the expected value" do
|
68
|
+
expect(described_class.new(series: series).standard_deviation.truncate(5)).to eq(1.58113)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when the series is all zeros" do
|
73
|
+
series = [0, 0, 0, 0]
|
74
|
+
|
75
|
+
it "returns 0" do
|
76
|
+
expect(described_class.new(series: series).standard_deviation).to eq(0)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#valid?" do
|
82
|
+
it "returns true when the series is valid" do
|
83
|
+
expect(stats.valid?).to be(true)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "returns false when the series is not valid" do
|
87
|
+
expect(described_class.new(series: []).valid?).to be(false)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe StochasticOscillator do
|
5
|
+
let(:series) {
|
6
|
+
[[34.375, 33.5312, 34.3125], [34.75, 33.9062, 34.125], [34.2188, 33.6875, 33.75],
|
7
|
+
[33.8281, 33.25, 33.6406], [33.4375, 33, 33.0156], [33.4688, 32.9375, 33.0469],
|
8
|
+
[34.375, 33.25, 34.2969], [34.7188, 34.0469, 34.1406], [34.625, 33.9375, 34.5469]]
|
9
|
+
}
|
10
|
+
let(:k_periods) { 5 }
|
11
|
+
let(:k_slow_periods) { 3 }
|
12
|
+
let(:d_periods) { 3 }
|
13
|
+
|
14
|
+
let(:oscillator) {
|
15
|
+
described_class.new(
|
16
|
+
series: series,
|
17
|
+
k_periods: k_periods,
|
18
|
+
k_slow_periods: k_slow_periods,
|
19
|
+
d_periods: d_periods
|
20
|
+
)
|
21
|
+
}
|
22
|
+
|
23
|
+
describe "#initialize" do
|
24
|
+
it "initializes the StochasticOscillator object" do
|
25
|
+
expect(oscillator).to be_an_instance_of(described_class)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "initializes with default k_periods of 14" do
|
29
|
+
expect(described_class.new(series: series).k_periods).to eq(14)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "initializes with default k_slow_periods of 3" do
|
33
|
+
expect(described_class.new(series: series).k_slow_periods).to eq(3)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "initializes with default d_periods of 3" do
|
37
|
+
expect(described_class.new(series: series).d_periods).to eq(3)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "class methods" do
|
42
|
+
describe "#call" do
|
43
|
+
let(:oscillator) {
|
44
|
+
described_class.call(
|
45
|
+
series: series,
|
46
|
+
k_periods: k_periods,
|
47
|
+
k_slow_periods: k_slow_periods,
|
48
|
+
d_periods: d_periods
|
49
|
+
)
|
50
|
+
}
|
51
|
+
|
52
|
+
it "returns the StochasticOscillator value" do
|
53
|
+
expect(oscillator).to eq(55.41)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "instance methods" do
|
59
|
+
describe "#call" do
|
60
|
+
it "returns the StochasticOscillator value" do
|
61
|
+
expect(oscillator.call).to eq(55.41)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#valid?" do
|
66
|
+
it "returns true when the series is valid" do
|
67
|
+
expect(oscillator.valid?).to be(true)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns false when the series is not valid" do
|
71
|
+
expect(
|
72
|
+
described_class.new(
|
73
|
+
series: [*1..(k_periods + d_periods - 1)],
|
74
|
+
k_periods: k_periods,
|
75
|
+
k_slow_periods: k_slow_periods,
|
76
|
+
d_periods: d_periods
|
77
|
+
).valid?
|
78
|
+
).to be(false)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "secondary series" do
|
84
|
+
series = [[34.375, 33.5312, 34.3125], [34.75, 33.9062, 34.125], [34.2188, 33.6875, 33.75],
|
85
|
+
[33.8281, 33.25, 33.6406], [33.4375, 33, 33.0156], [33.4688, 32.9375, 33.0469],
|
86
|
+
[34.375, 33.25, 34.2969], [34.7188, 34.0469, 34.1406], [34.625, 33.9375, 34.5469],
|
87
|
+
[34.9219, 34.0625, 34.3281]]
|
88
|
+
k_periods = 5
|
89
|
+
k_slow_periods = 3
|
90
|
+
d_periods = 3
|
91
|
+
|
92
|
+
expected_value = 70.7715
|
93
|
+
|
94
|
+
it "returns the expected value" do
|
95
|
+
expect(
|
96
|
+
described_class.new(
|
97
|
+
series: series,
|
98
|
+
k_periods: k_periods,
|
99
|
+
k_slow_periods: k_slow_periods,
|
100
|
+
d_periods: d_periods
|
101
|
+
).call
|
102
|
+
).to eq(expected_value)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RubyTechnicalAnalysis
|
4
|
+
RSpec.describe VolumeOscillator do
|
5
|
+
let(:series) { [17_604, 18_918, 21_030, 13_854, 10_866] }
|
6
|
+
let(:short_ma_period) { 2 }
|
7
|
+
let(:long_ma_period) { 5 }
|
8
|
+
|
9
|
+
let(:oscillator) {
|
10
|
+
described_class.new(
|
11
|
+
series: series,
|
12
|
+
short_ma_period: short_ma_period,
|
13
|
+
long_ma_period: long_ma_period
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
describe "#initialize" do
|
18
|
+
it "initializes the VolumeOscillator object" do
|
19
|
+
expect(oscillator).to be_an_instance_of(described_class)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "initializes with default short_ma_period of 20" do
|
23
|
+
expect(described_class.new(series: series).short_ma_period).to eq(20)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "initializes with default long_ma_period of 60" do
|
27
|
+
expect(described_class.new(series: series).long_ma_period).to eq(60)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "class methods" do
|
32
|
+
describe "#call" do
|
33
|
+
let(:oscillator) {
|
34
|
+
described_class.call(
|
35
|
+
series: series,
|
36
|
+
short_ma_period: short_ma_period,
|
37
|
+
long_ma_period: long_ma_period
|
38
|
+
)
|
39
|
+
}
|
40
|
+
|
41
|
+
it "returns the VolumeOscillator value" do
|
42
|
+
expect(oscillator).to eq(-24.88)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "instance methods" do
|
48
|
+
describe "#call" do
|
49
|
+
it "returns the VolumeOscillator value" do
|
50
|
+
expect(oscillator.call).to eq(-24.88)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#valid?" do
|
55
|
+
context "when the short_ma_period is greater than the long_ma_period" do
|
56
|
+
let(:short_ma_period) { 60 }
|
57
|
+
let(:long_ma_period) { 20 }
|
58
|
+
|
59
|
+
it "returns false" do
|
60
|
+
expect(oscillator.valid?).to eq(false)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when the long_ma_period is greater than the series length" do
|
65
|
+
let(:long_ma_period) { 100 }
|
66
|
+
|
67
|
+
it "returns false" do
|
68
|
+
expect(oscillator.valid?).to eq(false)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when the short_ma_period is less than the long_ma_period and the long_ma_period is less than the series length" do
|
73
|
+
it "returns true" do
|
74
|
+
expect(oscillator.valid?).to eq(true)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "secondary series" do
|
81
|
+
series = [17_604, 18_918, 21_030, 13_854, 10_866, 14_580]
|
82
|
+
short_ma_period = 2
|
83
|
+
long_ma_period = 5
|
84
|
+
|
85
|
+
expected_value = -19.73
|
86
|
+
|
87
|
+
it "returns the expected value" do
|
88
|
+
expect(
|
89
|
+
described_class.new(
|
90
|
+
series: series,
|
91
|
+
short_ma_period: short_ma_period,
|
92
|
+
long_ma_period: long_ma_period
|
93
|
+
).call
|
94
|
+
).to eq(expected_value)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|