Untitled

 avatar
unknown
plain_text
14 days ago
6.6 kB
5
Indexable
module Analyzers
  class SupportResistanceAnalysis < Base
    def analyze
      {
        primary_support: @current.support_level.to_f.round(4),
        primary_resistance: @current.resistance_level.to_f.round(4),
        fib_price_position: fib_price_position,
        pivot_position: pivot_position,
        volatility_impact: volatility_impact,
        order_flow: @current.order_flow,
        vwap_position_status: vwap_position_status,
        market_breadth: @current.market_breadth,
        breadth_impact: breadth_impact,
        
        support_volume_confirmation: support_volume_confirmation?,
        resistance_volume_confirmation: resistance_volume_confirmation?,
        support_price_rejection: support_price_rejection?,
        resistance_price_rejection: resistance_price_rejection?,
        fib_support_confluence: fib_support_confluence?,
        fib_resistance_confluence: fib_resistance_confluence?,
        above_ema_8: above_ema_8?,
        above_ema_20: above_ema_20?,
        above_ema_50: above_ema_50?,
        above_sma_20: above_sma_20?,
        ema_8_sr_quality: ema_8_sr_quality?,
        ema_20_sr_quality: ema_20_sr_quality?,
        ema_50_sr_quality: ema_50_sr_quality?,
        bollinger_support_near_lower: bollinger_support_near_lower?,
        bollinger_resistance_near_upper: bollinger_resistance_near_upper?,
        bollinger_squeeze: bollinger_squeeze?,
        keltner_support_near_lower: keltner_support_near_lower?,
        keltner_resistance_near_upper: keltner_resistance_near_upper?,
        ichimoku_support_near_tenkan: ichimoku_support_near_tenkan?,
        ichimoku_resistance_near_kijun: ichimoku_resistance_near_kijun?,
        ichimoku_cloud_support: ichimoku_cloud_support?,
        ichimoku_cloud_resistance: ichimoku_cloud_resistance?
      }
    end

    private

    def fib_price_position
      return nil unless fib_levels_present?

      if @current.close.to_f > @current.fibonacci_38_2.to_f
        :above_38
      elsif @current.close.to_f > @current.fibonacci_50.to_f
        :between_38_50
      elsif @current.close.to_f > @current.fibonacci_61_8.to_f
        :between_50_61
      else
        :below_61
      end
    end

    def pivot_position
      return nil unless @candles.size >= 1

      pivot = ((@candles[-1].high + @candles[-1].low + @candles[-1].close) / 3.0).to_f.round(4)
      
      if @current.close > pivot + (@candles[-1].high - @candles[-1].low)
        :above_r2
      elsif @current.close > pivot
        :above_pivot
      else
        :below_pivot
      end
    end

    def volatility_impact
      return nil unless @history.size >= 10

      current_atr_percentile = calculate_percentile(@current.atr, @history.last(10).map(&:atr))
      
      if current_atr_percentile > 75
        :high_volatility_breakout_likely
      elsif current_atr_percentile < 25
        :low_volatility_breakout_unlikely
      else
        :neutral_volatility
      end
    end

    def vwap_position_status
      @current.close.to_f > @current.vwap.to_f ? :above : :below
    end

    def breadth_impact
      case @current.market_breadth
      when 'bullish_breadth' then :supports_breakout
      when 'bearish_breadth' then :supports_breakdown
      else :neutral_impact
      end
    end

    def support_volume_confirmation?
      @current.volume_at_support > @history.last(3).map(&:volume_at_support).average
    end

    def resistance_volume_confirmation?
      @current.volume_at_resistance > @history.last(3).map(&:volume_at_resistance).average
    end

    def support_price_rejection?
      @candles.size >= 2 && @candles[-1].low <= @current.support_level && @candles[-1].close > @current.support_level
    end

    def resistance_price_rejection?
      @candles.size >= 2 && @candles[-1].high >= @current.resistance_level && @candles[-1].close < @current.resistance_level
    end

    def fib_support_confluence?
      (@current.support_level - @current.fibonacci_38_2).abs < @current.atr * 0.1
    end

    def fib_resistance_confluence?
      (@current.resistance_level - @current.fibonacci_61_8).abs < @current.atr * 0.1
    end

    def above_ema_8?
      @current.close > @current.ema_8
    end

    def above_ema_20?
      @current.close > @current.ema_20
    end

    def above_ema_50?
      @current.close > @current.ema_50
    end

    def above_sma_20?
      @current.close > @current.sma_20
    end

    def ema_8_sr_quality?
      (@current.ema_8 - @current.support_level).abs < @current.atr * 0.5 || 
      (@current.resistance_level - @current.ema_8).abs < @current.atr * 0.5
    end

    def ema_20_sr_quality?
      (@current.ema_20 - @current.support_level).abs < @current.atr * 0.5 || 
      (@current.resistance_level - @current.ema_20).abs < @current.atr * 0.5
    end

    def ema_50_sr_quality?
      (@current.ema_50 - @current.support_level).abs < @current.atr * 0.5 || 
      (@current.resistance_level - @current.ema_50).abs < @current.atr * 0.5
    end

    def bollinger_support_near_lower?
      (@current.support_level - @current.bollinger_lower).abs < @current.atr * 0.5
    end

    def bollinger_resistance_near_upper?
      (@current.resistance_level - @current.bollinger_upper).abs < @current.atr * 0.5
    end

    def bollinger_squeeze?
      (@current.bollinger_upper - @current.bollinger_lower) < (@current.keltner_upper - @current.keltner_lower)
    end

    def keltner_support_near_lower?
      (@current.support_level - @current.keltner_lower).abs < @current.atr * 0.5
    end

    def keltner_resistance_near_upper?
      (@current.resistance_level - @current.keltner_upper).abs < @current.atr * 0.5
    end

    def ichimoku_support_near_tenkan?
      (@current.support_level - @current.ichimoku_tenkan_sen).abs < @current.atr * 0.5
    end

    def ichimoku_resistance_near_kijun?
      (@current.resistance_level - @current.ichimoku_kijun_sen).abs < @current.atr * 0.5
    end

    def ichimoku_cloud_support?
      @current.close > @current.ichimoku_senkou_span_a && 
      @current.close > @current.ichimoku_senkou_span_b
    end

    def ichimoku_cloud_resistance?
      @current.close < @current.ichimoku_senkou_span_a && 
      @current.close < @current.ichimoku_senkou_span_b
    end

    def fib_levels_present?
      @current.fibonacci_38_2 && @current.fibonacci_50 && @current.fibonacci_61_8
    end

    def calculate_percentile(value, data)
      return nil if data.empty?
      
      sorted = data.sort
      n = sorted.size
      rank = sorted.bsearch_index { |x| x >= value } || n
      
      (rank.to_f / n * 100).round(2)
    end
  end
end
Editor is loading...
Leave a Comment