iron_warbler 2.0.7.7 → 2.0.7.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -16
- data/app/assets/javascript/iron_warbler/application.js +3 -0
- data/app/assets/stylesheets/iron_warbler/positions.scss +47 -0
- data/app/assets/stylesheets/iron_warbler/strategies.scss +0 -0
- data/app/assets/stylesheets/iron_warbler/utils.css +44 -0
- data/app/controllers/iro/alerts_controller.rb +6 -6
- data/app/controllers/iro/application_controller.rb +3 -2
- data/app/controllers/iro/datapoints_controller.rb +0 -2
- data/app/controllers/iro/positions_controller.rb +62 -0
- data/app/controllers/iro/profiles_controller.rb +0 -2
- data/app/controllers/iro/purses_controller.rb +65 -0
- data/app/controllers/iro/stocks_controller.rb +11 -4
- data/app/controllers/iro/strategies_controller.rb +66 -0
- data/app/models/iro/alert.rb +15 -4
- data/app/models/iro/datapoint.rb +108 -3
- data/app/models/iro/date.rb +10 -0
- data/app/models/iro/option.rb +13 -5
- data/app/models/iro/position.rb +222 -0
- data/app/models/iro/price_item.rb +5 -2
- data/app/models/iro/purse.rb +17 -0
- data/app/models/iro/stock.rb +19 -8
- data/app/models/iro/strategy.rb +38 -0
- data/app/models/tda/option.rb +137 -0
- data/app/views/iro/_analytics.erb +16 -0
- data/app/views/iro/_main_header.haml +23 -0
- data/app/views/iro/alerts/index.haml +1 -1
- data/app/views/iro/positions/_form.haml +59 -0
- data/app/views/iro/positions/_reasons.haml +4 -0
- data/app/views/iro/positions/_table.haml +137 -0
- data/app/views/iro/positions/edit.haml +4 -0
- data/app/views/iro/positions/new.haml +4 -0
- data/app/views/iro/purses/_form.haml +9 -0
- data/app/views/iro/purses/edit.haml +3 -0
- data/app/views/iro/purses/index.haml +11 -0
- data/app/views/iro/purses/show.haml +10 -0
- data/app/views/iro/stocks/_form.haml +4 -0
- data/app/views/iro/strategies/_form.haml +37 -0
- data/app/views/iro/strategies/_header.haml +8 -0
- data/app/views/iro/strategies/_show.haml +18 -0
- data/app/views/iro/strategies/_table.haml +18 -0
- data/app/views/iro/strategies/edit.haml +3 -0
- data/app/views/iro/strategies/new.haml +3 -0
- data/app/views/layouts/iro/application.haml +48 -13
- data/config/initializers/assets.rb +10 -0
- data/config/routes.rb +6 -0
- data/lib/iron_warbler.rb +4 -1
- data/lib/tasks/db_tasks.rake +54 -1
- data/lib/tasks/iro_tasks.rake +35 -0
- data/lib/tasks/iro_tasks.rake-old +128 -0
- metadata +122 -40
- data/app/assets/stylesheets/iron_warbler/main.css +0 -13
- data/app/assets/stylesheets/scaffold.css +0 -80
- data/app/models/iro/application_record.rb +0 -4
- data/app/models/iro/profile.rb +0 -4
- data/app/views/iro/alerts/edit.html.erb +0 -6
- data/app/views/iro/alerts/new.html.erb +0 -5
- data/app/views/iro/alerts/show.html.erb +0 -34
- data/app/views/iro/profiles/_form.html.erb +0 -32
- data/app/views/iro/profiles/edit.html.erb +0 -6
- data/app/views/iro/profiles/index.html.erb +0 -31
- data/app/views/iro/profiles/new.html.erb +0 -5
- data/app/views/iro/profiles/show.html.erb +0 -19
- data/db/migrate/20231210204830_create_iro_profiles.rb +0 -12
- data/db/migrate/20231210205837_create_iro_alerts.rb +0 -16
- data/db/migrate/20231219204329_create_dates.rb +0 -13
- data/db/migrate/20231219205644_create_datapoint.rb +0 -15
- data/db/migrate/20231220193201_create_stocks.rb +0 -11
- data/db/migrate/20231220194903_add_alert_status.rb +0 -5
- data/db/migrate/20231220223730_create_iro_price_item.rb +0 -57
- /data/app/models/tda/{api.rb → stock.rb} +0 -0
@@ -0,0 +1,222 @@
|
|
1
|
+
|
2
|
+
class Iro::Position
|
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
|
+
belongs_to :strategy, class_name: 'Iro::Strategy', inverse_of: :positions
|
16
|
+
|
17
|
+
field :ticker
|
18
|
+
validates :ticker, presence: true
|
19
|
+
index({ purse_id: 1, ticker: 1 })
|
20
|
+
|
21
|
+
KINDS = [ nil, 'covered_call', 'credit_put_spread', 'credit_call_spread' ]
|
22
|
+
field :kind
|
23
|
+
|
24
|
+
field :strike, type: :float
|
25
|
+
validates :strike, presence: true
|
26
|
+
|
27
|
+
field :expires_on
|
28
|
+
validates :expires_on, presence: true
|
29
|
+
|
30
|
+
field :quantity, type: :integer
|
31
|
+
validates :quantity, presence: true
|
32
|
+
|
33
|
+
field :begin_on
|
34
|
+
field :begin_price, type: :float
|
35
|
+
field :begin_delta, type: :float
|
36
|
+
|
37
|
+
field :end_on
|
38
|
+
field :end_price, type: :float
|
39
|
+
field :end_delta, type: :float
|
40
|
+
|
41
|
+
field :net_amount
|
42
|
+
field :net_percent
|
43
|
+
|
44
|
+
def current_underlying_strike
|
45
|
+
Iro::Stock.find_by( ticker: ticker ).last
|
46
|
+
end
|
47
|
+
|
48
|
+
def refresh
|
49
|
+
out = Tda::Option.get_quote({
|
50
|
+
contractType: 'CALL',
|
51
|
+
strike: strike,
|
52
|
+
expirationDate: expires_on,
|
53
|
+
ticker: ticker,
|
54
|
+
})
|
55
|
+
update({
|
56
|
+
end_delta: out[:delta],
|
57
|
+
end_price: out[:last],
|
58
|
+
})
|
59
|
+
print '_'
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
field :next_delta, type: :float
|
64
|
+
field :next_outcome, type: :float
|
65
|
+
field :next_symbol
|
66
|
+
field :next_mark
|
67
|
+
field :next_reasons, type: :array, default: []
|
68
|
+
field :should_rollp, type: :float
|
69
|
+
|
70
|
+
def should_roll?
|
71
|
+
puts! 'shold_roll?'
|
72
|
+
|
73
|
+
update({
|
74
|
+
next_reasons: [],
|
75
|
+
next_symbol: nil,
|
76
|
+
next_delta: nil,
|
77
|
+
})
|
78
|
+
|
79
|
+
if must_roll?
|
80
|
+
out = 1.0
|
81
|
+
elsif can_roll?
|
82
|
+
|
83
|
+
if end_delta < strategy.threshold_delta
|
84
|
+
next_reasons.push "delta is lower than threshold"
|
85
|
+
out = 0.91
|
86
|
+
elsif 1 - end_price/begin_price > strategy.threshold_netp
|
87
|
+
next_reasons.push "made enough percent profit (dubious)"
|
88
|
+
out = 0.61
|
89
|
+
else
|
90
|
+
next_reasons.push "neutral"
|
91
|
+
out = 0.33
|
92
|
+
end
|
93
|
+
|
94
|
+
else
|
95
|
+
out = 0.0
|
96
|
+
end
|
97
|
+
|
98
|
+
update({
|
99
|
+
next_delta: next_position[:delta],
|
100
|
+
next_outcome: next_position[:mark] - end_price,
|
101
|
+
next_symbol: next_position[:symbol],
|
102
|
+
next_mark: next_position[:mark],
|
103
|
+
should_rollp: out,
|
104
|
+
# status: Iro::Position::STATE_PROPOSED,
|
105
|
+
})
|
106
|
+
|
107
|
+
puts! next_reasons, 'next_reasons'
|
108
|
+
puts! out, 'out'
|
109
|
+
return out > 0.5
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
## expires_on = cc.expires_on ; nil
|
114
|
+
def can_roll?
|
115
|
+
## only if less than 7 days left
|
116
|
+
( expires_on.to_date - Time.now.to_date ).to_i < 7
|
117
|
+
end
|
118
|
+
|
119
|
+
## If I'm near below water
|
120
|
+
##
|
121
|
+
## expires_on = cc.expires_on ; strategy = cc.strategy ; strike = cc.strike ; nil
|
122
|
+
def must_roll?
|
123
|
+
if ( current_underlying_strike + strategy.buffer_above_water ) > strike
|
124
|
+
return true
|
125
|
+
end
|
126
|
+
## @TODO: This one should not happen, I should log appropriately. _vp_ 2023-03-19
|
127
|
+
if ( expires_on.to_date - Time.now.to_date ).to_i < 1
|
128
|
+
return true
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
## strike = cc.strike ; strategy = cc.strategy ; nil
|
133
|
+
def near_below_water?
|
134
|
+
strike < current_underlying_strike + strategy.buffer_above_water
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
## 2023-03-18 _vp_ Continue.
|
140
|
+
## 2023-03-19 _vp_ Continue.
|
141
|
+
## 2023-08-05 _vp_ an Important method
|
142
|
+
##
|
143
|
+
## expires_on = cc.expires_on ; strategy = cc.strategy ; ticker = cc.ticker ; end_price = cc.end_price ; next_expires_on = cc.next_expires_on ; nil
|
144
|
+
##
|
145
|
+
## out.map { |p| [ p[:strikePrice], p[:delta] ] }
|
146
|
+
##
|
147
|
+
def next_position
|
148
|
+
return @next_position if @next_position
|
149
|
+
return {} if ![ STATUS_ACTIVE, STATUS_PROPOSED ].include?( status )
|
150
|
+
|
151
|
+
## 7 days ahead - not configurable so far
|
152
|
+
out = Tda::Option.get_quotes({
|
153
|
+
ticker: ticker,
|
154
|
+
expirationDate: next_expires_on,
|
155
|
+
contractType: 'CALL',
|
156
|
+
})
|
157
|
+
|
158
|
+
## above_water
|
159
|
+
if strategy.buffer_above_water.present?
|
160
|
+
out = out.select do |i|
|
161
|
+
i[:strikePrice] > current_underlying_strike + strategy.buffer_above_water
|
162
|
+
end
|
163
|
+
# next_reasons.push "buffer_above_water above #{current_underlying_strike + strategy.buffer_above_water}"
|
164
|
+
end
|
165
|
+
|
166
|
+
if near_below_water?
|
167
|
+
msg = "Panic! climb at a loss. Skip the rest of the calculation."
|
168
|
+
next_reasons.push msg
|
169
|
+
## @TODO: if not enough money in the purse, cannot roll? 2023-03-19
|
170
|
+
|
171
|
+
# byebug
|
172
|
+
|
173
|
+
## Take a small loss here.
|
174
|
+
prev = nil
|
175
|
+
out.each_with_index do |i, idx|
|
176
|
+
next if idx == 0
|
177
|
+
if i[:last] < end_price
|
178
|
+
prev ||= i
|
179
|
+
end
|
180
|
+
end
|
181
|
+
out = [ prev ]
|
182
|
+
|
183
|
+
else
|
184
|
+
## Normal flow, making money.
|
185
|
+
## @TODO: test! _vp_ 2023-03-19
|
186
|
+
|
187
|
+
## next_min_strike
|
188
|
+
if strategy.next_min_strike.present?
|
189
|
+
out = out.select do |i|
|
190
|
+
i[:strikePrice] >= strategy.next_min_strike
|
191
|
+
end
|
192
|
+
# next_reasons.push "next_min_strike above #{strategy.next_min_strike}"
|
193
|
+
end
|
194
|
+
# json_puts! out.map { |p| [p[:delta], p[:symbol]] }, 'next_min_strike'
|
195
|
+
|
196
|
+
## max_delta
|
197
|
+
if strategy.next_max_delta.present?
|
198
|
+
out = out.select do |i|
|
199
|
+
i[:delta] = 0.0 if i[:delta] == "NaN"
|
200
|
+
i[:delta] <= strategy.next_max_delta
|
201
|
+
end
|
202
|
+
# next_reasons.push "next_max_delta below #{strategy.next_max_delta}"
|
203
|
+
end
|
204
|
+
# json_puts! out.map { |p| [p[:delta], p[:symbol]] }, 'next_max_delta'
|
205
|
+
end
|
206
|
+
|
207
|
+
@next_position = out[0] || {}
|
208
|
+
end
|
209
|
+
|
210
|
+
## @TODO: Test this. _vp_ 2023-04-01
|
211
|
+
def next_expires_on
|
212
|
+
out = expires_on.to_time + 7.days
|
213
|
+
while !out.friday?
|
214
|
+
out = out + 1.day
|
215
|
+
end
|
216
|
+
while !out.workday?
|
217
|
+
out = out - 1.day
|
218
|
+
end
|
219
|
+
return out
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
class Iro::Purse
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
store_in collection: 'iro_purses'
|
6
|
+
|
7
|
+
field :slug
|
8
|
+
validates :slug, presence: true, uniqueness: true
|
9
|
+
index({ slug: -1 }, { unique: true })
|
10
|
+
|
11
|
+
has_many :positions, class_name: 'Iro::Position', inverse_of: :purse
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
slug
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/app/models/iro/stock.rb
CHANGED
@@ -1,18 +1,29 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
self.table_name = 'iro_stocks'
|
2
|
+
class Iro::Stock
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
store_in collection: 'iro_stocks'
|
7
6
|
|
8
7
|
STATUS_ACTIVE = 'active'
|
9
8
|
STATUS_INACTIVE = 'inactive'
|
10
|
-
STATUSES = [ 'active', 'inactive' ]
|
9
|
+
STATUSES = [ nil, 'active', 'inactive' ]
|
10
|
+
def self.active
|
11
|
+
where( status: STATUS_ACTIVE )
|
12
|
+
end
|
13
|
+
field :status
|
11
14
|
|
15
|
+
field :ticker
|
12
16
|
validates :ticker, uniqueness: true, presence: true
|
13
17
|
|
14
|
-
|
15
|
-
|
18
|
+
field :last, type: :float
|
19
|
+
|
20
|
+
def self.list
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.tickers_list
|
24
|
+
[nil] + all.map( &:ticker )
|
16
25
|
end
|
17
26
|
|
27
|
+
# has_many :strategies, class_name: 'Iro::Strategy', inverse_of: :stock
|
28
|
+
|
18
29
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
class Iro::Strategy
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
store_in collection: 'iro_strategies'
|
6
|
+
|
7
|
+
field :slug
|
8
|
+
validates :slug, presence: true, uniqueness: true
|
9
|
+
|
10
|
+
has_many :positions, class_name: 'Iro::Position', inverse_of: :strategy
|
11
|
+
|
12
|
+
## multiple strategies per ticker
|
13
|
+
field :ticker
|
14
|
+
validates :ticker, presence: true
|
15
|
+
index({ ticker: 1 })
|
16
|
+
# belongs_to :stock, class_name: 'Iro::Stock', inverse_of: :strategies
|
17
|
+
|
18
|
+
|
19
|
+
field :buffer_above_water, type: :float
|
20
|
+
field :next_max_delta, type: :float
|
21
|
+
field :next_min_strike, type: :float
|
22
|
+
field :threshold_delta, type: :float
|
23
|
+
field :threshold_netp, type: :float
|
24
|
+
|
25
|
+
def self.for_ticker ticker
|
26
|
+
where( ticker: ticker )
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
slug
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.list
|
35
|
+
[[nil,nil]] + all.map { |ttt| [ ttt.slug, ttt.id ] }
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
class Tda::Option
|
5
|
+
|
6
|
+
include ::HTTParty
|
7
|
+
base_uri 'https://api.tdameritrade.com'
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
## 2023-02-05 _vp_ :: Gets the entire chain
|
12
|
+
##
|
13
|
+
def self.get_chain params
|
14
|
+
opts = { symbol: params[:ticker] } ## use 'GME' as symbol here even though a symbol is eg 'GME_021023P2.5'
|
15
|
+
query = { apikey: ::TD_AMERITRADE[:apiKey] }.merge opts
|
16
|
+
# puts! query, 'input opts'
|
17
|
+
|
18
|
+
path = "/v1/marketdata/chains"
|
19
|
+
out = self.get path, { query: query }
|
20
|
+
timestamp = DateTime.parse out.headers['date']
|
21
|
+
out = out.parsed_response.deep_symbolize_keys
|
22
|
+
|
23
|
+
|
24
|
+
outs = []
|
25
|
+
%w| put call |.each do |contractType|
|
26
|
+
tmp_sym = "#{contractType}ExpDateMap".to_sym
|
27
|
+
_out = out[tmp_sym]
|
28
|
+
_out.each do |date, vs| ## date="2023-02-10:5"
|
29
|
+
vs.each do |strike, _v| ## strike="18.5"
|
30
|
+
v = _v[0] ## v={} many attrs
|
31
|
+
v = v.except( :lastSize, :optionDeliverablesList, :settlementType,
|
32
|
+
:deliverableNote, :pennyPilot, :mini )
|
33
|
+
v.each do |k, i|
|
34
|
+
if i == 'NaN'
|
35
|
+
v[k] = nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
v[:timestamp] = timestamp
|
40
|
+
v[:ticker] = params[:ticker]
|
41
|
+
outs.push( v )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
outs.each do |x|
|
47
|
+
opi = ::Iro::OptionPriceItem.create( x )
|
48
|
+
if !opi.persisted?
|
49
|
+
puts! opi.errors.full_messages, "Cannot create OptionPriceItem"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
## 2023-03-18 _vp_ This is what I should be using to check if a position should be rolled.
|
56
|
+
##
|
57
|
+
def self.get_quote params
|
58
|
+
::Tda::Option.get_quotes(params)[0]
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
## params: contractType, strike, expirationDate, ticker
|
63
|
+
##
|
64
|
+
## ow = { contractType: 'PUT', ticker: 'GME', date: '2022-12-09' }
|
65
|
+
## query = {:apikey=>"<>", :toDate=>"2022-12-09", :fromDate=>"2022-12-09", :symbol=>"GME"}
|
66
|
+
##
|
67
|
+
## 2023-02-04 _vp_ :: Too specific, but I want the entire chain, every 1-min
|
68
|
+
## 2023-02-06 _vp_ :: Continue.
|
69
|
+
##
|
70
|
+
def self.get_quotes params
|
71
|
+
puts! params, 'Tda::Option#get_quotes'
|
72
|
+
opts = {}
|
73
|
+
|
74
|
+
#
|
75
|
+
# Validate input ???
|
76
|
+
#
|
77
|
+
validOpts = %i| contractType |
|
78
|
+
validOpts.each do |s|
|
79
|
+
if params[s]
|
80
|
+
opts[s] = params[s]
|
81
|
+
else
|
82
|
+
raise Iwa::InputError.new("Invalid input, missing '#{s}'.")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
if params[:expirationDate]
|
86
|
+
opts[:fromDate] = opts[:toDate] = params[:expirationDate]
|
87
|
+
else
|
88
|
+
raise Iwa::InputError.new("Invalid input, missing 'date'.")
|
89
|
+
end
|
90
|
+
if params[:ticker]
|
91
|
+
opts[:symbol] = params[:ticker].upcase
|
92
|
+
else
|
93
|
+
raise Iwa::InputError.new("Invalid input, missing 'ticker'.")
|
94
|
+
end
|
95
|
+
|
96
|
+
if params[:strike]
|
97
|
+
opts[:strike] = params[:strike]
|
98
|
+
end
|
99
|
+
|
100
|
+
query = { apikey: ::TD_AMERITRADE[:apiKey] }.merge opts
|
101
|
+
# puts! query, 'input opts'
|
102
|
+
|
103
|
+
path = "/v1/marketdata/chains"
|
104
|
+
out = self.get path, { query: query }
|
105
|
+
timestamp = DateTime.parse out.headers['date']
|
106
|
+
## out = HTTParty.get "https://api.tdameritrade.com#{path}", { query: query }
|
107
|
+
out = out.parsed_response.deep_symbolize_keys
|
108
|
+
|
109
|
+
|
110
|
+
tmp_sym = "#{opts[:contractType].to_s.downcase}ExpDateMap".to_sym
|
111
|
+
outs = []
|
112
|
+
out = out[tmp_sym]
|
113
|
+
out.each do |date, vs|
|
114
|
+
vs.each do |strike, _v|
|
115
|
+
v = _v[0]
|
116
|
+
v = v.except( :lastSize, :optionDeliverablesList, :settlementType,
|
117
|
+
:deliverableNote, :pennyPilot, :mini )
|
118
|
+
v[:timestamp] = timestamp
|
119
|
+
outs.push( v )
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# puts! outs, 'outs'
|
124
|
+
return outs
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
=begin
|
131
|
+
|
132
|
+
outs = Tda::Option.get_quotes({
|
133
|
+
contractType: 'CALL', strike: 20.0, expirationDate: '2024-01-12',
|
134
|
+
ticker: 'GME',
|
135
|
+
})
|
136
|
+
|
137
|
+
=end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
<!-- Matomo -->
|
3
|
+
<script>
|
4
|
+
var _paq = window._paq = window._paq || [];
|
5
|
+
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
6
|
+
_paq.push(['trackPageView']);
|
7
|
+
_paq.push(['enableLinkTracking']);
|
8
|
+
(function() {
|
9
|
+
var u="//analytics.wasya.co/";
|
10
|
+
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
11
|
+
_paq.push(['setSiteId', '13']); /* 13 :: email.wasya.co */
|
12
|
+
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
13
|
+
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
14
|
+
})();
|
15
|
+
</script>
|
16
|
+
<!-- End Matomo Code -->
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
.main-header.maxwidth
|
3
|
+
|
4
|
+
%i.fa.fa-compress.collapse-expand#collapseHeaderEmail
|
5
|
+
Iron Warbler
|
6
|
+
|
7
|
+
-# .header.collapse-expand#IroMenu
|
8
|
+
-# %h5.title Iron Warbler
|
9
|
+
|
10
|
+
%ul
|
11
|
+
%li= link_to 'ROOT', root_path
|
12
|
+
%li
|
13
|
+
= link_to "Stocks (#{Iro::Stock.all.length})", stocks_path
|
14
|
+
-# %li= link_to 'Options', options_path
|
15
|
+
-# %li Max Pain
|
16
|
+
%li
|
17
|
+
= link_to "Alerts (#{Iro::Alert.all.length})", alerts_path
|
18
|
+
%li
|
19
|
+
= link_to "Purses (#{Iro::Purse.all.length})", purses_path
|
20
|
+
%li
|
21
|
+
= render '/iro/strategies/header'
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
|
2
|
+
.positions--form
|
3
|
+
= form_for position do |f|
|
4
|
+
.actions
|
5
|
+
= f.submit
|
6
|
+
|
7
|
+
.field
|
8
|
+
%label Purse
|
9
|
+
-# = f.select :purse_id, options_for_select( @
|
10
|
+
= f.text_field :purse_id
|
11
|
+
|
12
|
+
%label Status
|
13
|
+
= f.select :status, options_for_select( Iro::Position::STATUSES, selected: position.status )
|
14
|
+
|
15
|
+
%br
|
16
|
+
%br
|
17
|
+
|
18
|
+
.field
|
19
|
+
%label Ticker
|
20
|
+
= f.select :ticker, options_for_select( @tickers_list, selected: position.ticker )
|
21
|
+
|
22
|
+
|
23
|
+
%label Kind
|
24
|
+
= f.select :kind, options_for_select( Iro::Position::KINDS, selected: position.kind )
|
25
|
+
%label Strategy
|
26
|
+
= f.select :strategy_id, options_for_select( @strategies_list, selected: position.strategy_id )
|
27
|
+
|
28
|
+
|
29
|
+
%label Strike
|
30
|
+
= f.text_field :strike
|
31
|
+
|
32
|
+
.field
|
33
|
+
%label Expires on
|
34
|
+
= f.text_field :expires_on
|
35
|
+
|
36
|
+
|
37
|
+
%label Quantity
|
38
|
+
= f.text_field :quantity
|
39
|
+
|
40
|
+
%br
|
41
|
+
%br
|
42
|
+
|
43
|
+
.flex-row
|
44
|
+
%label Begin on
|
45
|
+
= f.text_field :begin_on
|
46
|
+
%label Begin price
|
47
|
+
= f.text_field :begin_price
|
48
|
+
%label Begin delta
|
49
|
+
= f.text_field :begin_delta
|
50
|
+
.flex-row
|
51
|
+
%label End on
|
52
|
+
= f.text_field :end_on
|
53
|
+
%label End price
|
54
|
+
= f.text_field :end_price
|
55
|
+
%label End delta
|
56
|
+
= f.text_field :end_delta
|
57
|
+
|
58
|
+
.actions
|
59
|
+
= f.submit
|