Class: DhanHQ::Analysis::OptionsBuyingAdvisor

Inherits:
Object
  • Object
show all
Defined in:
lib/dhanhq/analysis/options_buying_advisor.rb

Overview

Options buying advisor for INDEX options (NIFTY/BANKNIFTY/SENSEX)

Constant Summary collapse

DEFAULT_CONFIG =
{
  timeframe_weights: { m1: 0.1, m5: 0.2, m15: 0.25, m25: 0.15, m60: 0.3 },
  min_adx_for_trend: 22,
  strong_adx: 35,
  min_oi: 1_000,
  max_spread_pct: 3.0,
  preferred_deltas: {
    ce: { otm: (0.35..0.45), atm: (0.48..0.52), itm: (0.55..0.70) },
    pe: { otm: (-0.45..-0.35), atm: (-0.52..-0.48), itm: (-0.70..-0.55) }
  },
  risk: { sl_pct: 0.30, tp_pct: 0.60, trail_arm_pct: 0.20, trail_step_pct: 0.10 },
  atr_to_rupees_factor: 1.0,
  min_confidence: 0.58
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(data:, config: {}) ⇒ OptionsBuyingAdvisor

Returns a new instance of OptionsBuyingAdvisor.



26
27
28
29
# File 'lib/dhanhq/analysis/options_buying_advisor.rb', line 26

def initialize(data:, config: {})
  @data   = deep_symbolize(data || {})
  @config = deep_merge(DEFAULT_CONFIG, config || {})
end

Instance Method Details

#callObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/dhanhq/analysis/options_buying_advisor.rb', line 31

def call
  validate!
  return unsupported("unsupported instrument") unless index_instrument?(@data[:meta])

  ensure_option_chain!

  bias = BiasAggregator.new(@data[:indicators], @config).call
  # Neutral override: if higher TF trend is strong and short-term momentum aligns, allow a modest-confidence entry
  bias = neutral_override(bias) if bias[:bias] == :neutral
  if bias[:bias] == :neutral || bias[:confidence].to_f < @config[:min_confidence].to_f
    return no_trade("neutral/low confidence")
  end

  side = bias[:bias] == :bullish ? :ce : :pe
  moneyness = MoneynessHelper.pick_moneyness(indicators: @data[:indicators],
                                             min_adx: @config[:min_adx_for_trend],
                                             strong_adx: @config[:strong_adx],
                                             bias: bias[:bias])
  strike_pick = select_strike(side: side, moneyness: moneyness)
  return no_trade("no liquid strikes passed filters") unless strike_pick

  build_recommendation(side: side, moneyness: moneyness, bias: bias, strike_pick: strike_pick)
end