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,115 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "SMA" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close)
|
7
|
+
indicator = TechnicalAnalysis::Sma
|
8
|
+
|
9
|
+
describe 'Simple Moving Average' do
|
10
|
+
it 'Calculates SMA (5 day)' do
|
11
|
+
output = indicator.calculate(input_data, period: 5, price_key: :close)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :sma=>148.488},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :sma=>149.41},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :sma=>150.808},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :sma=>152.468},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :sma=>154.046},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :sma=>157.04199999999997},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :sma=>154.824},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :sma=>153.422},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :sma=>153.54199999999997},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :sma=>154.49},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :sma=>156.27},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :sma=>159.692},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :sma=>162.642},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :sma=>165.46599999999998},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :sma=>167.108},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :sma=>167.61999999999998},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :sma=>168.752},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :sma=>169.35399999999998},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :sma=>170.108},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :sma=>171.626},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :sma=>174.864},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :sma=>176.66},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :sma=>178.872},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :sma=>180.11600000000004},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :sma=>179.62600000000003},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :sma=>177.58599999999998},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :sma=>176.32799999999997},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :sma=>175.77400000000003},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :sma=>174.982},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :sma=>177.30599999999998},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :sma=>181.088},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :sma=>184.91199999999998},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :sma=>186.916},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :sma=>189.96599999999998},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :sma=>191.628},
|
50
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :sma=>193.816},
|
51
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :sma=>197.23200000000003},
|
52
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :sma=>201.862},
|
53
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :sma=>204.17000000000002},
|
54
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :sma=>205.654},
|
55
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :sma=>206.256},
|
56
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :sma=>209.002},
|
57
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :sma=>210.78400000000002},
|
58
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :sma=>212.69},
|
59
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :sma=>214.82000000000002},
|
60
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :sma=>216.584},
|
61
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :sma=>216.1},
|
62
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :sma=>215.346},
|
63
|
+
{:date_time=>"2018-10-29T00:00:00.000Z", :sma=>217.23200000000003},
|
64
|
+
{:date_time=>"2018-10-26T00:00:00.000Z", :sma=>218.914},
|
65
|
+
{:date_time=>"2018-10-25T00:00:00.000Z", :sma=>219.51600000000002},
|
66
|
+
{:date_time=>"2018-10-24T00:00:00.000Z", :sma=>218.76},
|
67
|
+
{:date_time=>"2018-10-23T00:00:00.000Z", :sma=>219.97999999999996},
|
68
|
+
{:date_time=>"2018-10-22T00:00:00.000Z", :sma=>219.86400000000003},
|
69
|
+
{:date_time=>"2018-10-19T00:00:00.000Z", :sma=>219.206},
|
70
|
+
{:date_time=>"2018-10-18T00:00:00.000Z", :sma=>219.766},
|
71
|
+
{:date_time=>"2018-10-17T00:00:00.000Z", :sma=>219.452},
|
72
|
+
{:date_time=>"2018-10-16T00:00:00.000Z", :sma=>218.48600000000002},
|
73
|
+
{:date_time=>"2018-10-15T00:00:00.000Z", :sma=>219.43}
|
74
|
+
]
|
75
|
+
|
76
|
+
expect(normalized_output).to eq(expected_output)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "Throws exception if not enough data" do
|
80
|
+
expect {indicator.calculate(input_data, period: input_data.size+1, price_key: :close)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'Returns the symbol' do
|
84
|
+
indicator_symbol = indicator.indicator_symbol
|
85
|
+
expect(indicator_symbol).to eq('sma')
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'Returns the name' do
|
89
|
+
indicator_name = indicator.indicator_name
|
90
|
+
expect(indicator_name).to eq('Simple Moving Average')
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'Returns the valid options' do
|
94
|
+
valid_options = indicator.valid_options
|
95
|
+
expect(valid_options).to eq(%i(period price_key))
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'Validates options' do
|
99
|
+
valid_options = { period: 22, price_key: :close }
|
100
|
+
options_validated = indicator.validate_options(valid_options)
|
101
|
+
expect(options_validated).to eq(true)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'Throws exception for invalid options' do
|
105
|
+
invalid_options = { test: 10 }
|
106
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'Calculates minimum data size' do
|
110
|
+
options = { period: 4 }
|
111
|
+
expect(indicator.min_data_size(options)).to eq(4)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "SR" do
|
6
|
+
input_data = SpecHelper.get_test_data(:high, :low, :close)
|
7
|
+
indicator = TechnicalAnalysis::Sr
|
8
|
+
|
9
|
+
describe 'Stochastic Oscillator' do
|
10
|
+
it 'Calculates SR (14 day)' do
|
11
|
+
output = indicator.calculate(input_data, period: 14, signal_period: 3)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :sr=>44.44007858546172, :sr_signal=>33.739408752366685},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :sr=>34.27340383862123, :sr_signal=>26.631612985573174},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :sr=>22.50474383301711, :sr_signal=>15.414319829465327},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :sr=>23.1166912850812, :sr_signal=>22.449561749124218},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :sr=>0.6215243702976702, :sr_signal=>29.04987430254469},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :sr=>43.61046959199379, :sr_signal=>41.21118809340517},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :sr=>42.917628945342614, :sr_signal=>38.09610922104404},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :sr=>37.105465742879105, :sr_signal=>36.300579364484854},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :sr=>34.2652329749104, :sr_signal=>24.155555094877986},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :sr=>37.531039375665074, :sr_signal=>13.772232369077116},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :sr=>0.6703929340585003, :sr_signal=>2.9825336838014445},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :sr=>3.1152647975077716, :sr_signal=>5.080152544595593},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :sr=>5.161943319838063, :sr_signal=>9.054487961785336},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :sr=>6.963249516440942, :sr_signal=>9.149838987845628},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :sr=>15.038271049077, :sr_signal=>10.145121695692445},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :sr=>5.447996398018944, :sr_signal=>16.886182356334803},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :sr=>9.94909763998139, :sr_signal=>23.970384081443694},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :sr=>35.26145303100408, :sr_signal=>28.8292457195742},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :sr=>26.700601573345605, :sr_signal=>24.711525960000667},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :sr=>24.525682554372914, :sr_signal=>16.048800203857994},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :sr=>22.908293752283477, :sr_signal=>13.89015200407954},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :sr=>0.712424304917594, :sr_signal=>14.928180772069608},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :sr=>18.049737955037553, :sr_signal=>32.719433096383845},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :sr=>26.022380056253674, :sr_signal=>36.07538954462583},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :sr=>54.0861812778603, :sr_signal=>36.063267521212616},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :sr=>28.117607299763502, :sr_signal=>26.965799836520265},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :sr=>25.986013986014044, :sr_signal=>20.92157984180065},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :sr=>26.79377822378325, :sr_signal=>15.905669844455621},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :sr=>9.984947315604659, :sr_signal=>7.140989430040055},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :sr=>10.938283993978956, :sr_signal=>4.922619471840783},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :sr=>0.49973698053655363, :sr_signal=>2.3224159491234997},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :sr=>3.329837441006842, :sr_signal=>2.931860503912096},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :sr=>3.137673425827104, :sr_signal=>8.775890351328327},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :sr=>2.32807064490234, :sr_signal=>12.744181659747374},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :sr=>20.86192698325554, :sr_signal=>12.764205325281347},
|
50
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :sr=>15.04254735108424, :sr_signal=>6.651276276015249},
|
51
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :sr=>2.388141641504267, :sr_signal=>2.0532129671343387},
|
52
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :sr=>2.5231398354572394, :sr_signal=>9.31549269113536},
|
53
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :sr=>1.2483574244415094, :sr_signal=>21.674753063199656},
|
54
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :sr=>24.174980813507332, :sr_signal=>36.326426195958085},
|
55
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :sr=>39.60092095165012, :sr_signal=>35.431056536198575},
|
56
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :sr=>45.203376822716805, :sr_signal=>26.605269889997487},
|
57
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :sr=>21.48887183422879, :sr_signal=>15.172229388808171},
|
58
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :sr=>13.123561013046874, :sr_signal=>37.649110405476506},
|
59
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :sr=>10.904255319148854, :sr_signal=>56.740227701017325},
|
60
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :sr=>88.91951488423378, :sr_signal=>66.35428151414929},
|
61
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :sr=>70.39691289966935, :sr_signal=>46.83290323914804},
|
62
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :sr=>39.746416758544726, :sr_signal=>32.241290132123396}
|
63
|
+
]
|
64
|
+
|
65
|
+
expect(normalized_output).to eq(expected_output)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "Throws exception if not enough data" do
|
69
|
+
expect {indicator.calculate(input_data, period: input_data.size+1)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'Returns the symbol' do
|
73
|
+
indicator_symbol = indicator.indicator_symbol
|
74
|
+
expect(indicator_symbol).to eq('sr')
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'Returns the name' do
|
78
|
+
indicator_name = indicator.indicator_name
|
79
|
+
expect(indicator_name).to eq('Stochastic Oscillator')
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'Returns the valid options' do
|
83
|
+
valid_options = indicator.valid_options
|
84
|
+
expect(valid_options).to eq(%i(period signal_period))
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'Validates options' do
|
88
|
+
valid_options = { period: 22, signal_period: 4 }
|
89
|
+
options_validated = indicator.validate_options(valid_options)
|
90
|
+
expect(options_validated).to eq(true)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'Throws exception for invalid options' do
|
94
|
+
invalid_options = { test: 10 }
|
95
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'Calculates minimum data size' do
|
99
|
+
options = { period: 4, signal_period: 2 }
|
100
|
+
expect(indicator.min_data_size(options)).to eq(5)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "TRIX" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close)
|
7
|
+
indicator = TechnicalAnalysis::Trix
|
8
|
+
|
9
|
+
describe 'Triple Exponential Average' do
|
10
|
+
it 'Calculates TRIX (15 day)' do
|
11
|
+
output = indicator.calculate(input_data, period: 15, price_key: :close)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :trix=>-0.007522826289174942},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :trix=>-0.007639218329257057},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :trix=>-0.007682172922749195},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :trix=>-0.00767662212545961},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :trix=>-0.007665196848424279},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :trix=>-0.007658933006361239},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :trix=>-0.007775594696883065},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :trix=>-0.007833433859114468},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :trix=>-0.007824502562605692},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :trix=>-0.00776162437514068},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :trix=>-0.007643867247128558},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :trix=>-0.007455715388896471},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :trix=>-0.00735126292321306},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :trix=>-0.007332615495168546},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :trix=>-0.007365504921638632},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :trix=>-0.007428539823046746},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :trix=>-0.007473061875390961},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :trix=>-0.007537530463588133},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :trix=>-0.007622995995719011},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :trix=>-0.007673381215454718}
|
35
|
+
]
|
36
|
+
|
37
|
+
expect(normalized_output).to eq(expected_output)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "Throws exception if not enough data" do
|
41
|
+
expect {indicator.calculate(input_data, period: input_data.size+1, price_key: :close)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'Returns the symbol' do
|
45
|
+
indicator_symbol = indicator.indicator_symbol
|
46
|
+
expect(indicator_symbol).to eq('trix')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'Returns the name' do
|
50
|
+
indicator_name = indicator.indicator_name
|
51
|
+
expect(indicator_name).to eq('Triple Exponential Average')
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'Returns the valid options' do
|
55
|
+
valid_options = indicator.valid_options
|
56
|
+
expect(valid_options).to eq(%i(period price_key))
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'Validates options' do
|
60
|
+
valid_options = { period: 22, price_key: :close }
|
61
|
+
options_validated = indicator.validate_options(valid_options)
|
62
|
+
expect(options_validated).to eq(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'Throws exception for invalid options' do
|
66
|
+
invalid_options = { test: 10 }
|
67
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'Calculates minimum data size' do
|
71
|
+
options = { period: 4 }
|
72
|
+
expect(indicator.min_data_size(options)).to eq(11)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "TSI" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close)
|
7
|
+
indicator = TechnicalAnalysis::Tsi
|
8
|
+
|
9
|
+
describe 'True Strength Index' do
|
10
|
+
it 'Calculates True Strength Index' do
|
11
|
+
output = indicator.calculate(input_data, low_period: 13, high_period: 25, price_key: :close)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :tsi=>-28.91017661103889},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :tsi=>-30.97413963420104},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :tsi=>-32.39480993311267},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :tsi=>-32.874679857827935},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :tsi=>-33.579027007940994},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :tsi=>-31.495178028566524},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :tsi=>-32.785927300024994},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :tsi=>-34.28080772951784},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :tsi=>-35.41195667338275},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :tsi=>-36.802531445786066},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :tsi=>-38.83883734905748},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :tsi=>-36.202827241203856},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :tsi=>-33.78946079860395},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :tsi=>-32.23640227177938},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :tsi=>-31.30170501401141},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :tsi=>-31.403055885745307},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :tsi=>-30.569488217596724},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :tsi=>-29.91401235092671},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :tsi=>-30.375476807689427},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :tsi=>-30.15935663446155},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :tsi=>-29.704744795960114},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :tsi=>-29.357900955250976},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :tsi=>-28.4796578607378},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :tsi=>-28.752945178257534},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :tsi=>-29.524570107700253},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :tsi=>-32.212798598181024}
|
41
|
+
]
|
42
|
+
|
43
|
+
expect(normalized_output).to eq(expected_output)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "Throws exception if not enough data" do
|
47
|
+
low_period = 13
|
48
|
+
high_period = 25
|
49
|
+
size_limit = low_period + high_period - 1
|
50
|
+
input_data = input_data.first(size_limit)
|
51
|
+
|
52
|
+
expect {indicator.calculate(input_data, low_period: low_period, high_period: high_period, price_key: :close)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'Returns the symbol' do
|
56
|
+
indicator_symbol = indicator.indicator_symbol
|
57
|
+
expect(indicator_symbol).to eq('tsi')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'Returns the name' do
|
61
|
+
indicator_name = indicator.indicator_name
|
62
|
+
expect(indicator_name).to eq('True Strength Index')
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'Returns the valid options' do
|
66
|
+
valid_options = indicator.valid_options
|
67
|
+
expect(valid_options).to eq(%i(low_period high_period price_key))
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'Validates options' do
|
71
|
+
valid_options = { low_period: 10, high_period: 20, price_key: :close }
|
72
|
+
options_validated = indicator.validate_options(valid_options)
|
73
|
+
expect(options_validated).to eq(true)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'Throws exception for invalid options' do
|
77
|
+
invalid_options = { test: 10 }
|
78
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'Calculates minimum data size' do
|
82
|
+
options = { low_period: 10, high_period: 20 }
|
83
|
+
expect(indicator.min_data_size(options)).to eq(30)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "UO" do
|
6
|
+
input_data = SpecHelper.get_test_data(:high, :low, :close)
|
7
|
+
indicator = TechnicalAnalysis::Uo
|
8
|
+
|
9
|
+
describe 'Ultimate Oscillator' do
|
10
|
+
it 'Calculates UO (5 day)' do
|
11
|
+
output = indicator.calculate(input_data, short_period: 7, medium_period: 14, long_period: 28, short_weight: 4, medium_weight: 2, long_weight: 1)
|
12
|
+
normalized_output = output.map(&:to_hash)
|
13
|
+
|
14
|
+
expected_output = [
|
15
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :uo=>47.28872762629681},
|
16
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :uo=>44.828908983561035},
|
17
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :uo=>46.58165158841807},
|
18
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :uo=>50.726610056055335},
|
19
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :uo=>43.660461129633255},
|
20
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :uo=>51.63477005783912},
|
21
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :uo=>46.12625788315007},
|
22
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :uo=>44.736408028234784},
|
23
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :uo=>44.80062908207362},
|
24
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :uo=>38.89197235556109},
|
25
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :uo=>24.01487703769969},
|
26
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :uo=>28.31825074884628},
|
27
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :uo=>30.219780692869403},
|
28
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :uo=>31.693410049073588},
|
29
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :uo=>42.6017793901735},
|
30
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :uo=>38.091246151228205},
|
31
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :uo=>43.99139965247388},
|
32
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :uo=>42.5926187322538},
|
33
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :uo=>46.56343334880161},
|
34
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :uo=>47.39018769748099},
|
35
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :uo=>46.78620949538559},
|
36
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :uo=>46.3795568325064},
|
37
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :uo=>54.531561679403225},
|
38
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :uo=>54.53131218526129},
|
39
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :uo=>58.63742128493122},
|
40
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :uo=>48.76091038333585},
|
41
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :uo=>42.75825214517756},
|
42
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :uo=>39.6100967511459},
|
43
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :uo=>36.448196445521205},
|
44
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :uo=>37.129780535443615},
|
45
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :uo=>30.31628731487427},
|
46
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :uo=>30.12209085444982},
|
47
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :uo=>29.938582222468735},
|
48
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :uo=>33.50557345611348},
|
49
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :uo=>37.48593642184523}
|
50
|
+
]
|
51
|
+
|
52
|
+
expect(normalized_output).to eq(expected_output)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "Throws exception if not enough data" do
|
56
|
+
expect {indicator.calculate(input_data, long_period: input_data.size+2)}.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'Returns the symbol' do
|
60
|
+
indicator_symbol = indicator.indicator_symbol
|
61
|
+
expect(indicator_symbol).to eq('uo')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'Returns the name' do
|
65
|
+
indicator_name = indicator.indicator_name
|
66
|
+
expect(indicator_name).to eq('Ultimate Oscillator')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'Returns the valid options' do
|
70
|
+
valid_options = indicator.valid_options
|
71
|
+
expect(valid_options).to eq(%i(short_period medium_period long_period short_weight medium_weight long_weight))
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'Validates options' do
|
75
|
+
valid_options = { short_period: 7, medium_period: 14, long_period: 28, short_weight: 4, medium_weight: 2, long_weight: 1 }
|
76
|
+
options_validated = indicator.validate_options(valid_options)
|
77
|
+
expect(options_validated).to eq(true)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'Throws exception for invalid options' do
|
81
|
+
invalid_options = { test: 10 }
|
82
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'Calculates minimum data size' do
|
86
|
+
options = { short_period: 7, medium_period: 14, long_period: 20, short_weight: 4, medium_weight: 2, long_weight: 1 }
|
87
|
+
expect(indicator.min_data_size(options)).to eq(21)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|