iron_warbler 2.0.7.26 → 2.0.7.28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/iron_warbler/purses.scss +31 -0
- data/app/assets/stylesheets/iron_warbler/utils.scss +28 -3
- data/app/controllers/iro/api/stocks_controller.rb +7 -4
- data/app/controllers/iro/positions_controller.rb +27 -21
- data/app/controllers/iro/stocks_controller.rb +20 -0
- data/app/models/iro/datapoint.rb +1 -1
- data/app/models/iro/option.rb +23 -11
- data/app/models/iro/position.rb +51 -53
- data/app/models/iro/{price_item.rb → priceitem.rb} +5 -1
- data/app/models/iro/purse.rb +9 -2
- data/app/models/iro/stock.rb +2 -0
- data/app/models/iro/strategy.rb +87 -50
- data/app/models/tda/option.rb +10 -4
- data/app/models/tda/stock.rb +13 -7
- data/app/views/iro/_main_header.haml +4 -3
- data/app/views/iro/api/stocks/index.json.jbuilder +5 -0
- data/app/views/iro/api/stocks/show.json.jbuilder +11 -0
- data/app/views/iro/api/stocks/show.json.jbuilder-bk +12 -0
- data/app/views/iro/positions/_form.haml +4 -2
- data/app/views/iro/positions/_gameui_short_credit_call_spread.haml +38 -0
- data/app/views/iro/positions/_header_short_credit_call_spread.haml +50 -0
- data/app/views/iro/positions/_new.haml +23 -0
- data/app/views/iro/positions/_prepare_short_credit_call_spread.haml +1 -0
- data/app/views/iro/purses/_form_extra_fields.haml +18 -22
- data/app/views/iro/purses/_header.haml +8 -17
- data/app/views/iro/purses/show.haml +3 -2
- data/app/views/iro/stocks/_form.haml +4 -3
- data/app/views/iro/stocks/edit.haml +4 -0
- data/app/views/iro/stocks/index.haml +21 -6
- data/app/views/iro/stocks/show.haml +5 -0
- data/app/views/iro/strategies/_form.haml +14 -11
- data/app/views/iro/strategies/_show.haml +1 -1
- data/config/routes.rb +2 -1
- data/lib/iro/engine.rb +1 -0
- data/lib/iron_warbler.rb +0 -2
- data/lib/tasks/iro_tasks.rake +2 -2
- metadata +13 -4
- data/app/views/iro/api/stocks/show.jbuilder +0 -11
data/app/models/iro/strategy.rb
CHANGED
@@ -8,56 +8,74 @@ class Iro::Strategy
|
|
8
8
|
field :slug
|
9
9
|
validates :slug, presence: true, uniqueness: true
|
10
10
|
|
11
|
-
|
11
|
+
field :description
|
12
|
+
|
13
|
+
LONG = 'is_long'
|
12
14
|
SHORT = 'is_short'
|
13
15
|
field :long_or_short, type: :string
|
14
16
|
validates :long_or_short, presence: true
|
15
17
|
|
16
|
-
field :description
|
17
|
-
|
18
|
-
has_many :positions, class_name: 'Iro::Position', inverse_of: :strategy
|
19
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
|
20
21
|
belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
|
21
22
|
has_and_belongs_to_many :purses, class_name: 'Iro::Purse', inverse_of: :strategies
|
22
23
|
|
23
|
-
KIND_COVERED_CALL
|
24
|
-
|
25
|
-
|
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'
|
26
30
|
KINDS = [ nil,
|
27
31
|
KIND_COVERED_CALL,
|
32
|
+
KIND_IRON_CONDOR,
|
33
|
+
KIND_LONG_CREDIT_PUT_SPREAD,
|
28
34
|
KIND_LONG_DEBIT_CALL_SPREAD,
|
35
|
+
KIND_SHORT_CREDIT_CALL_SPREAD,
|
29
36
|
KIND_SHORT_DEBIT_PUT_SPREAD,
|
30
37
|
]
|
31
38
|
field :kind
|
32
39
|
|
33
|
-
def
|
40
|
+
def put_call
|
34
41
|
case kind
|
35
|
-
when
|
36
|
-
'
|
37
|
-
when
|
38
|
-
'
|
39
|
-
when KIND_SHORT_DEBIT_PUT_SPREAD
|
40
|
-
'
|
41
|
-
|
42
|
-
'
|
42
|
+
when Iro::Strategy::KIND_LONG_DEBIT_CALL_SPREAD
|
43
|
+
put_call = 'CALL'
|
44
|
+
when Iro::Strategy::KIND_SHORT_CREDIT_CALL_SPREAD
|
45
|
+
put_call = 'CALL'
|
46
|
+
when Iro::Strategy::KIND_SHORT_DEBIT_PUT_SPREAD
|
47
|
+
put_call = 'PUT'
|
48
|
+
when Iro::Strategy::KIND_COVERED_CALL
|
49
|
+
put_call = 'CALL'
|
43
50
|
end
|
44
51
|
end
|
45
52
|
|
46
|
-
field :
|
47
|
-
field :threshold_delta,
|
48
|
-
field :threshold_netp,
|
49
|
-
field :
|
53
|
+
field :threshold_buffer_above_water, type: :float
|
54
|
+
field :threshold_delta, type: :float
|
55
|
+
field :threshold_netp, type: :float
|
56
|
+
field :threshold_dte, type: :integer, default: 1
|
50
57
|
|
51
|
-
field :next_inner_delta,
|
52
|
-
field :
|
53
|
-
field :
|
54
|
-
field :next_outer_strike,
|
55
|
-
field :next_spread_amount,
|
58
|
+
field :next_inner_delta, type: :float
|
59
|
+
field :next_inner_strike, type: :float
|
60
|
+
field :next_outer_delta, type: :float
|
61
|
+
field :next_outer_strike, type: :float
|
62
|
+
field :next_spread_amount, type: :float # e.g. $20 for a $2000 NVDA spread
|
56
63
|
field :next_buffer_above_water, type: :float
|
57
64
|
|
58
|
-
|
59
|
-
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
def begin_delta_covered_call p
|
71
|
+
p.inner.begin_delta
|
60
72
|
end
|
73
|
+
def begin_delta_long_debit_call_spread p
|
74
|
+
p.outer.begin_delta - p.inner.begin_delta
|
75
|
+
end
|
76
|
+
alias_method :begin_delta_short_debit_put_spread, :begin_delta_long_debit_call_spread
|
77
|
+
alias_method :begin_delta_short_credit_call_spread, :begin_delta_long_debit_call_spread
|
78
|
+
|
61
79
|
|
62
80
|
def breakeven_covered_call p
|
63
81
|
p.inner.strike + p.inner.begin_price
|
@@ -67,27 +85,32 @@ class Iro::Strategy
|
|
67
85
|
end
|
68
86
|
alias_method :breakeven_short_debit_put_spread, :breakeven_long_debit_call_spread
|
69
87
|
|
88
|
+
|
89
|
+
def end_delta_covered_call p
|
90
|
+
p.inner.end_delta
|
91
|
+
end
|
92
|
+
def end_delta_long_debit_call_spread p
|
93
|
+
p.outer.end_delta - p.inner.end_delta
|
94
|
+
end
|
95
|
+
alias_method :end_delta_short_debit_put_spread, :end_delta_long_debit_call_spread
|
96
|
+
alias_method :end_delta_short_credit_call_spread, :end_delta_long_debit_call_spread
|
97
|
+
|
98
|
+
|
70
99
|
def max_gain_covered_call p
|
71
100
|
p.inner.begin_price * 100 - 0.66 # @TODO: is this *100 really?
|
72
101
|
end
|
73
102
|
def max_gain_long_debit_call_spread p
|
74
|
-
## 100 *
|
103
|
+
## 100 * disallowed for gameui
|
75
104
|
( p.inner.strike - p.outer.strike - p.outer.begin_price + p.inner.begin_price ) # - 2*0.66
|
76
105
|
end
|
106
|
+
def max_gain_short_credit_call_spread p
|
107
|
+
p.inner.begin_price - p.outer.begin_price
|
108
|
+
end
|
77
109
|
def max_gain_short_debit_put_spread p
|
78
|
-
## 100 *
|
110
|
+
## 100 * disallowed for gameui
|
79
111
|
( p.outer.strike - p.inner.strike - p.outer.begin_price + p.inner.begin_price ) # - 2*0.66
|
80
112
|
end
|
81
113
|
|
82
|
-
def net_amount_covered_call p
|
83
|
-
( p.inner.begin_price - p.inner.end_price )
|
84
|
-
end
|
85
|
-
def net_amount_long_debit_call_spread p
|
86
|
-
outer = p.outer.end_price - p.outer.begin_price
|
87
|
-
inner = p.inner.begin_price - p.inner.end_price
|
88
|
-
out = ( outer + inner )
|
89
|
-
end
|
90
|
-
alias_method :net_amount_short_debit_put_spread, :net_amount_long_debit_call_spread
|
91
114
|
|
92
115
|
def max_loss_covered_call p
|
93
116
|
p.inner.begin_price*10 # just suppose 10,000%
|
@@ -98,22 +121,31 @@ class Iro::Strategy
|
|
98
121
|
def max_loss_short_debit_put_spread p # different
|
99
122
|
out = p.inner.strike - p.outer.strike
|
100
123
|
end
|
124
|
+
def max_loss_short_credit_call_spread p
|
125
|
+
out = p.outer.strike - p.inner.strike
|
126
|
+
end
|
101
127
|
|
102
|
-
|
103
|
-
|
128
|
+
|
129
|
+
def net_amount_covered_call p
|
130
|
+
( p.inner.begin_price - p.inner.end_price )
|
104
131
|
end
|
105
|
-
def
|
106
|
-
p.outer.
|
132
|
+
def net_amount_long_debit_call_spread p
|
133
|
+
outer = p.outer.end_price - p.outer.begin_price
|
134
|
+
inner = p.inner.begin_price - p.inner.end_price
|
135
|
+
out = ( outer + inner )
|
107
136
|
end
|
108
|
-
alias_method :
|
137
|
+
alias_method :net_amount_short_credit_call_spread , :net_amount_long_debit_call_spread
|
138
|
+
alias_method :net_amount_short_debit_put_spread, :net_amount_long_debit_call_spread
|
109
139
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
140
|
+
|
141
|
+
## 2024-05-09 @TODO
|
142
|
+
def next_inner_strike_on expires_on
|
143
|
+
outs = Tda::Option.get_quotes({
|
144
|
+
contractType: put_call,
|
145
|
+
expirationDate: expires_on,
|
146
|
+
ticker: stock.ticker,
|
147
|
+
})
|
115
148
|
end
|
116
|
-
alias_method :end_delta_short_debit_put_spread, :end_delta_long_debit_call_spread
|
117
149
|
|
118
150
|
|
119
151
|
|
@@ -196,10 +228,15 @@ class Iro::Strategy
|
|
196
228
|
end
|
197
229
|
|
198
230
|
|
231
|
+
## scopes
|
232
|
+
|
233
|
+
def self.for_ticker ticker
|
234
|
+
where( ticker: ticker )
|
235
|
+
end
|
199
236
|
|
200
237
|
|
201
238
|
def to_s
|
202
|
-
|
239
|
+
slug
|
203
240
|
end
|
204
241
|
def self.list long_or_short = nil
|
205
242
|
these = long_or_short ? where( long_or_short: long_or_short ) : all
|
data/app/models/tda/option.rb
CHANGED
@@ -4,7 +4,8 @@ require 'httparty'
|
|
4
4
|
class Tda::Option
|
5
5
|
|
6
6
|
include ::HTTParty
|
7
|
-
base_uri 'https://api.tdameritrade.com'
|
7
|
+
# base_uri 'https://api.tdameritrade.com'
|
8
|
+
base_uri 'https://api.schwabapi.com/marketdata/v1'
|
8
9
|
|
9
10
|
|
10
11
|
##
|
@@ -68,7 +69,7 @@ class Tda::Option
|
|
68
69
|
## 2023-02-06 _vp_ :: Continue.
|
69
70
|
##
|
70
71
|
def self.get_quotes params
|
71
|
-
|
72
|
+
puts! params, 'Tda::Option#get_quotes'
|
72
73
|
opts = {}
|
73
74
|
|
74
75
|
#
|
@@ -100,8 +101,13 @@ class Tda::Option
|
|
100
101
|
query = { apikey: ::TD_AMERITRADE[:apiKey] }.merge opts
|
101
102
|
# puts! query, 'input opts'
|
102
103
|
|
103
|
-
|
104
|
-
|
104
|
+
headers = {
|
105
|
+
Authorize: "Bearer #{::TD_AMERITRADE[:access_token]}",
|
106
|
+
}
|
107
|
+
|
108
|
+
|
109
|
+
path = "/chains"
|
110
|
+
out = self.get path, { headers: headers, query: query }
|
105
111
|
timestamp = DateTime.parse out.headers['date']
|
106
112
|
## out = HTTParty.get "https://api.tdameritrade.com#{path}", { query: query }
|
107
113
|
out = out.parsed_response.deep_symbolize_keys
|
data/app/models/tda/stock.rb
CHANGED
@@ -3,7 +3,7 @@ require 'httparty'
|
|
3
3
|
|
4
4
|
class Tda::Stock
|
5
5
|
include ::HTTParty
|
6
|
-
base_uri 'https://api.
|
6
|
+
base_uri 'https://api.schwabapi.com/marketdata/v1'
|
7
7
|
|
8
8
|
## alias
|
9
9
|
def self.get_quote which
|
@@ -13,9 +13,15 @@ class Tda::Stock
|
|
13
13
|
## tickers = "GME"
|
14
14
|
## tickers = "NVDA,GME"
|
15
15
|
def self.get_quotes tickers
|
16
|
-
path = "/
|
17
|
-
|
16
|
+
path = "/quotes"
|
17
|
+
headers = {
|
18
|
+
accept: 'application/json',
|
19
|
+
Authorization: "Bearer #{::SCHWAB_DATA[:access_token]}",
|
20
|
+
}
|
21
|
+
inns = self.get path, { headers: headers, query: { symbols: tickers } }
|
18
22
|
inns = inns.parsed_response
|
23
|
+
# puts! inns, 'parsed response'
|
24
|
+
|
19
25
|
if [ NilClass, String ].include?( inns.class )
|
20
26
|
return []
|
21
27
|
end
|
@@ -23,8 +29,9 @@ class Tda::Stock
|
|
23
29
|
inns[k] = v.deep_symbolize_keys
|
24
30
|
end
|
25
31
|
outs = []
|
26
|
-
inns.each do |symbol,
|
27
|
-
|
32
|
+
inns.each do |symbol, _obj|
|
33
|
+
obj = _obj[:quote]
|
34
|
+
outs.push ::Iro::Priceitem.create!({
|
28
35
|
putCall: 'STOCK',
|
29
36
|
symbol: symbol,
|
30
37
|
ticker: symbol,
|
@@ -37,8 +44,7 @@ class Tda::Stock
|
|
37
44
|
closePrice: obj[:closePrice],
|
38
45
|
highPrice: obj[:highPrice],
|
39
46
|
lowPrice: obj[:lowPrice],
|
40
|
-
|
41
|
-
timestamp: Time.at( obj[:quoteTimeInLong]/1000 ),
|
47
|
+
timestamp: Time.at( obj[:quoteTime]/1000 ),
|
42
48
|
totalVolume: obj[:totalVolume],
|
43
49
|
mark: obj[:mark],
|
44
50
|
exchangeName: obj[:exchangeName],
|
@@ -4,9 +4,9 @@
|
|
4
4
|
|
5
5
|
%i.fa.fa-compress.collapse-expand#collapseHeaderTrading
|
6
6
|
Wco Trading
|
7
|
-
.
|
8
|
-
.d-flex
|
9
|
-
%ul
|
7
|
+
.W
|
8
|
+
.d-flex.flex-wrap
|
9
|
+
%ul
|
10
10
|
%li
|
11
11
|
= link_to "Stocks (#{Iro::Stock.all.length})", stocks_path
|
12
12
|
= link_to '[sync]', sync_stocks_path
|
@@ -26,6 +26,7 @@
|
|
26
26
|
%li
|
27
27
|
= link_to p, purse_path(p)
|
28
28
|
= link_to '[ui]', purse_gameui_path(p)
|
29
|
+
|
29
30
|
.a
|
30
31
|
= link_to 'Strategies', strategies_path
|
31
32
|
%ul
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
json.priceitems do
|
3
|
+
json.array! @datapoints do |p|
|
4
|
+
json.date p[:quote_at].in_time_zone('UTC').to_date
|
5
|
+
json.quote_at p[:quote_at]
|
6
|
+
json.open p[:open]
|
7
|
+
json.high p[:high]
|
8
|
+
json.low p[:low]
|
9
|
+
json.close p[:value]
|
10
|
+
json.volume p[:volume]
|
11
|
+
end
|
12
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
- long_or_short = position.long_or_short || position.strategy&.long_or_short || params[:long_or_short]
|
3
|
+
|
4
|
+
.positions--form{ class: params[:long_or_short] || long_or_short }
|
3
5
|
= form_for position do |f|
|
4
6
|
.actions
|
5
7
|
= f.submit
|
@@ -18,7 +20,7 @@
|
|
18
20
|
|
19
21
|
.field
|
20
22
|
%label long or short?
|
21
|
-
= f.select :long_or_short, options_for_select([nil, Iro::Strategy::LONG, Iro::Strategy::SHORT], selected:
|
23
|
+
= f.select :long_or_short, options_for_select([nil, Iro::Strategy::LONG, Iro::Strategy::SHORT], selected: long_or_short )
|
22
24
|
|
23
25
|
%label Strategy
|
24
26
|
= f.select :strategy_id, options_for_select( @strategies_list, selected: position.strategy_id )
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
- pos = position
|
3
|
+
- stock = pos.stock
|
4
|
+
- nearest_strike = stock.last.round
|
5
|
+
- u = pos.purse.unit # pixels per dollar
|
6
|
+
|
7
|
+
.collapse-expand.d-flex{ id: "gameui-pos-#{pos.id}" }
|
8
|
+
[<>]
|
9
|
+
.maxwidth= render "/iro/positions/header", pos: pos
|
10
|
+
.a
|
11
|
+
= render "/iro/positions/header_#{pos.strategy.kind}", pos: pos
|
12
|
+
.StockCoordinatesW
|
13
|
+
.StockCoordinates{ style: "height: #{pos.q() *pos.purse.height}px " }
|
14
|
+
.grid= render "/iro/stocks/grid_#{pos.strategy.long_or_short}", stock: stock, position: pos
|
15
|
+
|
16
|
+
.Origin{ style: "left: #{ ( nearest_strike - stock.last )* u}px" }
|
17
|
+
.label Last: #{pp_amount stock.last}
|
18
|
+
.c
|
19
|
+
|
20
|
+
- left = "#{ ( pos.outer.strike - stock.last ).abs() *-1*u}px"
|
21
|
+
- width = "#{ ( pos.inner.strike - pos.outer.strike ).abs() *u}px"
|
22
|
+
.PositionW{ class: pos.strategy.kind, style: "left: #{left}; width: #{width}; " }
|
23
|
+
.Position
|
24
|
+
.MaxGain{ style: "width: #{pos.max_gain * u}px" }
|
25
|
+
.RollGuide
|
26
|
+
|
27
|
+
- if pos.net_amount >= 0
|
28
|
+
.Net.NetPositive{ style: "width: #{ (pos.net_amount) * u }px; right: 0" }
|
29
|
+
.label
|
30
|
+
net
|
31
|
+
= pp_amount pos.net_amount
|
32
|
+
- else
|
33
|
+
.Net.NetNegative{ style: "width: #{ (-1 * pos.net_amount) * u }px; left: 100%" }
|
34
|
+
.label
|
35
|
+
net
|
36
|
+
= pp_amount pos.net_amount
|
37
|
+
.c
|
38
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
-##
|
3
|
+
-## Same file for the spreads
|
4
|
+
-##
|
5
|
+
|
6
|
+
- collapse_key ||= pos.id
|
7
|
+
%i.fa.fa-expand.collapse-expand.floaty-collapse{ id: "gameui-pos-detail-#{collapse_key}" }
|
8
|
+
.maxwidth
|
9
|
+
|
10
|
+
%table.bordered{ class: pos.long_or_short }
|
11
|
+
%tbody.long-or-short-item
|
12
|
+
%tr
|
13
|
+
%td <b>#{pp_amount pos.outer.strike}</b>
|
14
|
+
%td= pp_amount pos.outer.begin_price
|
15
|
+
%td= pos.outer.begin_delta
|
16
|
+
%td -
|
17
|
+
%td= pp_amount pos.outer.end_price
|
18
|
+
%td= pp_delta pos.outer.end_delta
|
19
|
+
%tr
|
20
|
+
%td <b>#{pp_amount pos.inner.strike}</b>
|
21
|
+
%td= pp_amount pos.inner.begin_price
|
22
|
+
%td= pp_delta pos.inner.begin_delta
|
23
|
+
%td -
|
24
|
+
%td= pp_amount pos.inner.end_price
|
25
|
+
%td= pp_delta pos.inner.end_delta
|
26
|
+
|
27
|
+
.header.d-flex
|
28
|
+
%ul.mb-0
|
29
|
+
%li
|
30
|
+
-## yes *100
|
31
|
+
<b>max gain:</b> #{pp_amount pos.max_gain} :: #{pp_amount pos.max_gain * 100 * pos.q}
|
32
|
+
-# %li
|
33
|
+
-# <b>end_outer,inner_price:</b> #{pp_amount pos.end_outer_price} -> #{pp_amount pos.end_inner_price}
|
34
|
+
-#
|
35
|
+
-# -## yes *100
|
36
|
+
-# <b>max loss:</b> #{pp_amount pos.max_loss} :: #{pp_amount pos.max_loss * 100 * pos.q}
|
37
|
+
|
38
|
+
%li
|
39
|
+
<b>Exposure:</b> #{pp_amount pos.max_loss() *100*pos.q()}
|
40
|
+
%li
|
41
|
+
<b>Breakeven:</b> #{pp_amount pos.inner.strike + pos.max_gain()}
|
42
|
+
- ## no *100
|
43
|
+
%li <b>Net:</b> #{pp_amount pos.net_amount} :: #{pp_amount pos.net_amount() *100*pos.q} <i>#{pp_percent pos.net_percent}</i>
|
44
|
+
|
45
|
+
- if 'prepare' == pos.status
|
46
|
+
%ul.mb-0
|
47
|
+
%li
|
48
|
+
<b>next_gain_loss_amount:</b> #{pp_amount pos.next_gain_loss_amount}
|
49
|
+
\:: #{pp_amount pos.next_gain_loss_amount * 100 * pos.q}
|
50
|
+
<i>#{pp_percent pos.next_gain_loss_amount/pos.max_loss*-1}</i>
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
.d-flex
|
3
|
+
.Card
|
4
|
+
= form_for Iro::Position.new(strategy: Iro::Strategy.new), url: new_position_path, method: :get do |f|
|
5
|
+
= hidden_field_tag 'position[purse_id]', purse.id
|
6
|
+
|
7
|
+
.formrow-v1
|
8
|
+
.label +Position
|
9
|
+
|
10
|
+
.d-flex.flex-column
|
11
|
+
%label Strategy
|
12
|
+
= f.select :strategy_id, options_for_select(@strategies_list)
|
13
|
+
|
14
|
+
.d-flex.flex-column
|
15
|
+
%label Expires on
|
16
|
+
= f.select :expires_on, options_for_select( Iro::Option.expirations_list )
|
17
|
+
|
18
|
+
.d-flex.flex-column
|
19
|
+
%label Q
|
20
|
+
= f.text_field :quantity, class: 'w-3em'
|
21
|
+
|
22
|
+
= f.submit '>'
|
23
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
app/views/iro/positions/_prepare_short_debit_put_spread.haml
|
@@ -1,30 +1,26 @@
|
|
1
1
|
|
2
|
-
.
|
3
|
-
%label unit
|
4
|
-
= f.number_field :unit
|
5
|
-
px/usd
|
6
|
-
|
7
|
-
%label height
|
8
|
-
= f.number_field :height
|
9
|
-
px/q
|
10
|
-
|
2
|
+
.purses--form-extra-fields
|
11
3
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
4
|
+
.d-flex.flex-wrap
|
5
|
+
%label unit
|
6
|
+
= f.number_field :unit
|
7
|
+
.unit px/usd
|
16
8
|
|
9
|
+
%label height
|
10
|
+
= f.number_field :height
|
11
|
+
.unit px/q
|
17
12
|
|
13
|
+
%label summary_unit
|
14
|
+
= f.number_field :summary_unit, step: 0.000001
|
15
|
+
.unit px/usd
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
.d-flex.flex-wrap
|
18
|
+
%label mark_every_n_usd
|
19
|
+
= f.number_field :mark_every_n_usd, step: 0.01
|
20
|
+
.unit
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
%label n_next_positions
|
23
|
+
= f.number_field :n_next_positions
|
24
|
+
.unit
|
29
25
|
|
30
26
|
|
@@ -4,30 +4,21 @@
|
|
4
4
|
.header
|
5
5
|
%h5.title
|
6
6
|
Purse `#{purse.slug}`
|
7
|
+
-# (#{purse.positions.length})
|
8
|
+
|
7
9
|
= link_to '[~]', edit_purse_path(purse)
|
8
10
|
= link_to '[table]', purse_path(purse)
|
9
11
|
= link_to '[gameUI]', purse_gameui_path(purse)
|
10
|
-
(#{purse.positions.length})
|
11
12
|
|
12
|
-
|
13
|
+
%ul
|
14
|
+
%li <b>Total:</b> #{pp_amount purse.balance}
|
15
|
+
%li <b>Available:</b> #{pp_amount purse.available}
|
13
16
|
|
14
|
-
.Card.d-flex
|
15
|
-
= form_for Iro::Position.new(strategy: Iro::Strategy.new), url: new_position_path, method: :get do |f|
|
16
|
-
.a +Position
|
17
|
-
= hidden_field_tag 'position[purse_id]', purse.id
|
18
|
-
.field
|
19
|
-
= f.select :strategy_id, options_for_select(@strategies_list)
|
20
|
-
-# .field
|
21
|
-
-# = f.radio_button :long_or_short, :long
|
22
|
-
-# %label long
|
23
|
-
-# = f.radio_button :long_or_short, :short
|
24
|
-
-# %label short
|
25
|
-
= f.submit 'Go'
|
26
|
-
-# = link_to '[+position]', new_position_path({ purse_id: purse.id })
|
27
|
-
-# = link_to '[+short]', new_position_path({ purse_id: purse.id, long_or_short: Iro::Strategy::SHORT })
|
28
17
|
|
18
|
+
= render '/iro/positions/new', purse: purse
|
29
19
|
|
30
|
-
|
20
|
+
|
21
|
+
- if true # params[:template] == 'gameui'
|
31
22
|
.mini-inputs
|
32
23
|
= form_for purse, html: { class: 'd-flex' } do |f|
|
33
24
|
= render '/iro/purses/form_extra_fields', f: f
|
@@ -1,8 +1,9 @@
|
|
1
1
|
|
2
2
|
.purses-show.padded
|
3
|
-
.row
|
4
|
-
.col-md-6
|
3
|
+
.row.no-gutters
|
4
|
+
.col-md-6.pr-3
|
5
5
|
= render '/iro/purses/header', purse: @purse
|
6
6
|
.col-md-6
|
7
7
|
= render '/iro/purses/summary', purse: @purse, collapse_key: 'views-show'
|
8
|
+
|
8
9
|
= render '/iro/positions/table', positions: @positions
|
@@ -7,14 +7,15 @@
|
|
7
7
|
- if stock.new_record?
|
8
8
|
%label New
|
9
9
|
- else
|
10
|
+
%label status
|
10
11
|
= f.select :status, options_for_select([ Iro::Stock::STATUS_ACTIVE, Iro::Stock::STATUS_INACTIVE ], selected: stock.status)
|
11
12
|
.field
|
12
13
|
= f.label :ticker
|
13
14
|
= f.text_field :ticker
|
14
15
|
|
15
|
-
.field
|
16
|
-
|
17
|
-
|
16
|
+
-# .field
|
17
|
+
-# %label Last
|
18
|
+
-# = f.number_field :last, placeholder: '80.0', step: 0.01
|
18
19
|
|
19
20
|
.field
|
20
21
|
%label options price increment
|
@@ -1,10 +1,25 @@
|
|
1
1
|
|
2
|
-
.stocks
|
2
|
+
.stocks-index.maxwidth
|
3
3
|
.maxwidth
|
4
4
|
%h5 Stocks
|
5
5
|
|
6
|
-
%
|
7
|
-
|
8
|
-
%
|
9
|
-
|
10
|
-
|
6
|
+
%table.bordered.padded
|
7
|
+
%thead
|
8
|
+
%tr
|
9
|
+
%td Ticker
|
10
|
+
%td last price
|
11
|
+
%td n priceitems
|
12
|
+
%tbody
|
13
|
+
- @stocks.each do |stock|
|
14
|
+
%tr
|
15
|
+
%td
|
16
|
+
= link_to '[~]', edit_stock_path(stock)
|
17
|
+
= link_to '[api]', stock_path(stock, format: :json)
|
18
|
+
<b>#{stock.ticker}</b>
|
19
|
+
%td
|
20
|
+
#{pp_amount stock.last}
|
21
|
+
%td
|
22
|
+
= stock.priceitems.length
|
23
|
+
|
24
|
+
%hr
|
25
|
+
= render 'iro/stocks/form', stock: Iro::Stock.new
|