iron_warbler 2.0.7.50 → 2.0.7.52
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/positions.scss +1 -1
- data/app/assets/stylesheets/iron_warbler/purses_gameui.scss +52 -21
- data/app/assets/stylesheets/iron_warbler/purses_summary.scss +8 -1
- data/app/controllers/iro/application_controller.rb +9 -0
- data/app/controllers/iro/positions_controller.rb +119 -23
- data/app/controllers/iro/purses_controller.rb +7 -12
- data/app/controllers/iro/stocks_controller.rb +18 -4
- data/app/views/iro/_main_header.haml +6 -4
- data/app/views/iro/positions/_gameui_covered_call.haml +0 -6
- data/app/views/iro/positions/_gameui_long_credit_put_spread.haml +4 -2
- data/app/views/iro/positions/_gameui_short_credit_call_spread.haml +4 -2
- data/app/views/iro/positions/_header.haml +5 -3
- data/app/views/iro/positions/_header_short_credit_call_spread.haml +2 -2
- data/app/views/iro/positions/_prepare_header_long_credit_put_spread.haml +8 -8
- data/app/views/iro/positions/_prepare_header_short_credit_call_spread.haml +8 -10
- data/app/views/iro/positions/_table.haml +4 -0
- data/app/views/iro/positions/_table_fast.haml +150 -0
- data/app/views/iro/positions/_table_tr_long_credit_put_spread.haml +8 -4
- data/app/views/iro/positions/_vcfg_form.haml +28 -0
- data/app/views/iro/positions/close_prep2.haml +24 -0
- data/app/views/iro/positions/index.haml +7 -1
- data/app/views/iro/positions/prepare2.haml +4 -1
- data/app/views/iro/purses/_form.haml +4 -0
- data/app/views/iro/purses/_gameui_fast.haml +23 -0
- data/app/views/iro/purses/_header.haml +6 -11
- data/app/views/iro/purses/_summary2.haml +2 -1
- data/app/views/iro/purses/gameui.haml +3 -2
- data/app/views/iro/purses/table.haml +5 -0
- data/app/views/iro/stocks/index.haml +15 -7
- data/app/views/iro/stocks/show.haml +30 -12
- data/app/views/iro/strategies/_form_spread.haml +9 -1
- data/app/views/iro/strategies/_table.haml +11 -4
- data/app/views/iro/strategies/index.haml +1 -1
- data/config/routes.rb +19 -17
- data/lib/iron_warbler.rb +10 -0
- data/lib/tasks/coins_tasks.rake-bk +114 -0
- data/lib/tasks/iro_tasks.rake +21 -96
- data/lib/tasks/old_tasks.rake +32 -0
- data/lib/tasks/positions_tasks.rake +172 -0
- data/lib/tasks/treasuries_tasks.rake-bk +114 -0
- metadata +26 -7
- data/app/assets/stylesheets/iron_warbler/purses_gameui.scss-bk +0 -112
- data/app/views/iro/positions/_header_spread.haml +0 -30
- data/app/views/iro/purses/done/gameui.haml-bk +0 -44
- data/app/views/iro/purses/done/gameui.haml-bk2 +0 -89
- /data/app/views/iro/purses/{show.haml → _show_fast.haml} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c0703c3e0ebcb7c822c9a20d2b15d0c2793f85c19e15f117eee26e9b31d8550e
|
|
4
|
+
data.tar.gz: 62926b4b746be26e4415d3f9daad710cd24f052c3405c10127d0ca324f41b474
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3749f60970e6476f1679d8adf4388c2a7ebdc033b74e63b8baf4aa466dc2a808c04597594286f9e25a9e094909a1ba76194a94225095cebabf4114b179883be6
|
|
7
|
+
data.tar.gz: b2a1469adf02dc2cb227893d088afb6268b03c9b01a7b784eefbea01f1219efa448707b00f2b83fa42c41d012968dd4a0a1ed53eda7dfba5189872f06f2d25b7
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
.purses-gameuiW {
|
|
3
|
-
border: 1px solid
|
|
3
|
+
border: 1px solid #333;
|
|
4
4
|
width: 100%;
|
|
5
5
|
// overflow-x: scroll;
|
|
6
6
|
overflow-y: hidden;
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
.divider-expiry {
|
|
12
12
|
height: 5px;
|
|
13
13
|
width: 100%;
|
|
14
|
-
background:
|
|
14
|
+
background: #333;
|
|
15
15
|
}
|
|
16
16
|
.divider-ticker {
|
|
17
17
|
height: 2px;
|
|
18
18
|
width: 100%;
|
|
19
|
-
background:
|
|
19
|
+
background: #333;
|
|
20
20
|
margin-bottom: 20px;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -53,15 +53,55 @@
|
|
|
53
53
|
width: 5px;
|
|
54
54
|
background: yellow;
|
|
55
55
|
}
|
|
56
|
-
.PositionW.short_debit_put_spread {
|
|
57
|
-
background: rgba(255,153,0, 0.25);
|
|
58
|
-
}
|
|
59
56
|
.PositionW {
|
|
60
57
|
top: 0;
|
|
61
58
|
border: 2px solid black;
|
|
62
|
-
|
|
59
|
+
|
|
63
60
|
position: absolute;
|
|
64
61
|
height: 100%;
|
|
62
|
+
|
|
63
|
+
.Position {
|
|
64
|
+
position: absolute;
|
|
65
|
+
left: 0;
|
|
66
|
+
top: 0;
|
|
67
|
+
|
|
68
|
+
width: 100%;
|
|
69
|
+
height: 100%;
|
|
70
|
+
|
|
71
|
+
.Quantities {
|
|
72
|
+
// background: rgba(0,0,0, 0.1);
|
|
73
|
+
|
|
74
|
+
width: 33%;
|
|
75
|
+
height: 100%;
|
|
76
|
+
position: absolute;
|
|
77
|
+
|
|
78
|
+
display: flex;
|
|
79
|
+
justify-content: space-evenly;
|
|
80
|
+
flex-direction: column;
|
|
81
|
+
|
|
82
|
+
.item {
|
|
83
|
+
width: 100%;
|
|
84
|
+
border-bottom: 1px solid #333;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
.PositionW.long_credit_put_spread {
|
|
92
|
+
background: linear-gradient(to left, rgba(0,255,255, 0.6), transparent);
|
|
93
|
+
// background: linear-gradient(to left, rgba(0,0,0, 0.5), transparent);
|
|
94
|
+
.Quantities {
|
|
95
|
+
left: 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
.PositionW.short_credit_call_spread {
|
|
99
|
+
background: linear-gradient(to right, rgba(0,255,255, 0.5), transparent);
|
|
100
|
+
background: linear-gradient(to right, rgba(0,0,0, 0.5), transparent);
|
|
101
|
+
background: linear-gradient(to right, rgba(236,164,60, 0.6), transparent);
|
|
102
|
+
.Quantities {
|
|
103
|
+
right: 0;
|
|
104
|
+
}
|
|
65
105
|
}
|
|
66
106
|
.reviewing {
|
|
67
107
|
.PositionW {
|
|
@@ -70,23 +110,14 @@
|
|
|
70
110
|
}
|
|
71
111
|
}
|
|
72
112
|
|
|
73
|
-
.
|
|
74
|
-
position: absolute;
|
|
75
|
-
left: 0;
|
|
76
|
-
top: 0;
|
|
77
|
-
|
|
78
|
-
width: 100%;
|
|
79
|
-
height: 100%;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.MaxGain,
|
|
84
|
-
.Breakeven {
|
|
113
|
+
.MaxGain {
|
|
85
114
|
position: absolute;
|
|
86
115
|
right: 0;
|
|
87
116
|
bottom: 0;
|
|
88
|
-
border: 2px dotted
|
|
89
|
-
|
|
117
|
+
border: 2px dotted #eee;
|
|
118
|
+
border: 2px dotted rgb(61,98,66);
|
|
119
|
+
background: rgba(255,255,255, 0.5);
|
|
120
|
+
background: rgba(61,98,66, 0.5);
|
|
90
121
|
height: 25%;
|
|
91
122
|
}
|
|
92
123
|
.PositionW.is-short .MaxGain {
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
.purses--summary2 {
|
|
6
6
|
// border: 1px solid yellow;
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
.collapse-expand {
|
|
10
|
+
transform-origin: left bottom;
|
|
11
|
+
transform: rotate(270deg);
|
|
12
|
+
width: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
label {
|
|
9
16
|
position: absolute;
|
|
10
17
|
}
|
|
@@ -22,7 +29,7 @@
|
|
|
22
29
|
z-index: 11;
|
|
23
30
|
height: 400px;
|
|
24
31
|
position: relative;
|
|
25
|
-
background: rgba(255,255,255, 0.75);
|
|
32
|
+
// background: rgba(255,255,255, 0.75);
|
|
26
33
|
|
|
27
34
|
}
|
|
28
35
|
.PurseSummary {
|
|
@@ -9,6 +9,7 @@ class Iro::ApplicationController < Wco::ApplicationController
|
|
|
9
9
|
layout 'iro/application'
|
|
10
10
|
|
|
11
11
|
before_action :set_lists, except: %i| schwab_sync |
|
|
12
|
+
before_action :set_vcfg
|
|
12
13
|
|
|
13
14
|
def home
|
|
14
15
|
authorize! :home, Iro
|
|
@@ -33,5 +34,13 @@ class Iro::ApplicationController < Wco::ApplicationController
|
|
|
33
34
|
@purses = Iro::Purse.all.order_by( slug: :asc )
|
|
34
35
|
end
|
|
35
36
|
|
|
37
|
+
def set_vcfg
|
|
38
|
+
params[:vcfg] ||= {
|
|
39
|
+
statuses: [ 'active', 'pending' ],
|
|
40
|
+
template: Iro::Purse::TEMPLATE_GAMEUI,
|
|
41
|
+
}
|
|
42
|
+
params[:vcfg].permit!
|
|
43
|
+
end
|
|
44
|
+
|
|
36
45
|
|
|
37
46
|
end
|
|
@@ -5,11 +5,48 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
|
5
5
|
@position = Iro::Position.find params[:id]
|
|
6
6
|
authorize! :check, @position
|
|
7
7
|
outs = Tda::Order.check_status @position.schwab_order_id
|
|
8
|
-
@position.update({ schwab_status: outs[:status] })
|
|
9
8
|
puts! outs, 'outs'
|
|
9
|
+
|
|
10
|
+
if outs[:errors]
|
|
11
|
+
flash[:alert] = 'need to sync?!'
|
|
12
|
+
redirect_to request.referrer
|
|
13
|
+
return
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
attrs = { schwab_status: outs[:status] }
|
|
17
|
+
if 'FILLED' == outs[:status]
|
|
18
|
+
attrs[:status] = Iro::Position::STATUS_CLOSED
|
|
19
|
+
outs[:orderLegCollection].each do |leg|
|
|
20
|
+
hash = Iro::Option.symbol_to_h leg[:instrument][:symbol]
|
|
21
|
+
price = outs[:orderActivityCollection][0][:executionLegs].select do |exec_leg|
|
|
22
|
+
exec_leg[:instrumentId] == leg[:instrument][:instrumentId]
|
|
23
|
+
end[0][:price]
|
|
24
|
+
if @position.inner.matches_h( hash )
|
|
25
|
+
attrs[:inner_attributes] = { end_price: price }
|
|
26
|
+
end
|
|
27
|
+
if @position.outer.matches_h( hash )
|
|
28
|
+
attrs[:outer_attributes] = { end_price: price }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
puts! attrs,' attrs'
|
|
33
|
+
@position.update(attrs)
|
|
34
|
+
|
|
10
35
|
redirect_to request.referrer
|
|
11
36
|
end
|
|
12
37
|
|
|
38
|
+
def close_prep2
|
|
39
|
+
@position = Iro::Position.find params[:id]
|
|
40
|
+
authorize! :close, @position
|
|
41
|
+
@position.inner.sync
|
|
42
|
+
# @position.inner.update({ begin_price: @position.inner.end_price })
|
|
43
|
+
@position.outer.sync
|
|
44
|
+
# @position.outer.update({ begin_price: @position.outer.end_price })
|
|
45
|
+
@position.update({ pending_price: @position.close_price, intent: Iro::Position::INTENT_CLOSE })
|
|
46
|
+
@query = Tda::Order.close_credit_spread_q @position
|
|
47
|
+
@page_title = "Closing #{@position} ..."
|
|
48
|
+
end
|
|
49
|
+
|
|
13
50
|
def create
|
|
14
51
|
@position = Iro::Position.new pos_params
|
|
15
52
|
authorize! :create, @position
|
|
@@ -81,7 +118,20 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
|
81
118
|
|
|
82
119
|
def index
|
|
83
120
|
authorize! :index, Iro::Position
|
|
84
|
-
|
|
121
|
+
params[:vcfg] ||= {} # "view config"
|
|
122
|
+
template = params[:vcfg][:template] || Iro::Purse::TEMPLATE_TABLE
|
|
123
|
+
|
|
124
|
+
@purse = Iro::Purse.find_by( slug: 'all' )
|
|
125
|
+
@positions = Iro::Position.all().includes( :strategy, :inner, :outer, :stock, :purse
|
|
126
|
+
).order_by( expires_on: :asc, ticker: :asc, long_or_short: :asc, inner_strike: :asc )
|
|
127
|
+
|
|
128
|
+
if params[:vcfg][:statuses]
|
|
129
|
+
@positions = @positions.where( :status.in => params[:vcfg][:statuses] )
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
puts! @positions
|
|
133
|
+
|
|
134
|
+
@page_title = 'All Positions'
|
|
85
135
|
end
|
|
86
136
|
|
|
87
137
|
## only callable from _new.haml, with position partially pre-filled
|
|
@@ -101,14 +151,38 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
|
101
151
|
set_position_lists
|
|
102
152
|
end
|
|
103
153
|
|
|
104
|
-
## only credit-spread
|
|
154
|
+
## only open credit-spread,
|
|
155
|
+
## roll a credit-spread
|
|
105
156
|
def reprice
|
|
106
157
|
@position = Iro::Position.find params[:id]
|
|
107
158
|
authorize! :roll, @position
|
|
108
|
-
@position.update({ pending_price: params[:pending_price] })
|
|
159
|
+
flash_notice @position.update({ pending_price: params[:pending_price] })
|
|
160
|
+
|
|
161
|
+
if @position.schwab_order_id
|
|
162
|
+
Tda::Order.cancel_order!( @position.schwab_order_id )
|
|
163
|
+
outs = Tda::Order.place_order!( @position.schwab_query )
|
|
164
|
+
flag = @position.update({
|
|
165
|
+
schwab_order_id: outs[:schwab_order_id],
|
|
166
|
+
schwab_status: outs[:schwab_status],
|
|
167
|
+
status: Iro::Position::STATUS_PENDING,
|
|
168
|
+
})
|
|
169
|
+
flash_notice "Updated schwab order!"
|
|
170
|
+
end
|
|
109
171
|
|
|
110
|
-
|
|
111
|
-
|
|
172
|
+
redirect_to request.referrer
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def place_order
|
|
176
|
+
@position = Iro::Position.find params[:id]
|
|
177
|
+
authorize! :place_order, @position
|
|
178
|
+
|
|
179
|
+
query = case @position.intent
|
|
180
|
+
when Iro::Position::INTENT_CLOSE
|
|
181
|
+
Tda::Order.close_credit_spread_q @position
|
|
182
|
+
else
|
|
183
|
+
throw '_TODO: hls - placing order, not implemented'
|
|
184
|
+
end
|
|
185
|
+
outs = Tda::Order.place_order!( query )
|
|
112
186
|
|
|
113
187
|
flag = @position.update({
|
|
114
188
|
schwab_order_id: outs[:schwab_order_id],
|
|
@@ -117,24 +191,24 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
|
117
191
|
})
|
|
118
192
|
|
|
119
193
|
flash_notice flag
|
|
120
|
-
|
|
121
|
-
redirect_to request.referrer
|
|
194
|
+
redirect_to controller: :purses, action: :show, template: 'show', view_status: 'pending', id: @position.purse_id
|
|
122
195
|
end
|
|
123
196
|
|
|
124
|
-
##
|
|
125
|
-
def
|
|
197
|
+
## credit-spread
|
|
198
|
+
def open
|
|
126
199
|
@position = Iro::Position.find params[:id]
|
|
127
200
|
authorize! :roll, @position
|
|
128
201
|
@position.inner.sync
|
|
129
202
|
@position.inner.update({ begin_price: @position.inner.end_price })
|
|
130
203
|
@position.outer.sync
|
|
131
204
|
@position.outer.update({ begin_price: @position.outer.end_price })
|
|
132
|
-
@position.update({ pending_price: @position.
|
|
133
|
-
@query = Tda::Order.credit_spread_q @position
|
|
205
|
+
@position.update({ pending_price: @position.open_price })
|
|
206
|
+
@query = @position.schwab_query # Tda::Order.credit_spread_q @position
|
|
134
207
|
end
|
|
135
208
|
|
|
136
209
|
## 2025-10-14 long_credit_put_spread
|
|
137
210
|
## 2026-02-21 short_credit_call_spread
|
|
211
|
+
## That's for looking at the ui, with buttons 'select'
|
|
138
212
|
def prepare
|
|
139
213
|
@position = Iro::Position.find params[:id]
|
|
140
214
|
authorize! :roll, @position
|
|
@@ -152,23 +226,23 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
|
152
226
|
self.send("_prepare_#{@position.strategy.kind}")
|
|
153
227
|
end
|
|
154
228
|
|
|
229
|
+
## Manually selected one, I suppose
|
|
230
|
+
## _TODO: pos is autonext position, but should be this position?
|
|
231
|
+
## rename to: def select ?
|
|
155
232
|
def prepare2
|
|
233
|
+
if params[:prev_id]
|
|
234
|
+
prev = Iro::Position.find params[:prev_id]
|
|
235
|
+
prev.update({ autonxt_id: params[:id] })
|
|
236
|
+
Iro::Position.where( prev_id: params[:prev_id], status: 'proposed' ).update_all( status: 'prepare' )
|
|
237
|
+
end
|
|
238
|
+
|
|
156
239
|
@position = Iro::Position.find params[:id]
|
|
157
240
|
authorize! :roll, @position
|
|
158
241
|
@position.update({
|
|
159
242
|
status: Iro::Position::STATUS_PROPOSED,
|
|
243
|
+
intent: @position.strategy.intent,
|
|
244
|
+
pending_price: @position.roll_price,
|
|
160
245
|
})
|
|
161
|
-
if params[:prev_id]
|
|
162
|
-
prev = Iro::Position.find params[:prev_id]
|
|
163
|
-
prev.update({ autonxt_id: params[:id] })
|
|
164
|
-
@position.reload
|
|
165
|
-
else
|
|
166
|
-
if @position.autoprev
|
|
167
|
-
;
|
|
168
|
-
else
|
|
169
|
-
throw 'Must pass prev_id here.'
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
246
|
|
|
173
247
|
@query = case @position.strategy.kind
|
|
174
248
|
when Iro::Strategy::KIND_LONG_CREDIT_PUT_SPREAD,
|
|
@@ -181,6 +255,28 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
|
181
255
|
end
|
|
182
256
|
end
|
|
183
257
|
|
|
258
|
+
## 2026-04-08 try-close only so far.
|
|
259
|
+
## pos is this position, not autonext.
|
|
260
|
+
def prepare2_intent
|
|
261
|
+
@position = Iro::Position.find params[:id]
|
|
262
|
+
authorize! :roll, @position
|
|
263
|
+
case @position.strategy.intent
|
|
264
|
+
when Iro::Strategy::INTENT_CLOSE
|
|
265
|
+
|
|
266
|
+
@position.inner.sync
|
|
267
|
+
@position.inner.update({ begin_price: @position.inner.end_price })
|
|
268
|
+
@position.outer.sync
|
|
269
|
+
@position.outer.update({ begin_price: @position.outer.end_price })
|
|
270
|
+
@position.update({ pending_price: @position.close_price, intent: Iro::Position::INTENT_CLOSE })
|
|
271
|
+
# @query = Tda::Order.close_credit_spread_q @position
|
|
272
|
+
|
|
273
|
+
else
|
|
274
|
+
throw 'unknown intent - trt'
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
|
|
184
280
|
## credit-spread
|
|
185
281
|
def place3
|
|
186
282
|
@position = Iro::Position.find params[:id]
|
|
@@ -22,7 +22,7 @@ class Iro::PursesController < Iro::ApplicationController
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def edit
|
|
25
|
-
@purse = Iro::Purse.find(params[:id])
|
|
25
|
+
@purse = Iro::Purse.unscoped.find(params[:id]) rescue Iro::Purse.unscoped.find_by( slug: params[:id] )
|
|
26
26
|
authorize! :edit, @purse
|
|
27
27
|
end
|
|
28
28
|
|
|
@@ -33,25 +33,20 @@ class Iro::PursesController < Iro::ApplicationController
|
|
|
33
33
|
|
|
34
34
|
## table or gameui
|
|
35
35
|
def show
|
|
36
|
-
@purse = Iro::Purse.find(params[:id])
|
|
36
|
+
@purse = Iro::Purse.unscoped.find(params[:id]) rescue Iro::Purse.unscoped.find_by( slug: params[:id] )
|
|
37
37
|
authorize! :show, @purse
|
|
38
|
-
params[:template] ||= 'show'
|
|
39
|
-
params[:view_status] ||= 'active'
|
|
40
38
|
@unit = @purse.unit # 12 ## pixels per dollar
|
|
41
39
|
@height = @purse.height # 100 ## pixels
|
|
42
40
|
@n_dollars = 50 ## * unit * 2 = length of the grid
|
|
43
41
|
|
|
44
|
-
@positions = @purse.positions.where( status
|
|
42
|
+
@positions = @purse.positions.where( :status.in => params[:vcfg][:statuses]
|
|
45
43
|
).includes( :strategy
|
|
46
44
|
).order_by( expires_on: :asc, ticker: :asc, long_or_short: :asc, inner_strike: :asc )
|
|
47
45
|
|
|
48
|
-
if 'all' == params[:view_status]
|
|
49
|
-
@positions = @positions.unscope( where: :status )
|
|
50
|
-
end
|
|
51
|
-
|
|
52
46
|
calc_summary
|
|
53
47
|
|
|
54
|
-
|
|
48
|
+
@page_title = @purse.to_s
|
|
49
|
+
render params[:vcfg][:template]
|
|
55
50
|
end
|
|
56
51
|
|
|
57
52
|
def sync
|
|
@@ -79,12 +74,12 @@ class Iro::PursesController < Iro::ApplicationController
|
|
|
79
74
|
count = count+1
|
|
80
75
|
end
|
|
81
76
|
|
|
82
|
-
flash[:notice] = '
|
|
77
|
+
flash[:notice] = 'Synced the purse.'
|
|
83
78
|
redirect_to request.referrer
|
|
84
79
|
end
|
|
85
80
|
|
|
86
81
|
def update
|
|
87
|
-
@purse = Iro::Purse.find(params[:id])
|
|
82
|
+
@purse = Iro::Purse.unscoped.find(params[:id]) rescue Iro::Purse.unscoped.find_by( slug: params[:id] )
|
|
88
83
|
authorize! :update, @purse
|
|
89
84
|
if @purse.update params[:purse].permit!
|
|
90
85
|
flash[:notice] = 'ok'
|
|
@@ -12,20 +12,37 @@ class Iro::StocksController < Iro::ApplicationController
|
|
|
12
12
|
if @stock.save
|
|
13
13
|
flash_notice @stock
|
|
14
14
|
else
|
|
15
|
+
@stock = Iro::Stock.unscoped.find_by ticker: stock_params[:ticker]
|
|
16
|
+
flag = @stock.update( deleted_at: nil, options_price_increment: stock_params[:options_price_increment] )
|
|
15
17
|
flash_alert @stock
|
|
16
18
|
end
|
|
17
19
|
redirect_to action: :index
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def destroy
|
|
23
|
+
authorize! :destroy, @stock
|
|
21
24
|
@stock.destroy
|
|
22
|
-
redirect_to stocks_url, notice: 'Stock was
|
|
25
|
+
redirect_to stocks_url, notice: 'Stock was destroyed.'
|
|
23
26
|
end
|
|
24
27
|
|
|
25
28
|
def edit
|
|
26
29
|
authorize! :edit, @stock
|
|
27
30
|
end
|
|
28
31
|
|
|
32
|
+
def get_historic_data
|
|
33
|
+
authorize! :show, Iro::Stock
|
|
34
|
+
@stock = Iro::Stock.find params[:id]
|
|
35
|
+
@stock.get_historic_data( params[:date_from].to_date )
|
|
36
|
+
redirect_to action: :show, id: params[:id]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def recompute_volatility
|
|
40
|
+
authorize! :show, Iro::Stock
|
|
41
|
+
@stock = Iro::Stock.find params[:id]
|
|
42
|
+
@stock.volatility( recompute: true )
|
|
43
|
+
redirect_to action: :show, id: params[:id]
|
|
44
|
+
end
|
|
45
|
+
|
|
29
46
|
def index
|
|
30
47
|
@all_stocks = Iro::Stock.all
|
|
31
48
|
authorize! :index, Iro::Stock
|
|
@@ -47,11 +64,8 @@ class Iro::StocksController < Iro::ApplicationController
|
|
|
47
64
|
authorize! :refresh, Iro::Stock
|
|
48
65
|
tickers = Iro::Stock.all.map { |s| s.ticker }.join(',')
|
|
49
66
|
outs = Tda::Stock.get_quotes tickers
|
|
50
|
-
puts! outs, 'got all tickers'
|
|
51
67
|
|
|
52
68
|
outs.map do |out|
|
|
53
|
-
puts! out, 'a ticker'
|
|
54
|
-
|
|
55
69
|
Iro::Stock.where( ticker: out[:symbol] ).update_all( last: out[:last] )
|
|
56
70
|
end
|
|
57
71
|
flash_notice 'refreshed stocks'
|
|
@@ -22,19 +22,21 @@
|
|
|
22
22
|
-# = link_to "Purses (#{Iro::Purse.all.length})", purses_path
|
|
23
23
|
%li
|
|
24
24
|
= render '/iro/strategies/header'
|
|
25
|
+
%li
|
|
26
|
+
= link_to 'Positions', iro.positions_path
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
.ml-3
|
|
28
30
|
= link_to "Purses (#{Iro::Purse.all.length})", purses_path
|
|
29
31
|
= link_to '[+]', purses_path
|
|
30
32
|
%ul
|
|
31
|
-
- @purses.each do |
|
|
33
|
+
- @purses.each do |purse|
|
|
32
34
|
%li
|
|
33
|
-
=
|
|
35
|
+
= purse
|
|
34
36
|
|
|
35
|
-
= link_to '[#]', purse_path(
|
|
37
|
+
= link_to '[#]', purse_path(purse, vcfg: params[:vcfg].merge({ template: Iro::Purse::TEMPLATE_TABLE }))
|
|
36
38
|
|
|
37
|
-
= link_to '[
|
|
39
|
+
= link_to '[oo]', purse_path(purse, vcfg: params[:vcfg].merge({ template: Iro::Purse::TEMPLATE_GAMEUI }))
|
|
38
40
|
|
|
39
41
|
-#
|
|
40
42
|
= link_to 'Strategies', strategies_path
|
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
-# 2026-02-16 I have not verified any of this
|
|
9
9
|
-#
|
|
10
10
|
|
|
11
|
-
.
|
|
12
|
-
[<>]
|
|
11
|
+
.d-flex.--gameui-long-credit-put-spread{ id: "gameui-pos-#{pos.id}" }
|
|
13
12
|
.maxwidth= render "/iro/positions/header", pos: pos
|
|
14
13
|
.--gameui-long-credit-put-spread
|
|
15
14
|
= render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
|
|
@@ -28,6 +27,9 @@
|
|
|
28
27
|
.Position
|
|
29
28
|
.MaxGain{ style: "width: #{pos.max_gain * u}px" }
|
|
30
29
|
.RollGuide
|
|
30
|
+
.Quantities
|
|
31
|
+
- (pos.q-1).times do
|
|
32
|
+
.item
|
|
31
33
|
|
|
32
34
|
- if pos.net_amount >= 0
|
|
33
35
|
.Net.NetPositive{ style: "width: #{ pos.net_amount() *u}px;" }
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
-## 2026-04-05 move loss inside, gain outside
|
|
11
11
|
-##
|
|
12
12
|
|
|
13
|
-
.
|
|
14
|
-
[<>]
|
|
13
|
+
.d-flex.--gameui-short-credit-call-spread{ id: "gameui-pos-#{pos.id}" }
|
|
15
14
|
.maxwidth= render "/iro/positions/header", pos: pos
|
|
16
15
|
.--gameui-short-credit-call-spread
|
|
17
16
|
= render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
|
|
@@ -30,6 +29,9 @@
|
|
|
30
29
|
.Position
|
|
31
30
|
.MaxGain{ style: "width: #{pos.max_gain * u}px" }
|
|
32
31
|
.RollGuide
|
|
32
|
+
.Quantities
|
|
33
|
+
- (pos.q-1).times do
|
|
34
|
+
.item
|
|
33
35
|
|
|
34
36
|
- if pos.net_amount >= 0
|
|
35
37
|
.Net.NetPositive{ style: "width: #{ pos.net_amount*u }px; left: #{-1* pos.net_amount() *u + border_px}px" }
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
|
|
2
2
|
.positions--header.maxwidth
|
|
3
|
+
|
|
3
4
|
= pos
|
|
4
|
-
= render '/iro/strategies/show', collapse_key: pos.id, strategy: pos.strategy
|
|
5
|
+
-# = render '/iro/strategies/show', collapse_key: pos.id, strategy: pos.strategy
|
|
5
6
|
= link_to '[prepare]', position_prepare_to_roll_path(pos) if pos.persisted?
|
|
6
|
-
-# .d-inline-block= button_to 'close', close_position_path(pos), data: { confirm: 'Are you sure?' }
|
|
7
7
|
= link_to '[close]', close_position_path(pos)
|
|
8
8
|
= link_to '[~]', edit_position_path(pos) if pos.persisted?
|
|
9
|
-
|
|
9
|
+
.d-inline-block= button_to 'x', position_path(pos), method: :delete, data: { confirm: 'Are you sure?' }
|
|
10
|
+
.gray <i>#{pos.status}</i>
|
|
11
|
+
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
.maxwidth.positions--header.--header-short-credit-call-spread
|
|
7
7
|
%ul
|
|
8
8
|
%li
|
|
9
|
-
<b>begin $:</b> [#{pp_amount pos.inner.begin_price}
|
|
9
|
+
<b>begin $:</b> [#{pp_amount pos.inner.begin_price} >> #{pp_amount pos.outer.begin_price}]
|
|
10
10
|
<b>D:</b> [[#{pos.inner.begin_delta} >> #{pos.outer.begin_delta}]]
|
|
11
11
|
<b>net_ea/max_gain_ea:</b> #{pp_amount pos.net_amount * 100}/#{pp_amount pos.max_gain * 100} :: #{pp_percent pos.net_percent}
|
|
12
12
|
<b>breakeven:</b> #{pp_amount pos.breakeven}
|
|
13
13
|
<b>max_loss:</b> #{pp_amount pos.max_loss * 100*q}
|
|
14
14
|
%li
|
|
15
|
-
<b>end $:</b> [#{pp_amount pos.inner.end_price}
|
|
15
|
+
<b>end $:</b> [#{pp_amount pos.inner.end_price} >> #{pp_amount pos.outer.end_price}]
|
|
16
16
|
<b>D:</b> [[#{pos.inner.end_delta} >> #{pos.outer.end_delta}]]
|
|
17
17
|
<b>net*q</b> #{pp_amount pos.net_amount * 100*q}
|
|
18
18
|
<b>max_gain*q:</b> #{pp_amount pos.max_gain * 100*q}
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
.maxwidth.--prepare-header-long-credit-put-spread
|
|
6
6
|
%ul.m-0.p-0
|
|
7
7
|
%li
|
|
8
|
-
|
|
9
|
-
<b>
|
|
10
|
-
<b>
|
|
11
|
-
<b>breakeven:</b> #{pp_amount pos.breakeven}
|
|
12
|
-
<b>Net:</b> #{pp_amount pos.next_gain_loss_amount}
|
|
8
|
+
#{pos.expires_on} [#{pp_amount pos.outer.strike} << #{pp_amount pos.inner.strike}]
|
|
9
|
+
<b>net_ea:</b> #{pp_amount pos.next_gain_loss_amount}
|
|
10
|
+
<b>max_loss_ea:</b> #{pp_amount pos.max_loss * 100}
|
|
13
11
|
%li
|
|
14
|
-
|
|
15
|
-
<b>
|
|
16
|
-
|
|
12
|
+
<b>begin $:</b> [#{pp_amount pos.outer.begin_price} << #{pp_amount pos.inner.begin_price}]
|
|
13
|
+
<b>D:</b> [[#{pos.outer.begin_delta} << #{pos.inner.begin_delta}]]
|
|
14
|
+
<b>max_gain_ea:</b> #{pp_amount pos.max_gain * 100}
|
|
15
|
+
<b>breakeven:</b> #{pp_amount pos.breakeven}
|
|
16
|
+
|
|
@@ -5,15 +5,13 @@
|
|
|
5
5
|
.maxwidth.--prepare-header-short-credit-call-spread
|
|
6
6
|
%ul.m-0.p-0
|
|
7
7
|
%li
|
|
8
|
-
|
|
9
|
-
<b>
|
|
10
|
-
<b>
|
|
11
|
-
<b>max_gain_ea:</b> #{pp_amount pos.max_gain * 100}
|
|
12
|
-
<b>breakeven:</b> #{pp_amount pos.breakeven}
|
|
13
|
-
<b>Net Ea:</b> #{pp_amount pos.next_gain_loss_amount}
|
|
14
|
-
%li
|
|
15
|
-
-# 2026-02-24 this ordering
|
|
16
|
-
#{pos.expires_on} <b>#{pos.strategy.kind}</b> [#{pp_amount pos.inner.strike} -> #{pp_amount pos.outer.strike}]
|
|
17
|
-
<b>max_loss_ea:</b> #{pp_amount pos.max_loss * 100}
|
|
8
|
+
#{pos.expires_on} [#{pp_amount pos.inner.strike} >> #{pp_amount pos.outer.strike}]
|
|
9
|
+
<b>net_ea:</b> #{pp_amount pos.next_gain_loss_amount}
|
|
10
|
+
<b>max_loss_ea:</b> #{pp_amount pos.max_loss * 100}
|
|
18
11
|
%li
|
|
12
|
+
<b>begin $:</b> [#{pp_amount pos.inner.begin_price} >> #{pp_amount pos.outer.begin_price}]
|
|
13
|
+
<b>D:</b> [[#{pos.inner.begin_delta} >> #{pos.outer.begin_delta}]]
|
|
14
|
+
<b>max_gain_ea:</b> #{pp_amount pos.max_gain * 100}
|
|
15
|
+
<b>breakeven:</b> #{pp_amount pos.breakeven}
|
|
16
|
+
|
|
19
17
|
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
= form_tag positions_path, method: :delete, id: 'positionsXmultiSubmit' do
|
|
9
9
|
= hidden_field_tag "positions_xmulti", ''
|
|
10
10
|
= submit_tag 'X-multi', data: { confirm: 'Are you sure?' }
|
|
11
|
+
|
|
12
|
+
%th.intent
|
|
13
|
+
Intent
|
|
11
14
|
%th.ticker
|
|
12
15
|
.a Stock
|
|
13
16
|
%th
|
|
@@ -52,6 +55,7 @@
|
|
|
52
55
|
%td{ colspan: 18 }
|
|
53
56
|
.h-50px
|
|
54
57
|
|
|
58
|
+
-## Renders the same thing regardless of strategy!
|
|
55
59
|
= render "iro/positions/table_tr_#{position.strategy.kind}", position: position
|
|
56
60
|
|
|
57
61
|
|