app/controllers/iro/positions_controller.rb in iron_warbler-2.0.7.22 vs app/controllers/iro/positions_controller.rb in iron_warbler-2.0.7.23
- old
+ new
@@ -1,18 +1,32 @@
class Iro::PositionsController < Iro::ApplicationController
before_action :set_lists
def new
- @position = Iro::Position.new purse_id: params[:purse_id]
+ @position = Iro::Position.new
authorize! :new, @posision
+
+ if params[:id]
+ old = Iro::Position.find params[:id]
+ old = old.attributes
+ old.delete :_id
+ puts! old, 'old'
+ @position = Iro::Position.new old
+ end
+ if params[:purse_id]
+ @position.purse_id = params[:purse_id]
+ end
+
end
def create
@position = Iro::Position.new params[:position].permit!
authorize! :create, @position
+ @position.sync
+
if @position.save
flash_notice @position
redirect_to controller: :purses, action: :show, id: @position.purse_id.to_s
else
flash_alert @position
@@ -31,44 +45,201 @@
def edit
@position = Iro::Position.find params[:id]
authorize! :edit, @position
end
+ def propose
+ @strategy = Iro::Strategy.find params[:strategy_id]
+ authorize! :show, @strategy
+
+ @purse = Iro::Purse.find params[:purse_id]
+
+ ## short debit put spread
+ outs = Tda::Option.get_quotes({
+ contractType: 'PUT',
+ expirationDate: '2024-03-28',
+ ticker: @strategy.stock.ticker,
+ })
+ outs = outs.select do |out|
+ out[:bidSize]+out[:askSize] > 0
+ end
+ outs = outs.select do |out|
+ out[:strikePrice] > @strategy.buffer_above_water + @strategy.stock.last
+ end
+ outs = outs.select do |out|
+ out[:strikePrice] > @strategy.next_inner_strike
+ end
+ outs = outs.select do |out|
+ out[:delta] < @strategy.next_inner_delta
+ end
+
+ inner = outs[0]
+ outs = outs.select do |out|
+ out[:strikePrice] >= inner[:strikePrice] + @strategy.next_spread_amount
+ end
+ outer = outs[0]
+
+ if inner && outer
+ next_position = Iro::Position.new({
+ status: 'proposed',
+ stock: @strategy.stock,
+ inner_strike: inner[:strikePrice],
+ outer_strike: outer[:strikePrice],
+ begin_outer_price: outer[:last],
+ begin_outer_delta: outer[:delta],
+ begin_inner_price: inner[:last],
+ begin_inner_delta: inner[:delta],
+ begin_on: Time.now.to_date,
+ expires_on: '2024-03-28',
+ purse: @purse,
+ strategy: @strategy,
+ quantity: 1,
+ })
+ next_position.sync
+ next_position.save
+ else
+ flash_alert 'cannot propose a new one'
+ end
+ redirect_to request.referrer
+ end
+
def refresh
@position = pos = Iro::Position.find params[:id]
authorize! :refresh, @position
- ## covered call
- out = Tda::Option.get_quote({
- contractType: 'CALL',
- strike: pos.inner_strike,
- expirationDate: pos.expires_on,
- ticker: pos.stock.ticker,
- })
- puts! out, 'out'
- @position.update({
- end_inner_price: ( out.bid + out.ask ) / 2,
- end_inner_delta: out.delta,
- })
+ @position.sync
+ @position.calc_rollp
+
redirect_to request.referrer || purse_path( @position.purse )
end
- def roll
+ def prepare
@position = Iro::Position.find params[:id]
authorize! :roll, @position
- stock = @position.stock
+ @prev = @position
+ @purse = @position.purse
+ @stock = @position.stock
+ @n_dollars = 100
- @positions = [
- Iro::Position.new({ stock: stock, begin_inner_price: 5.21, inner_strike: 91, expires_on: '2024-04-05', gain_loss_amount: -1.25 }),
- Iro::Position.new({ stock: stock, begin_inner_price: 5.77, inner_strike: 90, expires_on: '2024-04-05', gain_loss_amount: -0.7 }),
- Iro::Position.new({ stock: stock, begin_inner_price: 6.4, inner_strike: 89, expires_on: '2024-04-05', gain_loss_amount: -0.03 }),
- Iro::Position.new({ stock: stock, begin_inner_price: 6.85, inner_strike: 88, expires_on: '2024-04-05', gain_loss_amount: 0.6 }),
- Iro::Position.new({ stock: stock, begin_inner_price: 7.07, inner_strike: 87, expires_on: '2024-04-05', gain_loss_amount: 1.22 }),
- ]
+ ## holiday schedule
+ @next_expires_on = @prev.expires_on.to_datetime.next_occurring(:monday).next_occurring(:friday)
+ if !@next_expires_on.workday?
+ @next_expires_on = Time.previous_business_day( @next_expires_on )
+ end
+
+ ## dealing with too many strikes in the chain
+ while true
+ @nn = ( @position.purse.n_next_positions/2 ).ceil
+ upper = Tda::Option.get_quote({
+ contractType: 'CALL',
+ strike: @prev.inner_strike + @nn*@stock.options_price_increment,
+ expirationDate: @next_expires_on,
+ ticker: @stock.ticker,
+ })
+ if !upper.symbol
+ puts! 'too high'
+ flash_alert 'too high'
+ @purse.n_next_positions = @purse.n_next_positions - 1
+ @purse.n_next_positions = 1 if @purse.n_next_positions < 1
+ @purse.save!
+ next
+ end
+ lower = Tda::Option.get_quote({
+ contractType: 'CALL',
+ strike: @prev.inner_strike - @nn*@stock.options_price_increment,
+ expirationDate: @next_expires_on,
+ ticker: @stock.ticker,
+ })
+ if !lower.symbol
+ puts! 'too low'
+ flash_alert 'too low'
+ @purse.n_next_positions = @purse.n_next_positions - 1
+ @purse.n_next_positions = 1 if @purse.n_next_positions < 1
+ @purse.save!
+ next
+ end
+ break
+ end
+
+ self.send("_prepare_#{@position.strategy.kind}")
end
+ def _prepare_covered_call
+ @positions = []
+ (-@nn..@nn).each do |idx|
+ next_ = Iro::Position.new({
+ stock: @stock,
+ inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
+ expires_on: @next_expires_on,
+ purse: @position.purse,
+ strategy: @position.strategy,
+ quantity: @position.quantity,
+ })
+ next_.sync
+ next_.begin_inner_price = next_.end_inner_price
+ next_.begin_inner_delta = next_.end_inner_delta
+ next_.next_gain_loss_amount = next_.begin_inner_price - @prev.end_inner_price
+ puts! next_, 'next_'
+ puts! next_.next_gain_loss_amount, 'amount'
+ @positions.push next_
+ end
+ end
+
+ def _prepare_long_debit_call_spread
+ @positions = []
+ (-@nn..@nn).each do |idx|
+ next_ = Iro::Position.new({
+ stock: @stock,
+ inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
+ outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
+ expires_on: @next_expires_on,
+ purse: @position.purse,
+ strategy: @position.strategy,
+ quantity: @position.quantity,
+ })
+ next_.sync
+ next_.begin_inner_price = next_.end_inner_price
+ next_.begin_inner_delta = next_.end_inner_delta
+
+ next_.begin_outer_price = next_.end_outer_price
+ next_.begin_outer_delta = next_.end_outer_delta
+ next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
+ next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
+ puts! next_, 'next_'
+ puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
+ @positions.push next_
+ end
+ @positions = @positions.reverse
+ end
+
+ def _prepare_short_debit_put_spread
+ @positions = []
+ (-@nn..@nn).each do |idx|
+ next_ = Iro::Position.new({
+ stock: @stock,
+ inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
+ outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
+ expires_on: @next_expires_on,
+ purse: @position.purse,
+ strategy: @position.strategy,
+ quantity: @position.quantity,
+ })
+ next_.sync
+ next_.begin_inner_price = next_.end_inner_price
+ next_.begin_inner_delta = next_.end_inner_delta
+
+ next_.begin_outer_price = next_.end_outer_price
+ next_.begin_outer_delta = next_.end_outer_delta
+ next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
+ next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
+ puts! next_, 'next_'
+ puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
+ @positions.push next_
+ end
+ end
+
def update
@position = Iro::Position.find params[:id]
authorize! :update, @position
if @position.update params[:position].permit!
@@ -84,10 +255,13 @@
## private
##
private
def set_lists
+ super
+
+ @purses_list = Iro::Purse.list
@strategies_list = Iro::Strategy.list(params[:long_or_short])
- @stocks_list = Iro::Stock.list
+ @stocks_list = Iro::Stock.list
end
end