app/controllers/iro/positions_controller.rb in iron_warbler-2.0.7.25 vs app/controllers/iro/positions_controller.rb in iron_warbler-2.0.7.26

- old
+ new

@@ -1,38 +1,26 @@ class Iro::PositionsController < Iro::ApplicationController before_action :set_lists - def new - @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! + pos = @position = Iro::Position.new pos_params + o_attrs = { + expires_on: pos.expires_on, + put_call: pos.put_call, + stock_id: pos.stock_id, + } + pos.inner = Iro::Option.new params[:inner].permit!.merge( o_attrs ) + pos.outer = Iro::Option.new params[:outer].permit!.merge( o_attrs ) 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 - redirect_to request.referrer + render action: :new # redirect_to request.referrer end end def destroy @position = Iro::Position.find params[:id] @@ -45,287 +33,282 @@ def edit @position = Iro::Position.find params[:id] authorize! :edit, @position end - ## this is auto-driven - def propose - @strategy = Iro::Strategy.find params[:strategy_id] - authorize! :show, @strategy + def new + strategy = Iro::Strategy.find params[:position][:strategy_id] + @position = Iro::Position.new( params[:position].permit!.merge({ + status: :active, + inner: Iro::Option.new, + outer: Iro::Option.new, + stock_id: strategy.stock_id, + }) ) + authorize! :new, @posision - @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 + if params[:id] + old = Iro::Position.find params[:id] + old = old.attributes + old.delete :_id + puts! old, 'old' + @position = Iro::Position.new old 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 + end - inner = outs[0] - outs = outs.select do |out| - out[:strikePrice] >= inner[:strikePrice] + @strategy.next_spread_amount - end - outer = outs[0] + def prepare + @position = Iro::Position.find params[:id] + authorize! :roll, @position - 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, + @prev = @position + @purse = @position.purse + @stock = @position.stock + @n_dollars = 100 + + ## dealing with too many strikes in the chain + while true + @nn = ( @position.purse.n_next_positions/2 ).ceil + upper = Tda::Option.get_quote({ + contractType: @position.put_call, + strike: @prev.inner.strike + @nn*@stock.options_price_increment, + expirationDate: @prev.next_expires_on, + ticker: @stock.ticker, }) - next_position.sync - next_position.save - else - flash_alert 'cannot propose a new one' + 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: @position.put_call, + strike: @prev.inner.strike - @nn*@stock.options_price_increment, + expirationDate: @prev.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 - redirect_to request.referrer - end - def refresh - @position = pos = Iro::Position.find params[:id] - authorize! :refresh, @position - - @position.sync - @position.calc_rollp - - redirect_to request.referrer || purse_path( @position.purse ) + self.send("_prepare_#{@position.strategy.kind}") end - -## long debit call spread + ## long debit call spread def prepare2 @position = Iro::Position.find params[:id] authorize! :roll, @position pos = @position stock = @position.stock - next_outer = @position.outer || Iro::Option.create({ - stock: stock, - strike: pos.outer_strike, - expires_on: pos.expires_on, - position: pos, - last: pos.begin_outer_price, - }) - - next_inner = @position.inner || Iro::Option.create({ - stock: stock, - strike: pos.inner_strike, - expires_on: pos.expires_on, - position: pos, - last: pos.begin_inner_price, - }) - - prev_outer = pos.prev.outer - prev_inner = pos.prev.inner - - price = pos.prev.outer.last - pos.prev.inner.last + pos.nxt.inner.last - pos.nxt.outer.last - @query = { - orderType: "NET_DEBIT", + orderType: price > 0 ? "NET_CREDIT" : "NET_DEBIT", session: "NORMAL", price: price, duration: "DAY", orderStrategyType: "SINGLE", orderLegCollection: [ - ## @TODO: this is only entering the next position, need to also close out the previous. + ## close { + instruction: "BUY_TO_CLOSE", + quantity: pos.q, + instrument: { + symbol: pos.autoprev.inner.symbol, + assetType: "OPTION", + }, + }, + { + instruction: "SELL_TO_CLOSE", + quantity: pos.q, + instrument: { + symbol: pos.autoprev.outer.symbol, + assetType: "OPTION", + }, + }, + + ## open + { instruction: "BUY_TO_OPEN", - quantity: q, + quantity: pos.q, instrument: { - symbol: outer.symbol, + symbol: pos.outer.symbol, assetType: "OPTION", }, }, { instruction: "SELL_TO_OPEN", - quantity: q, + quantity: pos.q, instrument: { - symbol: inner.symbol, + symbol: pos.inner.symbol, assetType: "OPTION", }, }, ], } + puts! @query, '@query' end - -## long debit call spread + ## long debit call spread def prepare3 - out = Tda::Option.roll_long_debit_call_spread( position ) - end + pos = @position = Iro::Position.find params[:id] + authorize! :place_order, @position - def prepare - @position = Iro::Position.find params[:id] - authorize! :roll, @position + # out = Tda::Option.roll_long_debit_call_spread( position ) - @prev = @position - @purse = @position.purse - @stock = @position.stock - @n_dollars = 100 + ## @TODO: it's pending here, the order has not been placed. - ## 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 + flags = [] - ## 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 + flags.push pos.prev.update({ status: Iro::Position::STATUS_CLOSED }) + flags.push pos.update({ status: Iro::Position::STATUS_ACTIVE }) + flags.push pos.purse.update({ + available_amount: pos.purse.available_amount + price + pos.q*100, + }) - self.send("_prepare_#{@position.strategy.kind}") + flash_notice flags + redirect_to controller: :purses, action: :show, template: :gameui, id: pos.purse_id 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, + inner_strike: @prev.inner.strike - idx*@stock.options_price_increment, + expires_on: @prev.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.find_or_create_by({ - status: 'prepare', - 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, + expires_on: @prev.next_expires_on, + inner_strike: @prev.inner.strike - idx*@stock.options_price_increment, + outer_strike: @prev.outer.strike - idx*@stock.options_price_increment, + prev_id: @prev.id, purse: @position.purse, - strategy: @position.strategy, quantity: @position.quantity, - prev_id: @prev.id, + status: 'prepare', + stock: @stock, + strategy: @position.strategy, }) + pos = next_ + next_.inner ||= Iro::Option.new({ + # begin_price: pos[:begin_inner_price], + # begin_delta: pos[:begin_inner_delta], + expires_on: pos[:expires_on], + inner: pos, + put_call: pos.put_call, + stock_id: pos[:stock_id], + strike: pos[:inner_strike], + }) + next_.outer ||= Iro::Option.new({ + # begin_price: pos[:begin_inner_price], + # begin_delta: pos[:begin_inner_delta], + expires_on: pos[:expires_on], + outer: pos, + put_call: pos.put_call, + stock_id: pos[:stock_id], + strike: pos[:outer_strike], + }) + next_.sync - next_.begin_inner_price = next_.end_inner_price - next_.begin_inner_delta = next_.end_inner_delta + next_.inner.begin_price = next_.inner.end_price + next_.inner.begin_delta = next_.inner.end_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 + next_.outer.begin_price = next_.outer.end_price + next_.outer.begin_delta = next_.outer.end_delta + + next_.next_gain_loss_amount = @prev.outer.end_price - @prev.inner.end_price + next_.next_gain_loss_amount += next_.inner.begin_price - next_.outer.begin_price next_.save - puts! next_, 'next_' - puts! next_.next_gain_loss_amount, 'next_gain_loss_amount' @positions.push next_ end @positions = @positions.reverse end + alias_method :_prepare_short_debit_put_spread, :_prepare_long_debit_call_spread - 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_ + def sync + @position = pos = Iro::Position.find params[:id] + authorize! :refresh, @position + + @position.sync + @position.calc_rollp + if true # @position.rollp > 0.5 + @position.calc_nxt end + + redirect_to request.referrer || purse_path( @position.purse ) end + ## + ## only updates some attributes + ## def update - @position = Iro::Position.find params[:id] + pos = @position = Iro::Position.find params[:id] authorize! :update, @position - if @position.update params[:position].permit! + if @position.update pos_params + o_attrs = { + expires_on: pos.expires_on, + put_call: pos.put_call, + stock_id: pos.stock_id, + } + pos.inner.update params[:inner].permit!.merge( o_attrs ) + pos.outer.update params[:outer].permit!.merge( o_attrs ) + flash_notice @position redirect_to controller: :purses, action: :show, id: @position.purse_id.to_s else flash_alert @position redirect_to request.referrer end end + + ## ## private ## private + def pos_params + params[:position].permit( :purse_id, :status, :stock_id, + :strategy_id, :expires_on, :quantity, :begin_on, + :long_or_short, + ) + end + + def price + pos = @position + out = pos.autoprev.outer.end_price - pos.autoprev.inner.end_price + pos.inner.begin_price - pos.outer.begin_price + return out + end + + def set_lists super - @purses_list = Iro::Purse.list @strategies_list = Iro::Strategy.list(params[:long_or_short]) @stocks_list = Iro::Stock.list end