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,96 @@
|
|
1
|
+
module TechnicalAnalysis
|
2
|
+
# Daily Return
|
3
|
+
class Dr < 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
|
+
"dr"
|
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
|
+
"Daily Return"
|
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(price_key)
|
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(**params)
|
42
|
+
1
|
43
|
+
end
|
44
|
+
|
45
|
+
# Calculates the daily return (percent expressed as a decimal) for the data over the given period
|
46
|
+
# https://en.wikipedia.org/wiki/Rate_of_return
|
47
|
+
#
|
48
|
+
# @param data [Array] Array of hashes with keys (:date_time, :value)
|
49
|
+
# @param price_key [Symbol] The hash key for the price data. Default :value
|
50
|
+
#
|
51
|
+
# @return [Array<DrValue>] An array of DrValue instances
|
52
|
+
def self.calculate(data, price_key: :value)
|
53
|
+
price_key = price_key.to_sym
|
54
|
+
Validation.validate_numeric_data(data, price_key)
|
55
|
+
Validation.validate_length(data, min_data_size({}))
|
56
|
+
Validation.validate_date_time_key(data)
|
57
|
+
|
58
|
+
data = data.sort_by { |row| row[:date_time] }
|
59
|
+
|
60
|
+
output = []
|
61
|
+
prev_price = data.first[price_key].to_f
|
62
|
+
|
63
|
+
data.each do |v|
|
64
|
+
current_price = v[:close].to_f
|
65
|
+
|
66
|
+
output << DrValue.new(date_time: v[:date_time], dr: ((current_price / prev_price) - 1))
|
67
|
+
|
68
|
+
prev_price = current_price
|
69
|
+
end
|
70
|
+
|
71
|
+
output.sort_by(&:date_time).reverse
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
# The value class to be returned by calculations
|
77
|
+
class DrValue
|
78
|
+
|
79
|
+
# @return [String] the date_time of the obversation as it was provided
|
80
|
+
attr_accessor :date_time
|
81
|
+
|
82
|
+
# @return [Float] the dr calculation value
|
83
|
+
attr_accessor :dr
|
84
|
+
|
85
|
+
def initialize(date_time: nil, dr: nil)
|
86
|
+
@date_time = date_time
|
87
|
+
@dr = dr
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [Hash] the attributes as a hash
|
91
|
+
def to_hash
|
92
|
+
{ date_time: @date_time, dr: @dr }
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module TechnicalAnalysis
|
2
|
+
# Ease of Movement
|
3
|
+
class Eom < 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
|
+
"eom"
|
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
|
+
"Ease of Movement"
|
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 + 1
|
43
|
+
end
|
44
|
+
|
45
|
+
# Calculates the ease of movement (EoM) for the data over the given period
|
46
|
+
# https://en.wikipedia.org/wiki/Ease_of_movement
|
47
|
+
#
|
48
|
+
# @param data [Array] Array of hashes with keys (:date_time, :high, :low, :volume)
|
49
|
+
# @param period [Integer] The given period to calculate the EoM
|
50
|
+
#
|
51
|
+
# @return [Array<Hash>] An array of EomValue instances
|
52
|
+
def self.calculate(data, period: 14)
|
53
|
+
period = period.to_i
|
54
|
+
Validation.validate_numeric_data(data, :high, :low, :volume)
|
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
|
+
prev_price = data.shift
|
63
|
+
|
64
|
+
data.each do |v|
|
65
|
+
distance_moved = ((v[:high] + v[:low]) / 2) - ((prev_price[:high] + prev_price[:low]) / 2)
|
66
|
+
box_ratio = (v[:volume] / 100_000_000.00) / (v[:high] - v[:low])
|
67
|
+
emv = distance_moved / box_ratio
|
68
|
+
|
69
|
+
period_values << emv
|
70
|
+
|
71
|
+
if period_values.size == period
|
72
|
+
output << EomValue.new(date_time: v[:date_time], eom: ArrayHelper.average(period_values))
|
73
|
+
period_values.shift
|
74
|
+
end
|
75
|
+
|
76
|
+
prev_price = v
|
77
|
+
end
|
78
|
+
|
79
|
+
output.sort_by(&:date_time).reverse
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# The value class to be returned by calculations
|
85
|
+
class EomValue
|
86
|
+
|
87
|
+
# @return [String] the date_time of the obversation as it was provided
|
88
|
+
attr_accessor :date_time
|
89
|
+
|
90
|
+
# @return [Float] the eom calculation value
|
91
|
+
attr_accessor :eom
|
92
|
+
|
93
|
+
def initialize(date_time: nil, eom: nil)
|
94
|
+
@date_time = date_time
|
95
|
+
@eom = eom
|
96
|
+
end
|
97
|
+
|
98
|
+
# @return [Hash] the attributes as a hash
|
99
|
+
def to_hash
|
100
|
+
{ date_time: @date_time, eom: @eom }
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module TechnicalAnalysis
|
2
|
+
# Force Index
|
3
|
+
class Fi < 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
|
+
"fi"
|
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
|
+
"Force Index"
|
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 force index (FI) for the data
|
47
|
+
# https://en.wikipedia.org/wiki/Force_index
|
48
|
+
#
|
49
|
+
# @param data [Array] Array of hashes with keys (:date_time, :close, :volume)
|
50
|
+
#
|
51
|
+
# @return [Array<FiValue>] An array of FiValue 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
|
+
|
62
|
+
data.each do |v|
|
63
|
+
fi = ((v[:close] - prev_price[:close]) * v[:volume])
|
64
|
+
|
65
|
+
output << FiValue.new(date_time: v[:date_time], fi: fi)
|
66
|
+
|
67
|
+
prev_price = v
|
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 FiValue
|
77
|
+
|
78
|
+
# @return [String] the date_time of the obversation as it was provided
|
79
|
+
attr_accessor :date_time
|
80
|
+
|
81
|
+
# @return [Float] the fi calculation value
|
82
|
+
attr_accessor :fi
|
83
|
+
|
84
|
+
def initialize(date_time: nil, fi: nil)
|
85
|
+
@date_time = date_time
|
86
|
+
@fi = fi
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Hash] the attributes as a hash
|
90
|
+
def to_hash
|
91
|
+
{ date_time: @date_time, fi: @fi }
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
module TechnicalAnalysis
|
2
|
+
# Ichimoku Kinko Hyo
|
3
|
+
class Ichimoku < 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
|
+
"ichimoku"
|
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
|
+
"Ichimoku Kinko Hyo"
|
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(low_period medium_period high_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(medium_period: 26, high_period: 52, **params)
|
42
|
+
high_period.to_i + medium_period.to_i - 1
|
43
|
+
end
|
44
|
+
|
45
|
+
# Calculates the 5 points of Ichimoku Kinko Hyo (Ichimoku) for the data over the given period
|
46
|
+
# 1. tenkan_sen (Conversion Line)
|
47
|
+
# 2. kijun_sen (Base Line)
|
48
|
+
# 3. senkou_span_a (Leading Span A)
|
49
|
+
# 4. senkou_span_b (Leading Span B)
|
50
|
+
# 5. chickou_span (Lagging Span)
|
51
|
+
# https://en.wikipedia.org/wiki/Ichimoku_Kink%C5%8D_Hy%C5%8D
|
52
|
+
#
|
53
|
+
# @param data [Array] Array of hashes with keys (:date_time, :high, :low, :close)
|
54
|
+
# @param low_period [Integer] The given period to calculate tenkan_sen (Conversion Line)
|
55
|
+
# @param medium_period [Integer] The given period to calculate kijun_sen (Base Line), senkou_span_a (Leading Span A), and chikou_span (Lagging Span)
|
56
|
+
# @param high_period [Integer] The given period to calculate senkou_span_b (Leading Span B)
|
57
|
+
#
|
58
|
+
# @return [Array<IchimokuValue>] An array of IchimokuValue instances
|
59
|
+
def self.calculate(data, low_period: 9, medium_period: 26, high_period: 52)
|
60
|
+
low_period = low_period.to_i
|
61
|
+
medium_period = medium_period.to_i
|
62
|
+
high_period = high_period.to_i
|
63
|
+
Validation.validate_numeric_data(data, :high, :low, :close)
|
64
|
+
Validation.validate_length(data, min_data_size(high_period: high_period, medium_period: medium_period))
|
65
|
+
Validation.validate_date_time_key(data)
|
66
|
+
|
67
|
+
data = data.sort_by { |row| row[:date_time] }
|
68
|
+
|
69
|
+
index = high_period + medium_period - 2
|
70
|
+
output = []
|
71
|
+
|
72
|
+
while index < data.size
|
73
|
+
date_time = data[index][:date_time]
|
74
|
+
|
75
|
+
tenkan_sen = calculate_midpoint(index, low_period, data)
|
76
|
+
kinjun_sen = calculate_midpoint(index, medium_period, data)
|
77
|
+
senkou_span_a = calculate_senkou_span_a(index, low_period, medium_period, data)
|
78
|
+
senkou_span_b = calculate_senkou_span_b(index, medium_period, high_period, data)
|
79
|
+
chikou_span = calculate_chikou_span(index, medium_period, data)
|
80
|
+
|
81
|
+
output << IchimokuValue.new(
|
82
|
+
date_time: date_time,
|
83
|
+
tenkan_sen: tenkan_sen,
|
84
|
+
kijun_sen: kinjun_sen,
|
85
|
+
senkou_span_a: senkou_span_a,
|
86
|
+
senkou_span_b: senkou_span_b,
|
87
|
+
chikou_span: chikou_span
|
88
|
+
)
|
89
|
+
|
90
|
+
index += 1
|
91
|
+
end
|
92
|
+
|
93
|
+
output.sort_by(&:date_time).reverse
|
94
|
+
end
|
95
|
+
|
96
|
+
private_class_method def self.lowest_low(prices)
|
97
|
+
prices.map { |price| price[:low] }.min
|
98
|
+
end
|
99
|
+
|
100
|
+
private_class_method def self.highest_high(prices)
|
101
|
+
prices.map { |price| price[:high] }.max
|
102
|
+
end
|
103
|
+
|
104
|
+
private_class_method def self.calculate_midpoint(index, period, data)
|
105
|
+
period_range = ((index - (period - 1))..index)
|
106
|
+
period_data = data[period_range]
|
107
|
+
lowest_low = lowest_low(period_data)
|
108
|
+
highest_high = highest_high(period_data)
|
109
|
+
|
110
|
+
((highest_high + lowest_low) / 2.0)
|
111
|
+
end
|
112
|
+
|
113
|
+
private_class_method def self.calculate_senkou_span_a(index, low_period, medium_period, data)
|
114
|
+
mp_ago_index = (index - (medium_period - 1))
|
115
|
+
|
116
|
+
tenkan_sen_mp_ago = calculate_midpoint(mp_ago_index, low_period, data)
|
117
|
+
kinjun_sen_mp_ago = calculate_midpoint(mp_ago_index, medium_period, data)
|
118
|
+
|
119
|
+
((tenkan_sen_mp_ago + kinjun_sen_mp_ago) / 2.0)
|
120
|
+
end
|
121
|
+
|
122
|
+
private_class_method def self.calculate_senkou_span_b(index, medium_period, high_period, data)
|
123
|
+
mp_ago_index = (index - (medium_period - 1))
|
124
|
+
|
125
|
+
calculate_midpoint(mp_ago_index, high_period, data)
|
126
|
+
end
|
127
|
+
|
128
|
+
private_class_method def self.calculate_chikou_span(index, medium_period, data)
|
129
|
+
mp_ago_index = (index - (medium_period - 1))
|
130
|
+
|
131
|
+
data[mp_ago_index][:close]
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
# The value class to be returned by calculations
|
137
|
+
class IchimokuValue
|
138
|
+
|
139
|
+
# @return [String] the date_time of the obversation as it was provided
|
140
|
+
attr_accessor :date_time
|
141
|
+
|
142
|
+
# @return [Float] the tenkan_sen calculation value
|
143
|
+
attr_accessor :tenkan_sen
|
144
|
+
|
145
|
+
# @return [Float] the kijun_sen calculation value
|
146
|
+
attr_accessor :kijun_sen
|
147
|
+
|
148
|
+
# @return [Float] the senkou_span_a calculation value
|
149
|
+
attr_accessor :senkou_span_a
|
150
|
+
|
151
|
+
# @return [Float] the senkou_span_b calculation value
|
152
|
+
attr_accessor :senkou_span_b
|
153
|
+
|
154
|
+
# @return [Float] the chikou_span calculation value
|
155
|
+
attr_accessor :chikou_span
|
156
|
+
|
157
|
+
def initialize(date_time: nil, tenkan_sen: nil, kijun_sen: nil, senkou_span_a: nil, senkou_span_b: nil, chikou_span: nil)
|
158
|
+
@date_time = date_time
|
159
|
+
@tenkan_sen = tenkan_sen
|
160
|
+
@kijun_sen = kijun_sen
|
161
|
+
@senkou_span_a = senkou_span_a
|
162
|
+
@senkou_span_b = senkou_span_b
|
163
|
+
@chikou_span = chikou_span
|
164
|
+
end
|
165
|
+
|
166
|
+
# @return [Hash] the attributes as a hash
|
167
|
+
def to_hash
|
168
|
+
{
|
169
|
+
date_time: @date_time,
|
170
|
+
tenkan_sen: @tenkan_sen,
|
171
|
+
kijun_sen: @kijun_sen,
|
172
|
+
senkou_span_a: @senkou_span_a,
|
173
|
+
senkou_span_b: @senkou_span_b,
|
174
|
+
chikou_span: @chikou_span
|
175
|
+
}
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|