iron_warbler 2.0.7.18 → 2.0.7.20

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascript/iron_warbler/application.js +2 -0
  3. data/app/assets/javascript/iron_warbler/gameui.js +9 -0
  4. data/app/assets/stylesheets/iron_warbler/application.css +13 -3
  5. data/app/assets/stylesheets/iron_warbler/positions.scss +9 -1
  6. data/app/assets/stylesheets/iron_warbler/purses_gameui.scss +191 -0
  7. data/app/assets/stylesheets/iron_warbler/purses_gameui.scss-bk +112 -0
  8. data/app/assets/stylesheets/iron_warbler/utils.scss +82 -0
  9. data/app/controllers/iro/api/stocks_controller.rb +87 -0
  10. data/app/controllers/iro/api_controller.rb +19 -0
  11. data/app/controllers/iro/positions_controller.rb +16 -4
  12. data/app/controllers/iro/purses_controller.rb +8 -3
  13. data/app/controllers/iro/strategies_controller.rb +7 -7
  14. data/app/helpers/iro/application_helper.rb +5 -2
  15. data/app/models/iro/alert.rb +2 -1
  16. data/app/models/iro/datapoint.rb +48 -8
  17. data/app/models/iro/position.rb +55 -14
  18. data/app/models/iro/position_covered_call.rb +4 -0
  19. data/app/models/iro/position_debit_spread.rb +251 -0
  20. data/app/models/iro/price_item.rb +51 -1
  21. data/app/models/iro/stock.rb +5 -2
  22. data/app/models/iro/strategy.rb +76 -10
  23. data/app/models/tda/stock.rb +3 -0
  24. data/app/views/iro/_main_header.haml +18 -17
  25. data/app/views/iro/api/stocks/show.jbuilder +11 -0
  26. data/app/views/iro/positions/_form.haml +11 -38
  27. data/app/views/iro/positions/_formpart_4data.haml +46 -0
  28. data/app/views/iro/positions/_gameui_covered_call.haml +36 -0
  29. data/app/views/iro/positions/_gameui_covered_call.haml-bk +59 -0
  30. data/app/views/iro/positions/_gameui_long_debit_call_spread.haml +37 -0
  31. data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +39 -0
  32. data/app/views/iro/positions/_header.haml +6 -0
  33. data/app/views/iro/positions/_header_covered_call.haml +6 -0
  34. data/app/views/iro/positions/_header_long_debit_call_spread.haml +14 -0
  35. data/app/views/iro/positions/_header_short_debit_put_spread.haml +1 -0
  36. data/app/views/iro/positions/_table.haml +118 -123
  37. data/app/views/iro/positions/roll.haml +83 -0
  38. data/app/views/iro/positions/trash/_header_short_debit_put_spread.haml +9 -0
  39. data/app/views/iro/purses/_header.haml +18 -0
  40. data/app/views/iro/purses/gameui.haml +18 -0
  41. data/app/views/iro/purses/gameui.haml-bk +44 -0
  42. data/app/views/iro/purses/gameui.haml-bk2 +89 -0
  43. data/app/views/iro/purses/show.haml +1 -7
  44. data/app/views/iro/stocks/_grid_is_long.haml +13 -0
  45. data/app/views/iro/stocks/_grid_is_short.haml +13 -0
  46. data/app/views/iro/strategies/_form.haml +12 -5
  47. data/app/views/iro/strategies/_show.haml +3 -2
  48. data/app/views/iro/strategies/_table.haml +16 -10
  49. data/app/views/iro/strategies/index.haml +8 -0
  50. data/app/views/layouts/iro/application.haml +1 -1
  51. data/config/routes.rb +14 -1
  52. data/lib/tasks/db_tasks.rake +9 -3
  53. metadata +29 -8
  54. data/app/assets/stylesheets/iron_warbler/alerts.css +0 -8
  55. data/app/assets/stylesheets/iron_warbler/datapoints.css +0 -0
  56. data/app/assets/stylesheets/iron_warbler/profiles.css +0 -4
  57. data/app/assets/stylesheets/iron_warbler/strategies.scss +0 -0
  58. data/app/assets/stylesheets/iron_warbler/utils.css +0 -44
  59. data/app/jobs/iro/application_job.rb-trash +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6b3c19fdfe0c9cd47b253a92b6065f067d3004022865d700059ad3190287f35
4
- data.tar.gz: abd93b990583e6ab2c644b74647014767a43947d81fdf7f1b15abf198efad96c
3
+ metadata.gz: 0deda82521a6d2995c6cf495e7276550ce2d9f12541b829dbc903c0c1d64050c
4
+ data.tar.gz: 8742db15fd84ccd0f344f194380b4074d9b615dc9b95b1f88ddf41504601408c
5
5
  SHA512:
6
- metadata.gz: 106e70eda991a01d9ce69a265958ea2dbe25fb27a0b316297b303ec97c5cffb6cb274b78a4ceb827d107f7644122947038c8cce696fcd8f8240cffb6cfe9e28f
7
- data.tar.gz: 3b51d655011169c98ef738174c054733aaa4ebe737ebd53b0725f4f062e7b939bc4d72e3561a8c12d309240b68ded7d311ac91819da0b74d21f411240a249987
6
+ metadata.gz: ae6c37ed5e85029f73f1fefcb825020e8da3ab4e69e7e85ae16bdfa29ba62673bb3a32f75124026fba0e6155423cbc5fd0cc3695a7c994bf6662d6287b7f4c69
7
+ data.tar.gz: 4bbb876537fb451b1734fd3b0a431de13ff03e8cff9eeed75851b19048580091dbb16ef2376dee6ee9ddd9df65d8bee9b2d50a15e8b0afaa9403323f306a8de1
@@ -1,3 +1,5 @@
1
1
 
2
+ //= require ./gameui
3
+
2
4
  // console.log('Loaded iron_warbler/application.js')
3
5
 
@@ -0,0 +1,9 @@
1
+
2
+ $(function() {
3
+
4
+ const tmp = $('.purses-gameuiW').attr('data-margin-left')
5
+ logg(tmp, 'tmp')
6
+
7
+ $('.purses-gameuiW').scrollLeft( tmp );
8
+
9
+ }); // END
@@ -12,8 +12,18 @@
12
12
  *
13
13
  *= require_tree .
14
14
  *= require_self
15
- */
15
+ **/
16
16
 
17
- body {
18
- colod: red !important;
17
+ html {
18
+ --iro-color-long: lightseagreen;
19
+ --iro-color-short: orange;
20
+
21
+ --iro-color-grid1: #ccc;
22
+ --iro-color-grid2: #999;
23
+ --iro-color-bg1: #efefef;
24
+ --iro-color-bg2: #fefefe;
19
25
  }
26
+
27
+ /* body {
28
+ color: red !important;
29
+ } */
@@ -15,7 +15,7 @@
15
15
  border: 1px solid red;
16
16
 
17
17
  > * {
18
- border: 1px solid yellow;
18
+ // border: 1px solid yellow;
19
19
  // background: #ddd;
20
20
 
21
21
  transform-origin: 0 0;
@@ -43,5 +43,13 @@
43
43
  th.next_symbol {
44
44
  width: 120px;
45
45
  }
46
+
47
+ tr.is_long {
48
+ border-left: 5px solid var(--iro-color-long);
49
+ }
50
+ tr.is_short {
51
+ border-left: 5px solid var(--iro-color-short);
52
+ }
53
+
46
54
  }
47
55
  }
@@ -0,0 +1,191 @@
1
+
2
+ .purses-gameuiW {
3
+ border: 1px solid red;
4
+ width: 100%;
5
+ overflow: scroll;
6
+ }
7
+
8
+ .purses-gameui {
9
+
10
+ .Origin::before {
11
+ position: absolute;
12
+ top: -1em;
13
+ content: "";
14
+ margin-left: -1em;
15
+ border: 1em solid transparent;
16
+ border-top: 1em solid black;
17
+ }
18
+ .Origin {
19
+ position: absolute;
20
+ top: 0;
21
+ // background: rgba(255,255,0, 0.5);
22
+ height: 100%;
23
+ width: 100%;
24
+
25
+ > .label {
26
+ width: 300px;
27
+
28
+ position: absolute;
29
+ top: -1.5em;
30
+ left: 1.2em;
31
+ z-index: 2;
32
+ }
33
+ }
34
+ .PositionW {
35
+ top: 0;
36
+ border: 2px solid black;
37
+ background: rgba(0,255,255, 0.25);
38
+ position: absolute;
39
+ height: 100%;
40
+ }
41
+ .reviewing {
42
+ .PositionW {
43
+ border-radius: 10px 10px 0 0;
44
+ height: 90%;
45
+ }
46
+ }
47
+
48
+ .Position {
49
+ position: absolute;
50
+ background: rgba(0,255,255, 0.25);
51
+ width: 100%;
52
+ height: 90%;
53
+
54
+ left: 0;
55
+ top: 0;
56
+
57
+ }
58
+
59
+ .MaxGain {
60
+ position: absolute;
61
+ right: 0;
62
+ bottom: -10%;
63
+ border: 2px solid green;
64
+ background: rgba(0,255,0, 0.5);
65
+ height: 10%;
66
+ }
67
+
68
+ .sprite {
69
+ position: absolute;
70
+ }
71
+ .sprite-bottom {
72
+ bottom: 0;
73
+ }
74
+
75
+ .StockCoordinatesW {
76
+ // width: 500px;
77
+
78
+ // background: var(--iro-color-bg2);
79
+ // border: 1px solid red;
80
+ margin-bottom: 2em;
81
+
82
+ position: relative;
83
+
84
+ z-index: 1;
85
+ }
86
+ .StockCoordinates {
87
+ border-left: 1px solid var(--iro-color-grid1);
88
+ border-bottom: 1px solid var(--iro-color-grid1);
89
+
90
+ height: 50px;
91
+
92
+ margin-left: 50%;
93
+ margin-bottom: 0em;
94
+
95
+ position: relative;
96
+
97
+ .Breakeven {
98
+ // background: cyan;
99
+ border-right: 2px solid lightblue;
100
+
101
+ .half-circle {
102
+ width: 100%;
103
+ height: 100%; /* as the half of the width */
104
+ background-color: lightblue;
105
+ border-top-left-radius: 100%; /* 100px of height + 10px of border */
106
+ border-top-right-radius: 100%; /* 100px of height + 10px of border */
107
+ // border: 10px solid gray;
108
+ // border-bottom: 0;
109
+ }
110
+ }
111
+
112
+ .Last {
113
+ border-left: 2px dotted red;
114
+ }
115
+ .label {
116
+ width: 200px;
117
+ color: gray;
118
+ }
119
+
120
+ .marker {
121
+ position: absolute;
122
+ height: 100%;
123
+ }
124
+
125
+ .Net {
126
+ position: absolute;
127
+ // bottom: 3em;
128
+ // z-index: 3;
129
+ height: 90%;
130
+
131
+ // border-bottom: 5px solid red;
132
+ .label {
133
+ color: white;
134
+ text-shadow: 1px 1px black;
135
+ }
136
+ }
137
+ .NetPositive {
138
+ border: 2px dashed #339966;
139
+ background: rgba(32,64,96, 0.5);
140
+ }
141
+ .NetNegative {
142
+ background: rgba(255,0,0, 0.75);
143
+ }
144
+
145
+ .grid-mark:nth-child(4n + 1) {
146
+ border: 1px solid red;
147
+ display: none;
148
+ }
149
+ .grid-mark:nth-child(4n) {
150
+ border: 1px solid red;
151
+ display: none;
152
+ }
153
+ .grid-mark:nth-child(6n + 1) {
154
+ border: 1px solid red;
155
+ display: none;
156
+ }
157
+ .grid-mark:nth-child(6n) {
158
+ border: 1px solid red;
159
+ display: none;
160
+ }
161
+ .grid-mark:nth-child(3n + 1) {
162
+ border: 1px solid red;
163
+ display: none;
164
+ }
165
+ .grid-mark:nth-child(3n) {
166
+ border: 1px solid red;
167
+ display: none;
168
+ }
169
+
170
+ .grid-mark {
171
+ height: 100%;
172
+ position: absolute;
173
+ top: 0;
174
+ width: 100px;
175
+ z-index: -2;
176
+ border-left: 1px dashed var(--iro-color-grid1);
177
+
178
+ .label {
179
+ transform: rotate(-30deg);
180
+ font-size: 0.8em;
181
+
182
+ position: absolute;
183
+ // bottom: -1em;
184
+ z-index: 0;
185
+ }
186
+ }
187
+
188
+
189
+ }
190
+
191
+ }
@@ -0,0 +1,112 @@
1
+
2
+ .purses-gameui {
3
+
4
+
5
+ .Origin::before {
6
+ content: "";
7
+ margin-left: -1em;
8
+ border: 1em solid transparent;
9
+ border-top: 1em solid black;
10
+ }
11
+ .Origin {
12
+ position: absolute;
13
+ top: 0;
14
+ left: calc( 50% );
15
+ // z-index: -2;
16
+ }
17
+ .sprite {
18
+ position: absolute;
19
+ }
20
+ .sprite-bottom {
21
+ bottom: 0;
22
+ }
23
+
24
+ .CoordinatesW {
25
+ // width: 500px;
26
+
27
+ background: var(--iro-color-bg2);
28
+ border: 1px solid red;
29
+ margin-bottom: 3em;
30
+
31
+ position: relative;
32
+
33
+ z-index: 1;
34
+ }
35
+ .Coordinates {
36
+ border-left: 1px solid var(--iro-color-grid1);
37
+ border-bottom: 1px solid var(--iro-color-grid1);
38
+
39
+ background: yellow;
40
+
41
+ height: 100px;
42
+
43
+ margin-left: 50%;
44
+
45
+ position: relative;
46
+
47
+ .Breakeven {
48
+ // background: cyan;
49
+ border-right: 2px solid lightblue;
50
+
51
+ .half-circle {
52
+ width: 100%;
53
+ height: 100%; /* as the half of the width */
54
+ background-color: lightblue;
55
+ border-top-left-radius: 100%; /* 100px of height + 10px of border */
56
+ border-top-right-radius: 100%; /* 100px of height + 10px of border */
57
+ // border: 10px solid gray;
58
+ // border-bottom: 0;
59
+ }
60
+ }
61
+
62
+ .Last {
63
+ border-left: 2px dotted red;
64
+ }
65
+ .label {
66
+ width: 200px;
67
+ color: gray;
68
+ }
69
+
70
+ .marker {
71
+ position: absolute;
72
+ height: 100%;
73
+ }
74
+
75
+ .Net {
76
+
77
+ position: absolute;
78
+ bottom: 3em;
79
+ z-index: 3;
80
+
81
+ background: #339966;
82
+ // border-bottom: 5px solid red;
83
+ .label {
84
+ color: white;
85
+ }
86
+ }
87
+
88
+ .grid-mark {
89
+ height: 100%;
90
+ position: absolute;
91
+ top: 0;
92
+ width: 100px;
93
+ z-index: 1;
94
+ border-left: 1px dashed var(--iro-color-grid1);
95
+
96
+ .label {
97
+ position: absolute;
98
+ bottom: -1em;
99
+ z-index: 0;
100
+ }
101
+ }
102
+ .mark0 {
103
+ .label {
104
+ bottom: -2em;
105
+ }
106
+ }
107
+
108
+
109
+
110
+ }
111
+
112
+ }
@@ -0,0 +1,82 @@
1
+
2
+
3
+
4
+ .long-or-short::before {
5
+ // content: '[LONG]';
6
+ }
7
+ .long-or-short-item,
8
+ .long-or-short-container .is_long,
9
+ .long-or-short-container .is_short {
10
+ display: flex;
11
+ flex-direction: column;
12
+ }
13
+
14
+ .long-or-short-container .is_long,
15
+ .is_long .long-or-short-item {
16
+ border-left: 3px solid var(--iro-color-long);
17
+ padding-left: 5px;
18
+ }
19
+ .long-or-short-container .is_short,
20
+ .is_short .long-or-short-item {
21
+ border-left: 3px solid var(--iro-color-short);
22
+ padding-left: 5px;
23
+ }
24
+
25
+ .is_short .long-or-short-item::before {
26
+ // content: '[SHORT]';
27
+ }
28
+ .is_short .long-or-short-item,
29
+ .long-or-short-container .is_short {
30
+ flex-direction: column-reverse;
31
+ }
32
+
33
+ /* F */
34
+
35
+ .flex-row {
36
+ display: flex;
37
+ margin-bottom: 0.4em;
38
+ }
39
+
40
+ .floaty-collapse {
41
+ float: left;
42
+ z-index: 5;
43
+ position: relative;
44
+ background: white;
45
+ }
46
+ .field {
47
+ min-width: 100px;
48
+ margin-right: 1em;
49
+ }
50
+
51
+ /* M */
52
+
53
+ .modal-absolute {
54
+ border: 1px solid green;
55
+ border-radius: 5px;
56
+ box-shadow: 2px 2px;
57
+
58
+ padding: 0.5em;
59
+
60
+ position: absolute;
61
+
62
+ min-width: 200px;
63
+ width: 400px;
64
+
65
+ min-height: 200px;
66
+ height: 300px;
67
+ /* overflow: auto; */
68
+
69
+ background: white;
70
+
71
+ z-index: 2;
72
+
73
+ }
74
+
75
+
76
+
77
+ /* W */
78
+
79
+ .w-min-50px {
80
+ min-width: 50px;
81
+ }
82
+
@@ -0,0 +1,87 @@
1
+
2
+ class Iro::Api::StocksController < Iro::ApiController
3
+ before_action :set_stock, only: [:show, :edit, :update, :destroy]
4
+
5
+ def index
6
+ authorize! :index, Iro::Stock
7
+
8
+ respond_to do |format|
9
+ format.json do
10
+ render
11
+ end
12
+ end
13
+ end
14
+
15
+ def show
16
+ authorize! :show, @stock
17
+ end_on = Time.now.to_date.in_time_zone('UTC')
18
+
19
+ begin_on = params[:begin_on].to_date.in_time_zone('UTC') if params[:begin_on]
20
+ end_on = params[:end_on].to_date.in_time_zone('UTC') if params[:end_on]
21
+
22
+ case params[:period]
23
+ when '1-mo'
24
+ begin_on = ( Time.now - 30.days ).to_date.in_time_zone('UTC')
25
+ # end_on = Time.now.to_date.in_time_zone('UTC')
26
+ when '3-mo'
27
+ begin_on = ( Time.now - 90.days ).to_date.in_time_zone('UTC')
28
+ # end_on = Time.now.to_date.in_time_zone('UTC')
29
+ when '1-yr'
30
+ begin_on = ( Time.now - 1.year ).to_date.in_time_zone('UTC')
31
+ # end_on = Time.now.to_date.in_time_zone('UTC')
32
+ end
33
+
34
+ @datapoints = Iro::Datapoint.where({
35
+ :quote_at.gte => begin_on,
36
+ :quote_at.lte => end_on,
37
+ symbol: params[:ticker],
38
+ }).order_by({ quote_at: :asc })
39
+ end
40
+
41
+ def new
42
+ @stock = Iro::Stock.new
43
+ authorize! :new, @stock
44
+ end
45
+
46
+ def edit
47
+ end
48
+
49
+ def create
50
+ @stock = Iro::Stock.new(stock_params)
51
+ authorize! :create, @stock
52
+
53
+ if @stock.save
54
+ flash_notice @stock
55
+ else
56
+ flash_alert @stock
57
+ end
58
+ redirect_to action: :index
59
+ end
60
+
61
+ def update
62
+ @stock = Iro::Stock.find params[:id]
63
+ authorize! :update, @stock
64
+ if @stock.update(stock_params)
65
+ flash_notice @stock
66
+ else
67
+ flash_alert @stock
68
+ end
69
+ redirect_to request.referrer
70
+ end
71
+
72
+ def destroy
73
+ @stock.destroy
74
+ redirect_to stocks_url, notice: 'Stock was successfully destroyed.'
75
+ end
76
+
77
+ ##
78
+ ## private
79
+ ##
80
+ private
81
+
82
+ def set_stock
83
+ @stock = Iro::Stock.find_by({ ticker: params[:ticker] })
84
+ end
85
+
86
+ end
87
+
@@ -0,0 +1,19 @@
1
+
2
+ class Iro::ApiController < ActionController::Base
3
+ layout false
4
+
5
+ before_action :decode_jwt
6
+
7
+ ##
8
+ ## private
9
+ ##
10
+ private
11
+
12
+ def decode_jwt
13
+ out = JWT.decode params[:jwt_token], nil, false
14
+ email = out[0]['email']
15
+ user = User.find_by({ email: email })
16
+ sign_in user
17
+ end
18
+
19
+ end
@@ -1,6 +1,5 @@
1
1
 
2
2
  class Iro::PositionsController < Iro::ApplicationController
3
-
4
3
  before_action :set_lists
5
4
 
6
5
  def new
@@ -32,8 +31,21 @@ class Iro::PositionsController < Iro::ApplicationController
32
31
  def edit
33
32
  @position = Iro::Position.find params[:id]
34
33
  authorize! :edit, @position
34
+ end
35
+
36
+ def roll
37
+ @position = Iro::Position.find params[:id]
38
+ authorize! :roll, @position
39
+
40
+ stock = @position.stock
35
41
 
36
- @strategies_list = Iro::Strategy.for_ticker( @position.ticker ).list
42
+ @positions = [
43
+ Iro::Position.new({ stock: stock, begin_inner_price: 5.21, inner_strike: 91, expires_on: '2024-04-05', gain_loss_amount: -1.25 }),
44
+ Iro::Position.new({ stock: stock, begin_inner_price: 5.77, inner_strike: 90, expires_on: '2024-04-05', gain_loss_amount: -0.7 }),
45
+ Iro::Position.new({ stock: stock, begin_inner_price: 6.4, inner_strike: 89, expires_on: '2024-04-05', gain_loss_amount: -0.03 }),
46
+ Iro::Position.new({ stock: stock, begin_inner_price: 6.85, inner_strike: 88, expires_on: '2024-04-05', gain_loss_amount: 0.6 }),
47
+ Iro::Position.new({ stock: stock, begin_inner_price: 7.07, inner_strike: 87, expires_on: '2024-04-05', gain_loss_amount: 1.22 }),
48
+ ]
37
49
  end
38
50
 
39
51
  def update
@@ -55,8 +67,8 @@ class Iro::PositionsController < Iro::ApplicationController
55
67
  private
56
68
 
57
69
  def set_lists
58
- @strategies_list = Iro::Strategy.list
59
- @tickers_list = Iro::Stock.tickers_list
70
+ @strategies_list = Iro::Strategy.list(params[:long_or_short])
71
+ @stocks_list = Iro::Stock.list
60
72
  end
61
73
 
62
74
  end
@@ -23,8 +23,6 @@ class Iro::PursesController < Iro::ApplicationController
23
23
  def edit
24
24
  @purse = Iro::Purse.find(params[:id])
25
25
  authorize! :edit, @purse
26
-
27
-
28
26
  end
29
27
 
30
28
  def index
@@ -36,7 +34,14 @@ class Iro::PursesController < Iro::ApplicationController
36
34
  @purse = Iro::Purse.find(params[:id])
37
35
  authorize! :show, @purse
38
36
 
39
- @positions = Iro::Position.all
37
+ @positions = @purse.positions.includes( :strategy
38
+ ).order({ expires_on: :desc })
39
+
40
+ @unit = 12 ## pixels per dollar
41
+ @height = 100 ## pixels
42
+ @grid_size = 75 ## dollars to each side of origin
43
+
44
+ render params[:template]
40
45
  end
41
46
 
42
47
  def update
@@ -3,11 +3,6 @@ class Iro::StrategiesController < Iro::ApplicationController
3
3
 
4
4
  before_action :set_lists
5
5
 
6
- def new
7
- @strategy = Iro::Strategy.new
8
- authorize! :new, @posision
9
- end
10
-
11
6
  def create
12
7
  @strategy = Iro::Strategy.new params[:strategy].permit!
13
8
  authorize! :create, @strategy
@@ -37,7 +32,12 @@ class Iro::StrategiesController < Iro::ApplicationController
37
32
  def index
38
33
  authorize! :index, Iro::Strategy
39
34
  @strategies = Iro::Strategy.all
40
- render '_table'
35
+ # render '_table'
36
+ end
37
+
38
+ def new
39
+ @strategy = Iro::Strategy.new
40
+ authorize! :new, @posision
41
41
  end
42
42
 
43
43
  def update
@@ -60,7 +60,7 @@ class Iro::StrategiesController < Iro::ApplicationController
60
60
 
61
61
  def set_lists
62
62
  @strategies_list = Iro::Strategy.list
63
- @tickers_list = Iro::Stock.tickers_list
63
+ @tickers_list = Iro::Stock.list
64
64
  end
65
65
 
66
66
  end
@@ -1,4 +1,7 @@
1
- module Iro
2
- module ApplicationHelper
1
+ module Iro::ApplicationHelper
2
+
3
+ def pp_delta delta
4
+ '%.2f' % delta rescue '-'
3
5
  end
6
+
4
7
  end
@@ -35,7 +35,8 @@ class Iro::Alert
35
35
  def do_run
36
36
  alert = self
37
37
  begin
38
- price = Tda::Stock.get_quote( alert.symbol ).last
38
+ price = Tda::Stock.get_quote( alert.symbol )&.last
39
+ return if !price
39
40
 
40
41
  if ( alert.direction == alert.class::DIRECTION_ABOVE && price >= alert.strike ) ||
41
42
  ( alert.direction == alert.class::DIRECTION_BELOW && price <= alert.strike )