Module: Coinbot::OrderBook::RSI
- Defined in:
- lib/coinbot/order_book/rsi.rb
Class Method Summary collapse
-
.calculate(opts = {}) ⇒ Object
- Supported Method Parameters
-
Coinbot::OrderBook::RSI.calculate( order_book: 'required - order book data structure' ).
-
.help ⇒ Object
Display Usage for this Module.
-
.status(opts = {}) ⇒ Object
- Supported Method Parameters
-
Coinbot::OrderBook::RSI.status( ).
Class Method Details
.calculate(opts = {}) ⇒ Object
- Supported Method Parameters
-
Coinbot::OrderBook::RSI.calculate(
order_book: 'required - order book data structure'
)
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 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 168 169 |
# File 'lib/coinbot/order_book/rsi.rb', line 77 public_class_method def self.calculate(opts = {}) # Relative Strength Index (RSI) ALGORITHM last_ticker_price = opts[:last_ticker_price].to_f candles = opts[:candles] rsi_history = opts[:rsi_history] rsi_candle = 14 # We only need 13 candles closed as the 14th # leverages current ticker price. return rsi_history.push('--') if candles.length < rsi_candle # step 1 # Calculate the bar-to-bar changes for each bar # This is change = candle close - previous candle close # If the change is positive, add it to gains_arr # If the change is negative or zero, add 0 to gains_arr # If the change is negative, add absolute value of change to loss_arr # If the change is positive or zero, add 0 to loss_arr gain_arr = [] loss_arr = [] candles.last(rsi_candle)[..-2].map do |in_scope| candle_close = in_scope[:candle_close].to_f candle_open = in_scope[:candle_open].to_f candle_price_diff = candle_close - candle_open gain_arr.push(candle_price_diff) if candle_price_diff.positive? gain_arr.push(0) if candle_price_diff.negative? || candle_price_diff.zero? loss_arr.push(candle_price_diff.abs) if candle_price_diff.negative? loss_arr.push(0) if candle_price_diff.positive? || candle_price_diff.zero? end # Last Candle w/ Current Ticker Data last_candle_open = candles.last[:candle_open].to_f last_candle_price_diff = last_ticker_price - last_candle_open gain_arr.push(last_candle_price_diff) if last_candle_price_diff.positive? gain_arr.push(0) if last_candle_price_diff.negative? || last_candle_price_diff.zero? loss_arr.push(last_candle_price_diff.abs) if last_candle_price_diff.negative? loss_arr.push(0) if last_candle_price_diff.positive? || last_candle_price_diff.zero? # step 2 # Calculate the average gain and average loss # This can be done using several methods # We'll use Wilders smoothing method first_avg_gain = gain_arr.sum / rsi_candle first_avg_loss = loss_arr.sum / rsi_candle avg_gain = ((first_avg_gain * 13) + gain_arr.last) / rsi_candle avg_loss = ((first_avg_loss * 13) + loss_arr.last) / rsi_candle # step 3 and 4 # Calculate the Relative Strength and the Relative Strength Index (RSI) # What situation in the market would give us the maximum possible RSI value? # This would be a totally bullish market with no down days. # AvgD would be zero, AvgU some positive number. # Relative Strength would be something positive divided by zero. # Mathematically, you cannot calculate this. In this case the RSI value is defined as 100. if avg_loss.zero? # avg_loss was 0.0 resulting in avg_gain / 0.0 = Float::INFINITY rsi = format('%0.2f', 100) else rs = avg_gain / avg_loss rsi = format('%0.2f', 100 - (100 / (1 + rs))) end rsi_hash = { time: Time.now.strftime('%Y-%m-%d %H:%M:%S.%N%z'), rsi: rsi } rsi_history.push(rsi_hash) # Retain a sane amount of history rsi_hist_retention = 900 if rsi_history.length >= rsi_hist_retention # [retain_history..] << Not a typo - equivalent to # [retain_record..-1] retain_record = rsi_hist_retention * -1 rsi_hist_arr = rsi_history[retain_record..] rsi_history = rsi_hist_arr end rsi_history rescue StandardError => e raise "#{e} RSI_HISTORY: #{rsi_history.inspect}" end |
.help ⇒ Object
Display Usage for this Module
173 174 175 176 177 |
# File 'lib/coinbot/order_book/rsi.rb', line 173 public_class_method def self.help puts "USAGE: golden_cross_indicator_hash = #{self}.status() " end |
.status(opts = {}) ⇒ Object
- Supported Method Parameters
-
Coinbot::OrderBook::RSI.status( )
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 |
# File 'lib/coinbot/order_book/rsi.rb', line 12 public_class_method def self.status(opts = {}) indicator_status = opts[:indicator_status] rsi_history = opts[:rsi_history] candles = opts[:candles] invested = opts[:invested] bot_conf = opts[:bot_conf] max_rsi_to_buy = bot_conf[:weights][:rsi][:max_rsi_to_buy].to_f indicator_hash = {} indicator_hash[:invested] = invested indicator_hash[:status] = 'RSI' return unless rsi_history.length > 1 # If -- to_f will cast as 0.0 # raise rsi_history.inspect # uniq_rsi_hist = rsi_history.uniq { |h| h[:rsi] } uniq_rsi_hist = rsi_history.uniq return if uniq_rsi_hist.last == '--' last_rsi = uniq_rsi_hist.last[:rsi] if uniq_rsi_hist.length == 1 && candles.length == 1 last_rsi = candles[-2][:rsi_history].last[:rsi] if uniq_rsi_hist.length == 1 && candles.length > 1 last_rsi = uniq_rsi_hist[-2][:rsi] if uniq_rsi_hist.length > 1 && candles.length > 1 rsi = uniq_rsi_hist.last[:rsi] indicator_hash[:color] = :white # if rsi != '--' if rsi != '--' && last_rsi != '--' indicator_hash[:color] = :green if rsi.to_f.positive? && rsi.to_f > last_rsi.to_f # indicator_hash[:color] = :green if rsi.to_f.positive? && # rsi.to_f < max_rsi_to_buy indicator_hash[:color] = :yellow if rsi.to_f.positive? && rsi.to_f == last_rsi.to_f indicator_hash[:color] = :red if rsi.to_f.positive? && ( rsi.to_f < last_rsi.to_f || rsi.to_f >= max_rsi_to_buy ) # indicator_hash[:color] = :red if rsi.to_f.positive? && # rsi.to_f >= max_rsi_to_buy end indicator_status.rsi = indicator_hash rescue StandardError => e raise e end |