iron_warbler 2.0.7.25 → 2.0.7.26

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/iron_warbler/Card.scss +6 -0
  3. data/app/assets/stylesheets/iron_warbler/positions.scss +1 -1
  4. data/app/assets/stylesheets/iron_warbler/purses_summary.scss +31 -19
  5. data/app/controllers/iro/application_controller.rb +6 -0
  6. data/app/controllers/iro/positions_controller.rb +183 -200
  7. data/app/controllers/iro/purses_controller.rb +3 -1
  8. data/app/controllers/iro/stocks_controller.rb +2 -2
  9. data/app/models/iro/option.rb +38 -150
  10. data/app/models/iro/option_black_scholes.rb +149 -0
  11. data/app/models/iro/position.rb +154 -209
  12. data/app/models/iro/purse.rb +34 -4
  13. data/app/models/iro/strategy.rb +49 -47
  14. data/app/views/iro/_main_header.haml +4 -2
  15. data/app/views/iro/options/_show_mini.haml +8 -0
  16. data/app/views/iro/positions/_form.haml +8 -3
  17. data/app/views/iro/positions/_formpart_4data.haml +41 -38
  18. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml +4 -4
  19. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml-trash +42 -0
  20. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +1 -0
  21. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml-trash +40 -0
  22. data/app/views/iro/positions/_header.haml +2 -0
  23. data/app/views/iro/positions/_header_long_debit_call_spread.haml +43 -25
  24. data/app/views/iro/positions/_prepare_long_debit_call_spread.haml +2 -3
  25. data/app/views/iro/positions/_prepare_short_debit_put_spread.haml +2 -1
  26. data/app/views/iro/positions/_table.haml +25 -26
  27. data/app/views/iro/positions/prepare.haml +6 -4
  28. data/app/views/iro/positions/prepare2.haml +15 -4
  29. data/app/views/iro/purses/_form_extra_fields.haml +7 -3
  30. data/app/views/iro/purses/_header.haml +19 -5
  31. data/app/views/iro/purses/_summary.haml +69 -62
  32. data/app/views/iro/purses/show.haml +1 -1
  33. data/app/views/iro/strategies/_form.haml +26 -19
  34. data/app/views/iro/strategies/_show.haml +6 -4
  35. data/config/routes.rb +5 -3
  36. metadata +7 -2
  37. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8184e7abf0df5faad6e8d99504be22235e0fa846801be7bd2869e7f81631349b
4
- data.tar.gz: ac0dab40337f109eadccd06b943203e19c507abc9a05cc3e66f0f453b8275d82
3
+ metadata.gz: 4afc65383198cc16143683cc82db6ee65604f14a8d13d4d7bc262210ceb14940
4
+ data.tar.gz: 04c7d9a3585dd1036c8f227a1cbbe38fbc6e7d71f68977f3183ac07bdbaba3cf
5
5
  SHA512:
6
- metadata.gz: e892adf76bb1fecaf319f614bb4249689bd5b761e46b234f5e27b89d3640b0f6fcfb7f9cfba5ecd25873b8c9af40ab7d9e8e706293d09879447c7188ae47303d
7
- data.tar.gz: e037e728a1a2beb3f4f07ec46f5c40c188514960bd961570fb603e5a73842377a01268c9e1ff8538e8c7bc1afc213dc4df5a73fd826be9209838318f2aaee65b
6
+ metadata.gz: a905e844e0542aa1f7500c1c1bc25a234f2698bc8bfb1e75d83fb7ab2ba24dcc28ed261a876f1add4d9dec80decb32cb84ed1694ac3b8e3657be48f8a36b86bc
7
+ data.tar.gz: d9478f1d454dbcbee3b6fc703233f7d72049ac128f1ad2e550e38286483ccc51a863e8ace598511c2c28a6ce8a26240215d97ff2d524e5a3e03dcbdc5fb1eb40
@@ -0,0 +1,6 @@
1
+
2
+ .Card {
3
+ background: white;
4
+ }
5
+
6
+
@@ -21,7 +21,7 @@
21
21
 
22
22
  > * {
23
23
  transform-origin: 0 0;
24
- rotate: -40deg;
24
+ // rotate: -40deg;
25
25
 
26
26
  padding: .4em 0;
27
27
  width: 120px;
@@ -40,32 +40,38 @@
40
40
  .summary-amount {
41
41
  position: relative;
42
42
  width: 100px;
43
+ margin-right: 2em;
43
44
 
44
45
  .net-gl {
45
46
  width: 100%;
46
47
  background: rgba(0,0,0, 0.5);
47
48
  }
48
- }
49
- .summary-delta {
50
- position: relative;
51
- margin-right: 1em;
52
- width: 1em;
53
49
 
54
- > div {
55
- border: 1px dotted yellow;
56
- }
57
- .begin {
58
- width: 1em;
50
+ .delta {
51
+ position: absolute;
52
+ left: 100px;
53
+ height: 100%;
59
54
 
60
- background: black;
61
- }
62
- .end {
63
- width: .5em;
64
- left: .25em;
55
+ > div {
56
+ border: 1px dotted yellow;
57
+ width: 0.5em;
58
+ }
59
+ .begin {
60
+ width: 1em;
65
61
 
66
- background: rgba(255,0,0, 0.5);
62
+ background: black;
63
+ }
64
+ .end {
65
+ width: .5em;
66
+ left: .25em;
67
+
68
+ background: rgba(255,0,0, 0.5);
69
+ }
67
70
  }
71
+
68
72
  }
73
+
74
+
69
75
  .loss {
70
76
  }
71
77
  .gain {
@@ -73,12 +79,18 @@
73
79
  .max-gl {
74
80
  position: absolute;
75
81
  width: 100%;
82
+
83
+ label {
84
+ position: absolute;
85
+ }
86
+
87
+
76
88
  }
77
89
  .max-gl.long {
78
- background: rgba(255,0,0, 0.5);
79
90
  }
80
- .max-gl-short {
81
- background: rgba(255,153,0, 0.5);
91
+ .max-gl.short {
92
+ display: flex;
93
+ flex-direction: column-reverse;
82
94
  }
83
95
  .long {
84
96
  position: absolute;
@@ -1,4 +1,9 @@
1
1
 
2
+ Pu ||= Iro::Purse
3
+ Str ||= Iro::Strategy
4
+ Po ||= Iro::Position
5
+ O ||= Iro::Option
6
+ Sto ||= Iro::Stock
2
7
 
3
8
  class Iro::ApplicationController < Wco::ApplicationController
4
9
  layout 'iro/application'
@@ -17,6 +22,7 @@ class Iro::ApplicationController < Wco::ApplicationController
17
22
  def set_lists
18
23
  @purses = Iro::Purse.all
19
24
  @strategies = Iro::Strategy.all
25
+ @strategies_list = Iro::Strategy.list
20
26
  end
21
27
 
22
28
 
@@ -2,35 +2,23 @@
2
2
  class Iro::PositionsController < Iro::ApplicationController
3
3
  before_action :set_lists
4
4
 
5
- def new
6
- @position = Iro::Position.new
7
- authorize! :new, @posision
8
-
9
- if params[:id]
10
- old = Iro::Position.find params[:id]
11
- old = old.attributes
12
- old.delete :_id
13
- puts! old, 'old'
14
- @position = Iro::Position.new old
15
- end
16
- if params[:purse_id]
17
- @position.purse_id = params[:purse_id]
18
- end
19
-
20
- end
21
-
22
5
  def create
23
- @position = Iro::Position.new params[:position].permit!
6
+ pos = @position = Iro::Position.new pos_params
7
+ o_attrs = {
8
+ expires_on: pos.expires_on,
9
+ put_call: pos.put_call,
10
+ stock_id: pos.stock_id,
11
+ }
12
+ pos.inner = Iro::Option.new params[:inner].permit!.merge( o_attrs )
13
+ pos.outer = Iro::Option.new params[:outer].permit!.merge( o_attrs )
24
14
  authorize! :create, @position
25
15
 
26
- @position.sync
27
-
28
16
  if @position.save
29
17
  flash_notice @position
30
18
  redirect_to controller: :purses, action: :show, id: @position.purse_id.to_s
31
19
  else
32
20
  flash_alert @position
33
- redirect_to request.referrer
21
+ render action: :new # redirect_to request.referrer
34
22
  end
35
23
  end
36
24
 
@@ -47,73 +35,72 @@ class Iro::PositionsController < Iro::ApplicationController
47
35
  authorize! :edit, @position
48
36
  end
49
37
 
50
- ## this is auto-driven
51
- def propose
52
- @strategy = Iro::Strategy.find params[:strategy_id]
53
- authorize! :show, @strategy
54
-
55
- @purse = Iro::Purse.find params[:purse_id]
56
-
57
- ## short debit put spread
58
- outs = Tda::Option.get_quotes({
59
- contractType: 'PUT',
60
- expirationDate: '2024-03-28',
61
- ticker: @strategy.stock.ticker,
62
- })
63
- outs = outs.select do |out|
64
- out[:bidSize]+out[:askSize] > 0
65
- end
66
- outs = outs.select do |out|
67
- out[:strikePrice] > @strategy.buffer_above_water + @strategy.stock.last
68
- end
69
- outs = outs.select do |out|
70
- out[:strikePrice] > @strategy.next_inner_strike
71
- end
72
- outs = outs.select do |out|
73
- out[:delta] < @strategy.next_inner_delta
74
- end
38
+ def new
39
+ strategy = Iro::Strategy.find params[:position][:strategy_id]
40
+ @position = Iro::Position.new( params[:position].permit!.merge({
41
+ status: :active,
42
+ inner: Iro::Option.new,
43
+ outer: Iro::Option.new,
44
+ stock_id: strategy.stock_id,
45
+ }) )
46
+ authorize! :new, @posision
75
47
 
76
- inner = outs[0]
77
- outs = outs.select do |out|
78
- out[:strikePrice] >= inner[:strikePrice] + @strategy.next_spread_amount
79
- end
80
- outer = outs[0]
81
-
82
- if inner && outer
83
- next_position = Iro::Position.new({
84
- status: 'proposed',
85
- stock: @strategy.stock,
86
- inner_strike: inner[:strikePrice],
87
- outer_strike: outer[:strikePrice],
88
- begin_outer_price: outer[:last],
89
- begin_outer_delta: outer[:delta],
90
- begin_inner_price: inner[:last],
91
- begin_inner_delta: inner[:delta],
92
- begin_on: Time.now.to_date,
93
- expires_on: '2024-03-28',
94
- purse: @purse,
95
- strategy: @strategy,
96
- quantity: 1,
97
- })
98
- next_position.sync
99
- next_position.save
100
- else
101
- flash_alert 'cannot propose a new one'
48
+ if params[:id]
49
+ old = Iro::Position.find params[:id]
50
+ old = old.attributes
51
+ old.delete :_id
52
+ puts! old, 'old'
53
+ @position = Iro::Position.new old
102
54
  end
103
- redirect_to request.referrer
104
55
  end
105
56
 
106
- def refresh
107
- @position = pos = Iro::Position.find params[:id]
108
- authorize! :refresh, @position
57
+ def prepare
58
+ @position = Iro::Position.find params[:id]
59
+ authorize! :roll, @position
109
60
 
110
- @position.sync
111
- @position.calc_rollp
61
+ @prev = @position
62
+ @purse = @position.purse
63
+ @stock = @position.stock
64
+ @n_dollars = 100
112
65
 
113
- redirect_to request.referrer || purse_path( @position.purse )
66
+ ## dealing with too many strikes in the chain
67
+ while true
68
+ @nn = ( @position.purse.n_next_positions/2 ).ceil
69
+ upper = Tda::Option.get_quote({
70
+ contractType: @position.put_call,
71
+ strike: @prev.inner.strike + @nn*@stock.options_price_increment,
72
+ expirationDate: @prev.next_expires_on,
73
+ ticker: @stock.ticker,
74
+ })
75
+ if !upper.symbol
76
+ puts! 'too high'
77
+ flash_alert 'too high'
78
+ @purse.n_next_positions = @purse.n_next_positions - 1
79
+ @purse.n_next_positions = 1 if @purse.n_next_positions < 1
80
+ @purse.save!
81
+ next
82
+ end
83
+ lower = Tda::Option.get_quote({
84
+ contractType: @position.put_call,
85
+ strike: @prev.inner.strike - @nn*@stock.options_price_increment,
86
+ expirationDate: @prev.next_expires_on,
87
+ ticker: @stock.ticker,
88
+ })
89
+ if !lower.symbol
90
+ puts! 'too low'
91
+ flash_alert 'too low'
92
+ @purse.n_next_positions = @purse.n_next_positions - 1
93
+ @purse.n_next_positions = 1 if @purse.n_next_positions < 1
94
+ @purse.save!
95
+ next
96
+ end
97
+ break
98
+ end
99
+
100
+ self.send("_prepare_#{@position.strategy.kind}")
114
101
  end
115
102
 
116
- -## long debit call spread
103
+ ## long debit call spread
117
104
  def prepare2
118
105
  @position = Iro::Position.find params[:id]
119
106
  authorize! :roll, @position
@@ -121,119 +108,83 @@ class Iro::PositionsController < Iro::ApplicationController
121
108
  pos = @position
122
109
  stock = @position.stock
123
110
 
124
- next_outer = @position.outer || Iro::Option.create({
125
- stock: stock,
126
- strike: pos.outer_strike,
127
- expires_on: pos.expires_on,
128
- position: pos,
129
- last: pos.begin_outer_price,
130
- })
131
-
132
- next_inner = @position.inner || Iro::Option.create({
133
- stock: stock,
134
- strike: pos.inner_strike,
135
- expires_on: pos.expires_on,
136
- position: pos,
137
- last: pos.begin_inner_price,
138
- })
139
-
140
- prev_outer = pos.prev.outer
141
- prev_inner = pos.prev.inner
142
-
143
- price = pos.prev.outer.last - pos.prev.inner.last + pos.nxt.inner.last - pos.nxt.outer.last
144
-
145
111
  @query = {
146
- orderType: "NET_DEBIT",
112
+ orderType: price > 0 ? "NET_CREDIT" : "NET_DEBIT",
147
113
  session: "NORMAL",
148
114
  price: price,
149
115
  duration: "DAY",
150
116
  orderStrategyType: "SINGLE",
151
117
  orderLegCollection: [
152
- ## @TODO: this is only entering the next position, need to also close out the previous.
118
+ ## close
119
+ {
120
+ instruction: "BUY_TO_CLOSE",
121
+ quantity: pos.q,
122
+ instrument: {
123
+ symbol: pos.autoprev.inner.symbol,
124
+ assetType: "OPTION",
125
+ },
126
+ },
127
+ {
128
+ instruction: "SELL_TO_CLOSE",
129
+ quantity: pos.q,
130
+ instrument: {
131
+ symbol: pos.autoprev.outer.symbol,
132
+ assetType: "OPTION",
133
+ },
134
+ },
135
+
136
+ ## open
153
137
  {
154
138
  instruction: "BUY_TO_OPEN",
155
- quantity: q,
139
+ quantity: pos.q,
156
140
  instrument: {
157
- symbol: outer.symbol,
141
+ symbol: pos.outer.symbol,
158
142
  assetType: "OPTION",
159
143
  },
160
144
  },
161
145
  {
162
146
  instruction: "SELL_TO_OPEN",
163
- quantity: q,
147
+ quantity: pos.q,
164
148
  instrument: {
165
- symbol: inner.symbol,
149
+ symbol: pos.inner.symbol,
166
150
  assetType: "OPTION",
167
151
  },
168
152
  },
169
153
  ],
170
154
  }
155
+ puts! @query, '@query'
171
156
  end
172
157
 
173
- -## long debit call spread
158
+ ## long debit call spread
174
159
  def prepare3
175
- out = Tda::Option.roll_long_debit_call_spread( position )
176
- end
160
+ pos = @position = Iro::Position.find params[:id]
161
+ authorize! :place_order, @position
177
162
 
178
- def prepare
179
- @position = Iro::Position.find params[:id]
180
- authorize! :roll, @position
163
+ # out = Tda::Option.roll_long_debit_call_spread( position )
181
164
 
182
- @prev = @position
183
- @purse = @position.purse
184
- @stock = @position.stock
185
- @n_dollars = 100
165
+ ## @TODO: it's pending here, the order has not been placed.
186
166
 
187
- ## holiday schedule
188
- @next_expires_on = @prev.expires_on.to_datetime.next_occurring(:monday).next_occurring(:friday)
189
- if !@next_expires_on.workday?
190
- @next_expires_on = Time.previous_business_day( @next_expires_on )
191
- end
167
+ flags = []
192
168
 
193
- ## dealing with too many strikes in the chain
194
- while true
195
- @nn = ( @position.purse.n_next_positions/2 ).ceil
196
- upper = Tda::Option.get_quote({
197
- contractType: 'CALL',
198
- strike: @prev.inner_strike + @nn*@stock.options_price_increment,
199
- expirationDate: @next_expires_on,
200
- ticker: @stock.ticker,
201
- })
202
- if !upper.symbol
203
- puts! 'too high'
204
- flash_alert 'too high'
205
- @purse.n_next_positions = @purse.n_next_positions - 1
206
- @purse.n_next_positions = 1 if @purse.n_next_positions < 1
207
- @purse.save!
208
- next
209
- end
210
- lower = Tda::Option.get_quote({
211
- contractType: 'CALL',
212
- strike: @prev.inner_strike - @nn*@stock.options_price_increment,
213
- expirationDate: @next_expires_on,
214
- ticker: @stock.ticker,
215
- })
216
- if !lower.symbol
217
- puts! 'too low'
218
- flash_alert 'too low'
219
- @purse.n_next_positions = @purse.n_next_positions - 1
220
- @purse.n_next_positions = 1 if @purse.n_next_positions < 1
221
- @purse.save!
222
- next
223
- end
224
- break
225
- end
169
+ flags.push pos.prev.update({ status: Iro::Position::STATUS_CLOSED })
170
+ flags.push pos.update({ status: Iro::Position::STATUS_ACTIVE })
171
+ flags.push pos.purse.update({
172
+ available_amount: pos.purse.available_amount + price + pos.q*100,
173
+ })
226
174
 
227
- self.send("_prepare_#{@position.strategy.kind}")
175
+ flash_notice flags
176
+ redirect_to controller: :purses, action: :show, template: :gameui, id: pos.purse_id
228
177
  end
229
178
 
179
+
180
+
230
181
  def _prepare_covered_call
231
182
  @positions = []
232
183
  (-@nn..@nn).each do |idx|
233
184
  next_ = Iro::Position.new({
234
185
  stock: @stock,
235
- inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
236
- expires_on: @next_expires_on,
186
+ inner_strike: @prev.inner.strike - idx*@stock.options_price_increment,
187
+ expires_on: @prev.next_expires_on,
237
188
  purse: @position.purse,
238
189
  strategy: @position.strategy,
239
190
  quantity: @position.quantity,
@@ -242,8 +193,6 @@ class Iro::PositionsController < Iro::ApplicationController
242
193
  next_.begin_inner_price = next_.end_inner_price
243
194
  next_.begin_inner_delta = next_.end_inner_delta
244
195
  next_.next_gain_loss_amount = next_.begin_inner_price - @prev.end_inner_price
245
- puts! next_, 'next_'
246
- puts! next_.next_gain_loss_amount, 'amount'
247
196
  @positions.push next_
248
197
  end
249
198
  end
@@ -252,63 +201,82 @@ class Iro::PositionsController < Iro::ApplicationController
252
201
  @positions = []
253
202
  (-@nn..@nn).each do |idx|
254
203
  next_ = Iro::Position.find_or_create_by({
255
- status: 'prepare',
256
- stock: @stock,
257
- inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
258
- outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
259
- expires_on: @next_expires_on,
204
+ expires_on: @prev.next_expires_on,
205
+ inner_strike: @prev.inner.strike - idx*@stock.options_price_increment,
206
+ outer_strike: @prev.outer.strike - idx*@stock.options_price_increment,
207
+ prev_id: @prev.id,
260
208
  purse: @position.purse,
261
- strategy: @position.strategy,
262
209
  quantity: @position.quantity,
263
- prev_id: @prev.id,
210
+ status: 'prepare',
211
+ stock: @stock,
212
+ strategy: @position.strategy,
213
+ })
214
+ pos = next_
215
+ next_.inner ||= Iro::Option.new({
216
+ # begin_price: pos[:begin_inner_price],
217
+ # begin_delta: pos[:begin_inner_delta],
218
+ expires_on: pos[:expires_on],
219
+ inner: pos,
220
+ put_call: pos.put_call,
221
+ stock_id: pos[:stock_id],
222
+ strike: pos[:inner_strike],
264
223
  })
224
+ next_.outer ||= Iro::Option.new({
225
+ # begin_price: pos[:begin_inner_price],
226
+ # begin_delta: pos[:begin_inner_delta],
227
+ expires_on: pos[:expires_on],
228
+ outer: pos,
229
+ put_call: pos.put_call,
230
+ stock_id: pos[:stock_id],
231
+ strike: pos[:outer_strike],
232
+ })
233
+
265
234
  next_.sync
266
- next_.begin_inner_price = next_.end_inner_price
267
- next_.begin_inner_delta = next_.end_inner_delta
235
+ next_.inner.begin_price = next_.inner.end_price
236
+ next_.inner.begin_delta = next_.inner.end_delta
237
+
238
+ next_.outer.begin_price = next_.outer.end_price
239
+ next_.outer.begin_delta = next_.outer.end_delta
268
240
 
269
- next_.begin_outer_price = next_.end_outer_price
270
- next_.begin_outer_delta = next_.end_outer_delta
271
- next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
272
- next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
241
+ next_.next_gain_loss_amount = @prev.outer.end_price - @prev.inner.end_price
242
+ next_.next_gain_loss_amount += next_.inner.begin_price - next_.outer.begin_price
273
243
  next_.save
274
- puts! next_, 'next_'
275
- puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
276
244
  @positions.push next_
277
245
  end
278
246
  @positions = @positions.reverse
279
247
  end
248
+ alias_method :_prepare_short_debit_put_spread, :_prepare_long_debit_call_spread
280
249
 
281
- def _prepare_short_debit_put_spread
282
- @positions = []
283
- (-@nn..@nn).each do |idx|
284
- next_ = Iro::Position.new({
285
- stock: @stock,
286
- inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
287
- outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
288
- expires_on: @next_expires_on,
289
- purse: @position.purse,
290
- strategy: @position.strategy,
291
- quantity: @position.quantity,
292
- })
293
- next_.sync
294
- next_.begin_inner_price = next_.end_inner_price
295
- next_.begin_inner_delta = next_.end_inner_delta
296
250
 
297
- next_.begin_outer_price = next_.end_outer_price
298
- next_.begin_outer_delta = next_.end_outer_delta
299
- next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
300
- next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
301
- puts! next_, 'next_'
302
- puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
303
- @positions.push next_
251
+ def sync
252
+ @position = pos = Iro::Position.find params[:id]
253
+ authorize! :refresh, @position
254
+
255
+ @position.sync
256
+ @position.calc_rollp
257
+ if true # @position.rollp > 0.5
258
+ @position.calc_nxt
304
259
  end
260
+
261
+ redirect_to request.referrer || purse_path( @position.purse )
305
262
  end
306
263
 
264
+ ##
265
+ ## only updates some attributes
266
+ ##
307
267
  def update
308
- @position = Iro::Position.find params[:id]
268
+ pos = @position = Iro::Position.find params[:id]
309
269
  authorize! :update, @position
310
270
 
311
- if @position.update params[:position].permit!
271
+ if @position.update pos_params
272
+ o_attrs = {
273
+ expires_on: pos.expires_on,
274
+ put_call: pos.put_call,
275
+ stock_id: pos.stock_id,
276
+ }
277
+ pos.inner.update params[:inner].permit!.merge( o_attrs )
278
+ pos.outer.update params[:outer].permit!.merge( o_attrs )
279
+
312
280
  flash_notice @position
313
281
  redirect_to controller: :purses, action: :show, id: @position.purse_id.to_s
314
282
  else
@@ -317,14 +285,29 @@ class Iro::PositionsController < Iro::ApplicationController
317
285
  end
318
286
  end
319
287
 
288
+
289
+
320
290
  ##
321
291
  ## private
322
292
  ##
323
293
  private
324
294
 
295
+ def pos_params
296
+ params[:position].permit( :purse_id, :status, :stock_id,
297
+ :strategy_id, :expires_on, :quantity, :begin_on,
298
+ :long_or_short,
299
+ )
300
+ end
301
+
302
+ def price
303
+ pos = @position
304
+ out = pos.autoprev.outer.end_price - pos.autoprev.inner.end_price + pos.inner.begin_price - pos.outer.begin_price
305
+ return out
306
+ end
307
+
308
+
325
309
  def set_lists
326
310
  super
327
-
328
311
  @purses_list = Iro::Purse.list
329
312
  @strategies_list = Iro::Strategy.list(params[:long_or_short])
330
313
  @stocks_list = Iro::Stock.list
@@ -35,8 +35,10 @@ class Iro::PursesController < Iro::ApplicationController
35
35
  @purse = Iro::Purse.find(params[:id])
36
36
  authorize! :show, @purse
37
37
 
38
+
38
39
  @positions = @purse.positions.where( status: 'active' ).includes( :strategy
39
- ).order({ expires_on: :desc, stock: :desc })
40
+ ).order( expires_on: :asc, ticker: :desc, long_or_short: :asc, inner_strike: :asc )
41
+
40
42
 
41
43
  @unit = @purse.unit # 12 ## pixels per dollar
42
44
  @height = @purse.height # 100 ## pixels
@@ -32,14 +32,14 @@ class Iro::StocksController < Iro::ApplicationController
32
32
  authorize! :new, @stock
33
33
  end
34
34
 
35
- def refresh
35
+ def sync
36
36
  authorize! :refresh, Iro::Stock
37
37
  tickers = Iro::Stock.all.map { |s| s.ticker }.join(',')
38
38
  outs = Tda::Stock.get_quotes tickers
39
39
  outs.map do |out|
40
40
  Iro::Stock.where( ticker: out[:symbol] ).update( last: out[:last] )
41
41
  end
42
- flash_notice 'ok'
42
+ flash_notice 'refreshed stocks'
43
43
  redirect_to request.referrer
44
44
  end
45
45