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