iron_warbler 2.0.7.22 → 2.0.7.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.txt +19 -0
  3. data/app/assets/stylesheets/iron_warbler/application.css +12 -0
  4. data/app/assets/stylesheets/iron_warbler/positions.scss +2 -0
  5. data/app/assets/stylesheets/iron_warbler/positions_gameui.scss +11 -0
  6. data/app/assets/stylesheets/iron_warbler/purses_gameui.scss +11 -32
  7. data/app/assets/stylesheets/iron_warbler/purses_summary.scss +98 -0
  8. data/app/assets/stylesheets/iron_warbler/utils.scss +4 -0
  9. data/app/controllers/iro/alerts_controller.rb +2 -0
  10. data/app/controllers/iro/application_controller.rb +13 -0
  11. data/app/controllers/iro/positions_controller.rb +197 -23
  12. data/app/controllers/iro/purses_controller.rb +60 -6
  13. data/app/controllers/iro/stocks_controller.rb +30 -18
  14. data/app/controllers/iro/strategies_controller.rb +12 -1
  15. data/app/models/iro/alert.rb +1 -0
  16. data/app/models/iro/datapoint.rb +7 -7
  17. data/app/models/iro/option.rb +174 -3
  18. data/app/models/iro/position.rb +124 -56
  19. data/app/models/iro/purse.rb +18 -4
  20. data/app/models/iro/stock.rb +84 -0
  21. data/app/models/iro/strategy.rb +122 -27
  22. data/app/models/tda/option.rb +104 -8
  23. data/app/views/iro/_main_header.haml +28 -17
  24. data/app/views/iro/application/home.haml +6 -1
  25. data/app/views/iro/positions/_form.haml +1 -2
  26. data/app/views/iro/positions/_gameui_covered_call.haml +10 -13
  27. data/app/views/iro/positions/_gameui_covered_call.haml-bk +8 -0
  28. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml +5 -4
  29. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +5 -4
  30. data/app/views/iro/positions/_header.haml +2 -2
  31. data/app/views/iro/positions/_header_covered_call.haml +7 -1
  32. data/app/views/iro/positions/_header_long_debit_call_spread.haml +19 -1
  33. data/app/views/iro/positions/_prepare_covered_call.haml +25 -0
  34. data/app/views/iro/positions/_prepare_long_debit_call_spread.haml +23 -0
  35. data/app/views/iro/positions/_prepare_short_debit_put_spread.haml +23 -0
  36. data/app/views/iro/positions/_table.haml +33 -24
  37. data/app/views/iro/positions/prepare.haml +24 -0
  38. data/app/views/iro/positions/roll-cc.haml-bk +40 -0
  39. data/app/views/iro/positions/roll.haml-trash +42 -0
  40. data/app/views/iro/purses/_form.haml +9 -0
  41. data/app/views/iro/purses/_form_extra_fields.haml +25 -13
  42. data/app/views/iro/purses/_header.haml +15 -16
  43. data/app/views/iro/purses/_summary.haml +69 -0
  44. data/app/views/iro/purses/gameui.haml +13 -7
  45. data/app/views/iro/purses/index.haml +3 -1
  46. data/app/views/iro/purses/show.haml +5 -1
  47. data/app/views/iro/stocks/_form.haml +5 -0
  48. data/app/views/iro/stocks/_grid_is_long.haml +2 -2
  49. data/app/views/iro/stocks/_grid_is_short.haml +2 -2
  50. data/app/views/iro/stocks/index.haml +3 -2
  51. data/app/views/iro/strategies/_form.haml +12 -6
  52. data/app/views/iro/strategies/_show.haml +3 -3
  53. data/app/views/iro/strategies/_table.haml +15 -6
  54. data/app/views/iro/strategies/show.haml +14 -0
  55. data/app/views/layouts/iro/application.haml +4 -0
  56. data/config/routes.rb +6 -2
  57. data/lib/tasks/db_tasks.rake +1 -1
  58. data/lib/tasks/test_tasks.rake +54 -0
  59. metadata +28 -6
  60. data/app/models/iro/trash/position_covered_call.rb +0 -4
  61. data/app/models/iro/trash/position_debit_spread.rb +0 -251
  62. data/app/views/iro/positions/roll.haml +0 -83
  63. data/app/views/iro/positions/trash/_header_short_debit_put_spread.haml +0 -9
@@ -2,6 +2,7 @@
2
2
  class Iro::Strategy
3
3
  include Mongoid::Document
4
4
  include Mongoid::Timestamps
5
+ include Mongoid::Paranoia
5
6
  store_in collection: 'iro_strategies'
6
7
 
7
8
  field :slug
@@ -20,7 +21,7 @@ class Iro::Strategy
20
21
 
21
22
  KIND_COVERED_CALL = 'covered_call'
22
23
  KIND_LONG_DEBIT_CALL_SPREAD = 'long_debit_call_spread'
23
- KIND_SHORT_DEBIT_PUT_SPREAD = 'long_debit_call_spread'
24
+ KIND_SHORT_DEBIT_PUT_SPREAD = 'short_debit_put_spread'
24
25
  KINDS = [ nil,
25
26
  KIND_COVERED_CALL,
26
27
  KIND_LONG_DEBIT_CALL_SPREAD,
@@ -42,27 +43,31 @@ class Iro::Strategy
42
43
  end
43
44
 
44
45
  field :buffer_above_water, type: :float
45
- field :next_max_inner_delta, type: :float
46
- field :next_max_outer_delta, type: :float
47
- field :next_min_strike, type: :float
48
46
  field :threshold_delta, type: :float
49
47
  field :threshold_netp, type: :float
50
48
 
49
+ field :next_inner_delta, type: :float
50
+ field :next_outer_delta, type: :float
51
+ field :next_inner_strike, type: :float
52
+ field :next_outer_strike, type: :float
53
+ field :next_spread_amount, type: :float # e.g. $20 for a $2000 NVDA spread
54
+
55
+
51
56
  def self.for_ticker ticker
52
57
  where( ticker: ticker )
53
58
  end
54
59
 
55
- def breakeven p
56
- p.inner_strike - p.begin_outer_price + p.begin_inner_price
57
- end
58
-
59
- def breakeven p
60
+ def breakeven_covered_call p
60
61
  p.inner_strike + p.begin_inner_price
61
62
  end
63
+ def breakeven_long_debit_call_spread p
64
+ p.inner_strike - p.max_gain # p.begin_outer_price + p.begin_inner_price
65
+ end
66
+ alias_method :breakeven_short_debit_put_spread, :breakeven_long_debit_call_spread
62
67
 
63
68
  def max_gain_covered_call p
64
69
  # return p.begin_inner_price
65
- p.begin_inner_price * 100 - 0.66
70
+ p.begin_inner_price * 100 - 0.66 # @TODO: is this *100 really?
66
71
  end
67
72
  def max_gain_long_debit_call_spread p
68
73
  ## 100 * disalloed for gameui
@@ -73,40 +78,130 @@ class Iro::Strategy
73
78
  ( p.outer_strike - p.inner_strike - p.begin_outer_price + p.begin_inner_price ) # - 2*0.66
74
79
  end
75
80
 
81
+ def net_amount_covered_call p
82
+ ( p.begin_inner_price - p.end_inner_price )
83
+ end
84
+ def net_amount_long_debit_call_spread p
85
+ outer = p.end_outer_price - p.begin_outer_price
86
+ inner = p.begin_inner_price - p.end_inner_price
87
+ out = ( outer + inner )
88
+ end
89
+ alias_method :net_amount_short_debit_put_spread, :net_amount_long_debit_call_spread
90
+
76
91
  def max_loss_covered_call p
77
- return 'infinity'
92
+ p.begin_inner_price*10 # just suppose 10,000%
78
93
  end
79
94
  def max_loss_long_debit_call_spread p
80
- out = 100 * ( p.outer_strike - p.inner_strike )
95
+ out = p.outer_strike - p.inner_strike
81
96
  end
82
- def max_loss_short_debit_put_spread p
83
- out = -100 * ( p.outer_strike - p.inner_strike )
97
+ def max_loss_short_debit_put_spread p # different
98
+ out = p.inner_strike - p.outer_strike
84
99
  end
85
100
 
86
- def net_amount_covered_call p
87
- ( p.begin_inner_price - p.end_inner_price ) * 100
101
+ def begin_delta_covered_call p
102
+ p.begin_inner_delta
88
103
  end
89
- def net_amount_long_debit_call_spread p
90
- outer = p.end_outer_price - p.begin_outer_price
91
- inner = p.begin_inner_price - p.end_inner_price
92
- out = ( outer + inner ) * 100
104
+ def begin_delta_long_debit_call_spread p
105
+ p.begin_outer_delta - p.begin_inner_delta
93
106
  end
94
- alias_method :net_amount_short_debit_put_spread, :net_amount_long_debit_call_spread
107
+ alias_method :begin_delta_short_debit_put_spread, :begin_delta_long_debit_call_spread
95
108
 
109
+ def end_delta_covered_call p
110
+ p.end_inner_delta
111
+ end
112
+ def end_delta_long_debit_call_spread p
113
+ p.end_outer_delta - p.end_inner_delta
114
+ end
115
+ alias_method :end_delta_short_debit_put_spread, :end_delta_long_debit_call_spread
96
116
 
97
- def net_amount_long_debit_call_spread p
98
- outer = p.end_outer_price - p.begin_outer_price
99
- inner = p.begin_inner_price - p.end_inner_price
100
- out = ( outer + inner ) * 100
117
+
118
+
119
+ ##
120
+ ## decisions
121
+ ##
122
+
123
+ def calc_rollp_covered_call p
124
+
125
+ if ( p.expires_on.to_date - Time.now.to_date ).to_i < 1
126
+ return [ 0.99, '0 DTE, must exit' ]
127
+ end
128
+
129
+ if ( stock.last - buffer_above_water ) < p.inner_strike
130
+ return [ 0.98, "Last #{'%.2f' % stock.last} is " +
131
+ "#{'%.2f' % [p.inner_strike + buffer_above_water - stock.last]} " +
132
+ "below #{'%.2f' % [p.inner_strike + buffer_above_water]} water" ]
133
+ end
134
+
135
+ if p.end_inner_delta < threshold_delta
136
+ return [ 0.61, "Delta #{p.end_inner_delta} is lower than #{threshold_delta} threshold." ]
137
+ end
138
+
139
+ if 1 - p.end_inner_price/p.begin_inner_price > threshold_netp
140
+ return [ 0.51, "made enough #{'%.0f' % [(1 - p.end_inner_price/p.begin_inner_price )*100]}% profit" ]
141
+ end
142
+
143
+ return [ 0.33, '-' ]
101
144
  end
102
145
 
146
+ ## @TODO
147
+ def calc_rollp_long_debit_call_spread p
148
+
149
+ if ( p.expires_on.to_date - Time.now.to_date ).to_i < 1
150
+ return [ 0.99, '0 DTE, must exit' ]
151
+ end
152
+ if ( p.expires_on.to_date - Time.now.to_date ).to_i < 2
153
+ return [ 0.99, '1 DTE, must exit' ]
154
+ end
155
+
156
+ if ( stock.last - buffer_above_water ) < p.inner_strike
157
+ return [ 0.95, "Last #{'%.2f' % stock.last} is " +
158
+ "#{'%.2f' % [stock.last - p.inner_strike - buffer_above_water]} " +
159
+ "below #{'%.2f' % [p.inner_strike + buffer_above_water]} water" ]
160
+ end
161
+
162
+ if p.end_inner_delta < threshold_delta
163
+ return [ 0.79, "Delta #{p.end_inner_delta} is lower than #{threshold_delta} threshold." ]
164
+ end
165
+
166
+ if 1 - p.end_inner_price/p.begin_inner_price > threshold_netp
167
+ return [ 0.51, "made enough #{'%.0f' % [(1 - p.end_inner_price/p.begin_inner_price )*100]}% profit" ]
168
+ end
169
+
170
+ return [ 0.33, '-' ]
171
+ end
172
+
173
+ ## @TODO
174
+ def calc_rollp_short_debit_put_spread p
175
+
176
+ if ( p.expires_on.to_date - Time.now.to_date ).to_i < 1
177
+ return [ 0.99, '0 DTE, must exit' ]
178
+ end
179
+
180
+ if ( stock.last - buffer_above_water ) < p.inner_strike
181
+ return [ 0.98, "Last #{'%.2f' % stock.last} is " +
182
+ "#{'%.2f' % [stock.last - p.inner_strike - buffer_above_water]} " +
183
+ "above #{'%.2f' % [p.inner_strike + buffer_above_water]} water" ]
184
+ end
185
+
186
+ if p.end_inner_delta < threshold_delta
187
+ return [ 0.79, "Delta #{p.end_inner_delta} is lower than #{threshold_delta} threshold." ]
188
+ end
189
+
190
+ if 1 - p.end_inner_price/p.begin_inner_price > threshold_netp
191
+ return [ 0.51, "made enough #{'%.0f' % [(1 - p.end_inner_price/p.begin_inner_price )*100]}% profit" ]
192
+ end
193
+
194
+ return [ 0.33, '-' ]
195
+ end
196
+
197
+
103
198
 
104
199
 
105
200
  def to_s
106
- slug
201
+ "#{stock} #{kind_short} #{slug}"
107
202
  end
108
203
  def self.list long_or_short = nil
109
204
  these = long_or_short ? where( long_or_short: long_or_short ) : all
110
- [[nil,nil]] + these.map { |ttt| [ ttt.slug, ttt.id ] }
205
+ [[nil,nil]] + these.map { |ttt| [ ttt, ttt.id ] }
111
206
  end
112
207
  end
@@ -68,7 +68,7 @@ class Tda::Option
68
68
  ## 2023-02-06 _vp_ :: Continue.
69
69
  ##
70
70
  def self.get_quotes params
71
- puts! params, 'Tda::Option#get_quotes'
71
+ # puts! params, 'Tda::Option#get_quotes'
72
72
  opts = {}
73
73
 
74
74
  #
@@ -98,7 +98,7 @@ class Tda::Option
98
98
  end
99
99
 
100
100
  query = { apikey: ::TD_AMERITRADE[:apiKey] }.merge opts
101
- puts! query, 'input opts'
101
+ # puts! query, 'input opts'
102
102
 
103
103
  path = "/v1/marketdata/chains"
104
104
  out = self.get path, { query: query }
@@ -120,18 +120,114 @@ class Tda::Option
120
120
  end
121
121
  end
122
122
 
123
- puts! outs, 'outs'
123
+ # puts! outs, 'outs'
124
124
  return outs
125
125
  end
126
126
 
127
127
 
128
+ def self.close_credit_call
129
+ end
130
+ def self.close_long_debit_call_spread
131
+ end
132
+ def self.close_short_debit_put_spread
133
+ end
134
+
135
+ def self.get_token
136
+ opts = {
137
+ grant_type: 'authorization_code',
138
+ access_type: 'offline',
139
+ code: ::TD_AMERITRADE[:code],
140
+ }
141
+ end
142
+
143
+ def self.create_credit_call outer:, inner:, q:, price:
144
+ query = {
145
+ orderType: "NET_DEBIT",
146
+ session: "NORMAL",
147
+ price: price,
148
+ duration: "DAY",
149
+ orderStrategyType: "SINGLE",
150
+ orderLegCollection: [
151
+ {
152
+ instruction: "BUY_TO_OPEN",
153
+ quantity: q,
154
+ instrument: {
155
+ symbol: outer.symbol,
156
+ assetType: "OPTION",
157
+ },
158
+ },
159
+ {
160
+ instruction: "SELL_TO_OPEN",
161
+ quantity: q,
162
+ instrument: {
163
+ symbol: inner.symbol,
164
+ assetType: "OPTION",
165
+ },
166
+ },
167
+ ],
168
+ }
169
+ File.write('tmp/query.json', JSON.pretty_generate( query ))
170
+ puts! query, 'query'
171
+
172
+ return
173
+
174
+ headers = {
175
+ Authorize: "Bearer #{::TD_AMERITRADE[:access_token]}",
176
+ }
177
+
178
+ path = "/v1/accounts/#{::TD_AMERITRADE[:accountId]}/orders"
179
+ puts! path, 'path'
180
+ out = self.post path, { query: query, headers: headers }
181
+ timestamp = DateTime.parse out.headers['date']
182
+ out = out.parsed_response.deep_symbolize_keys
183
+ puts! out, 'created credit call?'
184
+ end
185
+ def self.create_long_debit_call_spread
186
+ end
187
+ def self.create_short_debit_put_spread
188
+ end
189
+
190
+ def self.roll_credit_call
191
+ end
192
+ def self.roll_long_debit_call_spread
193
+ end
194
+ def self.roll_short_debit_put_spread
195
+ end
196
+
197
+
128
198
  end
129
199
 
200
+ ##
201
+ ## From: https://developer.tdameritrade.com/content/place-order-samples
202
+ ## Buy Limit: Vertical Call Spread
203
+ ##
130
204
  =begin
205
+ {
206
+ "orderType": "NET_DEBIT",
207
+ "session": "NORMAL",
208
+ "price": "1.20",
209
+ "duration": "DAY",
210
+ "orderStrategyType": "SINGLE",
211
+ "orderLegCollection": [
212
+ {
213
+ "instruction": "BUY_TO_OPEN",
214
+ "quantity": 10,
215
+ "instrument": {
216
+ "symbol": "XYZ_011516C40",
217
+ "assetType": "OPTION"
218
+ }
219
+ },
220
+ {
221
+ "instruction": "SELL_TO_OPEN",
222
+ "quantity": 10,
223
+ "instrument": {
224
+ "symbol": "XYZ_011516C42.5",
225
+ "assetType": "OPTION"
226
+ }
227
+ }
228
+ ]
229
+ }
230
+ =end
231
+
131
232
 
132
- outs = Tda::Option.get_quotes({
133
- contractType: 'CALL', strike: 20.0, expirationDate: '2024-01-12',
134
- ticker: 'GME',
135
- })
136
233
 
137
- =end
@@ -1,24 +1,35 @@
1
1
 
2
- .application-main-header.main-header
2
+ .application--main-header.main-header.iro--main-header{ class: "#{ENV['RAILS_ENV']} #{ENV['RAILS_ENV'][0...3]=="dev" ? "development" : ''}" }
3
3
  .maxwidth
4
4
 
5
5
  %i.fa.fa-compress.collapse-expand#collapseHeaderTrading
6
- Iron Warbler
6
+ Wco Trading
7
+ .a
8
+ .d-flex
9
+ %ul{ style: "margin-top: 2em;" }
10
+ %li
11
+ = link_to "Stocks (#{Iro::Stock.all.length})", stocks_path
12
+ = link_to '[re]', refresh_stocks_path
13
+ -# %li= link_to 'Options', options_path
14
+ -# %li Max Pain
15
+ %li
16
+ = link_to "Alerts (#{Iro::Alert.all.length})", alerts_path
17
+ %li
18
+ = link_to "Purses (#{Iro::Purse.all.length})", purses_path
19
+ %li
20
+ = render '/iro/strategies/header'
7
21
 
8
- -# .header.collapse-expand#IroMenu
9
- -# %h5.title Iron Warbler
10
-
11
- %ul
12
- %li= link_to 'ROOT', root_path
13
- %li
14
- = link_to "Stocks (#{Iro::Stock.all.length})", stocks_path
15
- -# %li= link_to 'Options', options_path
16
- -# %li Max Pain
17
- %li
18
- = link_to "Alerts (#{Iro::Alert.all.length})", alerts_path
19
- %li
20
- = link_to "Purses (#{Iro::Purse.all.length})", purses_path
21
- %li
22
- = render '/iro/strategies/header'
22
+ .a
23
+ = link_to 'Purses', purses_path
24
+ %ul
25
+ - @purses.each do |p|
26
+ %li= link_to p, purse_path(p)
27
+ .a
28
+ = link_to 'Strategies', strategies_path
29
+ %ul
30
+ - @strategies.each do |s|
31
+ %li
32
+ = link_to s, strategy_path(s)
33
+ = link_to '[~]', edit_strategy_path(s)
23
34
 
24
35
 
@@ -1,2 +1,7 @@
1
1
 
2
- Hello, Iro Wor!
2
+ .maxwidth
3
+ Hello, Iro Wor!
4
+
5
+ %br
6
+ %br
7
+ %br
@@ -7,8 +7,7 @@
7
7
  .d-flex
8
8
  .field
9
9
  %label Purse
10
- -# = f.select :purse_id, options_for_select( @
11
- = f.text_field :purse_id
10
+ = f.select :purse_id, options_for_select( @purses_list, selected: position.purse_id )
12
11
 
13
12
  %label Status
14
13
  = f.select :status, options_for_select( Iro::Position::STATUSES, selected: position.status )
@@ -2,7 +2,7 @@
2
2
  - pos = position
3
3
  - stock = pos.stock
4
4
  - nearest_strike = stock.last.round
5
- - u = @unit # pixels per dollar
5
+ - u = pos.purse.unit # pixels per dollar
6
6
 
7
7
  .collapse-expand.d-flex{ id: "gameui-pos-#{pos.id}" }
8
8
  [<>]
@@ -10,32 +10,29 @@
10
10
  .a
11
11
  = render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
12
12
  .StockCoordinatesW
13
- .StockCoordinates{ style: "height: #{pos.purse.height}px " }
14
- = render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock
13
+ .StockCoordinates{ style: "height: #{pos.q() * u}px " }
14
+ .grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
15
15
 
16
16
  .Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
17
17
  .label Last: #{pp_amount stock.last}
18
- .c
19
18
 
20
- -## Good, remove trash, leave as implemented.
21
- -# - left = "#{ (stock.last - position.inner_strike - position.begin_inner_price) * u}px"
22
- -# - width = "#{ position.begin_inner_price * u}px"
23
19
  - left = "#{ (stock.last - pos.inner_strike) * u}px"
24
20
  - width = "0px"
25
- .PositionW{ style: "left: #{left} ; width: #{width} " }
21
+ .PositionW{ class: pos.strategy.kind, style: "left: #{left} ; width: #{width} " }
26
22
  .Position
23
+ .RollGuide
27
24
  .PositionC
28
25
 
29
- - if position.net_amount >= 0
30
- .Net.NetPositive{ style: "width: #{ (position.net_amount / 100) * u }px; right: 0" }
26
+ - if pos.net_amount >= 0
27
+ .Net.NetPositive{ style: "width: #{ (pos.net_amount / 100) * u }px; right: 0" }
31
28
  .label
32
29
  net
33
- = pp_amount position.net_amount
30
+ = pp_amount pos.net_amount
34
31
  - else
35
- .Net.NetNegative{ style: "width: #{ (-1 * position.net_amount / 100) * u }px; left: 100%" }
32
+ .Net.NetNegative{ style: "width: #{ (-1 * pos.net_amount / 100) * u }px; left: 100%" }
36
33
  .label
37
34
  net
38
- = pp_amount position.net_amount
35
+ = pp_amount pos.net_amount
39
36
 
40
37
  .Breakeven{ style: "width: #{ pos.begin_inner_price * u }px" }
41
38
  .label
@@ -1,4 +1,12 @@
1
1
 
2
+
3
+ -## Good, remove trash, leave as implemented.
4
+ -# - left = "#{ (stock.last - pos.inner_strike - pos.begin_inner_price) * u}px"
5
+ -# - width = "#{ pos.begin_inner_price * u}px"
6
+
7
+
8
+
9
+
2
10
  - unit = u = 50 # pixels per dollar
3
11
  - grid_size = 100 # dollars to each side of origin
4
12
  .purses-gameui.padded
@@ -2,7 +2,7 @@
2
2
  - pos = position
3
3
  - stock = pos.stock
4
4
  - nearest_strike = stock.last.round
5
- - u = @purse.unit # pixels per dollar
5
+ - u = pos.purse.unit # pixels per dollar
6
6
 
7
7
  .collapse-expand.d-flex{ id: "gameui-pos-#{pos.id}" }
8
8
  [<>]
@@ -10,8 +10,8 @@
10
10
  .a
11
11
  = render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
12
12
  .StockCoordinatesW
13
- .StockCoordinates{ style: "height: #{pos.purse.height}px " }
14
- = render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock
13
+ .StockCoordinates{ style: "height: #{pos.q() *u}px " }
14
+ .grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
15
15
 
16
16
  .Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
17
17
  .label Last: #{pp_amount stock.last}
@@ -19,9 +19,10 @@
19
19
 
20
20
  - left = "#{ ( pos.outer_strike - stock.last ) * u}px"
21
21
  - width = "#{ ( pos.inner_strike - pos.outer_strike ) * u}px"
22
- .PositionW{ style: "left: #{left}; width: #{width}; " }
22
+ .PositionW{ class: pos.strategy.kind, style: "left: #{left}; width: #{width}; " }
23
23
  .Position
24
24
  .MaxGain{ style: "width: #{pos.max_gain * u}px" }
25
+ .RollGuide
25
26
 
26
27
  - if pos.net_amount >= 0
27
28
  .Net.NetPositive{ style: "width: #{ (pos.net_amount / 100) * u }px; right: 0" }
@@ -2,7 +2,7 @@
2
2
  - pos = position
3
3
  - stock = pos.stock
4
4
  - nearest_strike = stock.last.round
5
- - u = @unit # pixels per dollar
5
+ - u = pos.purse.unit # pixels per dollar
6
6
 
7
7
 
8
8
  .collapse-expand.d-flex{ id: "gameui-pos-#{pos.id}" }
@@ -11,8 +11,8 @@
11
11
  .a
12
12
  = render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
13
13
  .StockCoordinatesW
14
- .StockCoordinates{ style: "height: #{pos.purse.height}px " }
15
- = render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock
14
+ .StockCoordinates{ style: "height: #{pos.q() *u}px " }
15
+ .grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
16
16
 
17
17
  .Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
18
18
  .label Last: #{pp_amount stock.last}
@@ -21,9 +21,10 @@
21
21
  -## these are different
22
22
  - left = "#{ ( stock.last - pos.outer_strike ) * u}px"
23
23
  - width = "#{ ( pos.outer_strike - pos.inner_strike ) * u}px"
24
- .PositionW{ style: "left: #{left}; width: #{width}; " }
24
+ .PositionW{ class: pos.strategy.kind, style: "left: #{left}; width: #{width}; " }
25
25
  .Position
26
26
  .MaxGain{ style: "width: #{pos.max_gain * u}px" }
27
+ .RollGuide
27
28
 
28
29
  - if pos.net_amount >= 0
29
30
  .Net.NetPositive{ style: "width: #{ (pos.net_amount / 100) * u }px; right: 0" }
@@ -1,6 +1,6 @@
1
1
 
2
2
  .positions--header.maxwidth
3
3
  = pos
4
- = link_to '[roll]', roll_position_path(pos)
5
- = link_to '[~]', edit_position_path(pos)
4
+ = link_to '[roll]', prepare_to_roll_position_path(pos) if pos.persisted?
5
+ = link_to '[~]', edit_position_path(pos) if pos.persisted?
6
6
  -# = render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
@@ -1,6 +1,12 @@
1
1
 
2
- %i.fa.fa-expand.collapse-expand.floaty-collapse{ id: "gameui-pos-detail-#{pos.id}" }
2
+ - collapse_key ||= pos.id
3
+ %i.fa.fa-expand.collapse-expand.floaty-collapse{ id: "gameui-pos-detail-#{collapse_key}" }
3
4
  .maxwidth
4
5
  %ul.m-0.p-0
6
+ - if !pos.persisted?
7
+ %li <b>expires_on:</b> #{pos.expires_on}
8
+ %li <b>inner_strike:</b> #{pp_amount pos.inner_strike}
9
+ %li <b>next_gain_loss_amount:</b> #{pp_amount pos.next_gain_loss_amount}
10
+
5
11
  %li <b>begin_inner_price:</b> #{pp_amount pos.begin_inner_price}
6
12
  %li <b>Net:</b> #{pp_amount pos.net_amount} &nbsp; <i>#{pp_percent pos.net_percent}</i>
@@ -1,14 +1,32 @@
1
1
 
2
2
 
3
3
  -## Same file for the spreads
4
- %i.fa.fa-expand.collapse-expand.floaty-collapse{ id: "gameui-pos-detail-#{pos.id}" }
4
+ - collapse_key ||= pos.id
5
+ %i.fa.fa-expand.collapse-expand.floaty-collapse{ id: "gameui-pos-detail-#{collapse_key}" }
5
6
  .maxwidth
6
7
  %ul.m-0.p-0
8
+ - if !pos.persisted?
9
+ %li <b>expires_on:</b> #{pos.expires_on}
10
+ %li <b>outer,inner_strike:</b> #{pp_amount pos.outer_strike} -> #{pp_amount pos.inner_strike}
11
+ %li
12
+ <b>next_gain_loss_amount:</b> #{pp_amount pos.next_gain_loss_amount}
13
+ \:: #{pp_amount pos.next_gain_loss_amount * 100 * pos.q}
14
+ &nbsp;&nbsp; <i>#{pp_percent pos.next_gain_loss_amount/pos.max_loss*-1}</i>
15
+
7
16
  %li <b>outer,inner_strike:</b> #{pp_amount pos.outer_strike} -> #{pp_amount pos.inner_strike}
8
17
  %li
9
18
  <b>begin_outer,inner_price:</b> #{pp_amount pos.begin_outer_price} -> #{pp_amount pos.begin_inner_price}
10
19
  &nbsp;&nbsp;
11
20
  -## yes *100
12
21
  <b>max gain:</b> #{pp_amount pos.max_gain} :: #{pp_amount pos.max_gain * 100 * pos.q}
22
+ %li
23
+ <b>end_outer,inner_price:</b> #{pp_amount pos.end_outer_price} -> #{pp_amount pos.end_inner_price}
24
+ &nbsp;&nbsp;
25
+ -## yes *100
26
+ <b>max loss:</b> #{pp_amount pos.max_loss} :: #{pp_amount pos.max_loss * 100 * pos.q}
27
+ %li
28
+ <b>Exposure:</b> #{pp_amount pos.max_loss() *-1*100*pos.q()}
29
+ %li
30
+ <b>Breakeven:</b> #{pp_amount pos.max_gain}
13
31
  - ## no *100
14
32
  %li <b>Net:</b> #{pp_amount pos.net_amount} :: #{pp_amount pos.net_amount * pos.q} &nbsp;&nbsp; <i>#{pp_percent pos.net_percent}</i>
@@ -0,0 +1,25 @@
1
+
2
+
3
+ - u = pos.purse.unit # 50 ## pixels per dollar
4
+ - strategy = pos.strategy
5
+ - nearest_strike = pos.stock.last.round
6
+ - stock = pos.stock
7
+
8
+
9
+ .StockCoordinatesW
10
+ .StockCoordinates{ style: "height: #{@position.purse.height}px " }
11
+
12
+ .grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
13
+
14
+ .Origin{ style: "left: #{ ( nearest_strike - pos.stock.last )* u}px" }
15
+ .label
16
+ Last:
17
+ = pos.stock.last
18
+ - amnt = pos.next_gain_loss_amount
19
+ -# - byebug
20
+ - border = amnt >= 0 ? "#{amnt * u}px solid green" : "#{amnt * -1 * u}px solid red"
21
+ - width = "#{ pos.begin_inner_price * u}px"
22
+ - left = "#{ (pos.stock.last - pos.inner_strike - pos.begin_inner_price) * u}px"
23
+ .PositionW{ style: "width: #{width}; left: #{left}; border-right: #{border};" }
24
+ .Position
25
+ .c
@@ -0,0 +1,23 @@
1
+
2
+ - u = pos.purse.unit # 50 ## pixels per dollar
3
+ - strategy = pos.strategy
4
+ - nearest_strike = pos.stock.last.round
5
+ - stock = pos.stock
6
+
7
+
8
+ .StockCoordinatesW
9
+ .StockCoordinates{ style: "height: #{@position.purse.height}px " }
10
+
11
+ .grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
12
+
13
+ .Origin{ style: "left: #{ ( nearest_strike - pos.stock.last )* u}px" }
14
+ .label Last: #{pos.stock.last }
15
+
16
+ - amnt = pos.next_gain_loss_amount
17
+ - border = amnt >= 0 ? "#{amnt * u}px solid green" : "#{amnt * -1 * u}px solid red"
18
+ - width = "#{ ( pos.inner_strike - pos.outer_strike ) * u}px"
19
+ - left = "#{ ( pos.outer_strike - pos.stock.last ) * u}px"
20
+ .PositionW{ style: "width: #{width}; left: #{left}; border-right: #{border};" }
21
+ .Position
22
+ .MaxGain{ style: "width: #{pos.max_gain * u}px" }
23
+ .c