app/models/iro/position.rb in iron_warbler-2.0.7.22 vs app/models/iro/position.rb in iron_warbler-2.0.7.23
- old
+ new
@@ -1,12 +1,13 @@
class Iro::Position
include Mongoid::Document
include Mongoid::Timestamps
+ include Mongoid::Paranoia
store_in collection: 'iro_positions'
- attr_accessor :gain_loss_amount
+ attr_accessor :next_gain_loss_amount
STATUS_ACTIVE = 'active'
STATUS_PROPOSED = 'proposed'
STATUSES = [ nil, 'active', 'inactive', 'proposed' ]
field :status
@@ -51,12 +52,19 @@
field :end_outer_delta, type: :float
field :end_inner_price, type: :float
field :end_inner_delta, type: :float
+ def begin_delta
+ strategy.send("begin_delta_#{strategy.kind}", self)
+ end
+ def end_delta
+ strategy.send("end_delta_#{strategy.kind}", self)
+ end
+
def breakeven
- strategy.breakeven(self)
+ strategy.send("breakeven_#{strategy.kind}", self)
end
def current_underlying_strike
Iro::Stock.find_by( ticker: ticker ).last
end
@@ -85,82 +93,142 @@
strategy.send("max_gain_#{strategy.kind}", self)
end
def max_loss # each
strategy.send("max_loss_#{strategy.kind}", self)
end
+ # def gain_loss_amount
+ # strategy.send("gain_loss_amount_#{strategy.kind}", self)
+ # end
field :next_delta, type: :float
field :next_outcome, type: :float
field :next_symbol
field :next_mark
field :next_reasons, type: :array, default: []
- field :should_rollp, type: :float
+ field :rollp, type: :float
- ##
- ## decisions
- ##
- def should_roll?
- puts! 'shold_roll?'
+ ## covered call
+ # def sync
+ # puts! [ inner_strike, expires_on, stock.ticker ], 'init sync'
+ # out = Tda::Option.get_quote({
+ # contractType: 'CALL',
+ # strike: inner_strike,
+ # expirationDate: expires_on,
+ # ticker: stock.ticker,
+ # })
+ # puts! out, 'sync'
+ # self.end_inner_price = ( out.bid + out.ask ) / 2
+ # self.end_inner_delta = out.delta
+ # end
- update({
- next_reasons: [],
- next_symbol: nil,
- next_delta: nil,
+ ## long call spread
+ # def sync
+ # # puts! [
+ # # [ inner_strike, expires_on, stock.ticker ],
+ # # [ outer_strike, expires_on, stock.ticker ],
+ # # ], 'init sync inner, outer'
+ # inner = Tda::Option.get_quote({
+ # contractType: 'CALL',
+ # strike: inner_strike,
+ # expirationDate: expires_on,
+ # ticker: stock.ticker,
+ # })
+ # outer = Tda::Option.get_quote({
+ # contractType: 'CALL',
+ # strike: outer_strike,
+ # expirationDate: expires_on,
+ # ticker: stock.ticker,
+ # })
+ # puts! [inner, outer], 'sync inner, outer'
+ # self.end_outer_price = ( outer.bid + outer.ask ) / 2
+ # self.end_outer_delta = outer.delta
+
+ # self.end_inner_price = ( inner.bid + inner.ask ) / 2
+ # self.end_inner_delta = inner.delta
+ # end
+
+ def sync
+ put_call = Iro::Strategy::LONG == strategy.long_or_short ? 'CALL' : 'PUT'
+ puts! [
+ [ inner_strike, expires_on, stock.ticker ],
+ [ outer_strike, expires_on, stock.ticker ],
+ ], 'init sync inner, outer'
+ inner = Tda::Option.get_quote({
+ contractType: put_call,
+ strike: inner_strike,
+ expirationDate: expires_on,
+ ticker: stock.ticker,
})
+ outer = Tda::Option.get_quote({
+ contractType: put_call,
+ strike: outer_strike,
+ expirationDate: expires_on,
+ ticker: stock.ticker,
+ })
+ puts! [inner, outer], 'sync inner, outer'
+ self.end_outer_price = ( outer.bid + outer.ask ) / 2
+ self.end_outer_delta = outer.delta
- if must_roll?
- out = 1.0
- elsif can_roll?
+ self.end_inner_price = ( inner.bid + inner.ask ) / 2
+ self.end_inner_delta = inner.delta
+ end
+ def sync_short_debit_put_spread
+ puts! [
+ [ inner_strike, expires_on, stock.ticker ],
+ [ outer_strike, expires_on, stock.ticker ],
+ ], 'init sync inner, outer'
+ inner = Tda::Option.get_quote({
+ contractType: 'PUT',
+ strike: inner_strike,
+ expirationDate: expires_on,
+ ticker: stock.ticker,
+ })
+ outer = Tda::Option.get_quote({
+ contractType: 'PUT',
+ strike: outer_strike,
+ expirationDate: expires_on,
+ ticker: stock.ticker,
+ })
+ puts! [inner, outer], 'sync inner, outer'
+ self.end_outer_price = ( outer.bid + outer.ask ) / 2
+ self.end_outer_delta = outer.delta
- if end_delta < strategy.threshold_delta
- next_reasons.push "delta is lower than threshold"
- out = 0.91
- elsif 1 - end_outer_price/begin_outer_price > strategy.threshold_netp
- next_reasons.push "made enough percent profit (dubious)"
- out = 0.61
- else
- next_reasons.push "neutral"
- out = 0.33
- end
+ self.end_inner_price = ( inner.bid + inner.ask ) / 2
+ self.end_inner_delta = inner.delta
+ end
- else
- out = 0.0
- end
+ ##
+ ## decisions
+ ##
- update({
- next_delta: next_position[:delta],
- next_outcome: next_position[:mark] - end_price,
- next_symbol: next_position[:symbol],
- next_mark: next_position[:mark],
- should_rollp: out,
- # status: Iro::Position::STATE_PROPOSED,
- })
+ def calc_rollp
+ self.next_reasons = []
+ self.next_symbol = nil
+ self.next_delta = nil
- puts! next_reasons, 'next_reasons'
- puts! out, 'out'
- return out > 0.5
+ out = strategy.send( "calc_rollp_#{strategy.kind}", self )
+
+ self.rollp = out[0]
+ self.next_reasons.push out[1]
+ save
+
+ # update({
+ # next_delta: next_position[:delta],
+ # next_outcome: next_position[:mark] - end_price,
+ # next_symbol: next_position[:symbol],
+ # next_mark: next_position[:mark],
+ # should_rollp: out,
+ # # status: Iro::Position::STATE_PROPOSED,
+ # })
end
## expires_on = cc.expires_on ; nil
def can_roll?
## only if less than 7 days left
( expires_on.to_date - Time.now.to_date ).to_i < 7
- end
-
- ## If I'm near below water
- ##
- ## expires_on = cc.expires_on ; strategy = cc.strategy ; strike = cc.strike ; nil
- def must_roll?
- if ( current_underlying_strike + strategy.buffer_above_water ) > strike
- return true
- end
- ## @TODO: This one should not happen, I should log appropriately. _vp_ 2023-03-19
- if ( expires_on.to_date - Time.now.to_date ).to_i < 1
- return true
- end
end
## strike = cc.strike ; strategy = cc.strategy ; nil
def near_below_water?
strike < current_underlying_strike + strategy.buffer_above_water