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,95 @@
|
|
1
|
+
module TechnicalAnalysis
|
2
|
+
# Volume-price Trend
|
3
|
+
class Vpt < Indicator
|
4
|
+
|
5
|
+
# Returns the symbol of the technical indicator
|
6
|
+
#
|
7
|
+
# @return [String] A string of the symbol of the technical indicator
|
8
|
+
def self.indicator_symbol
|
9
|
+
"vpt"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the name of the technical indicator
|
13
|
+
#
|
14
|
+
# @return [String] A string of the name of the technical indicator
|
15
|
+
def self.indicator_name
|
16
|
+
"Volume-price Trend"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an array of valid keys for options for this technical indicator
|
20
|
+
#
|
21
|
+
# @return [Array] An array of keys as symbols for valid options for this technical indicator
|
22
|
+
def self.valid_options
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Validates the provided options for this technical indicator
|
27
|
+
#
|
28
|
+
# @param options [Hash] The options for the technical indicator to be validated
|
29
|
+
#
|
30
|
+
# @return [Boolean] Returns true if options are valid or raises a ValidationError if they're not
|
31
|
+
def self.validate_options(options)
|
32
|
+
return true if options == {}
|
33
|
+
raise Validation::ValidationError.new "This indicator doesn't accept any options."
|
34
|
+
end
|
35
|
+
|
36
|
+
# Calculates the minimum number of observations needed to calculate the technical indicator
|
37
|
+
#
|
38
|
+
# @param options [Hash] The options for the technical indicator
|
39
|
+
#
|
40
|
+
# @return [Integer] Returns the minimum number of observations needed to calculate the technical
|
41
|
+
# indicator based on the options provided
|
42
|
+
def self.min_data_size(**params)
|
43
|
+
2
|
44
|
+
end
|
45
|
+
|
46
|
+
# Calculates the volume-price trend (VPT) for the data
|
47
|
+
# https://en.wikipedia.org/wiki/Volume%E2%80%93price_trend
|
48
|
+
#
|
49
|
+
# @param data [Array] Array of hashes with keys (:date_time, :close, :volume)
|
50
|
+
#
|
51
|
+
# @return [Array<VptValue>] An array of VptValue instances
|
52
|
+
def self.calculate(data)
|
53
|
+
Validation.validate_numeric_data(data, :close, :volume)
|
54
|
+
Validation.validate_length(data, min_data_size({}))
|
55
|
+
Validation.validate_date_time_key(data)
|
56
|
+
|
57
|
+
data = data.sort_by { |row| row[:date_time] }
|
58
|
+
|
59
|
+
output = []
|
60
|
+
prev_price = data.shift
|
61
|
+
prev_pvt = 0
|
62
|
+
|
63
|
+
data.each do |v|
|
64
|
+
pvt = prev_pvt + (((v[:close] - prev_price[:close]) / prev_price[:close]) * v[:volume])
|
65
|
+
output << VptValue.new(date_time: v[:date_time], vpt: pvt)
|
66
|
+
prev_price = v
|
67
|
+
prev_pvt = pvt
|
68
|
+
end
|
69
|
+
|
70
|
+
output.sort_by(&:date_time).reverse
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
# The value class to be returned by calculations
|
76
|
+
class VptValue
|
77
|
+
|
78
|
+
# @return [String] the date_time of the obversation as it was provided
|
79
|
+
attr_accessor :date_time
|
80
|
+
|
81
|
+
# @return [Float] the vpt calculation value
|
82
|
+
attr_accessor :vpt
|
83
|
+
|
84
|
+
def initialize(date_time: nil, vpt: nil)
|
85
|
+
@date_time = date_time
|
86
|
+
@vpt = vpt
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Hash] the attributes as a hash
|
90
|
+
def to_hash
|
91
|
+
{ date_time: @date_time, vpt: @vpt }
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module TechnicalAnalysis
|
2
|
+
# Williams %R
|
3
|
+
class Wr < Indicator
|
4
|
+
|
5
|
+
# Returns the symbol of the technical indicator
|
6
|
+
#
|
7
|
+
# @return [String] A string of the symbol of the technical indicator
|
8
|
+
def self.indicator_symbol
|
9
|
+
"wr"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Returns the name of the technical indicator
|
13
|
+
#
|
14
|
+
# @return [String] A string of the name of the technical indicator
|
15
|
+
def self.indicator_name
|
16
|
+
"Williams %R"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an array of valid keys for options for this technical indicator
|
20
|
+
#
|
21
|
+
# @return [Array] An array of keys as symbols for valid options for this technical indicator
|
22
|
+
def self.valid_options
|
23
|
+
%i(period)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Validates the provided options for this technical indicator
|
27
|
+
#
|
28
|
+
# @param options [Hash] The options for the technical indicator to be validated
|
29
|
+
#
|
30
|
+
# @return [Boolean] Returns true if options are valid or raises a ValidationError if they're not
|
31
|
+
def self.validate_options(options)
|
32
|
+
Validation.validate_options(options, valid_options)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Calculates the minimum number of observations needed to calculate the technical indicator
|
36
|
+
#
|
37
|
+
# @param options [Hash] The options for the technical indicator
|
38
|
+
#
|
39
|
+
# @return [Integer] Returns the minimum number of observations needed to calculate the technical
|
40
|
+
# indicator based on the options provided
|
41
|
+
def self.min_data_size(period: 14)
|
42
|
+
period.to_i
|
43
|
+
end
|
44
|
+
|
45
|
+
# Calculates the Williams %R (WR) for the data over the given period
|
46
|
+
# https://en.wikipedia.org/wiki/Williams_%25R
|
47
|
+
#
|
48
|
+
# @param data [Array] Array of hashes with keys (:date_time, :high, :low, :close)
|
49
|
+
# @param period [Integer] The given look-back period to calculate the WR
|
50
|
+
#
|
51
|
+
# @return [Array<WrValue>] An array of WrValue instances
|
52
|
+
def self.calculate(data, period: 14)
|
53
|
+
period = period.to_i
|
54
|
+
Validation.validate_numeric_data(data, :high, :low, :close)
|
55
|
+
Validation.validate_length(data, min_data_size(period: period))
|
56
|
+
Validation.validate_date_time_key(data)
|
57
|
+
|
58
|
+
data = data.sort_by { |row| row[:date_time] }
|
59
|
+
|
60
|
+
output = []
|
61
|
+
period_values = []
|
62
|
+
|
63
|
+
data.each do |v|
|
64
|
+
period_values << { high: v[:high], low: v[:low] }
|
65
|
+
|
66
|
+
if period_values.size == period
|
67
|
+
lowest_low = period_values.map { |pv| pv[:low] }.min
|
68
|
+
highest_high = period_values.map { |pv| pv[:high] }.max
|
69
|
+
|
70
|
+
wr = (highest_high - v[:close]) / (highest_high - lowest_low) * -100
|
71
|
+
|
72
|
+
output << WrValue.new(date_time: v[:date_time], wr: wr)
|
73
|
+
|
74
|
+
period_values.shift
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
output.sort_by(&:date_time).reverse
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
# The value class to be returned by calculations
|
84
|
+
class WrValue
|
85
|
+
|
86
|
+
# @return [String] the date_time of the obversation as it was provided
|
87
|
+
attr_accessor :date_time
|
88
|
+
|
89
|
+
# @return [Float] the wr calculation value
|
90
|
+
attr_accessor :wr
|
91
|
+
|
92
|
+
def initialize(date_time: nil, wr: nil)
|
93
|
+
@date_time = date_time
|
94
|
+
@wr = wr
|
95
|
+
end
|
96
|
+
|
97
|
+
# @return [Hash] the attributes as a hash
|
98
|
+
def to_hash
|
99
|
+
{ date_time: @date_time, wr: @wr }
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'ArrayHelper' do
|
5
|
+
array_of_numbers = [1, 3, 5, 7, 9].freeze
|
6
|
+
|
7
|
+
it 'Calculates sum' do
|
8
|
+
sum = TechnicalAnalysis::ArrayHelper.sum(array_of_numbers)
|
9
|
+
expect(sum).to eq(25)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'Calculates mean' do
|
13
|
+
mean = TechnicalAnalysis::ArrayHelper.mean(array_of_numbers)
|
14
|
+
expect(mean).to eq(5)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'Calculates average' do
|
18
|
+
average = TechnicalAnalysis::ArrayHelper.average(array_of_numbers)
|
19
|
+
expect(average).to eq(5)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'Calculates sample_variance' do
|
23
|
+
sample_variance = TechnicalAnalysis::ArrayHelper.sample_variance(array_of_numbers)
|
24
|
+
expect(sample_variance).to eq(10.0)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'Calculates standard_deviation' do
|
28
|
+
standard_deviation = TechnicalAnalysis::ArrayHelper.standard_deviation(array_of_numbers)
|
29
|
+
expect(standard_deviation).to eq(3.1622776601683795)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Validation' do
|
5
|
+
describe "date_time validation" do
|
6
|
+
input_data = SpecHelper.get_test_data(:close)
|
7
|
+
|
8
|
+
it 'Throws exception for invalid timestamp key' do
|
9
|
+
bad_date_time_key_data = input_data.each { |row| row[:bad_timestamp_key] = row.delete :date_time }
|
10
|
+
expect { TechnicalAnalysis::Validation.validate_date_time_key(bad_date_time_key_data) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "numeric validation" do
|
15
|
+
input_data = SpecHelper.get_test_data(:close)
|
16
|
+
|
17
|
+
it 'Throws exception for non numeric price data' do
|
18
|
+
non_numeric_data = input_data.each { |row| row[:close] = row.delete(:close).to_s }
|
19
|
+
expect { TechnicalAnalysis::Validation.validate_numeric_data(non_numeric_data, :close) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
class SpecHelper
|
4
|
+
|
5
|
+
TEST_DATA_PATH = File.join(File.dirname(__FILE__),'ta_test_data.csv')
|
6
|
+
FLOAT_KEYS = [:open, :high, :low, :close].freeze
|
7
|
+
INTEGER_KEYS = [:volume].freeze
|
8
|
+
|
9
|
+
def self.get_test_data(*columns)
|
10
|
+
@data = CSV.read(TEST_DATA_PATH, headers: true)
|
11
|
+
columns = columns.map(&:to_sym)
|
12
|
+
output = []
|
13
|
+
@data.each do |v|
|
14
|
+
col_hash = { date_time: v["date_time"] }
|
15
|
+
columns.each do |col|
|
16
|
+
value = v[col.to_s]
|
17
|
+
value = value.to_f if FLOAT_KEYS.include?(col)
|
18
|
+
value = value.to_i if INTEGER_KEYS.include?(col)
|
19
|
+
col_hash[col] = value
|
20
|
+
end
|
21
|
+
output << col_hash
|
22
|
+
end
|
23
|
+
output
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
date_time,close,volume,open,high,low
|
2
|
+
"2019-01-09T00:00:00.000Z",153.3100,45034370.0000,151.2900,154.5300,149.6300
|
3
|
+
"2019-01-08T00:00:00.000Z",150.7500,40622910.0000,149.5600,151.8200,148.5200
|
4
|
+
"2019-01-07T00:00:00.000Z",147.9300,54571440.0000,148.7000,148.8300,145.9000
|
5
|
+
"2019-01-04T00:00:00.000Z",148.2600,57423650.0000,144.5300,148.5499,143.8000
|
6
|
+
"2019-01-03T00:00:00.000Z",142.1900,91106840.0000,143.9800,145.7200,142.0000
|
7
|
+
"2019-01-02T00:00:00.000Z",157.9200,35637070.0000,154.8900,158.8500,154.2300
|
8
|
+
"2018-12-31T00:00:00.000Z",157.7400,34499390.0000,158.5300,159.3600,156.4800
|
9
|
+
"2018-12-28T00:00:00.000Z",156.2300,41740600.0000,157.5000,158.5200,154.5500
|
10
|
+
"2018-12-27T00:00:00.000Z",156.1500,51608850.0000,155.8400,156.7700,150.0700
|
11
|
+
"2018-12-26T00:00:00.000Z",157.1700,58133850.0000,148.3000,157.2300,146.7200
|
12
|
+
"2018-12-24T00:00:00.000Z",146.8300,37169230.0000,148.1500,151.5500,146.5900
|
13
|
+
"2018-12-21T00:00:00.000Z",150.7300,95497900.0000,156.8600,158.1600,149.6300
|
14
|
+
"2018-12-20T00:00:00.000Z",156.8300,64398230.0000,160.4000,162.1100,155.3000
|
15
|
+
"2018-12-19T00:00:00.000Z",160.8900,47597670.0000,166.0000,167.4500,159.0900
|
16
|
+
"2018-12-18T00:00:00.000Z",166.0700,33753490.0000,165.3800,167.5300,164.3900
|
17
|
+
"2018-12-17T00:00:00.000Z",163.9400,43250420.0000,165.4500,168.3500,162.7300
|
18
|
+
"2018-12-14T00:00:00.000Z",165.4800,40620360.0000,169.0000,169.0800,165.2800
|
19
|
+
"2018-12-13T00:00:00.000Z",170.9500,31754210.0000,170.4900,172.5700,169.5500
|
20
|
+
"2018-12-12T00:00:00.000Z",169.1000,35474680.0000,170.4000,171.9200,169.0200
|
21
|
+
"2018-12-11T00:00:00.000Z",168.6300,45968040.0000,171.6600,171.7900,167.0000
|
22
|
+
"2018-12-10T00:00:00.000Z",169.6000,61759000.0000,165.0000,170.0900,163.3300
|
23
|
+
"2018-12-07T00:00:00.000Z",168.4900,41678680.0000,173.4900,174.4900,168.3000
|
24
|
+
"2018-12-06T00:00:00.000Z",174.7200,42704910.0000,171.7600,174.7800,170.4200
|
25
|
+
"2018-12-04T00:00:00.000Z",176.6900,41141250.0000,180.9500,182.3899,176.2700
|
26
|
+
"2018-12-03T00:00:00.000Z",184.8200,40537700.0000,184.4600,184.9400,181.2100
|
27
|
+
"2018-11-30T00:00:00.000Z",178.5800,39424260.0000,180.2900,180.3300,177.0300
|
28
|
+
"2018-11-29T00:00:00.000Z",179.5500,41523580.0000,182.6600,182.8000,177.7000
|
29
|
+
"2018-11-28T00:00:00.000Z",180.9400,45941750.0000,176.7300,181.2900,174.9300
|
30
|
+
"2018-11-27T00:00:00.000Z",174.2400,41156140.0000,171.5100,174.7700,170.8800
|
31
|
+
"2018-11-26T00:00:00.000Z",174.6200,44662320.0000,174.2400,174.9500,170.2600
|
32
|
+
"2018-11-23T00:00:00.000Z",172.2900,23623970.0000,174.9400,176.5950,172.1000
|
33
|
+
"2018-11-21T00:00:00.000Z",176.7800,31096240.0000,179.7300,180.2700,176.5500
|
34
|
+
"2018-11-20T00:00:00.000Z",176.9800,67678680.0000,178.3700,181.4700,175.5100
|
35
|
+
"2018-11-19T00:00:00.000Z",185.8600,41626820.0000,190.0000,190.7000,184.9900
|
36
|
+
"2018-11-16T00:00:00.000Z",193.5300,36191330.0000,190.5000,194.9695,189.4600
|
37
|
+
"2018-11-15T00:00:00.000Z",191.4100,46271660.0000,188.3900,191.9700,186.9000
|
38
|
+
"2018-11-14T00:00:00.000Z",186.8000,60547340.0000,193.9000,194.4800,185.9300
|
39
|
+
"2018-11-13T00:00:00.000Z",192.2300,46725710.0000,191.6300,197.1800,191.4501
|
40
|
+
"2018-11-12T00:00:00.000Z",194.1700,50991030.0000,199.0000,199.8500,193.7900
|
41
|
+
"2018-11-09T00:00:00.000Z",204.4700,34317760.0000,205.5500,206.0100,202.2500
|
42
|
+
"2018-11-08T00:00:00.000Z",208.4900,25289270.0000,209.9800,210.1200,206.7500
|
43
|
+
"2018-11-07T00:00:00.000Z",209.9500,33291640.0000,205.9700,210.0600,204.1300
|
44
|
+
"2018-11-06T00:00:00.000Z",203.7700,31774720.0000,201.9200,204.7200,201.6900
|
45
|
+
"2018-11-05T00:00:00.000Z",201.5900,66072170.0000,204.3000,204.3900,198.1700
|
46
|
+
"2018-11-02T00:00:00.000Z",207.4800,91046560.0000,209.5500,213.6500,205.4300
|
47
|
+
"2018-11-01T00:00:00.000Z",222.2200,52954070.0000,219.0500,222.3600,216.8100
|
48
|
+
"2018-10-31T00:00:00.000Z",218.8600,38016810.0000,216.8800,220.4500,216.6200
|
49
|
+
"2018-10-30T00:00:00.000Z",213.3000,36487930.0000,211.1500,215.1800,209.2700
|
50
|
+
"2018-10-29T00:00:00.000Z",212.2400,45713690.0000,219.1900,219.6900,206.0900
|
51
|
+
"2018-10-26T00:00:00.000Z",216.3000,47191700.0000,215.9000,220.1900,212.6700
|
52
|
+
"2018-10-25T00:00:00.000Z",219.8000,29027340.0000,217.7100,221.3800,216.7500
|
53
|
+
"2018-10-24T00:00:00.000Z",215.0900,39992120.0000,222.6000,224.2300,214.5400
|
54
|
+
"2018-10-23T00:00:00.000Z",222.7300,38681170.0000,215.8300,223.2500,214.7000
|
55
|
+
"2018-10-22T00:00:00.000Z",220.6500,28751540.0000,219.7900,223.3600,218.9400
|
56
|
+
"2018-10-19T00:00:00.000Z",219.3100,32874330.0000,218.0600,221.2600,217.4300
|
57
|
+
"2018-10-18T00:00:00.000Z",216.0200,32389280.0000,217.8600,219.7400,213.0000
|
58
|
+
"2018-10-17T00:00:00.000Z",221.1900,22692880.0000,222.3000,222.6400,219.3400
|
59
|
+
"2018-10-16T00:00:00.000Z",222.1500,28802550.0000,218.9300,222.9900,216.7627
|
60
|
+
"2018-10-15T00:00:00.000Z",217.3600,30280450.0000,221.1600,221.8300,217.2700
|
61
|
+
"2018-10-12T00:00:00.000Z",222.1100,39494770.0000,220.4200,222.8800,216.8400
|
62
|
+
"2018-10-11T00:00:00.000Z",214.4500,52902320.0000,214.5200,219.5000,212.3200
|
63
|
+
"2018-10-10T00:00:00.000Z",216.3600,41084070.0000,225.4600,226.3500,216.0500
|
64
|
+
"2018-10-09T00:00:00.000Z",226.8700,26656630.0000,223.6400,227.2700,222.2462
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'technical-analysis'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe 'Indicators' do
|
5
|
+
describe "ADI" do
|
6
|
+
indicator = TechnicalAnalysis::Adi
|
7
|
+
|
8
|
+
describe 'Accumulation/Distribution Index' do
|
9
|
+
it 'Calculates ADI' do
|
10
|
+
|
11
|
+
input_data = SpecHelper.get_test_data(:volume, :high, :low, :close)
|
12
|
+
output = indicator.calculate(input_data)
|
13
|
+
normalized_output = output.map(&:to_hash)
|
14
|
+
|
15
|
+
expected_output = [
|
16
|
+
{:date_time=>"2019-01-09T00:00:00.000Z", :adi=>-112451134.66006838},
|
17
|
+
{:date_time=>"2019-01-08T00:00:00.000Z", :adi=>-135060226.53761944},
|
18
|
+
{:date_time=>"2019-01-07T00:00:00.000Z", :adi=>-149339794.90125585},
|
19
|
+
{:date_time=>"2019-01-04T00:00:00.000Z", :adi=>-170386118.17770624},
|
20
|
+
{:date_time=>"2019-01-03T00:00:00.000Z", :adi=>-220800308.5532927},
|
21
|
+
{:date_time=>"2019-01-02T00:00:00.000Z", :adi=>-139000081.24146464},
|
22
|
+
{:date_time=>"2018-12-31T00:00:00.000Z", :adi=>-160289759.42328274},
|
23
|
+
{:date_time=>"2018-12-28T00:00:00.000Z", :adi=>-155977335.67328295},
|
24
|
+
{:date_time=>"2018-12-27T00:00:00.000Z", :adi=>-149563792.60023466},
|
25
|
+
{:date_time=>"2018-12-26T00:00:00.000Z", :adi=>-191621153.9435182},
|
26
|
+
{:date_time=>"2018-12-24T00:00:00.000Z", :adi=>-249091249.23371798},
|
27
|
+
{:date_time=>"2018-12-21T00:00:00.000Z", :adi=>-215519041.4917826},
|
28
|
+
{:date_time=>"2018-12-20T00:00:00.000Z", :adi=>-144651314.99705797},
|
29
|
+
{:date_time=>"2018-12-19T00:00:00.000Z", :adi=>-109189734.6005822},
|
30
|
+
{:date_time=>"2018-12-18T00:00:00.000Z", :adi=>-82088668.90680213},
|
31
|
+
{:date_time=>"2018-12-17T00:00:00.000Z", :adi=>-84453563.11062376},
|
32
|
+
{:date_time=>"2018-12-14T00:00:00.000Z", :adi=>-59826989.44514345},
|
33
|
+
{:date_time=>"2018-12-13T00:00:00.000Z", :adi=>-23482456.813564237},
|
34
|
+
{:date_time=>"2018-12-12T00:00:00.000Z", :adi=>-21169236.217537448},
|
35
|
+
{:date_time=>"2018-12-11T00:00:00.000Z", :adi=>12348220.058324995},
|
36
|
+
{:date_time=>"2018-12-10T00:00:00.000Z", :adi=>27031122.187761355},
|
37
|
+
{:date_time=>"2018-12-07T00:00:00.000Z", :adi=>-25774650.00158758},
|
38
|
+
{:date_time=>"2018-12-06T00:00:00.000Z", :adi=>13345403.439446371},
|
39
|
+
{:date_time=>"2018-12-04T00:00:00.000Z", :adi=>-28184142.065140743},
|
40
|
+
{:date_time=>"2018-12-03T00:00:00.000Z", :adi=>7310177.429459017},
|
41
|
+
{:date_time=>"2018-11-30T00:00:00.000Z", :adi=>-30619198.70995107},
|
42
|
+
{:date_time=>"2018-11-29T00:00:00.000Z", :adi=>-28229849.61904212},
|
43
|
+
{:date_time=>"2018-11-28T00:00:00.000Z", :adi=>-16831219.815120786},
|
44
|
+
{:date_time=>"2018-11-27T00:00:00.000Z", :adi=>-57716487.89688186},
|
45
|
+
{:date_time=>"2018-11-26T00:00:00.000Z", :adi=>-87657844.24649628},
|
46
|
+
{:date_time=>"2018-11-23T00:00:00.000Z", :adi=>-126035061.64521725},
|
47
|
+
{:date_time=>"2018-11-21T00:00:00.000Z", :adi=>-104408223.70305927},
|
48
|
+
{:date_time=>"2018-11-20T00:00:00.000Z", :adi=>-77157217.68155372},
|
49
|
+
{:date_time=>"2018-11-19T00:00:00.000Z", :adi=>-42863658.35269459},
|
50
|
+
{:date_time=>"2018-11-16T00:00:00.000Z", :adi=>-13921718.702957403},
|
51
|
+
{:date_time=>"2018-11-15T00:00:00.000Z", :adi=>-31201198.431607798},
|
52
|
+
{:date_time=>"2018-11-14T00:00:00.000Z", :adi=>-67251111.0548819},
|
53
|
+
{:date_time=>"2018-11-13T00:00:00.000Z", :adi=>-19025685.861899547},
|
54
|
+
{:date_time=>"2018-11-12T00:00:00.000Z", :adi=>14980297.36136794},
|
55
|
+
{:date_time=>"2018-11-09T00:00:00.000Z", :adi=>59576412.70790268},
|
56
|
+
{:date_time=>"2018-11-08T00:00:00.000Z", :adi=>53370009.30364728},
|
57
|
+
{:date_time=>"2018-11-07T00:00:00.000Z", :adi=>52544543.51729703},
|
58
|
+
{:date_time=>"2018-11-06T00:00:00.000Z", :adi=>20488006.51898352},
|
59
|
+
{:date_time=>"2018-11-05T00:00:00.000Z", :adi=>8638028.433174696},
|
60
|
+
{:date_time=>"2018-11-02T00:00:00.000Z", :adi=>2052056.5039138943},
|
61
|
+
{:date_time=>"2018-11-01T00:00:00.000Z", :adi=>47686098.74235708},
|
62
|
+
{:date_time=>"2018-10-31T00:00:00.000Z", :adi=>-2596414.5729579534},
|
63
|
+
{:date_time=>"2018-10-30T00:00:00.000Z", :adi=>-9048353.606900878},
|
64
|
+
{:date_time=>"2018-10-29T00:00:00.000Z", :adi=>-22322304.45292461},
|
65
|
+
{:date_time=>"2018-10-26T00:00:00.000Z", :adi=>-17952613.497042313},
|
66
|
+
{:date_time=>"2018-10-25T00:00:00.000Z", :adi=>-16320985.571510637},
|
67
|
+
{:date_time=>"2018-10-24T00:00:00.000Z", :adi=>-25537009.286413625},
|
68
|
+
{:date_time=>"2018-10-23T00:00:00.000Z", :adi=>9915241.57013943},
|
69
|
+
{:date_time=>"2018-10-22T00:00:00.000Z", :adi=>-24060850.441556394},
|
70
|
+
{:date_time=>"2018-10-19T00:00:00.000Z", :adi=>-17555977.138388995},
|
71
|
+
{:date_time=>"2018-10-18T00:00:00.000Z", :adi=>-16955140.819851194},
|
72
|
+
{:date_time=>"2018-10-17T00:00:00.000Z", :adi=>-13591269.009762233},
|
73
|
+
{:date_time=>"2018-10-16T00:00:00.000Z", :adi=>-16341921.130974408},
|
74
|
+
{:date_time=>"2018-10-15T00:00:00.000Z", :adi=>-37374123.7894299},
|
75
|
+
{:date_time=>"2018-10-12T00:00:00.000Z", :adi=>-8288954.710482582},
|
76
|
+
{:date_time=>"2018-10-11T00:00:00.000Z", :adi=>-37713866.134323865},
|
77
|
+
{:date_time=>"2018-10-10T00:00:00.000Z", :adi=>-16199273.599504825},
|
78
|
+
{:date_time=>"2018-10-09T00:00:00.000Z", :adi=>22411774.711174767}
|
79
|
+
]
|
80
|
+
|
81
|
+
expect(normalized_output).to eq(expected_output)
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'Returns the symbol' do
|
85
|
+
indicator_symbol = indicator.indicator_symbol
|
86
|
+
expect(indicator_symbol).to eq('adi')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'Returns the name' do
|
90
|
+
indicator_name = indicator.indicator_name
|
91
|
+
expect(indicator_name).to eq('Accumulation/Distribution Index')
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'Returns the valid options' do
|
95
|
+
valid_options = indicator.valid_options
|
96
|
+
expect(valid_options).to eq([])
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'Validates options' do
|
100
|
+
valid_options = {}
|
101
|
+
options_validated = indicator.validate_options(valid_options)
|
102
|
+
expect(options_validated).to eq(true)
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'Throws exception for invalid options' do
|
106
|
+
invalid_options = { test: 10 }
|
107
|
+
expect { indicator.validate_options(invalid_options) }.to raise_exception(TechnicalAnalysis::Validation::ValidationError)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'Calculates minimum data size' do
|
111
|
+
options = {}
|
112
|
+
expect(indicator.min_data_size(options)).to eq(1)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|