technical-analysis 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/technical-analysis.rb +3 -0
- data/lib/technical_analysis.rb +41 -0
- data/lib/technical_analysis/helpers/array_helper.rb +27 -0
- data/lib/technical_analysis/helpers/stock_calculation.rb +25 -0
- data/lib/technical_analysis/helpers/validation.rb +33 -0
- data/lib/technical_analysis/indicators/adi.rb +101 -0
- data/lib/technical_analysis/indicators/adtv.rb +98 -0
- data/lib/technical_analysis/indicators/adx.rb +168 -0
- data/lib/technical_analysis/indicators/ao.rb +105 -0
- data/lib/technical_analysis/indicators/atr.rb +109 -0
- data/lib/technical_analysis/indicators/bb.rb +126 -0
- data/lib/technical_analysis/indicators/cci.rb +105 -0
- data/lib/technical_analysis/indicators/cmf.rb +105 -0
- data/lib/technical_analysis/indicators/cr.rb +95 -0
- data/lib/technical_analysis/indicators/dc.rb +108 -0
- data/lib/technical_analysis/indicators/dlr.rb +97 -0
- data/lib/technical_analysis/indicators/dpo.rb +106 -0
- data/lib/technical_analysis/indicators/dr.rb +96 -0
- data/lib/technical_analysis/indicators/eom.rb +104 -0
- data/lib/technical_analysis/indicators/fi.rb +95 -0
- data/lib/technical_analysis/indicators/ichimoku.rb +179 -0
- data/lib/technical_analysis/indicators/indicator.rb +138 -0
- data/lib/technical_analysis/indicators/kc.rb +124 -0
- data/lib/technical_analysis/indicators/kst.rb +132 -0
- data/lib/technical_analysis/indicators/macd.rb +144 -0
- data/lib/technical_analysis/indicators/mfi.rb +119 -0
- data/lib/technical_analysis/indicators/mi.rb +121 -0
- data/lib/technical_analysis/indicators/nvi.rb +102 -0
- data/lib/technical_analysis/indicators/obv.rb +104 -0
- data/lib/technical_analysis/indicators/obv_mean.rb +110 -0
- data/lib/technical_analysis/indicators/rsi.rb +133 -0
- data/lib/technical_analysis/indicators/sma.rb +98 -0
- data/lib/technical_analysis/indicators/sr.rb +122 -0
- data/lib/technical_analysis/indicators/trix.rb +127 -0
- data/lib/technical_analysis/indicators/tsi.rb +139 -0
- data/lib/technical_analysis/indicators/uo.rb +130 -0
- data/lib/technical_analysis/indicators/vi.rb +117 -0
- data/lib/technical_analysis/indicators/vpt.rb +95 -0
- data/lib/technical_analysis/indicators/wr.rb +103 -0
- data/spec/helpers/array_helper_spec.rb +31 -0
- data/spec/helpers/validaton_spec.rb +22 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/ta_test_data.csv +64 -0
- data/spec/technical_analysis/indicators/adi_spec.rb +116 -0
- data/spec/technical_analysis/indicators/adtv_spec.rb +98 -0
- data/spec/technical_analysis/indicators/adx_spec.rb +92 -0
- data/spec/technical_analysis/indicators/ao_spec.rb +86 -0
- data/spec/technical_analysis/indicators/atr_spec.rb +105 -0
- data/spec/technical_analysis/indicators/bb_spec.rb +100 -0
- data/spec/technical_analysis/indicators/cci_spec.rb +100 -0
- data/spec/technical_analysis/indicators/cmf_spec.rb +100 -0
- data/spec/technical_analysis/indicators/cr_spec.rb +119 -0
- data/spec/technical_analysis/indicators/dc_spec.rb +100 -0
- data/spec/technical_analysis/indicators/dlr_spec.rb +119 -0
- data/spec/technical_analysis/indicators/dpo_spec.rb +90 -0
- data/spec/technical_analysis/indicators/dr_spec.rb +119 -0
- data/spec/technical_analysis/indicators/eom_spec.rb +105 -0
- data/spec/technical_analysis/indicators/fi_spec.rb +118 -0
- data/spec/technical_analysis/indicators/ichimoku_spec.rb +95 -0
- data/spec/technical_analysis/indicators/indicator_spec.rb +120 -0
- data/spec/technical_analysis/indicators/kc_spec.rb +110 -0
- data/spec/technical_analysis/indicators/kst_spec.rb +78 -0
- data/spec/technical_analysis/indicators/macd_spec.rb +86 -0
- data/spec/technical_analysis/indicators/mfi_spec.rb +105 -0
- data/spec/technical_analysis/indicators/mi_spec.rb +79 -0
- data/spec/technical_analysis/indicators/nvi_spec.rb +119 -0
- data/spec/technical_analysis/indicators/obv_mean_spec.rb +109 -0
- data/spec/technical_analysis/indicators/obv_spec.rb +119 -0
- data/spec/technical_analysis/indicators/rsi_spec.rb +105 -0
- data/spec/technical_analysis/indicators/sma_spec.rb +115 -0
- data/spec/technical_analysis/indicators/sr_spec.rb +104 -0
- data/spec/technical_analysis/indicators/trix_spec.rb +76 -0
- data/spec/technical_analysis/indicators/tsi_spec.rb +87 -0
- data/spec/technical_analysis/indicators/uo_spec.rb +91 -0
- data/spec/technical_analysis/indicators/vi_spec.rb +105 -0
- data/spec/technical_analysis/indicators/vpt_spec.rb +118 -0
- data/spec/technical_analysis/indicators/wr_spec.rb +106 -0
- metadata +177 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "MI" do
|
6
|
+
input_data = SpecHelper.get_test_data(:high, :low)
|
7
|
+
indicator = TechnicalAnalysis::Mi
|
8
|
+
|
9
|
+
describe 'Simple Mass Index' do
|
10
|
+
it 'Calculates MI' do
|
11
|
+
output = indicator.calculate(input_data, ema_period: 9, sum_period: 25)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :mi=>24.77520633216394},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :mi=>24.80084030980544},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :mi=>24.924292786436485},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :mi=>25.026285600546654},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :mi=>25.018142841959207},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :mi=>25.04245599370965},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :mi=>25.03284918462693},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :mi=>25.020764664334674},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :mi=>24.964776002066408},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :mi=>24.791003528125515},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :mi=>24.564590708470064},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :mi=>24.454674020826847},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :mi=>24.303447406952383},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :mi=>24.12156756268421},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :mi=>23.94958830559542},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :mi=>23.879826345759078},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :mi=>23.792012619835983},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :mi=>23.82241708019551},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :mi=>23.835760161850434},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :mi=>23.89261610689666},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :mi=>23.890966368346767},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :mi=>23.8163614080134},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :mi=>23.82917406071097}
|
38
|
+
]
|
39
|
+
|
40
|
+
expect(normalized_output).to eq(expected_output)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "Throws exception if not enough data" do
|
44
|
+
expect {indicator.calculate(input_data, ema_period: input_data.size+1)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'Returns the symbol' do
|
48
|
+
indicator_symbol = indicator.indicator_symbol
|
49
|
+
expect(indicator_symbol).to eq('mi')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'Returns the name' do
|
53
|
+
indicator_name = indicator.indicator_name
|
54
|
+
expect(indicator_name).to eq('Mass Index')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'Returns the valid options' do
|
58
|
+
valid_options = indicator.valid_options
|
59
|
+
expect(valid_options).to eq(%i(ema_period sum_period))
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'Validates options' do
|
63
|
+
valid_options = { ema_period: 9, sum_period: 25 }
|
64
|
+
options_validated = indicator.validate_options(valid_options)
|
65
|
+
expect(options_validated).to eq(true)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'Throws exception for invalid options' do
|
69
|
+
invalid_options = { test: 10 }
|
70
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'Calculates minimum data size' do
|
74
|
+
options = { ema_period: 10, sum_period: 20 }
|
75
|
+
expect(indicator.min_data_size(options)).to eq(38)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "NVI" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close, :volume)
|
7
|
+
indicator = TechnicalAnalysis::Nvi
|
8
|
+
|
9
|
+
describe 'Negative Volume Index' do
|
10
|
+
it 'Calculates NVI' do
|
11
|
+
output = indicator.calculate(input_data)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :nvi=>1002.8410612825647},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :nvi=>1002.8410612825647},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :nvi=>1000.9347542454526},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :nvi=>1001.1573361960799},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :nvi=>996.888400265283},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :nvi=>996.888400265283},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :nvi=>996.888400265283},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :nvi=>995.9218765502475},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :nvi=>995.8706437612625},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :nvi=>996.519622574013},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :nvi=>996.519622574013},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :nvi=>999.1070305219995},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :nvi=>999.1070305219995},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :nvi=>999.1070305219995},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :nvi=>999.1070305219995},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :nvi=>997.8077746966976},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :nvi=>997.8077746966976},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :nvi=>997.8077746966976},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :nvi=>996.713747493859},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :nvi=>996.4350307767862},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :nvi=>997.0069647390503},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :nvi=>997.0069647390503},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :nvi=>1000.5726698672554},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :nvi=>1000.5726698672554},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :nvi=>1000.5726698672554},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :nvi=>1000.5726698672554},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :nvi=>1001.1129093548633},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :nvi=>1001.8811198113682},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :nvi=>1001.8811198113682},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :nvi=>1002.0987352047939},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :nvi=>1002.0987352047939},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :nvi=>1004.6386152817257},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :nvi=>1004.7516224011742},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :nvi=>1004.7516224011742},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :nvi=>1004.7516224011742},
|
50
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :nvi=>1003.6440522637729},
|
51
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :nvi=>1001.1761721781198},
|
52
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :nvi=>1001.1761721781198},
|
53
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :nvi=>1002.1752966566695},
|
54
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :nvi=>1002.1752966566695},
|
55
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :nvi=>1002.1752966566695},
|
56
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :nvi=>1002.8707003242093},
|
57
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :nvi=>1002.8707003242093},
|
58
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :nvi=>1001.7892974768458},
|
59
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :nvi=>1004.6281253156736},
|
60
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :nvi=>1004.6281253156736},
|
61
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :nvi=>1004.6281253156736},
|
62
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :nvi=>1004.6281253156736},
|
63
|
+
{:date_time=>"2018-10-29T00:00:00.000Z", :nvi=>1004.1286907133366},
|
64
|
+
{:date_time=>"2018-10-26T00:00:00.000Z", :nvi=>1006.0057133670583},
|
65
|
+
{:date_time=>"2018-10-25T00:00:00.000Z", :nvi=>1006.0057133670583},
|
66
|
+
{:date_time=>"2018-10-24T00:00:00.000Z", :nvi=>1003.8159323451605},
|
67
|
+
{:date_time=>"2018-10-23T00:00:00.000Z", :nvi=>1003.8159323451605},
|
68
|
+
{:date_time=>"2018-10-22T00:00:00.000Z", :nvi=>1003.8159323451605},
|
69
|
+
{:date_time=>"2018-10-19T00:00:00.000Z", :nvi=>1003.2049250951491},
|
70
|
+
{:date_time=>"2018-10-18T00:00:00.000Z", :nvi=>1003.2049250951491},
|
71
|
+
{:date_time=>"2018-10-17T00:00:00.000Z", :nvi=>1003.2049250951491},
|
72
|
+
{:date_time=>"2018-10-16T00:00:00.000Z", :nvi=>1003.6370655407939},
|
73
|
+
{:date_time=>"2018-10-15T00:00:00.000Z", :nvi=>1001.4333482054976},
|
74
|
+
{:date_time=>"2018-10-12T00:00:00.000Z", :nvi=>1003.5719281883889},
|
75
|
+
{:date_time=>"2018-10-11T00:00:00.000Z", :nvi=>1000.0},
|
76
|
+
{:date_time=>"2018-10-10T00:00:00.000Z", :nvi=>1000.0},
|
77
|
+
{:date_time=>"2018-10-09T00:00:00.000Z", :nvi=>1000.0}
|
78
|
+
]
|
79
|
+
|
80
|
+
expect(normalized_output).to eq(expected_output)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "Throws exception if not enough data" do
|
84
|
+
expect {indicator.calculate([])}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'Returns the symbol' do
|
88
|
+
indicator_symbol = indicator.indicator_symbol
|
89
|
+
expect(indicator_symbol).to eq('nvi')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'Returns the name' do
|
93
|
+
indicator_name = indicator.indicator_name
|
94
|
+
expect(indicator_name).to eq('Negative Volume Index')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'Returns the valid options' do
|
98
|
+
valid_options = indicator.valid_options
|
99
|
+
expect(valid_options).to eq([])
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'Validates options' do
|
103
|
+
valid_options = {}
|
104
|
+
options_validated = indicator.validate_options(valid_options)
|
105
|
+
expect(options_validated).to eq(true)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'Throws exception for invalid options' do
|
109
|
+
invalid_options = { test: 10 }
|
110
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'Calculates minimum data size' do
|
114
|
+
options = {}
|
115
|
+
expect(indicator.min_data_size(options)).to eq(1)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "OBV Mean" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close, :volume)
|
7
|
+
indicator = TechnicalAnalysis::ObvMean
|
8
|
+
|
9
|
+
describe 'On-balance Volume Mean' do
|
10
|
+
it 'Calculates OBV Mean (10 day)' do
|
11
|
+
output = indicator.calculate(input_data, period: 10)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :obv_mean=>-642606913.0},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :obv_mean=>-654187384.0},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :obv_mean=>-657547495.0},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :obv_mean=>-647295525.0},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :obv_mean=>-636060876.0},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :obv_mean=>-614324095.0},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :obv_mean=>-605073347.0},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :obv_mean=>-587933850.0},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :obv_mean=>-563282378.0},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :obv_mean=>-537632267.0},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :obv_mean=>-520690509.0},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :obv_mean=>-493338562.0},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :obv_mean=>-475879438.0},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :obv_mean=>-463802236.0},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :obv_mean=>-453894366.0},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :obv_mean=>-444632138.0},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :obv_mean=>-436048331.0},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :obv_mean=>-427847140.0},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :obv_mean=>-419555627.0},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :obv_mean=>-412682868.0},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :obv_mean=>-398147027.0},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :obv_mean=>-392674222.0},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :obv_mean=>-378663120.0},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :obv_mean=>-365710262.0},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :obv_mean=>-350260027.0},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :obv_mean=>-334761235.0},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :obv_mean=>-318827806.0},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :obv_mean=>-311463969.0},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :obv_mean=>-302197756.0},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :obv_mean=>-283664797.0},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :obv_mean=>-264148349.0},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :obv_mean=>-236733893.0},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :obv_mean=>-209152907.0},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :obv_mean=>-188010709.0},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :obv_mean=>-176813851.0},
|
50
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :obv_mean=>-163172458.0},
|
51
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :obv_mean=>-136807276.0},
|
52
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :obv_mean=>-111110335.0},
|
53
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :obv_mean=>-95269809.0},
|
54
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :obv_mean=>-87750647.0},
|
55
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :obv_mean=>-80759219.0},
|
56
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :obv_mean=>-72480397.0},
|
57
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :obv_mean=>-69633236.0},
|
58
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :obv_mean=>-59457699.0},
|
59
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :obv_mean=>-49972807.0},
|
60
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :obv_mean=>-49970286.0},
|
61
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :obv_mean=>-62359854.0},
|
62
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :obv_mean=>-66215087.0},
|
63
|
+
{:date_time=>"2018-10-29T00:00:00.000Z", :obv_mean=>-63999351.0},
|
64
|
+
{:date_time=>"2018-10-26T00:00:00.000Z", :obv_mean=>-61015077.0},
|
65
|
+
{:date_time=>"2018-10-25T00:00:00.000Z", :obv_mean=>-59574127.0},
|
66
|
+
{:date_time=>"2018-10-24T00:00:00.000Z", :obv_mean=>-66801824.0},
|
67
|
+
{:date_time=>"2018-10-23T00:00:00.000Z", :obv_mean=>-65836555.0}
|
68
|
+
]
|
69
|
+
|
70
|
+
expect(normalized_output).to eq(expected_output)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "Throws exception if not enough data" do
|
74
|
+
expect {indicator.calculate(input_data, period: input_data.size+1)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'Returns the symbol' do
|
78
|
+
indicator_symbol = indicator.indicator_symbol
|
79
|
+
expect(indicator_symbol).to eq('obv_mean')
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'Returns the name' do
|
83
|
+
indicator_name = indicator.indicator_name
|
84
|
+
expect(indicator_name).to eq('On-balance Volume Mean')
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'Returns the valid options' do
|
88
|
+
valid_options = indicator.valid_options
|
89
|
+
expect(valid_options).to eq(%i(period))
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'Validates options' do
|
93
|
+
valid_options = { period: 22 }
|
94
|
+
options_validated = indicator.validate_options(valid_options)
|
95
|
+
expect(options_validated).to eq(true)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'Throws exception for invalid options' do
|
99
|
+
invalid_options = { test: 10 }
|
100
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'Calculates minimum data size' do
|
104
|
+
options = { period: 4 }
|
105
|
+
expect(indicator.min_data_size(options)).to eq(5)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "OBV" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close, :volume)
|
7
|
+
indicator = TechnicalAnalysis::Obv
|
8
|
+
|
9
|
+
describe 'On-balance Volume' do
|
10
|
+
it 'Calculates OBV' do
|
11
|
+
output = indicator.calculate(input_data)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :obv=>-591085010},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :obv=>-636119380},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :obv=>-676742290},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :obv=>-622170850},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :obv=>-679594500},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :obv=>-588487660},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :obv=>-624124730},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :obv=>-658624120},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :obv=>-700364720},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :obv=>-648755870},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :obv=>-706889720},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :obv=>-669720490},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :obv=>-574222590},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :obv=>-509824360},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :obv=>-462226690},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :obv=>-495980180},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :obv=>-452729760},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :obv=>-412109400},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :obv=>-443863610},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :obv=>-479338290},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :obv=>-433370250},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :obv=>-495129250},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :obv=>-453450570},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :obv=>-410745660},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :obv=>-369604410},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :obv=>-410142110},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :obv=>-370717850},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :obv=>-329194270},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :obv=>-375136020},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :obv=>-333979880},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :obv=>-378642200},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :obv=>-355018230},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :obv=>-323921990},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :obv=>-256243310},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :obv=>-214616490},
|
50
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :obv=>-250807820},
|
51
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :obv=>-297079480},
|
52
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :obv=>-236532140},
|
53
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :obv=>-189806430},
|
54
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :obv=>-138815400},
|
55
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :obv=>-104497640},
|
56
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :obv=>-79208370},
|
57
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :obv=>-112500010},
|
58
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :obv=>-144274730},
|
59
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :obv=>-78202560},
|
60
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :obv=>12844000},
|
61
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :obv=>-40110070},
|
62
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :obv=>-78126880},
|
63
|
+
{:date_time=>"2018-10-29T00:00:00.000Z", :obv=>-114614810},
|
64
|
+
{:date_time=>"2018-10-26T00:00:00.000Z", :obv=>-68901120},
|
65
|
+
{:date_time=>"2018-10-25T00:00:00.000Z", :obv=>-21709420},
|
66
|
+
{:date_time=>"2018-10-24T00:00:00.000Z", :obv=>-50736760},
|
67
|
+
{:date_time=>"2018-10-23T00:00:00.000Z", :obv=>-10744640},
|
68
|
+
{:date_time=>"2018-10-22T00:00:00.000Z", :obv=>-49425810},
|
69
|
+
{:date_time=>"2018-10-19T00:00:00.000Z", :obv=>-78177350},
|
70
|
+
{:date_time=>"2018-10-18T00:00:00.000Z", :obv=>-111051680},
|
71
|
+
{:date_time=>"2018-10-17T00:00:00.000Z", :obv=>-78662400},
|
72
|
+
{:date_time=>"2018-10-16T00:00:00.000Z", :obv=>-55969520},
|
73
|
+
{:date_time=>"2018-10-15T00:00:00.000Z", :obv=>-84772070},
|
74
|
+
{:date_time=>"2018-10-12T00:00:00.000Z", :obv=>-54491620},
|
75
|
+
{:date_time=>"2018-10-11T00:00:00.000Z", :obv=>-93986390},
|
76
|
+
{:date_time=>"2018-10-10T00:00:00.000Z", :obv=>-41084070},
|
77
|
+
{:date_time=>"2018-10-09T00:00:00.000Z", :obv=>0}
|
78
|
+
]
|
79
|
+
|
80
|
+
expect(normalized_output).to eq(expected_output)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "Throws exception if not enough data" do
|
84
|
+
expect {indicator.calculate([])}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'Returns the symbol' do
|
88
|
+
indicator_symbol = indicator.indicator_symbol
|
89
|
+
expect(indicator_symbol).to eq('obv')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'Returns the name' do
|
93
|
+
indicator_name = indicator.indicator_name
|
94
|
+
expect(indicator_name).to eq('On-balance Volume')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'Returns the valid options' do
|
98
|
+
valid_options = indicator.valid_options
|
99
|
+
expect(valid_options).to eq([])
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'Validates options' do
|
103
|
+
valid_options = {}
|
104
|
+
options_validated = indicator.validate_options(valid_options)
|
105
|
+
expect(options_validated).to eq(true)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'Throws exception for invalid options' do
|
109
|
+
invalid_options = { test: 10 }
|
110
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'Calculates minimum data size' do
|
114
|
+
options = {}
|
115
|
+
expect(indicator.min_data_size(options)).to eq(1)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "RSI" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close)
|
7
|
+
indicator = TechnicalAnalysis::Rsi
|
8
|
+
|
9
|
+
describe 'Relative Strength Index' do
|
10
|
+
it 'Calculates RSI (14 day)' do
|
11
|
+
output = indicator.calculate(input_data, period: 14, price_key: :close)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :rsi=>41.01572095202713},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :rsi=>38.100858593859655},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :rsi=>34.80538400125879},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :rsi=>35.00790948034705},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :rsi=>27.835833051062522},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :rsi=>37.90003559360193},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :rsi=>37.66054013673465},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :rsi=>35.7297472286003},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :rsi=>35.63166885267985},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :rsi=>36.28727515078207},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :rsi=>22.94077952430888},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :rsi=>24.757134961511937},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :rsi=>27.973957664061984},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :rsi=>30.416532991054595},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :rsi=>33.926041361905774},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :rsi=>30.880956115136144},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :rsi=>31.866930881658718},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :rsi=>35.61772436774288},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :rsi=>33.146531878947414},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :rsi=>32.53565170863392},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :rsi=>33.115551932880564},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :rsi=>31.82436379692355},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :rsi=>35.38441991619841},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :rsi=>36.58615110748291},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :rsi=>42.06016450933706},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :rsi=>35.1442970032345},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :rsi=>35.760430191057694},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :rsi=>36.61457624117541},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :rsi=>29.027101402280678},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :rsi=>29.211255846774762},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :rsi=>26.558433878585916},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :rsi=>28.467396310763007},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :rsi=>28.552282046348225},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :rsi=>32.554453236286506},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :rsi=>36.677863857193564},
|
50
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :rsi=>34.550163030510646},
|
51
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :rsi=>29.78632377839773},
|
52
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :rsi=>32.36268849740294},
|
53
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :rsi=>33.31877385045367},
|
54
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :rsi=>38.99885805229995},
|
55
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :rsi=>41.56699725744853},
|
56
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :rsi=>42.51108193242363},
|
57
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :rsi=>36.875893042068746},
|
58
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :rsi=>34.78189708111985},
|
59
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :rsi=>37.93941116682432},
|
60
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :rsi=>48.08268788472883},
|
61
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :rsi=>44.96841382331871},
|
62
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :rsi=>39.38109368376431},
|
63
|
+
{:date_time=>"2018-10-29T00:00:00.000Z", :rsi=>38.27160493827161}
|
64
|
+
]
|
65
|
+
|
66
|
+
expect(normalized_output).to eq(expected_output)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "Throws exception if not enough data" do
|
70
|
+
expect {indicator.calculate(input_data, period: input_data.size+2, price_key: :close)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'Returns the symbol' do
|
74
|
+
indicator_symbol = indicator.indicator_symbol
|
75
|
+
expect(indicator_symbol).to eq('rsi')
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'Returns the name' do
|
79
|
+
indicator_name = indicator.indicator_name
|
80
|
+
expect(indicator_name).to eq('Relative Strength Index')
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'Returns the valid options' do
|
84
|
+
valid_options = indicator.valid_options
|
85
|
+
expect(valid_options).to eq(%i(period price_key))
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'Validates options' do
|
89
|
+
valid_options = { period: 22, price_key: :close }
|
90
|
+
options_validated = indicator.validate_options(valid_options)
|
91
|
+
expect(options_validated).to eq(true)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'Throws exception for invalid options' do
|
95
|
+
invalid_options = { test: 10 }
|
96
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'Calculates minimum data size' do
|
100
|
+
options = { period: 4 }
|
101
|
+
expect(indicator.min_data_size(options)).to eq(5)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|