class Iro::Position

def calc_nxt

def calc_nxt
  pos = self
  ## 7 days ahead - not configurable so far
  outs = Tda::Option.get_quotes({
    contractType: pos.put_call,
    expirationDate: next_expires_on,
    ticker: ticker,
  })
  outs_bk = outs.dup
  outs = outs.select do |out|
    out[:bidSize] + out[:askSize] > 0
  end
  if 'CALL' == pos.put_call
    ;
  elsif 'PUT' == pos.put_call
    outs = outs.reverse
  end
  ## next_inner_strike
  outs = outs.select do |out|
    if Iro::Strategy::CREDIT == pos.credit_or_debit
      if Iro::Strategy::SHORT == pos.long_or_short
        ## short credit call
        out[:strikePrice] >= strategy.next_inner_strike
      elsif Iro::Strategy::LONG == pos.long_or_short
        ## long credit put
        out[:strikePrice] <= strategy.next_inner_strike
      end
    else
      raise 'zz3 - @TODO: implement, debit spreads'
    end
  end
  puts! outs[0][:strikePrice], 'after calc next_inner_strike'
  puts! outs, 'outs'
  ## next_buffer_above_water
  outs = outs.select do |out|
    if Iro::Strategy::SHORT == pos.long_or_short
      out[:strikePrice] > strategy.next_buffer_above_water + strategy.stock.last
    elsif Iro::Strategy::LONG == pos.long_or_short
      out[:strikePrice] < strategy.stock.last - strategy.next_buffer_above_water
    else
      raise 'zz4 - this cannot happen'
    end
  end
  puts! outs[0][:strikePrice], 'after calc next_buffer_above_water'
  puts! outs, 'outs'
  ## next_inner_delta
  outs = outs.select do |out|
    if 'CALL' == pos.put_call
      out_delta  = out[:delta] rescue 1
      out_delta <= strategy.next_inner_delta
    elsif 'PUT' == pos.put_call
      out_delta  = out[:delta] rescue 0
      out_delta <= strategy.next_inner_delta
    else
      raise 'zz5 - this cannot happen'
    end
  end
  puts! outs[0][:strikePrice], 'after calc next_inner_delta'
  puts! outs, 'outs'
  inner = outs[0]
  outs = outs.select do |out|
    if 'CALL' == pos.put_call
      out[:strikePrice] >= inner[:strikePrice].to_f + strategy.next_spread_amount
    elsif 'PUT' == pos.put_call
      out[:strikePrice] <= inner[:strikePrice].to_f - strategy.next_spread_amount
    end
  end
  outer = outs[0]
  if inner && outer
    o_attrs = {
      expires_on: next_expires_on,
      put_call:   pos.put_call,
      stock_id:   pos.stock_id,
    }
    inner_ = Iro::Option.new(o_attrs.merge({
      strike:        inner[:strikePrice],
      begin_price: ( inner[:bid] + inner[:ask] )/2,
      begin_delta:   inner[:delta],
      end_price:   ( inner[:bid] + inner[:ask] )/2,
      end_delta:     inner[:delta],
    }))
    outer_ = Iro::Option.new(o_attrs.merge({
      strike:        outer[:strikePrice],
      begin_price: ( outer[:bid] + outer[:ask] )/2,
      begin_delta:   outer[:delta],
      end_price:   ( outer[:bid] + outer[:ask] )/2,
      end_delta:     outer[:delta],
    }))
    pos.autonxt ||= Iro::Position.new
    pos.autonxt.update({
      prev_gain_loss_amount: 'a',
      status:       'proposed',
      stock:        strategy.stock,
      inner:        inner_,
      outer:        outer_,
      inner_strike: inner_.strike,
      outer_strike: outer_.strike,
      begin_on:     Time.now.to_date,
      expires_on:   next_expires_on,
      purse:        purse,
      strategy:     strategy,
      quantity:     1,
      autoprev:     pos,
    })
    pos.autonxt.sync
    pos.autonxt.save!
    pos.save
    return pos
  else
    throw 'zmq - should not happen'
  end
end