-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathrelative_strength_index.rb
More file actions
74 lines (59 loc) · 2.15 KB
/
relative_strength_index.rb
File metadata and controls
74 lines (59 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
module RubyTechnicalAnalysis
# Relative Strength Index
#
# Find more information at: https://www.fidelity.com/viewpoints/active-investor/how-to-use-RSI
class RelativeStrengthIndex < Indicator
attr_reader :period
# @param series [Array] An array of prices, typically closing prices
# @param period [Integer] The number of periods to use in the calculation
def initialize(series: [], period: 14)
@period = period
@rsi = []
@smooth_up = []
@smooth_down = []
@wilders_is_set = false
super(series: series)
end
# @return [Float] The current RSI value
def call
calculate_rsi
end
# @return [Boolean] Whether or not the object is valid
def valid?
period < series.length
end
private
def _smooth_coef_one
@_smooth_coef_one ||= (1.0 / period)
end
def _smooth_coef_two
@_smooth_coef_two ||= (1 - _smooth_coef_one)
end
def calculate_channels(cla)
period.times.map do |index|
diff = (cla.at(index) - cla.at(index + 1))
[diff.negative? ? diff.abs : 0, diff.positive? ? diff : 0]
end.transpose
end
def calculate_initial_smoothing(up_ch, down_ch)
@smooth_up << RubyTechnicalAnalysis::WildersSmoothing.call(series: up_ch, period: period)
@smooth_down << RubyTechnicalAnalysis::WildersSmoothing.call(series: down_ch, period: period)
@wilders_is_set = true
end
def calculate_subsequent_smoothing(up_ch, down_ch)
@smooth_up << (_smooth_coef_one * up_ch.last + _smooth_coef_two * @smooth_up.last)
@smooth_down << (_smooth_coef_one * down_ch.last + _smooth_coef_two * @smooth_down.last)
end
def calculate_smoothing(up_ch, down_ch)
@wilders_is_set ? calculate_subsequent_smoothing(up_ch, down_ch) : calculate_initial_smoothing(up_ch, down_ch)
end
def calculate_rsi
(0..(series.size - period - 1)).flat_map do |index|
cla = series[index..index + period]
up_ch, down_ch = calculate_channels(cla)
calculate_smoothing(up_ch, down_ch)
@rsi << (100.00 - (100.00 / ((@smooth_up.last.to_f / @smooth_down.last) + 1)))
end.last
end
end
end