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.
- checksums.yaml +4 -4
- data/README.txt +19 -0
- data/app/assets/stylesheets/iron_warbler/application.css +12 -0
- data/app/assets/stylesheets/iron_warbler/positions.scss +2 -0
- data/app/assets/stylesheets/iron_warbler/positions_gameui.scss +11 -0
- data/app/assets/stylesheets/iron_warbler/purses_gameui.scss +11 -32
- data/app/assets/stylesheets/iron_warbler/purses_summary.scss +98 -0
- data/app/assets/stylesheets/iron_warbler/utils.scss +4 -0
- data/app/controllers/iro/alerts_controller.rb +2 -0
- data/app/controllers/iro/application_controller.rb +13 -0
- data/app/controllers/iro/positions_controller.rb +197 -23
- data/app/controllers/iro/purses_controller.rb +60 -6
- data/app/controllers/iro/stocks_controller.rb +30 -18
- data/app/controllers/iro/strategies_controller.rb +12 -1
- data/app/models/iro/alert.rb +1 -0
- data/app/models/iro/datapoint.rb +7 -7
- data/app/models/iro/option.rb +174 -3
- data/app/models/iro/position.rb +124 -56
- data/app/models/iro/purse.rb +18 -4
- data/app/models/iro/stock.rb +84 -0
- data/app/models/iro/strategy.rb +122 -27
- data/app/models/tda/option.rb +104 -8
- data/app/views/iro/_main_header.haml +28 -17
- data/app/views/iro/application/home.haml +6 -1
- data/app/views/iro/positions/_form.haml +1 -2
- data/app/views/iro/positions/_gameui_covered_call.haml +10 -13
- data/app/views/iro/positions/_gameui_covered_call.haml-bk +8 -0
- data/app/views/iro/positions/_gameui_long_debit_call_spread.haml +5 -4
- data/app/views/iro/positions/_gameui_short_debit_put_spread.haml +5 -4
- data/app/views/iro/positions/_header.haml +2 -2
- data/app/views/iro/positions/_header_covered_call.haml +7 -1
- data/app/views/iro/positions/_header_long_debit_call_spread.haml +19 -1
- data/app/views/iro/positions/_prepare_covered_call.haml +25 -0
- data/app/views/iro/positions/_prepare_long_debit_call_spread.haml +23 -0
- data/app/views/iro/positions/_prepare_short_debit_put_spread.haml +23 -0
- data/app/views/iro/positions/_table.haml +33 -24
- data/app/views/iro/positions/prepare.haml +24 -0
- data/app/views/iro/positions/roll-cc.haml-bk +40 -0
- data/app/views/iro/positions/roll.haml-trash +42 -0
- data/app/views/iro/purses/_form.haml +9 -0
- data/app/views/iro/purses/_form_extra_fields.haml +25 -13
- data/app/views/iro/purses/_header.haml +15 -16
- data/app/views/iro/purses/_summary.haml +69 -0
- data/app/views/iro/purses/gameui.haml +13 -7
- data/app/views/iro/purses/index.haml +3 -1
- data/app/views/iro/purses/show.haml +5 -1
- data/app/views/iro/stocks/_form.haml +5 -0
- data/app/views/iro/stocks/_grid_is_long.haml +2 -2
- data/app/views/iro/stocks/_grid_is_short.haml +2 -2
- data/app/views/iro/stocks/index.haml +3 -2
- data/app/views/iro/strategies/_form.haml +12 -6
- data/app/views/iro/strategies/_show.haml +3 -3
- data/app/views/iro/strategies/_table.haml +15 -6
- data/app/views/iro/strategies/show.haml +14 -0
- data/app/views/layouts/iro/application.haml +4 -0
- data/config/routes.rb +6 -2
- data/lib/tasks/db_tasks.rake +1 -1
- data/lib/tasks/test_tasks.rake +54 -0
- metadata +28 -6
- data/app/models/iro/trash/position_covered_call.rb +0 -4
- data/app/models/iro/trash/position_debit_spread.rb +0 -251
- data/app/views/iro/positions/roll.haml +0 -83
- data/app/views/iro/positions/trash/_header_short_debit_put_spread.haml +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b73ac7c5b7ca0d29fe20cd0db0dcdca4713a710790bff2cffe8c30c3a18d2d2
|
4
|
+
data.tar.gz: daef47e2b8841f0253e55d19a8c8703c7aff086c53711b52db3dfdb470a97a78
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e59a49397b934c8537abe40eb23eba846aa770956e02168722b2eb5fd6a1e19581388dc43d3ecb6e211e90cffec5cf8b02ef5eaa6efdcb1f40b4599c4125c8e8
|
7
|
+
data.tar.gz: 8f10a4503e57e02d17ca0dd7a310fc73489dfd22fb23e23f16a79de72f3a589790c09e9facbfb2441daf3fcef2b93456bcac12ce7a767c35ce7e29c2ccffc48f
|
data/README.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
= Install =
|
3
|
+
|
4
|
+
From: https://docs.galpy.org/en/latest/installation.html
|
5
|
+
|
6
|
+
brew install gsl
|
7
|
+
|
8
|
+
= Use =
|
9
|
+
|
10
|
+
calculator: https://www.omnicalculator.com/finance/black-scholes
|
11
|
+
|
12
|
+
From: https://pythoninoffice.com/calculate-black-scholes-option-price-in-python/
|
13
|
+
|
14
|
+
-=---
|
15
|
+
|
16
|
+
|
17
|
+
https://api.tdameritrade.com/v1/accounts/232718838/orders/13597943085
|
18
|
+
|
19
|
+
|
@@ -2,7 +2,8 @@
|
|
2
2
|
.purses-gameuiW {
|
3
3
|
border: 1px solid red;
|
4
4
|
width: 100%;
|
5
|
-
overflow: scroll;
|
5
|
+
// overflow-x: scroll;
|
6
|
+
overflow-y: hidden;
|
6
7
|
}
|
7
8
|
|
8
9
|
.purses-gameui {
|
@@ -31,6 +32,9 @@
|
|
31
32
|
z-index: 2;
|
32
33
|
}
|
33
34
|
}
|
35
|
+
.PositionW.short_debit_put_spread {
|
36
|
+
background: rgba(255,153,0, 0.25);
|
37
|
+
}
|
34
38
|
.PositionW {
|
35
39
|
top: 0;
|
36
40
|
border: 2px solid black;
|
@@ -47,13 +51,14 @@
|
|
47
51
|
|
48
52
|
.Position {
|
49
53
|
position: absolute;
|
50
|
-
background: rgba(0,255,255, 0.25);
|
51
54
|
width: 100%;
|
52
55
|
height: 90%;
|
53
56
|
|
54
57
|
left: 0;
|
55
58
|
top: 0;
|
56
59
|
}
|
60
|
+
|
61
|
+
|
57
62
|
/* only for covered calls */
|
58
63
|
.PositionC {
|
59
64
|
background: rgba(255,153,51, 0.5);
|
@@ -72,9 +77,9 @@
|
|
72
77
|
position: absolute;
|
73
78
|
right: 0;
|
74
79
|
bottom: -10%;
|
75
|
-
border: 2px
|
80
|
+
border: 2px dotted green;
|
76
81
|
background: rgba(0,255,0, 0.5);
|
77
|
-
height:
|
82
|
+
height: 0.5em;
|
78
83
|
}
|
79
84
|
|
80
85
|
.sprite {
|
@@ -138,32 +143,6 @@
|
|
138
143
|
background: rgba(255,0,0, 0.75);
|
139
144
|
}
|
140
145
|
|
141
|
-
|
142
|
-
// .grid-mark:nth-child(4n + 1) {
|
143
|
-
// border: 1px solid red;
|
144
|
-
// display: none;
|
145
|
-
// }
|
146
|
-
// .grid-mark:nth-child(4n) {
|
147
|
-
// border: 1px solid red;
|
148
|
-
// display: none;
|
149
|
-
// }
|
150
|
-
// .grid-mark:nth-child(6n + 1) {
|
151
|
-
// border: 1px solid red;
|
152
|
-
// display: none;
|
153
|
-
// }
|
154
|
-
// .grid-mark:nth-child(6n) {
|
155
|
-
// border: 1px solid red;
|
156
|
-
// display: none;
|
157
|
-
// }
|
158
|
-
// .grid-mark:nth-child(3n + 1) {
|
159
|
-
// border: 1px solid red;
|
160
|
-
// display: none;
|
161
|
-
// }
|
162
|
-
// .grid-mark:nth-child(3n) {
|
163
|
-
// border: 1px solid red;
|
164
|
-
// display: none;
|
165
|
-
// }
|
166
|
-
|
167
146
|
.grid-mark {
|
168
147
|
// border: 1px solid red;
|
169
148
|
|
@@ -202,8 +181,8 @@
|
|
202
181
|
.labelC {
|
203
182
|
background: white;
|
204
183
|
position: absolute;
|
205
|
-
|
206
|
-
|
184
|
+
bottom: -1em;
|
185
|
+
right: 0;
|
207
186
|
}
|
208
187
|
}
|
209
188
|
}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
|
2
|
+
.PurseSummaryW {
|
3
|
+
position: relative;
|
4
|
+
background: rgba(255,255,255, 0.75);
|
5
|
+
height: 400px;
|
6
|
+
width: 100%;
|
7
|
+
z-index: 5;
|
8
|
+
}
|
9
|
+
.PurseSummary {
|
10
|
+
position: absolute;
|
11
|
+
top: 200px;
|
12
|
+
|
13
|
+
display: flex;
|
14
|
+
|
15
|
+
width: 100%;
|
16
|
+
height: 0;
|
17
|
+
border-bottom: 1px dotted black;
|
18
|
+
|
19
|
+
.legendW {
|
20
|
+
position: relative;
|
21
|
+
// margin-top: 50%;
|
22
|
+
|
23
|
+
.legend {
|
24
|
+
margin-top: -50%;
|
25
|
+
|
26
|
+
// position: absolute;
|
27
|
+
// top: -200px;
|
28
|
+
// width: 400px;
|
29
|
+
// height: 400px;
|
30
|
+
|
31
|
+
background: white;
|
32
|
+
padding: 0.5em;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
|
37
|
+
/*
|
38
|
+
* summary amount and delta
|
39
|
+
**/
|
40
|
+
.summary-amount {
|
41
|
+
position: relative;
|
42
|
+
width: 100px;
|
43
|
+
|
44
|
+
.net-gl {
|
45
|
+
width: 100%;
|
46
|
+
background: rgba(0,0,0, 0.5);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
.summary-delta {
|
50
|
+
position: relative;
|
51
|
+
margin-right: 1em;
|
52
|
+
width: 1em;
|
53
|
+
|
54
|
+
> div {
|
55
|
+
border: 1px dotted yellow;
|
56
|
+
}
|
57
|
+
.begin {
|
58
|
+
width: 1em;
|
59
|
+
|
60
|
+
background: black;
|
61
|
+
}
|
62
|
+
.end {
|
63
|
+
width: .5em;
|
64
|
+
left: .25em;
|
65
|
+
|
66
|
+
background: rgba(255,0,0, 0.5);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
.loss {
|
70
|
+
}
|
71
|
+
.gain {
|
72
|
+
}
|
73
|
+
.max-gl {
|
74
|
+
position: absolute;
|
75
|
+
width: 100%;
|
76
|
+
}
|
77
|
+
.max-gl.long {
|
78
|
+
background: rgba(255,0,0, 0.5);
|
79
|
+
}
|
80
|
+
.max-gl-short {
|
81
|
+
background: rgba(255,153,0, 0.5);
|
82
|
+
}
|
83
|
+
.long {
|
84
|
+
position: absolute;
|
85
|
+
top: 0;
|
86
|
+
|
87
|
+
background: rgba(255,0,0, 0.5);
|
88
|
+
border: 1px solid red;
|
89
|
+
bottom: 0;
|
90
|
+
}
|
91
|
+
.short {
|
92
|
+
background: rgba(255,153,0, 0.5);
|
93
|
+
border: 1px solid orange;
|
94
|
+
|
95
|
+
position: absolute;
|
96
|
+
bottom: 0;
|
97
|
+
}
|
98
|
+
}
|
@@ -3,8 +3,21 @@
|
|
3
3
|
class Iro::ApplicationController < Wco::ApplicationController
|
4
4
|
layout 'iro/application'
|
5
5
|
|
6
|
+
before_action :set_lists
|
7
|
+
|
6
8
|
def home
|
7
9
|
authorize! :home, Iro
|
8
10
|
end
|
9
11
|
|
12
|
+
##
|
13
|
+
## private
|
14
|
+
##
|
15
|
+
private
|
16
|
+
|
17
|
+
def set_lists
|
18
|
+
@purses = Iro::Purse.all
|
19
|
+
@strategies = Iro::Strategy.all
|
20
|
+
end
|
21
|
+
|
22
|
+
|
10
23
|
end
|
@@ -3,14 +3,28 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
3
3
|
before_action :set_lists
|
4
4
|
|
5
5
|
def new
|
6
|
-
@position = Iro::Position.new
|
6
|
+
@position = Iro::Position.new
|
7
7
|
authorize! :new, @posision
|
8
|
+
|
9
|
+
if params[:id]
|
10
|
+
old = Iro::Position.find params[:id]
|
11
|
+
old = old.attributes
|
12
|
+
old.delete :_id
|
13
|
+
puts! old, 'old'
|
14
|
+
@position = Iro::Position.new old
|
15
|
+
end
|
16
|
+
if params[:purse_id]
|
17
|
+
@position.purse_id = params[:purse_id]
|
18
|
+
end
|
19
|
+
|
8
20
|
end
|
9
21
|
|
10
22
|
def create
|
11
23
|
@position = Iro::Position.new params[:position].permit!
|
12
24
|
authorize! :create, @position
|
13
25
|
|
26
|
+
@position.sync
|
27
|
+
|
14
28
|
if @position.save
|
15
29
|
flash_notice @position
|
16
30
|
redirect_to controller: :purses, action: :show, id: @position.purse_id.to_s
|
@@ -33,38 +47,195 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
33
47
|
authorize! :edit, @position
|
34
48
|
end
|
35
49
|
|
50
|
+
def propose
|
51
|
+
@strategy = Iro::Strategy.find params[:strategy_id]
|
52
|
+
authorize! :show, @strategy
|
53
|
+
|
54
|
+
@purse = Iro::Purse.find params[:purse_id]
|
55
|
+
|
56
|
+
## short debit put spread
|
57
|
+
outs = Tda::Option.get_quotes({
|
58
|
+
contractType: 'PUT',
|
59
|
+
expirationDate: '2024-03-28',
|
60
|
+
ticker: @strategy.stock.ticker,
|
61
|
+
})
|
62
|
+
outs = outs.select do |out|
|
63
|
+
out[:bidSize]+out[:askSize] > 0
|
64
|
+
end
|
65
|
+
outs = outs.select do |out|
|
66
|
+
out[:strikePrice] > @strategy.buffer_above_water + @strategy.stock.last
|
67
|
+
end
|
68
|
+
outs = outs.select do |out|
|
69
|
+
out[:strikePrice] > @strategy.next_inner_strike
|
70
|
+
end
|
71
|
+
outs = outs.select do |out|
|
72
|
+
out[:delta] < @strategy.next_inner_delta
|
73
|
+
end
|
74
|
+
|
75
|
+
inner = outs[0]
|
76
|
+
outs = outs.select do |out|
|
77
|
+
out[:strikePrice] >= inner[:strikePrice] + @strategy.next_spread_amount
|
78
|
+
end
|
79
|
+
outer = outs[0]
|
80
|
+
|
81
|
+
if inner && outer
|
82
|
+
next_position = Iro::Position.new({
|
83
|
+
status: 'proposed',
|
84
|
+
stock: @strategy.stock,
|
85
|
+
inner_strike: inner[:strikePrice],
|
86
|
+
outer_strike: outer[:strikePrice],
|
87
|
+
begin_outer_price: outer[:last],
|
88
|
+
begin_outer_delta: outer[:delta],
|
89
|
+
begin_inner_price: inner[:last],
|
90
|
+
begin_inner_delta: inner[:delta],
|
91
|
+
begin_on: Time.now.to_date,
|
92
|
+
expires_on: '2024-03-28',
|
93
|
+
purse: @purse,
|
94
|
+
strategy: @strategy,
|
95
|
+
quantity: 1,
|
96
|
+
})
|
97
|
+
next_position.sync
|
98
|
+
next_position.save
|
99
|
+
else
|
100
|
+
flash_alert 'cannot propose a new one'
|
101
|
+
end
|
102
|
+
redirect_to request.referrer
|
103
|
+
end
|
104
|
+
|
36
105
|
def refresh
|
37
106
|
@position = pos = Iro::Position.find params[:id]
|
38
107
|
authorize! :refresh, @position
|
39
108
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
strike: pos.inner_strike,
|
44
|
-
expirationDate: pos.expires_on,
|
45
|
-
ticker: pos.stock.ticker,
|
46
|
-
})
|
47
|
-
puts! out, 'out'
|
48
|
-
@position.update({
|
49
|
-
end_inner_price: ( out.bid + out.ask ) / 2,
|
50
|
-
end_inner_delta: out.delta,
|
51
|
-
})
|
109
|
+
@position.sync
|
110
|
+
@position.calc_rollp
|
111
|
+
|
52
112
|
redirect_to request.referrer || purse_path( @position.purse )
|
53
113
|
end
|
54
114
|
|
55
|
-
def
|
115
|
+
def prepare
|
56
116
|
@position = Iro::Position.find params[:id]
|
57
117
|
authorize! :roll, @position
|
58
118
|
|
59
|
-
|
119
|
+
@prev = @position
|
120
|
+
@purse = @position.purse
|
121
|
+
@stock = @position.stock
|
122
|
+
@n_dollars = 100
|
123
|
+
|
124
|
+
## holiday schedule
|
125
|
+
@next_expires_on = @prev.expires_on.to_datetime.next_occurring(:monday).next_occurring(:friday)
|
126
|
+
if !@next_expires_on.workday?
|
127
|
+
@next_expires_on = Time.previous_business_day( @next_expires_on )
|
128
|
+
end
|
129
|
+
|
130
|
+
## dealing with too many strikes in the chain
|
131
|
+
while true
|
132
|
+
@nn = ( @position.purse.n_next_positions/2 ).ceil
|
133
|
+
upper = Tda::Option.get_quote({
|
134
|
+
contractType: 'CALL',
|
135
|
+
strike: @prev.inner_strike + @nn*@stock.options_price_increment,
|
136
|
+
expirationDate: @next_expires_on,
|
137
|
+
ticker: @stock.ticker,
|
138
|
+
})
|
139
|
+
if !upper.symbol
|
140
|
+
puts! 'too high'
|
141
|
+
flash_alert 'too high'
|
142
|
+
@purse.n_next_positions = @purse.n_next_positions - 1
|
143
|
+
@purse.n_next_positions = 1 if @purse.n_next_positions < 1
|
144
|
+
@purse.save!
|
145
|
+
next
|
146
|
+
end
|
147
|
+
lower = Tda::Option.get_quote({
|
148
|
+
contractType: 'CALL',
|
149
|
+
strike: @prev.inner_strike - @nn*@stock.options_price_increment,
|
150
|
+
expirationDate: @next_expires_on,
|
151
|
+
ticker: @stock.ticker,
|
152
|
+
})
|
153
|
+
if !lower.symbol
|
154
|
+
puts! 'too low'
|
155
|
+
flash_alert 'too low'
|
156
|
+
@purse.n_next_positions = @purse.n_next_positions - 1
|
157
|
+
@purse.n_next_positions = 1 if @purse.n_next_positions < 1
|
158
|
+
@purse.save!
|
159
|
+
next
|
160
|
+
end
|
161
|
+
break
|
162
|
+
end
|
60
163
|
|
61
|
-
@
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
164
|
+
self.send("_prepare_#{@position.strategy.kind}")
|
165
|
+
end
|
166
|
+
|
167
|
+
def _prepare_covered_call
|
168
|
+
@positions = []
|
169
|
+
(-@nn..@nn).each do |idx|
|
170
|
+
next_ = Iro::Position.new({
|
171
|
+
stock: @stock,
|
172
|
+
inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
|
173
|
+
expires_on: @next_expires_on,
|
174
|
+
purse: @position.purse,
|
175
|
+
strategy: @position.strategy,
|
176
|
+
quantity: @position.quantity,
|
177
|
+
})
|
178
|
+
next_.sync
|
179
|
+
next_.begin_inner_price = next_.end_inner_price
|
180
|
+
next_.begin_inner_delta = next_.end_inner_delta
|
181
|
+
next_.next_gain_loss_amount = next_.begin_inner_price - @prev.end_inner_price
|
182
|
+
puts! next_, 'next_'
|
183
|
+
puts! next_.next_gain_loss_amount, 'amount'
|
184
|
+
@positions.push next_
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def _prepare_long_debit_call_spread
|
189
|
+
@positions = []
|
190
|
+
(-@nn..@nn).each do |idx|
|
191
|
+
next_ = Iro::Position.new({
|
192
|
+
stock: @stock,
|
193
|
+
inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
|
194
|
+
outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
|
195
|
+
expires_on: @next_expires_on,
|
196
|
+
purse: @position.purse,
|
197
|
+
strategy: @position.strategy,
|
198
|
+
quantity: @position.quantity,
|
199
|
+
})
|
200
|
+
next_.sync
|
201
|
+
next_.begin_inner_price = next_.end_inner_price
|
202
|
+
next_.begin_inner_delta = next_.end_inner_delta
|
203
|
+
|
204
|
+
next_.begin_outer_price = next_.end_outer_price
|
205
|
+
next_.begin_outer_delta = next_.end_outer_delta
|
206
|
+
next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
|
207
|
+
next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
|
208
|
+
puts! next_, 'next_'
|
209
|
+
puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
|
210
|
+
@positions.push next_
|
211
|
+
end
|
212
|
+
@positions = @positions.reverse
|
213
|
+
end
|
214
|
+
|
215
|
+
def _prepare_short_debit_put_spread
|
216
|
+
@positions = []
|
217
|
+
(-@nn..@nn).each do |idx|
|
218
|
+
next_ = Iro::Position.new({
|
219
|
+
stock: @stock,
|
220
|
+
inner_strike: @prev.inner_strike - idx*@stock.options_price_increment,
|
221
|
+
outer_strike: @prev.outer_strike - idx*@stock.options_price_increment,
|
222
|
+
expires_on: @next_expires_on,
|
223
|
+
purse: @position.purse,
|
224
|
+
strategy: @position.strategy,
|
225
|
+
quantity: @position.quantity,
|
226
|
+
})
|
227
|
+
next_.sync
|
228
|
+
next_.begin_inner_price = next_.end_inner_price
|
229
|
+
next_.begin_inner_delta = next_.end_inner_delta
|
230
|
+
|
231
|
+
next_.begin_outer_price = next_.end_outer_price
|
232
|
+
next_.begin_outer_delta = next_.end_outer_delta
|
233
|
+
next_.next_gain_loss_amount = @prev.end_outer_price - @prev.end_inner_price
|
234
|
+
next_.next_gain_loss_amount += next_.begin_inner_price - next_.begin_outer_price
|
235
|
+
puts! next_, 'next_'
|
236
|
+
puts! next_.next_gain_loss_amount, 'next_gain_loss_amount'
|
237
|
+
@positions.push next_
|
238
|
+
end
|
68
239
|
end
|
69
240
|
|
70
241
|
def update
|
@@ -86,8 +257,11 @@ class Iro::PositionsController < Iro::ApplicationController
|
|
86
257
|
private
|
87
258
|
|
88
259
|
def set_lists
|
260
|
+
super
|
261
|
+
|
262
|
+
@purses_list = Iro::Purse.list
|
89
263
|
@strategies_list = Iro::Strategy.list(params[:long_or_short])
|
90
|
-
@stocks_list
|
264
|
+
@stocks_list = Iro::Stock.list
|
91
265
|
end
|
92
266
|
|
93
267
|
end
|
@@ -7,10 +7,11 @@ class Iro::PursesController < Iro::ApplicationController
|
|
7
7
|
@purse = Iro::Purse.new params[:purse].permit!
|
8
8
|
authorize! :create, @purse
|
9
9
|
if @purse.save
|
10
|
-
|
10
|
+
;
|
11
11
|
else
|
12
|
-
|
12
|
+
flash_alert @purse
|
13
13
|
end
|
14
|
+
redirect_to action: :index
|
14
15
|
end
|
15
16
|
|
16
17
|
def destroy
|
@@ -34,13 +35,15 @@ class Iro::PursesController < Iro::ApplicationController
|
|
34
35
|
@purse = Iro::Purse.find(params[:id])
|
35
36
|
authorize! :show, @purse
|
36
37
|
|
37
|
-
@positions = @purse.positions.includes( :strategy
|
38
|
-
).order({ expires_on: :desc })
|
38
|
+
@positions = @purse.positions.where( status: 'active' ).includes( :strategy
|
39
|
+
).order({ expires_on: :desc, stock: :desc })
|
39
40
|
|
40
41
|
@unit = @purse.unit # 12 ## pixels per dollar
|
41
42
|
@height = @purse.height # 100 ## pixels
|
42
43
|
@n_dollars = 100 ## dollars to each side of origin
|
43
44
|
|
45
|
+
calc_summary
|
46
|
+
|
44
47
|
render params[:template]
|
45
48
|
end
|
46
49
|
|
@@ -49,7 +52,7 @@ class Iro::PursesController < Iro::ApplicationController
|
|
49
52
|
authorize! :update, @purse
|
50
53
|
if @purse.update params[:purse].permit!
|
51
54
|
flash[:notice] = 'ok'
|
52
|
-
redirect_to purse_path(@purse)
|
55
|
+
redirect_to request.referrer # purse_path(@purse)
|
53
56
|
else
|
54
57
|
flash_alert @purse
|
55
58
|
render :edit
|
@@ -61,9 +64,60 @@ class Iro::PursesController < Iro::ApplicationController
|
|
61
64
|
##
|
62
65
|
private
|
63
66
|
|
67
|
+
## for one stock only!
|
68
|
+
def calc_summary
|
69
|
+
@max_loss_long = 0
|
70
|
+
@max_loss_short = 0
|
71
|
+
|
72
|
+
@max_gain_long = 0
|
73
|
+
@max_gain_short = 0
|
74
|
+
|
75
|
+
@gain_long = 0
|
76
|
+
@gain_short = 0
|
77
|
+
|
78
|
+
@begin_delta_long = 0
|
79
|
+
@begin_delta_short = 0
|
80
|
+
@end_delta_long = 0
|
81
|
+
@end_delta_short = 0
|
82
|
+
|
83
|
+
@positions.each do |pos|
|
84
|
+
if Iro::Strategy::LONG == pos.strategy.long_or_short
|
85
|
+
@max_loss_long += pos.max_loss * pos.q * 100
|
86
|
+
@max_gain_long += pos.max_gain * pos.q * 100
|
87
|
+
@gain_long += pos.net_amount * pos.q * 100
|
88
|
+
|
89
|
+
@begin_delta_long += pos.begin_delta * pos.q
|
90
|
+
@end_delta_long += pos.end_delta * pos.q
|
91
|
+
end
|
92
|
+
if Iro::Strategy::SHORT == pos.strategy.long_or_short
|
93
|
+
@max_loss_short += pos.max_loss * pos.q * 100
|
94
|
+
@max_gain_short += pos.max_gain * pos.q * 100
|
95
|
+
@gain_short += pos.net_amount * pos.q * 100
|
96
|
+
|
97
|
+
@begin_delta_short += pos.begin_delta * pos.q
|
98
|
+
@end_delta_short += pos.end_delta * pos.q
|
99
|
+
end
|
100
|
+
end
|
101
|
+
# @max_loss_long *= -1
|
102
|
+
# @max_loss_short *= -1
|
103
|
+
@begin_delta_short *= -1
|
104
|
+
@end_delta_short *= -1
|
105
|
+
if @gain_long < 0
|
106
|
+
@loss_long = @gain_long
|
107
|
+
@gain_long = nil
|
108
|
+
end
|
109
|
+
if @gain_short < 0
|
110
|
+
@loss_short = @gain_short
|
111
|
+
@gain_short = nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
64
115
|
def set_lists
|
116
|
+
super
|
117
|
+
|
65
118
|
# @profiles_list = Wco::Profile.list
|
66
|
-
@
|
119
|
+
# @tickers_list = [[nil,nil]] + Iro::Stock.active.map { |s| [ s.ticker, s.ticker ] }
|
120
|
+
@stocks_list = Iro::Stock.list
|
67
121
|
|
68
122
|
end
|
69
123
|
|