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
@@ -0,0 +1,54 @@
1
+
2
+ namespace :test do
3
+
4
+ desc 'stock#volatility_mo'
5
+ task stock_vol_mo: :environment do
6
+ out = Iro::Stock.find_by( ticker: 'NVDA' ).volatility_from_mo
7
+ puts! out, 'out'
8
+ end
9
+
10
+ desc 'stock#volatility_yr'
11
+ task stock_vol_yr: :environment do
12
+ out = Iro::Stock.find_by( ticker: 'NVDA' ).volatility_from_yr
13
+ puts! out, 'out'
14
+ end
15
+
16
+ desc 'option#call_price'
17
+ task option_call_price: :environment do
18
+ stock = Iro::Stock.find_by( ticker: 'NVDA' )
19
+ stock.last = 884
20
+
21
+ option = Iro::Option.new({
22
+ stock: stock,
23
+ strike: 910,
24
+ expires_on: '2024-03-22',
25
+ # delta: 0.41,
26
+ })
27
+ out = option.put_price
28
+ puts! out, 'out'
29
+ end
30
+
31
+ desc 'place order'
32
+ task place_order: :environment do
33
+ stock = Iro::Stock.f 'GME'
34
+ outer = Iro::Option.new({
35
+ stock: stock,
36
+ put_call: 'CALL',
37
+ strike: 15.5,
38
+ expires_on: '2024-03-22',
39
+ })
40
+ inner = Iro::Option.new({
41
+ stock: stock,
42
+ put_call: 'CALL',
43
+ strike: 17.0,
44
+ expires_on: '2024-03-22',
45
+ })
46
+ out = Tda::Option.create_credit_call( inner: inner, outer: outer, q: 1, price: 0.01 )
47
+ puts! out, 'out'
48
+ end
49
+
50
+ end
51
+
52
+
53
+
54
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iron_warbler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7.22
4
+ version: 2.0.7.24
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Pudeyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-16 00:00:00.000000000 Z
11
+ date: 2024-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: business_time
@@ -192,20 +192,37 @@ dependencies:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
194
  version: 1.0.1
195
+ - !ruby/object:Gem::Dependency
196
+ name: distribution
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  description: A stocks and Options Trading Bot.
196
210
  email: victor@wasya.co
197
211
  executables: []
198
212
  extensions: []
199
213
  extra_rdoc_files: []
200
214
  files:
215
+ - README.txt
201
216
  - Rakefile
202
217
  - app/assets/config/iron_warbler_manifest.js
203
218
  - app/assets/javascript/iron_warbler/application.js
204
219
  - app/assets/javascript/iron_warbler/gameui.js
205
220
  - app/assets/stylesheets/iron_warbler/application.css
206
221
  - app/assets/stylesheets/iron_warbler/positions.scss
222
+ - app/assets/stylesheets/iron_warbler/positions_gameui.scss
207
223
  - app/assets/stylesheets/iron_warbler/purses_gameui.scss
208
224
  - app/assets/stylesheets/iron_warbler/purses_gameui.scss-bk
225
+ - app/assets/stylesheets/iron_warbler/purses_summary.scss
209
226
  - app/assets/stylesheets/iron_warbler/utils.scss
210
227
  - app/controllers/iro/alerts_controller.rb
211
228
  - app/controllers/iro/api/stocks_controller.rb
@@ -230,8 +247,6 @@ files:
230
247
  - app/models/iro/purse.rb
231
248
  - app/models/iro/stock.rb
232
249
  - app/models/iro/strategy.rb
233
- - app/models/iro/trash/position_covered_call.rb
234
- - app/models/iro/trash/position_debit_spread.rb
235
250
  - app/models/tda/option.rb
236
251
  - app/models/tda/stock.rb
237
252
  - app/views/iro/_analytics.erb
@@ -251,15 +266,20 @@ files:
251
266
  - app/views/iro/positions/_header_covered_call.haml
252
267
  - app/views/iro/positions/_header_long_debit_call_spread.haml
253
268
  - app/views/iro/positions/_header_short_debit_put_spread.haml
269
+ - app/views/iro/positions/_prepare_covered_call.haml
270
+ - app/views/iro/positions/_prepare_long_debit_call_spread.haml
271
+ - app/views/iro/positions/_prepare_short_debit_put_spread.haml
254
272
  - app/views/iro/positions/_reasons.haml
255
273
  - app/views/iro/positions/_table.haml
256
274
  - app/views/iro/positions/edit.haml
257
275
  - app/views/iro/positions/new.haml
258
- - app/views/iro/positions/roll.haml
259
- - app/views/iro/positions/trash/_header_short_debit_put_spread.haml
276
+ - app/views/iro/positions/prepare.haml
277
+ - app/views/iro/positions/roll-cc.haml-bk
278
+ - app/views/iro/positions/roll.haml-trash
260
279
  - app/views/iro/purses/_form.haml
261
280
  - app/views/iro/purses/_form_extra_fields.haml
262
281
  - app/views/iro/purses/_header.haml
282
+ - app/views/iro/purses/_summary.haml
263
283
  - app/views/iro/purses/edit.haml
264
284
  - app/views/iro/purses/gameui.haml
265
285
  - app/views/iro/purses/gameui.haml-bk
@@ -277,6 +297,7 @@ files:
277
297
  - app/views/iro/strategies/edit.haml
278
298
  - app/views/iro/strategies/index.haml
279
299
  - app/views/iro/strategies/new.haml
300
+ - app/views/iro/strategies/show.haml
280
301
  - app/views/layouts/iro/application.haml
281
302
  - config/initializers/assets.rb
282
303
  - config/routes.rb
@@ -285,6 +306,7 @@ files:
285
306
  - lib/tasks/db_tasks.rake
286
307
  - lib/tasks/iro_tasks.rake
287
308
  - lib/tasks/iro_tasks.rake-old
309
+ - lib/tasks/test_tasks.rake
288
310
  homepage: https://wasya.co
289
311
  licenses:
290
312
  - Proprietary
@@ -1,4 +0,0 @@
1
-
2
- class Iro::PositionCoveredCall < Iro::Position
3
-
4
- end
@@ -1,251 +0,0 @@
1
-
2
- class Iro::PositionDebitSpread < Iro::Positin
3
- include Mongoid::Document
4
- include Mongoid::Timestamps
5
- store_in collection: 'iro_positions'
6
-
7
- STATUS_ACTIVE = 'active'
8
- STATUS_PROPOSED = 'proposed'
9
- STATUSES = [ nil, 'active', 'inactive', 'proposed' ]
10
- field :status
11
- validates :status, presence: true
12
- scope :active, ->{ where( status: 'active' ) }
13
-
14
- belongs_to :purse, class_name: 'Iro::Purse', inverse_of: :positions
15
- index({ purse_id: 1, ticker: 1 })
16
-
17
- belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :positions
18
- def ticker
19
- stock&.ticker || '-'
20
- end
21
-
22
- belongs_to :strategy, class_name: 'Iro::Strategy', inverse_of: :positions
23
-
24
- field :outer_strike, type: :float
25
- validates :outer_strike, presence: true
26
-
27
- field :inner_strike, type: :float
28
- validates :inner_strike, presence: true
29
-
30
- field :expires_on
31
- validates :expires_on, presence: true
32
-
33
- field :quantity, type: :integer
34
- validates :quantity, presence: true
35
-
36
- field :begin_on
37
- field :begin_outer_price, type: :float
38
- field :begin_outer_delta, type: :float
39
-
40
- field :begin_inner_price, type: :float
41
- field :begin_inner_delta, type: :float
42
-
43
- field :end_on
44
- field :end_outer_price, type: :float
45
- field :end_outer_delta, type: :float
46
-
47
- field :end_inner_price, type: :float
48
- field :end_inner_delta, type: :float
49
-
50
- field :net_amount
51
- field :net_percent
52
-
53
- def current_underlying_strike
54
- Iro::Stock.find_by( ticker: ticker ).last
55
- end
56
-
57
- def refresh
58
- out = Tda::Option.get_quote({
59
- contractType: 'CALL',
60
- strike: strike,
61
- expirationDate: expires_on,
62
- ticker: ticker,
63
- })
64
- update({
65
- end_delta: out[:delta],
66
- end_price: out[:last],
67
- })
68
- print '_'
69
- end
70
-
71
- def net_amount # total
72
- outer = 0 - begin_outer_price + end_outer_price
73
- inner = begin_inner_price - end_inner_price
74
- out = ( outer + inner ) * 100 * quantity
75
- end
76
- def max_gain # total
77
- 100 * ( begin_outer_price - begin_inner_price ) * quantity
78
- end
79
- def max_loss
80
- out = 100 * ( outer_strike - inner_strike ) * quantity
81
- if strategy.long_or_short == Iro::Strategy::SHORT
82
- out = out * -1
83
- end
84
- return out
85
- end
86
-
87
-
88
- field :next_delta, type: :float
89
- field :next_outcome, type: :float
90
- field :next_symbol
91
- field :next_mark
92
- field :next_reasons, type: :array, default: []
93
- field :should_rollp, type: :float
94
-
95
- ##
96
- ## decisions
97
- ##
98
-
99
- def should_roll?
100
- puts! 'shold_roll?'
101
-
102
- update({
103
- next_reasons: [],
104
- next_symbol: nil,
105
- next_delta: nil,
106
- })
107
-
108
- if must_roll?
109
- out = 1.0
110
- elsif can_roll?
111
-
112
- if end_delta < strategy.threshold_delta
113
- next_reasons.push "delta is lower than threshold"
114
- out = 0.91
115
- elsif 1 - end_outer_price/begin_outer_price > strategy.threshold_netp
116
- next_reasons.push "made enough percent profit (dubious)"
117
- out = 0.61
118
- else
119
- next_reasons.push "neutral"
120
- out = 0.33
121
- end
122
-
123
- else
124
- out = 0.0
125
- end
126
-
127
- update({
128
- next_delta: next_position[:delta],
129
- next_outcome: next_position[:mark] - end_price,
130
- next_symbol: next_position[:symbol],
131
- next_mark: next_position[:mark],
132
- should_rollp: out,
133
- # status: Iro::Position::STATE_PROPOSED,
134
- })
135
-
136
- puts! next_reasons, 'next_reasons'
137
- puts! out, 'out'
138
- return out > 0.5
139
- end
140
-
141
-
142
- ## expires_on = cc.expires_on ; nil
143
- def can_roll?
144
- ## only if less than 7 days left
145
- ( expires_on.to_date - Time.now.to_date ).to_i < 7
146
- end
147
-
148
- ## If I'm near below water
149
- ##
150
- ## expires_on = cc.expires_on ; strategy = cc.strategy ; strike = cc.strike ; nil
151
- def must_roll?
152
- if ( current_underlying_strike + strategy.buffer_above_water ) > strike
153
- return true
154
- end
155
- ## @TODO: This one should not happen, I should log appropriately. _vp_ 2023-03-19
156
- if ( expires_on.to_date - Time.now.to_date ).to_i < 1
157
- return true
158
- end
159
- end
160
-
161
- ## strike = cc.strike ; strategy = cc.strategy ; nil
162
- def near_below_water?
163
- strike < current_underlying_strike + strategy.buffer_above_water
164
- end
165
-
166
-
167
-
168
- ## 2023-03-18 _vp_ Continue.
169
- ## 2023-03-19 _vp_ Continue.
170
- ## 2023-08-05 _vp_ an Important method
171
- ##
172
- ## expires_on = cc.expires_on ; strategy = cc.strategy ; ticker = cc.ticker ; end_price = cc.end_price ; next_expires_on = cc.next_expires_on ; nil
173
- ##
174
- ## out.map { |p| [ p[:strikePrice], p[:delta] ] }
175
- ##
176
- def next_position
177
- return @next_position if @next_position
178
- return {} if ![ STATUS_ACTIVE, STATUS_PROPOSED ].include?( status )
179
-
180
- ## 7 days ahead - not configurable so far
181
- out = Tda::Option.get_quotes({
182
- ticker: ticker,
183
- expirationDate: next_expires_on,
184
- contractType: 'CALL',
185
- })
186
-
187
- ## above_water
188
- if strategy.buffer_above_water.present?
189
- out = out.select do |i|
190
- i[:strikePrice] > current_underlying_strike + strategy.buffer_above_water
191
- end
192
- # next_reasons.push "buffer_above_water above #{current_underlying_strike + strategy.buffer_above_water}"
193
- end
194
-
195
- if near_below_water?
196
- msg = "Panic! climb at a loss. Skip the rest of the calculation."
197
- next_reasons.push msg
198
- ## @TODO: if not enough money in the purse, cannot roll? 2023-03-19
199
-
200
- # byebug
201
-
202
- ## Take a small loss here.
203
- prev = nil
204
- out.each_with_index do |i, idx|
205
- next if idx == 0
206
- if i[:last] < end_price
207
- prev ||= i
208
- end
209
- end
210
- out = [ prev ]
211
-
212
- else
213
- ## Normal flow, making money.
214
- ## @TODO: test! _vp_ 2023-03-19
215
-
216
- ## next_min_strike
217
- if strategy.next_min_strike.present?
218
- out = out.select do |i|
219
- i[:strikePrice] >= strategy.next_min_strike
220
- end
221
- # next_reasons.push "next_min_strike above #{strategy.next_min_strike}"
222
- end
223
- # json_puts! out.map { |p| [p[:delta], p[:symbol]] }, 'next_min_strike'
224
-
225
- ## max_delta
226
- if strategy.next_max_delta.present?
227
- out = out.select do |i|
228
- i[:delta] = 0.0 if i[:delta] == "NaN"
229
- i[:delta] <= strategy.next_max_delta
230
- end
231
- # next_reasons.push "next_max_delta below #{strategy.next_max_delta}"
232
- end
233
- # json_puts! out.map { |p| [p[:delta], p[:symbol]] }, 'next_max_delta'
234
- end
235
-
236
- @next_position = out[0] || {}
237
- end
238
-
239
- ## @TODO: Test this. _vp_ 2023-04-01
240
- def next_expires_on
241
- out = expires_on.to_time + 7.days
242
- while !out.friday?
243
- out = out + 1.day
244
- end
245
- while !out.workday?
246
- out = out - 1.day
247
- end
248
- return out
249
- end
250
-
251
- end
@@ -1,83 +0,0 @@
1
-
2
- - u = @purse.unit # 50 ## pixels per dollar
3
- - strategy = @position.strategy
4
-
5
- .purses-gameui.padded
6
- = render '/iro/purses/header', purse: @position.purse
7
-
8
- .a
9
- - position = @position
10
- - stock = position.stock
11
- %h4= stock
12
-
13
- .header
14
- = position.quantity
15
- = stock
16
- = position.expires_on.to_datetime.strftime("%b %d")
17
- = link_to '[roll]', roll_position_path(position)
18
- = link_to '[~]', edit_position_path(position)
19
-
20
- - nearest_strike = stock.last.round
21
- .StockCoordinatesW
22
-
23
- .StockCoordinates
24
- .grid-mark.mark0
25
- .label= nearest_strike
26
- - (1...@n_dollars).each_with_index do |idx|
27
- .grid-mark{ class: "mark#{idx}", style: "left: -#{idx * u}px" }
28
- .label
29
- = nearest_strike + idx
30
- .grid-mark{ class: "mark-#{idx}", style: "left: #{idx * u}px" }
31
- .label
32
- = nearest_strike - idx
33
- .Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
34
- .label
35
- Last:
36
- = stock.last
37
-
38
-
39
- .PositionW{ style: "width: #{ position.begin_inner_price * u}px; left: #{ (stock.last - position.inner_strike - position.begin_inner_price) * u}px" }
40
-
41
- .Position
42
- - if position.net_amount >= 0
43
- .Net.NetPositive{ style: "width: #{ (position.net_amount / 100) * u }px; right: 0" }
44
- .label
45
- net
46
- = pp_amount position.net_amount
47
- - else
48
- .Net.NetNegative{ style: "width: #{ (-1 * position.net_amount / 100) * u }px; left: 100%" }
49
- .label
50
- net
51
- = pp_amount position.net_amount
52
- .c
53
-
54
- - @positions.each do |position|
55
- .reviewing
56
- - stock = position.stock
57
- - nearest_strike = stock.last.round
58
- .StockCoordinatesW
59
- .StockCoordinates
60
- .grid-mark.mark0
61
- .label= nearest_strike
62
- - (1...@n_dollars).each_with_index do |idx|
63
- .grid-mark{ class: "mark#{idx}", style: "left: -#{idx * u}px" }
64
- .label
65
- = nearest_strike + idx
66
- .grid-mark{ class: "mark-#{idx}", style: "left: #{idx * u}px" }
67
- .label
68
- = nearest_strike - idx
69
- .Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
70
- .label
71
- Last:
72
- = stock.last
73
- - amnt = position.gain_loss_amount
74
- - border = amnt >= 0 ? "#{amnt * u}px solid green" : "#{amnt * -1 * u}px solid red"
75
- .PositionW{ style: "width: #{ position.begin_inner_price * u}px; left: #{ (stock.last - position.inner_strike - position.begin_inner_price) * u}px; border: #{border}; border-bottom-width: 2px" }
76
- .Position
77
- .c
78
-
79
-
80
-
81
-
82
- %br
83
- %br
@@ -1,9 +0,0 @@
1
-
2
- .maxwidth
3
- %ul.m-0.p-0
4
- %li <b>outer,inner_strike:</b> #{pp_amount pos.outer_strike} -> #{pp_amount pos.inner_strike}
5
- %li
6
- <b>begin_outer,inner_price:</b> #{pp_amount pos.begin_outer_price} -> #{pp_amount pos.begin_inner_price}
7
- &nbsp;&nbsp;
8
- <b>max gain:</b> #{pp_amount pos.max_gain}
9
- %li <b>Net:</b> #{pp_amount pos.net_amount} &nbsp;&nbsp; <i>#{pp_percent pos.net_percent}</i>