iron_warbler 2.0.7.43 → 2.0.7.45
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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/iron_warbler/utils.scss +9 -9
- data/app/controllers/iro/positions_controller.rb +1 -0
- data/app/controllers/iro/purses_controller.rb +3 -1
- data/app/controllers/iro/strategies_controller.rb +8 -3
- data/app/views/iro/positions/_form.haml +1 -1
- data/app/views/iro/positions/{_gameui_long_debit_call_spread.haml-trash → _gameui_spread.haml} +9 -8
- data/app/views/iro/positions/_header_spread.haml +12 -0
- data/app/views/iro/positions/_new.haml +4 -0
- data/app/views/iro/positions/done/_gameui_short_debit_put_spread.haml +1 -0
- data/app/views/iro/positions/done/_header_short_debit_put_spread.haml +1 -0
- data/app/views/iro/purses/_form.haml +3 -3
- data/app/views/iro/purses/index.haml +3 -2
- data/app/views/iro/strategies/_form_spread.haml +69 -0
- data/app/views/iro/strategies/{_form.haml → _form_wheel.haml} +12 -12
- data/app/views/iro/strategies/_header.haml +2 -1
- data/app/views/iro/strategies/_table.haml +3 -5
- data/app/views/iro/strategies/edit.haml +1 -1
- data/app/views/iro/strategies/index.haml +2 -1
- data/app/views/iro/strategies/new.haml +1 -1
- data/app/views/layouts/iro/application.haml +1 -1
- data/config/routes.rb +2 -0
- data/lib/iron_warbler.rb +2 -1
- data/lib/tasks/iro_tasks.rake +6 -0
- metadata +20 -30
- data/app/models/iro/alert.rb +0 -63
- data/app/models/iro/datapoint.rb +0 -187
- data/app/models/iro/date.rb +0 -10
- data/app/models/iro/option.rb +0 -151
- data/app/models/iro/option_black_scholes.rb +0 -149
- data/app/models/iro/position.rb +0 -299
- data/app/models/iro/priceitem.rb +0 -93
- data/app/models/iro/purse.rb +0 -72
- data/app/models/iro/stock.rb +0 -134
- data/app/models/iro/strategy.rb +0 -264
- data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +0 -1
- data/app/views/iro/positions/_gameui_short_debit_put_spread.haml-trash +0 -40
- data/app/views/iro/positions/_header_short_debit_put_spread.haml +0 -1
- data/app/views/iro/positions/roll.haml-trash +0 -42
- /data/app/views/iro/positions/{_gameui_covered_call.haml-bk → done/_gameui_covered_call.haml-bk} +0 -0
- /data/app/views/iro/positions/{_gameui_long_credit_put_spread.haml → done/_gameui_long_credit_put_spread.haml} +0 -0
- /data/app/views/iro/positions/{_gameui_long_debit_call_spread.haml → done/_gameui_long_debit_call_spread.haml} +0 -0
- /data/app/views/iro/positions/{_gameui_short_credit_call_spread.haml → done/_gameui_short_credit_call_spread.haml} +0 -0
- /data/app/views/iro/positions/{_header_long_credit_put_spread.haml → done/_header_long_credit_put_spread.haml} +0 -0
- /data/app/views/iro/positions/{_header_long_debit_call_spread.haml → done/_header_long_debit_call_spread.haml} +0 -0
- /data/app/views/iro/positions/{_header_short_credit_call_spread.haml → done/_header_short_credit_call_spread.haml} +0 -0
- /data/app/views/iro/positions/{roll-cc.haml-bk → done/roll-cc.haml-bk} +0 -0
- /data/app/views/iro/purses/{gameui.haml-bk → done/gameui.haml-bk} +0 -0
- /data/app/views/iro/purses/{gameui.haml-bk2 → done/gameui.haml-bk2} +0 -0
- /data/app/views/iro/stocks/{_grid_is_long.haml → _grid_long.haml} +0 -0
- /data/app/views/iro/stocks/{_grid_is_short.haml → _grid_short.haml} +0 -0
data/app/models/iro/strategy.rb
DELETED
@@ -1,264 +0,0 @@
|
|
1
|
-
|
2
|
-
class Iro::Strategy
|
3
|
-
include Mongoid::Document
|
4
|
-
include Mongoid::Timestamps
|
5
|
-
include Mongoid::Paranoia
|
6
|
-
store_in collection: 'iro_strategies'
|
7
|
-
|
8
|
-
field :slug
|
9
|
-
validates :slug, presence: true, uniqueness: true
|
10
|
-
|
11
|
-
field :description
|
12
|
-
|
13
|
-
LONG = 'is_long'
|
14
|
-
SHORT = 'is_short'
|
15
|
-
field :long_or_short, type: :string
|
16
|
-
validates :long_or_short, presence: true
|
17
|
-
|
18
|
-
|
19
|
-
has_many :positions, class_name: 'Iro::Position', inverse_of: :strategy
|
20
|
-
has_one :next_position, class_name: 'Iro::Position', inverse_of: :next_strategy
|
21
|
-
belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
|
22
|
-
has_and_belongs_to_many :purses, class_name: 'Iro::Purse', inverse_of: :strategies
|
23
|
-
|
24
|
-
KIND_COVERED_CALL = 'covered_call'
|
25
|
-
KIND_IRON_CONDOR = 'iron_condor'
|
26
|
-
KIND_LONG_CREDIT_PUT_SPREAD = 'long_credit_put_spread'
|
27
|
-
KIND_LONG_DEBIT_CALL_SPREAD = 'long_debit_call_spread'
|
28
|
-
KIND_SHORT_CREDIT_CALL_SPREAD = 'short_credit_call_spread'
|
29
|
-
KIND_SHORT_DEBIT_PUT_SPREAD = 'short_debit_put_spread'
|
30
|
-
KINDS = [ nil,
|
31
|
-
KIND_COVERED_CALL,
|
32
|
-
KIND_IRON_CONDOR,
|
33
|
-
KIND_LONG_CREDIT_PUT_SPREAD,
|
34
|
-
KIND_LONG_DEBIT_CALL_SPREAD,
|
35
|
-
KIND_SHORT_CREDIT_CALL_SPREAD,
|
36
|
-
KIND_SHORT_DEBIT_PUT_SPREAD,
|
37
|
-
];
|
38
|
-
field :kind
|
39
|
-
|
40
|
-
def put_call
|
41
|
-
case kind
|
42
|
-
when Iro::Strategy::KIND_LONG_CREDIT_PUT_SPREAD
|
43
|
-
put_call = 'PUT'
|
44
|
-
when Iro::Strategy::KIND_LONG_DEBIT_CALL_SPREAD
|
45
|
-
put_call = 'CALL'
|
46
|
-
when Iro::Strategy::KIND_SHORT_CREDIT_CALL_SPREAD
|
47
|
-
put_call = 'CALL'
|
48
|
-
when Iro::Strategy::KIND_SHORT_DEBIT_PUT_SPREAD
|
49
|
-
put_call = 'PUT'
|
50
|
-
when Iro::Strategy::KIND_COVERED_CALL
|
51
|
-
put_call = 'CALL'
|
52
|
-
else
|
53
|
-
throw 'zz9 - this should never happen'
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
field :threshold_buffer_above_water, type: :float
|
58
|
-
field :threshold_delta, type: :float
|
59
|
-
field :threshold_netp, type: :float
|
60
|
-
field :threshold_dte, type: :integer, default: 1
|
61
|
-
|
62
|
-
field :next_inner_delta, type: :float
|
63
|
-
field :next_inner_strike, type: :float
|
64
|
-
field :next_outer_delta, type: :float
|
65
|
-
field :next_outer_strike, type: :float
|
66
|
-
field :next_spread_amount, type: :float # e.g. $20 for a $2000 NVDA spread
|
67
|
-
field :next_buffer_above_water, type: :float
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
def begin_delta_covered_call p
|
75
|
-
p.inner.begin_delta
|
76
|
-
end
|
77
|
-
def begin_delta_long_credit_put_spread p
|
78
|
-
p.inner.begin_delta - p.outer.begin_delta
|
79
|
-
end
|
80
|
-
def begin_delta_long_debit_call_spread p
|
81
|
-
p.outer.begin_delta - p.inner.begin_delta
|
82
|
-
end
|
83
|
-
alias_method :begin_delta_short_debit_put_spread, :begin_delta_long_debit_call_spread
|
84
|
-
alias_method :begin_delta_short_credit_call_spread, :begin_delta_long_debit_call_spread
|
85
|
-
|
86
|
-
|
87
|
-
def breakeven_covered_call p
|
88
|
-
p.inner.strike + p.inner.begin_price
|
89
|
-
end
|
90
|
-
def breakeven_long_debit_call_spread p
|
91
|
-
p.inner.strike - p.max_gain
|
92
|
-
end
|
93
|
-
alias_method :breakeven_short_debit_put_spread, :breakeven_long_debit_call_spread
|
94
|
-
|
95
|
-
|
96
|
-
def end_delta_covered_call p
|
97
|
-
p.inner.end_delta
|
98
|
-
end
|
99
|
-
def end_delta_long_credit_put_spread p
|
100
|
-
p.inner.end_delta - p.outer.end_delta
|
101
|
-
end
|
102
|
-
def end_delta_long_debit_call_spread p
|
103
|
-
p.outer.end_delta - p.inner.end_delta
|
104
|
-
end
|
105
|
-
alias_method :end_delta_short_debit_put_spread, :end_delta_long_debit_call_spread
|
106
|
-
alias_method :end_delta_short_credit_call_spread, :end_delta_long_debit_call_spread
|
107
|
-
|
108
|
-
|
109
|
-
def max_gain_covered_call p
|
110
|
-
p.inner.begin_price * 100 - 0.66 # @TODO: is this *100 really?
|
111
|
-
end
|
112
|
-
def max_gain_long_credit_put_spread p
|
113
|
-
## 100 * disallowed for gameui
|
114
|
-
p.inner.begin_price - p.outer.begin_price
|
115
|
-
end
|
116
|
-
def max_gain_long_debit_call_spread p
|
117
|
-
## 100 * disallowed for gameui
|
118
|
-
( p.inner.strike - p.outer.strike - p.outer.begin_price + p.inner.begin_price ) # - 2*0.66
|
119
|
-
end
|
120
|
-
def max_gain_short_credit_call_spread p
|
121
|
-
p.inner.begin_price - p.outer.begin_price
|
122
|
-
end
|
123
|
-
def max_gain_short_debit_put_spread p
|
124
|
-
## 100 * disallowed for gameui
|
125
|
-
( p.outer.strike - p.inner.strike - p.outer.begin_price + p.inner.begin_price ) # - 2*0.66
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
def max_loss_covered_call p
|
130
|
-
p.inner.begin_price*10 # just suppose 10,000%
|
131
|
-
end
|
132
|
-
def max_loss_long_credit_put_spread p
|
133
|
-
out = p.inner.strike - p.outer.strike
|
134
|
-
end
|
135
|
-
def max_loss_long_debit_call_spread p
|
136
|
-
out = p.outer.strike - p.inner.strike
|
137
|
-
end
|
138
|
-
def max_loss_short_debit_put_spread p # different
|
139
|
-
out = p.inner.strike - p.outer.strike
|
140
|
-
end
|
141
|
-
def max_loss_short_credit_call_spread p
|
142
|
-
out = p.outer.strike - p.inner.strike
|
143
|
-
end
|
144
|
-
|
145
|
-
|
146
|
-
def net_amount_covered_call p
|
147
|
-
( p.inner.begin_price - p.inner.end_price )
|
148
|
-
end
|
149
|
-
def net_amount_long_debit_call_spread p
|
150
|
-
outer = p.outer.end_price - p.outer.begin_price
|
151
|
-
inner = p.inner.begin_price - p.inner.end_price
|
152
|
-
out = ( outer + inner )
|
153
|
-
end
|
154
|
-
alias_method :net_amount_long_credit_put_spread , :net_amount_long_debit_call_spread
|
155
|
-
alias_method :net_amount_short_credit_call_spread , :net_amount_long_debit_call_spread
|
156
|
-
alias_method :net_amount_short_debit_put_spread, :net_amount_long_debit_call_spread
|
157
|
-
|
158
|
-
|
159
|
-
## 2024-05-09 @TODO
|
160
|
-
def next_inner_strike_on expires_on
|
161
|
-
outs = Tda::Option.get_quotes({
|
162
|
-
contractType: put_call,
|
163
|
-
expirationDate: expires_on,
|
164
|
-
ticker: stock.ticker,
|
165
|
-
})
|
166
|
-
end
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
##
|
171
|
-
## decisions
|
172
|
-
##
|
173
|
-
|
174
|
-
def calc_rollp_covered_call p
|
175
|
-
|
176
|
-
if ( p.expires_on.to_date - Time.now.to_date ).to_i < 1
|
177
|
-
return [ 0.99, '0 DTE, must exit' ]
|
178
|
-
end
|
179
|
-
|
180
|
-
if ( stock.last - buffer_above_water ) < p.inner.strike
|
181
|
-
return [ 0.98, "Last #{'%.2f' % stock.last} is " +
|
182
|
-
"#{'%.2f' % [p.inner.strike + buffer_above_water - stock.last]} " +
|
183
|
-
"below #{'%.2f' % [p.inner.strike + buffer_above_water]} water" ]
|
184
|
-
end
|
185
|
-
|
186
|
-
if p.inner.end_delta < threshold_delta
|
187
|
-
return [ 0.61, "Delta #{p.inner.end_delta} is lower than #{threshold_delta} threshold." ]
|
188
|
-
end
|
189
|
-
|
190
|
-
if 1 - p.inner.end_price/p.inner.begin_price > threshold_netp
|
191
|
-
return [ 0.51, "made enough #{'%.02f' % [(1.0 - p.inner.end_price/p.inner.begin_price )*100]}% profit." ]
|
192
|
-
end
|
193
|
-
|
194
|
-
return [ 0.33, '-' ]
|
195
|
-
end
|
196
|
-
|
197
|
-
## @TODO
|
198
|
-
def calc_rollp_long_debit_call_spread p
|
199
|
-
|
200
|
-
if ( p.expires_on.to_date - Time.now.to_date ).to_i < 1
|
201
|
-
return [ 0.99, '0 DTE, must exit' ]
|
202
|
-
end
|
203
|
-
if ( p.expires_on.to_date - Time.now.to_date ).to_i < 2
|
204
|
-
return [ 0.99, '1 DTE, must exit' ]
|
205
|
-
end
|
206
|
-
|
207
|
-
if ( stock.last - buffer_above_water ) < p.inner.strike
|
208
|
-
return [ 0.95, "Last #{'%.2f' % stock.last} is " +
|
209
|
-
"#{'%.2f' % [stock.last - p.inner.strike - buffer_above_water]} " +
|
210
|
-
"below #{'%.2f' % [p.inner.strike + buffer_above_water]} water" ]
|
211
|
-
end
|
212
|
-
|
213
|
-
if p.inner.end_delta < threshold_delta
|
214
|
-
return [ 0.79, "Delta #{p.inner.end_delta} is lower than #{threshold_delta} threshold." ]
|
215
|
-
end
|
216
|
-
|
217
|
-
if 1 - p.inner.end_price/p.inner.begin_price > threshold_netp
|
218
|
-
return [ 0.51, "made enough #{'%.02f' % [(1.0 - p.inner.end_price/p.inner.begin_price )*100]}% profit^" ]
|
219
|
-
end
|
220
|
-
|
221
|
-
return [ 0.33, '-' ]
|
222
|
-
end
|
223
|
-
|
224
|
-
## @TODO
|
225
|
-
def calc_rollp_short_debit_put_spread p
|
226
|
-
|
227
|
-
if ( p.expires_on.to_date - Time.now.to_date ).to_i <= min_dte
|
228
|
-
return [ 0.99, "< #{min_dte}DTE, must exit" ]
|
229
|
-
end
|
230
|
-
|
231
|
-
if stock.last + buffer_above_water > p.inner.strike
|
232
|
-
return [ 0.98, "Last #{'%.2f' % stock.last} is " +
|
233
|
-
"#{'%.2f' % [stock.last + buffer_above_water - p.inner.strike]} " +
|
234
|
-
"above #{'%.2f' % [p.inner.strike - buffer_above_water]} water" ]
|
235
|
-
end
|
236
|
-
|
237
|
-
if p.inner.end_delta.abs < threshold_delta.abs
|
238
|
-
return [ 0.79, "Delta #{p.inner.end_delta} is lower than #{threshold_delta} threshold." ]
|
239
|
-
end
|
240
|
-
|
241
|
-
if p.net_percent > threshold_netp
|
242
|
-
return [ 0.51, "made enough #{'%.0f' % [p.net_percent*100]}% > #{"%.2f" % [threshold_netp*100]}% profit," ]
|
243
|
-
end
|
244
|
-
|
245
|
-
return [ 0.33, '-' ]
|
246
|
-
end
|
247
|
-
|
248
|
-
|
249
|
-
## scopes
|
250
|
-
|
251
|
-
def self.for_ticker ticker
|
252
|
-
where( ticker: ticker )
|
253
|
-
end
|
254
|
-
|
255
|
-
|
256
|
-
def to_s
|
257
|
-
slug
|
258
|
-
end
|
259
|
-
def self.list long_or_short = nil
|
260
|
-
these = long_or_short ? where( long_or_short: long_or_short ) : all
|
261
|
-
[[nil,nil]] + these.map { |ttt| [ ttt, ttt.id ] }
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
@@ -1 +0,0 @@
|
|
1
|
-
app/views/iro/positions/_gameui_long_debit_call_spread.haml
|
@@ -1,40 +0,0 @@
|
|
1
|
-
|
2
|
-
- pos = position
|
3
|
-
- stock = pos.stock
|
4
|
-
- nearest_strike = stock.last.round
|
5
|
-
- u = pos.purse.unit # pixels per dollar
|
6
|
-
|
7
|
-
|
8
|
-
.collapse-expand.d-flex{ id: "gameui-pos-#{pos.id}" }
|
9
|
-
[<>]
|
10
|
-
.maxwidth= render "/iro/positions/header", pos: pos
|
11
|
-
.a
|
12
|
-
= render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
|
13
|
-
.StockCoordinatesW
|
14
|
-
.StockCoordinates{ style: "height: #{pos.q() *u}px " }
|
15
|
-
.grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
|
16
|
-
|
17
|
-
.Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
|
18
|
-
.label Last: #{pp_amount stock.last}
|
19
|
-
.c
|
20
|
-
|
21
|
-
-## these are different
|
22
|
-
- left = "#{ ( stock.last - pos.outer.strike ) * u}px"
|
23
|
-
- width = "#{ ( pos.outer.strike - pos.inner.strike ) * u}px"
|
24
|
-
.PositionW{ class: pos.strategy.kind, style: "left: #{left}; width: #{width}; " }
|
25
|
-
.Position
|
26
|
-
.MaxGain{ style: "width: #{pos.max_gain * u}px" }
|
27
|
-
.RollGuide
|
28
|
-
|
29
|
-
- if pos.net_amount >= 0
|
30
|
-
.Net.NetPositive{ style: "width: #{ (pos.net_amount / 100) * u }px; right: 0" }
|
31
|
-
.label
|
32
|
-
net
|
33
|
-
= pp_amount pos.net_amount
|
34
|
-
- else
|
35
|
-
.Net.NetNegative{ style: "width: #{ (-1 * pos.net_amount / 100) * u }px; left: 100%" }
|
36
|
-
.label
|
37
|
-
net
|
38
|
-
= pp_amount pos.net_amount
|
39
|
-
.c
|
40
|
-
|
@@ -1 +0,0 @@
|
|
1
|
-
app/views/iro/positions/_header_long_debit_call_spread.haml
|
@@ -1,42 +0,0 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
-# .StockCoordinatesW
|
4
|
-
-# .StockCoordinates{ style: "height: #{pos.purse.height}px " }
|
5
|
-
|
6
|
-
-# .grid-mark.mark0
|
7
|
-
-# .label= nearest_strike
|
8
|
-
-# - (1...@n_dollars).each_with_index do |idx|
|
9
|
-
-# .grid-mark{ class: "mark#{idx}", style: "left: -#{idx * u}px" }
|
10
|
-
-# .label
|
11
|
-
-# = nearest_strike + idx
|
12
|
-
-# .grid-mark{ class: "mark-#{idx}", style: "left: #{idx * u}px" }
|
13
|
-
-# .label
|
14
|
-
-# = nearest_strike - idx
|
15
|
-
|
16
|
-
-# .Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
|
17
|
-
-# .label Last: #{pp_amount stock.last}
|
18
|
-
-# .c
|
19
|
-
|
20
|
-
-# - left = "#{ (stock.last - pos.inner_strike) * u}px"
|
21
|
-
-# - width = "0px"
|
22
|
-
-# .PositionW{ style: "left: #{left} ; width: #{width} " }
|
23
|
-
-# .Position
|
24
|
-
-# .PositionC
|
25
|
-
|
26
|
-
-# - if pos.net_amount >= 0
|
27
|
-
-# .Net.NetPositive{ style: "width: #{ (pos.net_amount / 100) * u }px; right: 0" }
|
28
|
-
-# .label
|
29
|
-
-# net
|
30
|
-
-# = pp_amount pos.net_amount
|
31
|
-
-# - else
|
32
|
-
-# .Net.NetNegative{ style: "width: #{ (-1 * pos.net_amount / 100) * u }px; left: 100%" }
|
33
|
-
-# .label
|
34
|
-
-# net
|
35
|
-
-# = pp_amount pos.net_amount
|
36
|
-
|
37
|
-
-# .Breakeven{ style: "width: #{ pos.begin_inner_price * u }px" }
|
38
|
-
-# .label
|
39
|
-
-# Breakeven:
|
40
|
-
-# = pos.begin_inner_price
|
41
|
-
-# .c
|
42
|
-
|
/data/app/views/iro/positions/{_gameui_covered_call.haml-bk → done/_gameui_covered_call.haml-bk}
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|