iron_warbler 2.0.7.22 → 2.0.7.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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