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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cebb47a68d7145641d296c6dba9d452facc1826e94515f1c372969449297686d
4
- data.tar.gz: 1856079c227ee3f079da067a2ef9b47c8f6c3f617b483527a5616192d0c95754
3
+ metadata.gz: 1b73ac7c5b7ca0d29fe20cd0db0dcdca4713a710790bff2cffe8c30c3a18d2d2
4
+ data.tar.gz: daef47e2b8841f0253e55d19a8c8703c7aff086c53711b52db3dfdb470a97a78
5
5
  SHA512:
6
- metadata.gz: 854b5350d8f9f7edd2f02bde20cf0a94cfbc6eb39a3662ef8e15c3395b2f5349e0466e8db813a7a338b743a69e6bd8ca3d18a4c090306c3da78a00cfe1e959ef
7
- data.tar.gz: 9586d7277cf4174e4515922849c0e4b7a5a385da8bebaf5ebc87d76c4e1c111ff7a89800d7eaaf6de30b4e708f22cee04afb2b51c9b8c90f53f762553d0023b1
6
+ metadata.gz: e59a49397b934c8537abe40eb23eba846aa770956e02168722b2eb5fd6a1e19581388dc43d3ecb6e211e90cffec5cf8b02ef5eaa6efdcb1f40b4599c4125c8e8
7
+ data.tar.gz: 8f10a4503e57e02d17ca0dd7a310fc73489dfd22fb23e23f16a79de72f3a589790c09e9facbfb2441daf3fcef2b93456bcac12ce7a767c35ce7e29c2ccffc48f
data/README.txt ADDED
@@ -0,0 +1,19 @@
1
+
2
+ = Install =
3
+
4
+ From: https://docs.galpy.org/en/latest/installation.html
5
+
6
+ brew install gsl
7
+
8
+ = Use =
9
+
10
+ calculator: https://www.omnicalculator.com/finance/black-scholes
11
+
12
+ From: https://pythoninoffice.com/calculate-black-scholes-option-price-in-python/
13
+
14
+ -=---
15
+
16
+
17
+ https://api.tdameritrade.com/v1/accounts/232718838/orders/13597943085
18
+
19
+
@@ -27,3 +27,15 @@ html {
27
27
  /* body {
28
28
  color: red !important;
29
29
  } */
30
+
31
+ .iro--main-header {
32
+ li {
33
+ margin-bottom: 0.2em;
34
+
35
+ a {
36
+ background: white;
37
+ padding: 0 0.2em;
38
+ }
39
+ }
40
+ }
41
+
@@ -0,0 +1,11 @@
1
+
2
+ .positions--prepare {
3
+ .RollGuide {
4
+ height: 100vh;
5
+ border: 1px dashed gray;
6
+ position: absolute;
7
+ right: 0;
8
+ overflow: hidden;
9
+ }
10
+ }
11
+
@@ -2,7 +2,8 @@
2
2
  .purses-gameuiW {
3
3
  border: 1px solid red;
4
4
  width: 100%;
5
- overflow: scroll;
5
+ // overflow-x: scroll;
6
+ overflow-y: hidden;
6
7
  }
7
8
 
8
9
  .purses-gameui {
@@ -31,6 +32,9 @@
31
32
  z-index: 2;
32
33
  }
33
34
  }
35
+ .PositionW.short_debit_put_spread {
36
+ background: rgba(255,153,0, 0.25);
37
+ }
34
38
  .PositionW {
35
39
  top: 0;
36
40
  border: 2px solid black;
@@ -47,13 +51,14 @@
47
51
 
48
52
  .Position {
49
53
  position: absolute;
50
- background: rgba(0,255,255, 0.25);
51
54
  width: 100%;
52
55
  height: 90%;
53
56
 
54
57
  left: 0;
55
58
  top: 0;
56
59
  }
60
+
61
+
57
62
  /* only for covered calls */
58
63
  .PositionC {
59
64
  background: rgba(255,153,51, 0.5);
@@ -72,9 +77,9 @@
72
77
  position: absolute;
73
78
  right: 0;
74
79
  bottom: -10%;
75
- border: 2px solid green;
80
+ border: 2px dotted green;
76
81
  background: rgba(0,255,0, 0.5);
77
- height: 10%;
82
+ height: 0.5em;
78
83
  }
79
84
 
80
85
  .sprite {
@@ -138,32 +143,6 @@
138
143
  background: rgba(255,0,0, 0.75);
139
144
  }
140
145
 
141
-
142
- // .grid-mark:nth-child(4n + 1) {
143
- // border: 1px solid red;
144
- // display: none;
145
- // }
146
- // .grid-mark:nth-child(4n) {
147
- // border: 1px solid red;
148
- // display: none;
149
- // }
150
- // .grid-mark:nth-child(6n + 1) {
151
- // border: 1px solid red;
152
- // display: none;
153
- // }
154
- // .grid-mark:nth-child(6n) {
155
- // border: 1px solid red;
156
- // display: none;
157
- // }
158
- // .grid-mark:nth-child(3n + 1) {
159
- // border: 1px solid red;
160
- // display: none;
161
- // }
162
- // .grid-mark:nth-child(3n) {
163
- // border: 1px solid red;
164
- // display: none;
165
- // }
166
-
167
146
  .grid-mark {
168
147
  // border: 1px solid red;
169
148
 
@@ -202,8 +181,8 @@
202
181
  .labelC {
203
182
  background: white;
204
183
  position: absolute;
205
- top: 1.5em;
206
- left: -1.5em;
184
+ bottom: -1em;
185
+ right: 0;
207
186
  }
208
187
  }
209
188
  }
@@ -0,0 +1,98 @@
1
+
2
+ .PurseSummaryW {
3
+ position: relative;
4
+ background: rgba(255,255,255, 0.75);
5
+ height: 400px;
6
+ width: 100%;
7
+ z-index: 5;
8
+ }
9
+ .PurseSummary {
10
+ position: absolute;
11
+ top: 200px;
12
+
13
+ display: flex;
14
+
15
+ width: 100%;
16
+ height: 0;
17
+ border-bottom: 1px dotted black;
18
+
19
+ .legendW {
20
+ position: relative;
21
+ // margin-top: 50%;
22
+
23
+ .legend {
24
+ margin-top: -50%;
25
+
26
+ // position: absolute;
27
+ // top: -200px;
28
+ // width: 400px;
29
+ // height: 400px;
30
+
31
+ background: white;
32
+ padding: 0.5em;
33
+ }
34
+ }
35
+
36
+
37
+ /*
38
+ * summary amount and delta
39
+ **/
40
+ .summary-amount {
41
+ position: relative;
42
+ width: 100px;
43
+
44
+ .net-gl {
45
+ width: 100%;
46
+ background: rgba(0,0,0, 0.5);
47
+ }
48
+ }
49
+ .summary-delta {
50
+ position: relative;
51
+ margin-right: 1em;
52
+ width: 1em;
53
+
54
+ > div {
55
+ border: 1px dotted yellow;
56
+ }
57
+ .begin {
58
+ width: 1em;
59
+
60
+ background: black;
61
+ }
62
+ .end {
63
+ width: .5em;
64
+ left: .25em;
65
+
66
+ background: rgba(255,0,0, 0.5);
67
+ }
68
+ }
69
+ .loss {
70
+ }
71
+ .gain {
72
+ }
73
+ .max-gl {
74
+ position: absolute;
75
+ width: 100%;
76
+ }
77
+ .max-gl.long {
78
+ background: rgba(255,0,0, 0.5);
79
+ }
80
+ .max-gl-short {
81
+ background: rgba(255,153,0, 0.5);
82
+ }
83
+ .long {
84
+ position: absolute;
85
+ top: 0;
86
+
87
+ background: rgba(255,0,0, 0.5);
88
+ border: 1px solid red;
89
+ bottom: 0;
90
+ }
91
+ .short {
92
+ background: rgba(255,153,0, 0.5);
93
+ border: 1px solid orange;
94
+
95
+ position: absolute;
96
+ bottom: 0;
97
+ }
98
+ }
@@ -52,6 +52,10 @@
52
52
 
53
53
  /* M */
54
54
 
55
+ .mini-inputs {
56
+ background: rgba(255,255,255, 0.25);
57
+ }
58
+
55
59
  .modal-absolute {
56
60
  border: 1px solid green;
57
61
  border-radius: 5px;
@@ -42,6 +42,8 @@ class Iro::AlertsController < Iro::ApplicationController
42
42
  private
43
43
 
44
44
  def set_lists
45
+ super
46
+
45
47
  # @profiles_list = Wco::Profile.list
46
48
  @stocks_list = Iro::Stock.list
47
49
  puts! @stocks_list, '@stocks_list'
@@ -3,8 +3,21 @@
3
3
  class Iro::ApplicationController < Wco::ApplicationController
4
4
  layout 'iro/application'
5
5
 
6
+ before_action :set_lists
7
+
6
8
  def home
7
9
  authorize! :home, Iro
8
10
  end
9
11
 
12
+ ##
13
+ ## private
14
+ ##
15
+ private
16
+
17
+ def set_lists
18
+ @purses = Iro::Purse.all
19
+ @strategies = Iro::Strategy.all
20
+ end
21
+
22
+
10
23
  end
@@ -3,14 +3,28 @@ class Iro::PositionsController < Iro::ApplicationController
3
3
  before_action :set_lists
4
4
 
5
5
  def new
6
- @position = Iro::Position.new purse_id: params[:purse_id]
6
+ @position = Iro::Position.new
7
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
+
8
20
  end
9
21
 
10
22
  def create
11
23
  @position = Iro::Position.new params[:position].permit!
12
24
  authorize! :create, @position
13
25
 
26
+ @position.sync
27
+
14
28
  if @position.save
15
29
  flash_notice @position
16
30
  redirect_to controller: :purses, action: :show, id: @position.purse_id.to_s
@@ -33,38 +47,195 @@ class Iro::PositionsController < Iro::ApplicationController
33
47
  authorize! :edit, @position
34
48
  end
35
49
 
50
+ def propose
51
+ @strategy = Iro::Strategy.find params[:strategy_id]
52
+ authorize! :show, @strategy
53
+
54
+ @purse = Iro::Purse.find params[:purse_id]
55
+
56
+ ## short debit put spread
57
+ outs = Tda::Option.get_quotes({
58
+ contractType: 'PUT',
59
+ expirationDate: '2024-03-28',
60
+ ticker: @strategy.stock.ticker,
61
+ })
62
+ outs = outs.select do |out|
63
+ out[:bidSize]+out[:askSize] > 0
64
+ end
65
+ outs = outs.select do |out|
66
+ out[:strikePrice] > @strategy.buffer_above_water + @strategy.stock.last
67
+ end
68
+ outs = outs.select do |out|
69
+ out[:strikePrice] > @strategy.next_inner_strike
70
+ end
71
+ outs = outs.select do |out|
72
+ out[:delta] < @strategy.next_inner_delta
73
+ end
74
+
75
+ inner = outs[0]
76
+ outs = outs.select do |out|
77
+ out[:strikePrice] >= inner[:strikePrice] + @strategy.next_spread_amount
78
+ end
79
+ outer = outs[0]
80
+
81
+ if inner && outer
82
+ next_position = Iro::Position.new({
83
+ status: 'proposed',
84
+ stock: @strategy.stock,
85
+ inner_strike: inner[:strikePrice],
86
+ outer_strike: outer[:strikePrice],
87
+ begin_outer_price: outer[:last],
88
+ begin_outer_delta: outer[:delta],
89
+ begin_inner_price: inner[:last],
90
+ begin_inner_delta: inner[:delta],
91
+ begin_on: Time.now.to_date,
92
+ expires_on: '2024-03-28',
93
+ purse: @purse,
94
+ strategy: @strategy,
95
+ quantity: 1,
96
+ })
97
+ next_position.sync
98
+ next_position.save
99
+ else
100
+ flash_alert 'cannot propose a new one'
101
+ end
102
+ redirect_to request.referrer
103
+ end
104
+
36
105
  def refresh
37
106
  @position = pos = Iro::Position.find params[:id]
38
107
  authorize! :refresh, @position
39
108
 
40
- ## covered call
41
- out = Tda::Option.get_quote({
42
- contractType: 'CALL',
43
- strike: pos.inner_strike,
44
- expirationDate: pos.expires_on,
45
- ticker: pos.stock.ticker,
46
- })
47
- puts! out, 'out'
48
- @position.update({
49
- end_inner_price: ( out.bid + out.ask ) / 2,
50
- end_inner_delta: out.delta,
51
- })
109
+ @position.sync
110
+ @position.calc_rollp
111
+
52
112
  redirect_to request.referrer || purse_path( @position.purse )
53
113
  end
54
114
 
55
- def roll
115
+ def prepare
56
116
  @position = Iro::Position.find params[:id]
57
117
  authorize! :roll, @position
58
118
 
59
- stock = @position.stock
119
+ @prev = @position
120
+ @purse = @position.purse
121
+ @stock = @position.stock
122
+ @n_dollars = 100
123
+
124
+ ## holiday schedule
125
+ @next_expires_on = @prev.expires_on.to_datetime.next_occurring(:monday).next_occurring(:friday)
126
+ if !@next_expires_on.workday?
127
+ @next_expires_on = Time.previous_business_day( @next_expires_on )
128
+ end
129
+
130
+ ## dealing with too many strikes in the chain
131
+ while true
132
+ @nn = ( @position.purse.n_next_positions/2 ).ceil
133
+ upper = Tda::Option.get_quote({
134
+ contractType: 'CALL',
135
+ strike: @prev.inner_strike + @nn*@stock.options_price_increment,
136
+ expirationDate: @next_expires_on,
137
+ ticker: @stock.ticker,
138
+ })
139
+ if !upper.symbol
140
+ puts! 'too high'
141
+ flash_alert 'too high'
142
+ @purse.n_next_positions = @purse.n_next_positions - 1
143
+ @purse.n_next_positions = 1 if @purse.n_next_positions < 1
144
+ @purse.save!
145
+ next
146
+ end
147
+ lower = Tda::Option.get_quote({
148
+ contractType: 'CALL',
149
+ strike: @prev.inner_strike - @nn*@stock.options_price_increment,
150
+ expirationDate: @next_expires_on,
151
+ ticker: @stock.ticker,
152
+ })
153
+ if !lower.symbol
154
+ puts! 'too low'
155
+ flash_alert 'too low'
156
+ @purse.n_next_positions = @purse.n_next_positions - 1
157
+ @purse.n_next_positions = 1 if @purse.n_next_positions < 1
158
+ @purse.save!
159
+ next
160
+ end
161
+ break
162
+ end
60
163
 
61
- @positions = [
62
- Iro::Position.new({ stock: stock, begin_inner_price: 5.21, inner_strike: 91, expires_on: '2024-04-05', gain_loss_amount: -1.25 }),
63
- Iro::Position.new({ stock: stock, begin_inner_price: 5.77, inner_strike: 90, expires_on: '2024-04-05', gain_loss_amount: -0.7 }),
64
- Iro::Position.new({ stock: stock, begin_inner_price: 6.4, inner_strike: 89, expires_on: '2024-04-05', gain_loss_amount: -0.03 }),
65
- Iro::Position.new({ stock: stock, begin_inner_price: 6.85, inner_strike: 88, expires_on: '2024-04-05', gain_loss_amount: 0.6 }),
66
- Iro::Position.new({ stock: stock, begin_inner_price: 7.07, inner_strike: 87, expires_on: '2024-04-05', gain_loss_amount: 1.22 }),
67
- ]
164
+ self.send("_prepare_#{@position.strategy.kind}")
165
+ end
166
+
167
+ def _prepare_covered_call
168
+ @positions = []
169
+ (-@nn..@nn).each do |idx|
170
+ next_ = Iro::Position.new({
171
+ stock: @stock,
172
+ inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
173
+ expires_on: @next_expires_on,
174
+ purse: @position.purse,
175
+ strategy: @position.strategy,
176
+ quantity: @position.quantity,
177
+ })
178
+ next_.sync
179
+ next_.begin_inner_price = next_.end_inner_price
180
+ next_.begin_inner_delta = next_.end_inner_delta
181
+ next_.next_gain_loss_amount = next_.begin_inner_price - @prev.end_inner_price
182
+ puts! next_, 'next_'
183
+ puts! next_.next_gain_loss_amount, 'amount'
184
+ @positions.push next_
185
+ end
186
+ end
187
+
188
+ def _prepare_long_debit_call_spread
189
+ @positions = []
190
+ (-@nn..@nn).each do |idx|
191
+ next_ = Iro::Position.new({
192
+ stock: @stock,
193
+ inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
194
+ outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
195
+ expires_on: @next_expires_on,
196
+ purse: @position.purse,
197
+ strategy: @position.strategy,
198
+ quantity: @position.quantity,
199
+ })
200
+ next_.sync
201
+ next_.begin_inner_price = next_.end_inner_price
202
+ next_.begin_inner_delta = next_.end_inner_delta
203
+
204
+ next_.begin_outer_price = next_.end_outer_price
205
+ next_.begin_outer_delta = next_.end_outer_delta
206
+ next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
207
+ next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
208
+ puts! next_, 'next_'
209
+ puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
210
+ @positions.push next_
211
+ end
212
+ @positions = @positions.reverse
213
+ end
214
+
215
+ def _prepare_short_debit_put_spread
216
+ @positions = []
217
+ (-@nn..@nn).each do |idx|
218
+ next_ = Iro::Position.new({
219
+ stock: @stock,
220
+ inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
221
+ outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
222
+ expires_on: @next_expires_on,
223
+ purse: @position.purse,
224
+ strategy: @position.strategy,
225
+ quantity: @position.quantity,
226
+ })
227
+ next_.sync
228
+ next_.begin_inner_price = next_.end_inner_price
229
+ next_.begin_inner_delta = next_.end_inner_delta
230
+
231
+ next_.begin_outer_price = next_.end_outer_price
232
+ next_.begin_outer_delta = next_.end_outer_delta
233
+ next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
234
+ next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
235
+ puts! next_, 'next_'
236
+ puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
237
+ @positions.push next_
238
+ end
68
239
  end
69
240
 
70
241
  def update
@@ -86,8 +257,11 @@ class Iro::PositionsController < Iro::ApplicationController
86
257
  private
87
258
 
88
259
  def set_lists
260
+ super
261
+
262
+ @purses_list = Iro::Purse.list
89
263
  @strategies_list = Iro::Strategy.list(params[:long_or_short])
90
- @stocks_list = Iro::Stock.list
264
+ @stocks_list = Iro::Stock.list
91
265
  end
92
266
 
93
267
  end
@@ -7,10 +7,11 @@ class Iro::PursesController < Iro::ApplicationController
7
7
  @purse = Iro::Purse.new params[:purse].permit!
8
8
  authorize! :create, @purse
9
9
  if @purse.save
10
- redirect_to action: :index, notice: 'Purse was successfully created.'
10
+ ;
11
11
  else
12
- render :new
12
+ flash_alert @purse
13
13
  end
14
+ redirect_to action: :index
14
15
  end
15
16
 
16
17
  def destroy
@@ -34,13 +35,15 @@ class Iro::PursesController < Iro::ApplicationController
34
35
  @purse = Iro::Purse.find(params[:id])
35
36
  authorize! :show, @purse
36
37
 
37
- @positions = @purse.positions.includes( :strategy
38
- ).order({ expires_on: :desc })
38
+ @positions = @purse.positions.where( status: 'active' ).includes( :strategy
39
+ ).order({ expires_on: :desc, stock: :desc })
39
40
 
40
41
  @unit = @purse.unit # 12 ## pixels per dollar
41
42
  @height = @purse.height # 100 ## pixels
42
43
  @n_dollars = 100 ## dollars to each side of origin
43
44
 
45
+ calc_summary
46
+
44
47
  render params[:template]
45
48
  end
46
49
 
@@ -49,7 +52,7 @@ class Iro::PursesController < Iro::ApplicationController
49
52
  authorize! :update, @purse
50
53
  if @purse.update params[:purse].permit!
51
54
  flash[:notice] = 'ok'
52
- redirect_to purse_path(@purse)
55
+ redirect_to request.referrer # purse_path(@purse)
53
56
  else
54
57
  flash_alert @purse
55
58
  render :edit
@@ -61,9 +64,60 @@ class Iro::PursesController < Iro::ApplicationController
61
64
  ##
62
65
  private
63
66
 
67
+ ## for one stock only!
68
+ def calc_summary
69
+ @max_loss_long = 0
70
+ @max_loss_short = 0
71
+
72
+ @max_gain_long = 0
73
+ @max_gain_short = 0
74
+
75
+ @gain_long = 0
76
+ @gain_short = 0
77
+
78
+ @begin_delta_long = 0
79
+ @begin_delta_short = 0
80
+ @end_delta_long = 0
81
+ @end_delta_short = 0
82
+
83
+ @positions.each do |pos|
84
+ if Iro::Strategy::LONG == pos.strategy.long_or_short
85
+ @max_loss_long += pos.max_loss * pos.q * 100
86
+ @max_gain_long += pos.max_gain * pos.q * 100
87
+ @gain_long += pos.net_amount * pos.q * 100
88
+
89
+ @begin_delta_long += pos.begin_delta * pos.q
90
+ @end_delta_long += pos.end_delta * pos.q
91
+ end
92
+ if Iro::Strategy::SHORT == pos.strategy.long_or_short
93
+ @max_loss_short += pos.max_loss * pos.q * 100
94
+ @max_gain_short += pos.max_gain * pos.q * 100
95
+ @gain_short += pos.net_amount * pos.q * 100
96
+
97
+ @begin_delta_short += pos.begin_delta * pos.q
98
+ @end_delta_short += pos.end_delta * pos.q
99
+ end
100
+ end
101
+ # @max_loss_long *= -1
102
+ # @max_loss_short *= -1
103
+ @begin_delta_short *= -1
104
+ @end_delta_short *= -1
105
+ if @gain_long < 0
106
+ @loss_long = @gain_long
107
+ @gain_long = nil
108
+ end
109
+ if @gain_short < 0
110
+ @loss_short = @gain_short
111
+ @gain_short = nil
112
+ end
113
+ end
114
+
64
115
  def set_lists
116
+ super
117
+
65
118
  # @profiles_list = Wco::Profile.list
66
- @stocks_list = [[nil,nil]] + Iro::Stock.active.map { |s| [ s.ticker, s.ticker ] }
119
+ # @tickers_list = [[nil,nil]] + Iro::Stock.active.map { |s| [ s.ticker, s.ticker ] }
120
+ @stocks_list = Iro::Stock.list
67
121
 
68
122
  end
69
123