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