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
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