Module: TA::Indicators
- Defined in:
- lib/ta/indicators.rb
Overview
Technical indicator calculations with fallback implementations
Class Method Summary collapse
- .adx(high, low, close, period) ⇒ Object
- .atr(high, low, close, period) ⇒ Object
- .ema(series, period) ⇒ Object
- .macd(series, fast, slow, signal) ⇒ Object
- .rsi(series, period) ⇒ Object
- .simple_adx(high, low, close, period) ⇒ Object
- .simple_atr(high, low, close, period) ⇒ Object
- .simple_macd(series, fast, slow, signal) ⇒ Object
- .simple_rsi(series, period) ⇒ Object
- .true_ranges(high, low, close) ⇒ Object
Class Method Details
.adx(high, low, close, period) ⇒ Object
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ta/indicators.rb', line 57 def adx(high, low, close, period) if defined?(RubyTechnicalAnalysis) && RubyTechnicalAnalysis.const_defined?(:ADX) return RubyTechnicalAnalysis::ADX.new(high: high, low: low, close: close, period: period).call end if defined?(TechnicalAnalysis) && TechnicalAnalysis.respond_to?(:adx) return TechnicalAnalysis.adx(high: high, low: low, close: close, period: period) end simple_adx(high, low, close, period) end |
.atr(high, low, close, period) ⇒ Object
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/ta/indicators.rb', line 68 def atr(high, low, close, period) if defined?(RubyTechnicalAnalysis) && RubyTechnicalAnalysis.const_defined?(:ATR) return RubyTechnicalAnalysis::ATR.new(high: high, low: low, close: close, period: period).call end if defined?(TechnicalAnalysis) && TechnicalAnalysis.respond_to?(:atr) return TechnicalAnalysis.atr(high: high, low: low, close: close, period: period) end simple_atr(high, low, close, period) end |
.ema(series, period) ⇒ Object
8 9 10 11 12 13 14 15 |
# File 'lib/ta/indicators.rb', line 8 def ema(series, period) return nil if series.nil? || series.empty? k = 2.0 / (period + 1) series.each_with_index.reduce(nil) do |ema_prev, (v, i)| i.zero? ? v.to_f : (v.to_f * k) + ((ema_prev || v.to_f) * (1 - k)) end end |
.macd(series, fast, slow, signal) ⇒ Object
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 |
# File 'lib/ta/indicators.rb', line 28 def macd(series, fast, slow, signal) if defined?(RubyTechnicalAnalysis) && RubyTechnicalAnalysis.const_defined?(:MACD) out = RubyTechnicalAnalysis::MACD.new(series: series, fast_period: fast, slow_period: slow, signal_period: signal).call if out.is_a?(Hash) m = out[:macd] s = out[:signal] h = out[:histogram] || out[:hist] m = m.last if m.is_a?(Array) s = s.last if s.is_a?(Array) h = h.last if h.is_a?(Array) return { macd: m, signal: s, hist: h } end end if defined?(TechnicalAnalysis) && TechnicalAnalysis.respond_to?(:macd) out = TechnicalAnalysis.macd(series, fast: fast, slow: slow, signal: signal) if out.is_a?(Hash) m = out[:macd] s = out[:signal] h = out[:hist] m = m.last if m.is_a?(Array) s = s.last if s.is_a?(Array) h = h.last if h.is_a?(Array) return { macd: m, signal: s, hist: h } end end simple_macd(series, fast, slow, signal) end |
.rsi(series, period) ⇒ Object
17 18 19 20 21 22 23 24 25 26 |
# File 'lib/ta/indicators.rb', line 17 def rsi(series, period) if defined?(RubyTechnicalAnalysis) && RubyTechnicalAnalysis.const_defined?(:RSI) return RubyTechnicalAnalysis::RSI.new(series: series, period: period).call end if defined?(TechnicalAnalysis) && TechnicalAnalysis.respond_to?(:rsi) return TechnicalAnalysis.rsi(series, period: period) end simple_rsi(series, period) end |
.simple_adx(high, low, close, period) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/ta/indicators.rb', line 141 def simple_adx(high, low, close, period) plus_dm = [0] minus_dm = [0] (1...high.size).each do |i| up_move = high[i] - high[i - 1] down_move = low[i - 1] - low[i] plus_dm << (up_move > down_move && up_move.positive? ? up_move : 0) minus_dm << (down_move > up_move && down_move.positive? ? down_move : 0) end trs = true_ranges(high, low, close) smooth_tr = trs.first(period).sum smooth_plus_dm = plus_dm.first(period).sum smooth_minus_dm = minus_dm.first(period).sum adx_vals = Array.new(high.size, nil) di_vals = [] (period...high.size).each do |i| smooth_tr = smooth_tr - (smooth_tr / period) + trs[i] smooth_plus_dm = smooth_plus_dm - (smooth_plus_dm / period) + plus_dm[i] smooth_minus_dm = smooth_minus_dm - (smooth_minus_dm / period) + minus_dm[i] plus_di = 100.0 * (smooth_plus_dm / smooth_tr) minus_di = 100.0 * (smooth_minus_dm / smooth_tr) dx = 100.0 * ((plus_di - minus_di).abs / (plus_di + minus_di)) di_vals << dx adx_vals[i] = di_vals.last(period).sum / period.to_f if di_vals.size >= period end adx_vals end |
.simple_atr(high, low, close, period) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/ta/indicators.rb', line 124 def simple_atr(high, low, close, period) trs = true_ranges(high, low, close) out = [] atr_prev = trs.first(period).sum / period.to_f trs.each_with_index do |tr, i| if i < period out << nil elsif i == period out << atr_prev else atr_prev = ((atr_prev * (period - 1)) + tr) / period.to_f out << atr_prev end end out end |
.simple_macd(series, fast, slow, signal) ⇒ Object
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/ta/indicators.rb', line 100 def simple_macd(series, fast, slow, signal) e_fast = ema(series, fast) e_slow = ema(series, slow) e_sig = ema(series, signal) return { macd: nil, signal: nil, hist: nil } if [e_fast, e_slow, e_sig].any?(&:nil?) macd_line = e_fast - e_slow signal_line = e_sig { macd: macd_line, signal: signal_line, hist: macd_line - signal_line } end |
.simple_rsi(series, period) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ta/indicators.rb', line 79 def simple_rsi(series, period) gains = [] losses = [] series.each_cons(2) do |a, b| ch = b - a gains << [ch, 0].max losses << [(-ch), 0].max end avg_gain = gains.first(period).sum / period.to_f avg_loss = losses.first(period).sum / period.to_f rsi_vals = Array.new(series.size, nil) gains.drop(period).each_with_index do |g, idx| l = losses[period + idx] avg_gain = ((avg_gain * (period - 1)) + g) / period avg_loss = ((avg_loss * (period - 1)) + l) / period rs = avg_loss.zero? ? 100.0 : (avg_gain / avg_loss) rsi_vals[period + 1 + idx] = 100.0 - (100.0 / (1 + rs)) end rsi_vals end |
.true_ranges(high, low, close) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ta/indicators.rb', line 111 def true_ranges(high, low, close) trs = [] close.each_with_index do |_c, i| if i.zero? trs << (high[i] - low[i]).abs else tr = [(high[i] - low[i]).abs, (high[i] - close[i - 1]).abs, (low[i] - close[i - 1]).abs].max trs << tr end end trs end |