Class: Iro::Option

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Document, Mongoid::Paranoia, Mongoid::Timestamps
Defined in:
app/models/iro/option.rb

Constant Summary collapse

CALL =

field :ticker validates :ticker, presence: true

'CALL'
PUT =
'PUT'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#recomputeObject

Returns the value of attribute recompute.



9
10
11
# File 'app/models/iro/option.rb', line 9

def recompute
  @recompute
end

Class Method Details

.expirations_list(full: false, n: 5) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/models/iro/option.rb', line 39

def self.expirations_list full: false, n: 5
  out = [[nil,nil]]
  day = Date.today - 5.days
  n.times do
    next_exp = day.next_occurring(:thursday).next_occurring(:friday)
    if !next_exp.workday?
      next_exp = Time.previous_business_day( next_exp )
    end

    out.push([ next_exp.strftime('%b %e'), next_exp.strftime('%Y-%m-%d') ])
    day = next_exp
  end
  return out
  # [
  #   [ nil, nil ],
  #   [ 'Mar 22', '2024-03-22'.to_date ],
  #   [ 'Mar 28', '2024-03-28'.to_date ],
  #   [ 'Apr 5',  '2024-04-05'.to_date ],
  #   [ 'Mar 12', '2024-03-12'.to_date ],
  #   [ 'Mar 19', '2024-03-19'.to_date ],
  # ]
end

.max_pain(hash) ⇒ Object



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
170
171
172
173
174
175
176
177
178
# File 'app/models/iro/option.rb', line 120

def self.max_pain hash
  outs = {}

  %w| put call |.each do |contractType|
    dates = hash["#{contractType}ExpDateMap"]
    dates.each do |_date, strikes| ## _date="2023-02-10:5"
      date = _date.split(':')[0].to_date.to_s
      outs[date] ||= {
        'all'  => {},
        'call' => {},
        'put'  => {},
        'summary' => {},
      }

      strikes.each do |_strike, _v| ## _strike="18.5"
        strike = _strike.to_f

        ## calls
        mem_c = 0
        strikes.keys.reverse.each do |_key|
          if _key == _strike
            break
          end
          key = _key.to_f
          tmp = hash["callExpDateMap"][_date][_key][0]['openInterest'] * ( key - strike )
          mem_c += tmp
        end
        outs[date]['call'][_strike] = mem_c

        ## puts
        mem_p = 0
        strikes.keys.each do |_key|
          if _key == _strike
            break
          end
          key = _key.to_f
          tmp = hash["putExpDateMap"][_date][_key][0]['openInterest'] * ( strike - key )
          mem_p += tmp
        end
        outs[date]['put'][_strike] = mem_p
        outs[date]['all'][_strike] = mem_c + mem_p

      end
    end
  end

  ## compute summary
  outs.each do |date, types|
    all = types['all']
    outs[date]['summary'] = { 'value' => all.keys[0] }
    all.each do |strike, amount|
      if amount < all[ outs[date]['summary']['value'] ]
        outs[date]['summary']['value'] = strike
      end
    end
  end

  return outs
end

Instance Method Details

#put_callObject

for now, recompute every time field :symbol each option can be a leg in a position, no uniqueness validates :symbol, uniqueness: true, presence: true



24
# File 'app/models/iro/option.rb', line 24

field :put_call, type: :string

#symbolObject

for schwab “COST 260306C01030000”



88
89
90
91
92
# File 'app/models/iro/option.rb', line 88

def symbol
  p_c_ = put_call == 'PUT' ? 'P' : 'C'
  strike_ = format("%08d", (strike.to_f * 1000).round)
  sym = "#{stock.ticker.ljust(6)}#{expires_on.strftime("%y%m%d")}#{p_c_}#{strike_}"
end

#symbol_oldObject

for TDA “COST_030626C1030”



75
76
77
78
79
80
81
82
83
84
# File 'app/models/iro/option.rb', line 75

def symbol_old
  if !self[:symbol]
    p_c_ = put_call == 'PUT' ? 'P' : 'C'
    strike_ = strike.to_i == strike ? strike.to_i : strike
    sym = "#{stock.ticker}_#{expires_on.strftime("%m%d%y")}#{p_c_}#{strike_}" # XYZ_011819P45
    self[:symbol] = sym
    save
  end
  self[:symbol]
end

#syncObject

before_save :sync, if: ->() { !Rails.env.test? } ## do not sync in test



107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/models/iro/option.rb', line 107

def sync
  out = Tda::Option.get_quote({
    contractType: put_call,
    strike: strike,
    expirationDate: expires_on.strftime('%Y-%m-%d'),
    ticker: ticker,
  })
  puts! out, "option sync of `#{self.to_s}`"
  self.end_price = ( out.bid + out.ask ) / 2 rescue 0
  self.end_delta = out.delta ? out.delta : 0.0
  self.save! ## 2026-02-19 this must be present.
end

#tickerObject



12
# File 'app/models/iro/option.rb', line 12

def ticker; stock.ticker; end

#to_sObject



32
33
34
# File 'app/models/iro/option.rb', line 32

def to_s
  "#{symbol} :: #{expires_on.strftime('%Y-%m-%d')} #{put_call} #{strike}"
end