ish_models 0.0.33.108 → 0.0.33.109

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d4271bf5f789a326f89817f1b17c258bb9391f6664549632d18c6d3c6e41912
4
- data.tar.gz: e9b16ac436c2d2487079f394c6a0cd34d01fe2cbde949d77a41f9efb2521b3e1
3
+ metadata.gz: e7b4296819e6aa79c292a1ecc7d1fe4aaae221e00071404dd3df07e8e46ca4e6
4
+ data.tar.gz: 89718fbbe1b9bf03e645ce2fd275f50b7908dbb3c90a021f0cd4bca29b6f4041
5
5
  SHA512:
6
- metadata.gz: 694f0ef821fe809d16a2dc6aba3cfc1d1605db9c8c3175d33223737b8419f63b186e82ef638d025dfcdc3cfa8891e134987be3df423cd6c19150d54073cc61c6
7
- data.tar.gz: ae4a52484b16ce20d3938986bc2e6bee80ee014035c54aea170df1782a02743ca20b754498ed2e6711cb99de03568073073b389c6aa45cc7fa3df0274bd8745b
6
+ metadata.gz: 1175f0f6d0f20be7097bbe3f1e9c290c41f9af6a742ef95b4d49aab1dd61f89f70b45f5900ca6566a938fc9f4c679bee9f6b69ea0a5d9e287573044fac1ac933
7
+ data.tar.gz: 84bbb47a571d8d2cfa0016b77e7cfcaa4b5d1b1686477988316e29ce8a8e04341c8dbd357bf52a6931d5b04f44eb0f6b611d7f7978e83c466da36b8da48f79f0
data/lib/gallery.rb CHANGED
@@ -110,7 +110,7 @@ class Gallery
110
110
  RENDER_TITLES = 'gallery_render_titles_const' # string b/c transmited over http
111
111
  RENDER_THUMBS = 'gallery_render_thumbs_const' # string b/c transmited over http
112
112
 
113
- belongs_to :newsparent, polymorphic: true
113
+ belongs_to :newsparent, polymorphic: true, optional: true
114
114
 
115
115
  end
116
116
 
@@ -0,0 +1,319 @@
1
+
2
+ =begin
3
+
4
+ c.update_attributes( call_sell_strike: 242, call_buy_strike: 243, put_sell_strike: 229, put_buy_strike: 228 )
5
+
6
+ =end
7
+
8
+ class Ish::IronCondor
9
+ include Mongoid::Document
10
+ include Mongoid::Timestamps
11
+
12
+ store_in collection: 'ish_iron_condor'
13
+
14
+ field :expires_on, type: Date
15
+ validates :expires_on, presence: true
16
+ field :n_contracts, type: Integer
17
+ validates :n_contracts, presence: true
18
+ field :ticker
19
+ validates :ticker, uniqueness: { scope: :expires_on }
20
+ validates :ticker, presence: true
21
+
22
+ #
23
+ # Internal, below
24
+ #
25
+
26
+ def created_on; created_at.to_date; end
27
+
28
+ def self.all_filled
29
+ where( status: :filled )
30
+ end
31
+
32
+ STATUSES = [ :queued, :placed, :filled, :rolling_up, :rolling_down, :rolled_up, :rolled_down, :expired ]
33
+ field :status
34
+ field :enter_price, type: Float
35
+ field :call_sell_strike, type: Float
36
+ field :call_buy_strike, type: Float
37
+ field :put_sell_strike, type: Float
38
+ field :put_buy_strike, type: Float
39
+ field :new_call_sell_strike, type: Float
40
+ field :new_call_buy_strike, type: Float
41
+ field :new_put_sell_strike, type: Float
42
+ field :new_put_buy_strike, type: Float
43
+
44
+ field :iv_annual, type: Float
45
+ def iv_period
46
+ n_days = created_on.business_days_until expires_on
47
+ result = iv_annual.to_f / Math.sqrt(252/n_days)
48
+ end
49
+ alias_method :period_iv, :iv_period
50
+
51
+ ## how close to a sell leg I need to be to take followup action
52
+ def panic_percentage
53
+ 0.01 # 1% for QQQ
54
+ end
55
+
56
+ def buysell_spread
57
+ 1 # $1 for QQQ
58
+ end
59
+
60
+ def get_call_sell_strike
61
+ result = enter_price * ( 1 - period_iv/100 )
62
+ result = result.ceil
63
+ end
64
+ def get_call_buy_strike
65
+ call_sell_strike + buysell_spread
66
+ end
67
+
68
+ def get_put_sell_strike
69
+ result = enter_price * ( 1 - period_iv/100 )
70
+ result = result.floor
71
+ end
72
+ def get_put_buy_strike
73
+ put_sell_strike - buysell_spread
74
+ end
75
+
76
+ def upper_panic_threshold
77
+ result = call_sell_strike * ( 1 - panic_percentage )
78
+ end
79
+
80
+ def lower_panic_threshold
81
+ result = put_sell_strike * ( 1 + panic_percentage )
82
+ end
83
+
84
+ def new_multileg_order_example_done
85
+ ticker = 'QQQ'
86
+ px = 0.08
87
+ account_id = ALLY_CREDS[:account_id]
88
+ n_contracts = 1
89
+ sell_strike = 237.0
90
+ buy_strike = 237.5
91
+ expiration = '2020-02-21'.to_date
92
+
93
+ tmpl = <<~AOL
94
+ <FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2">
95
+ <NewOrdMleg TmInForce="0" Px="#{px}" OrdTyp="2" Acct="#{account_id}">
96
+ <Ord OrdQty="#{n_contracts}" PosEfct="O">
97
+ <Leg Side="2" Strk="#{sell_strike}"
98
+ Mat="#{expiration.strftime('%Y-%m-%d')}T00:00:00.000-05:00" MMY="#{expiration.strftime('%y%m')}"
99
+ SecTyp="OPT" CFI="OC" Sym="#{ticker}"/>
100
+ </Ord>
101
+ <Ord OrdQty="#{n_contracts}" PosEfct="O">
102
+ <Leg Side="1" Strk="#{buy_strike}"
103
+ Mat="#{expiration.strftime('%Y-%m-%d')}T00:00:00.000-05:00" MMY="#{expiration.strftime('%y%m')}"
104
+ SecTyp="OPT" CFI="OC" Sym="#{ticker}"/>
105
+ </Ord>
106
+ </NewOrdMleg>
107
+ </FIXML>
108
+ AOL
109
+ end
110
+
111
+ def new_purchase_trash
112
+ ticker = 'AXU'
113
+ px = 2.06
114
+ account_id = ALLY_CREDS[:account_id]
115
+ n_contracts = 1
116
+ strike = 2.06
117
+
118
+ xml = <<~AOL
119
+ <FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2">
120
+ <Order TmInForce="0" Typ="1" Side="1" Acct="#{account_id}">
121
+ <Instrmt SecTyp="CS" Sym="#{ticker}"/>
122
+ <OrdQty Qty="1"/>
123
+ </Order>
124
+ </FIXML>
125
+ AOL
126
+ end
127
+
128
+ ## https://www.ally.com/api/invest/documentation/fixml/
129
+ ## https://www.ally.com/api/invest/documentation/trading/
130
+ ## follow up, roll up
131
+ ## buy call to close
132
+ ## sell call to close
133
+ ## sell call to open
134
+ ## buy call to open
135
+ def rollup_xml access_token=nil, natural=nil
136
+ @access_token ||= access_token
137
+
138
+ new_call_sell_strike = ( natural * ( 1 + period_iv ) ).ceil
139
+ new_call_buy_strike = new_call_sell_strike + buysell_spread
140
+
141
+ # get the costs of the option first, to compute `Px`
142
+ ymd = expires_on.strftime('%y%m%d')
143
+ price8 = (new_call_sell_strike*1000).to_i.to_s.rjust(8, '0')
144
+ path = "/v1/market/ext/quotes.json?symbols=#{ticker}#{ymd}C#{price8}"
145
+ puts! path, 'path sell'
146
+ response = @access_token.post(path, {'Accept' => 'application/json'})
147
+ json_sell = JSON.parse( response.body ).deep_symbolize_keys
148
+ json_sell_bid = json_sell[:response][:quotes][:quote][:bid].to_f
149
+ json_sell_ask = json_sell[:response][:quotes][:quote][:ask].to_f
150
+ puts! json_sell, 'json_sell'
151
+
152
+ price8 = (new_call_buy_strike*1000).to_s.rjust(8, '0')
153
+ path = "/v1/market/ext/quotes.json?symbols=#{ticker}#{ymd}C#{price8}"
154
+ response = @access_token.post(path, {'Accept' => 'application/json'})
155
+ json_buy = JSON.parse( response.body ).deep_symbolize_keys
156
+ json_buy_bid = json_buy[:response][:quotes][:quote][:bid].to_f
157
+ json_buy_ask = json_buy[:response][:quotes][:quote][:ask].to_f
158
+ puts! json_buy, 'json_buy'
159
+
160
+ px_sell = ( json_sell_bid.to_f + json_sell_ask ) / 2
161
+ px_sell = px_sell # .round 2
162
+ px_buy = ( json_buy_bid + json_buy_ask )/ 2
163
+ px_buy = px_buy # .round 2
164
+ px = px_sell - px_buy
165
+ px = ( px * 20 ).round.to_f / 20 # down to nearest 0.05
166
+ puts! px, 'px'
167
+
168
+ update( status: :rolling_up,
169
+ new_call_sell_strike: new_call_sell_strike,
170
+ new_call_buy_strike: new_call_buy_strike )
171
+
172
+ rollup_tmpl =<<~AOL
173
+ <?xml version="1.0" encoding="UTF-8"?>
174
+ <FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2">
175
+ <NewOrdMleg
176
+ OrdTyp="2"
177
+ Px="#{px}"
178
+ Acct="#{ALLY_CREDS[:account_id]}"
179
+ TmInForce="0"
180
+ >
181
+ <Ord OrdQty="#{n_contracts}" PosEfct="C" >
182
+ <Leg
183
+ AcctTyp="5"
184
+ Side="1"
185
+ Strk="#{call_sell_strike}"
186
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
187
+ MMY="#{expires_on.strftime('%Y%m')}"
188
+ SecTyp="OPT"
189
+ CFI="OC"
190
+ Sym="#{ticker}" />
191
+ </Ord>
192
+ <Ord OrdQty="#{n_contracts}" PosEfct="C" >
193
+ <Leg
194
+ Side="2"
195
+ Strk="#{call_buy_strike}"
196
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
197
+ MMY="#{expires_on.strftime('%Y%m')}"
198
+ SecTyp="OPT"
199
+ CFI="OC"
200
+ Sym="#{ticker}" />
201
+ </Ord>
202
+ <Ord OrdQty="#{n_contracts}" PosEfct="O" >
203
+ <Leg
204
+ Side="2"
205
+ Strk="#{new_call_sell_strike}"
206
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
207
+ MMY="#{expires_on.strftime('%Y%m')}"
208
+ SecTyp="OPT"
209
+ CFI="OC"
210
+ Sym="#{ticker}" />
211
+ </Ord>
212
+ <Ord OrdQty="#{n_contracts}" PosEfct="O" >
213
+ <Leg
214
+ Side="1"
215
+ Strk="#{new_call_buy_strike}"
216
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
217
+ MMY="#{expires_on.strftime('%Y%m')}"
218
+ SecTyp="OPT"
219
+ CFI="OC"
220
+ Sym="#{ticker}" />
221
+ </Ord>
222
+ </NewOrdMleg>
223
+ </FIXML>
224
+ AOL
225
+ end
226
+
227
+ def rolldown_xml access_token=nil, natural=nil
228
+ @access_token ||= access_token
229
+
230
+ new_put_sell_strike = ( natural * ( 1 - period_iv ) ).floor
231
+ new_put_buy_strike = new_put_sell_strike - buysell_spread
232
+
233
+ # get the costs of the option first, to compute `Px`
234
+ ymd = expires_on.strftime('%y%m%d')
235
+ price8 = (new_put_sell_strike*1000).to_i.to_s.rjust(8, '0')
236
+ path = "/v1/market/ext/quotes.json?symbols=#{ticker}#{ymd}C#{price8}"
237
+ puts! path, 'path sell'
238
+ response = @access_token.post(path, {'Accept' => 'application/json'})
239
+ json_sell = JSON.parse( response.body ).deep_symbolize_keys
240
+ json_sell_bid = json_sell[:response][:quotes][:quote][:bid].to_f
241
+ json_sell_ask = json_sell[:response][:quotes][:quote][:ask].to_f
242
+ puts! json_sell, 'json_sell'
243
+
244
+ price8 = (new_put_buy_strike*1000).to_s.rjust(8, '0')
245
+ path = "/v1/market/ext/quotes.json?symbols=#{ticker}#{ymd}C#{price8}"
246
+ response = @access_token.post(path, {'Accept' => 'application/json'})
247
+ json_buy = JSON.parse( response.body ).deep_symbolize_keys
248
+ json_buy_bid = json_buy[:response][:quotes][:quote][:bid].to_f
249
+ json_buy_ask = json_buy[:response][:quotes][:quote][:ask].to_f
250
+ puts! json_buy, 'json_buy'
251
+
252
+ px_sell = ( json_sell_bid.to_f + json_sell_ask ) / 2
253
+ px_sell = px_sell # .round 2
254
+ px_buy = ( json_buy_bid + json_buy_ask )/ 2
255
+ px_buy = px_buy # .round 2
256
+ px = px_sell - px_buy
257
+ px = ( px * 20 ).round.to_f / 20 # down to nearest 0.05
258
+ puts! px, 'px'
259
+
260
+ update( status: :rolling_down,
261
+ new_put_sell_strike: new_put_sell_strike,
262
+ new_put_buy_strike: new_put_buy_strike )
263
+
264
+ rollup_tmpl =<<~AOL
265
+ <?xml version="1.0" encoding="UTF-8"?>
266
+ <FIXML xmlns="http://www.fixprotocol.org/FIXML-5-0-SP2">
267
+ <NewOrdMleg
268
+ OrdTyp="2"
269
+ Px="#{px}"
270
+ Acct="#{ALLY_CREDS[:account_id]}"
271
+ TmInForce="0"
272
+ >
273
+ <Ord OrdQty="#{n_contracts}" PosEfct="C" >
274
+ <Leg
275
+ AcctTyp="5"
276
+ Side="1"
277
+ Strk="#{put_sell_strike}"
278
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
279
+ MMY="#{expires_on.strftime('%Y%m')}"
280
+ SecTyp="OPT"
281
+ CFI="OP"
282
+ Sym="#{ticker}" />
283
+ </Ord>
284
+ <Ord OrdQty="#{n_contracts}" PosEfct="C" >
285
+ <Leg
286
+ Side="2"
287
+ Strk="#{put_buy_strike}"
288
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
289
+ MMY="#{expires_on.strftime('%Y%m')}"
290
+ SecTyp="OPT"
291
+ CFI="OP"
292
+ Sym="#{ticker}" />
293
+ </Ord>
294
+ <Ord OrdQty="#{n_contracts}" PosEfct="O" >
295
+ <Leg
296
+ Side="2"
297
+ Strk="#{new_put_sell_strike}"
298
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
299
+ MMY="#{expires_on.strftime('%Y%m')}"
300
+ SecTyp="OPT"
301
+ CFI="OP"
302
+ Sym="#{ticker}" />
303
+ </Ord>
304
+ <Ord OrdQty="#{n_contracts}" PosEfct="O" >
305
+ <Leg
306
+ Side="1"
307
+ Strk="#{new_put_buy_strike}"
308
+ Mat="#{expires_on.strftime('%Y-%m-%d')}T00:00:00.000‐05:00"
309
+ MMY="#{expires_on.strftime('%Y%m')}"
310
+ SecTyp="OPT"
311
+ CFI="OP"
312
+ Sym="#{ticker}" />
313
+ </Ord>
314
+ </NewOrdMleg>
315
+ </FIXML>
316
+ AOL
317
+ end
318
+
319
+ end
@@ -0,0 +1,83 @@
1
+
2
+ # result = @access_token.get('/v1/accounts.json', {'Accept' => 'application/json'})
3
+ # json = JSON.parse result.body
4
+
5
+
6
+ class ::Ish::IronCondorWatcher
7
+
8
+ def initialize
9
+ @consumer = OAuth::Consumer.new ALLY_CREDS[:consumer_key], ALLY_CREDS[:consumer_secret], { :site => 'https://api.tradeking.com' }
10
+ @access_token = OAuth::AccessToken.new(@consumer, ALLY_CREDS[:access_token], ALLY_CREDS[:access_token_secret])
11
+ end
12
+
13
+
14
+ def new_order
15
+ condor = ::Ish::IronCondor.all.first
16
+ xml = condor.new_multileg_order_example
17
+ print! xml, 'xml'
18
+ path = "/v1/accounts/#{ALLY_CREDS[:account_id]}/orders.xml"
19
+ # path = "/v1/accounts/#{ALLY_CREDS[:account_id]}/orders/preview.xml"
20
+ response = @access_token.post(path, xml)
21
+ print! response.body, 'response'
22
+ end
23
+
24
+ def watch_once
25
+ condors = ::Ish::IronCondor.all_filled
26
+ condors.each do |condor|
27
+ puts! condor.ticker, 'Watching this condor'
28
+
29
+ path = "/v1/market/ext/quotes.json?symbols=#{condor.ticker}"
30
+ response = @access_token.get(path, {'Accept' => 'application/json'})
31
+ json = JSON.parse( response.body ).deep_symbolize_keys
32
+ bid = json[:response][:quotes][:quote][:bid].to_f
33
+ ask = json[:response][:quotes][:quote][:ask].to_f
34
+ natural = ( bid + ask ) / 2
35
+
36
+ puts! [ bid, ask ], 'bid, ask'
37
+ puts! [ condor.upper_panic_threshold, condor.lower_panic_threshold ], 'upper/lower panic'
38
+
39
+ ## upper panic
40
+ if bid > condor.upper_panic_threshold
41
+ xml = condor.rollup_xml access_token=@access_token, natural=natural
42
+ print! xml, 'xml'
43
+
44
+ IshManager::ApplicationMailer.condor_followup_alert( condor, { action: :rollup } ).deliver_later
45
+
46
+ ## place order
47
+ path_preview = "/v1/accounts/#{ALLY_CREDS[:account_id]}/orders/preview.xml"
48
+ response = @access_token.post( path_preview, xml )
49
+ print! response.body
50
+ # path_order = "/v1/accounts/#{ALLY_CREDS[:account_id]}/orders.xml"
51
+ # response = @access_token.post( path_order, xml )
52
+ # print! response.body
53
+ end
54
+
55
+ ## lower panic
56
+ if ask < condor.lower_panic_threshold
57
+ xml = condor.rolldown_xml access_token=@access_token, natural=natural
58
+ print! xml, 'xml'
59
+
60
+ IshManager::ApplicationMailer.condor_followup_alert( condor, { action: :rolldown } ).deliver_later
61
+
62
+ ## place order
63
+ path_preview = "/v1/accounts/#{ALLY_CREDS[:account_id]}/orders/preview.xml"
64
+ response = @access_token.post( path_preview, xml )
65
+ print! response.body
66
+ # path_order = "/v1/accounts/#{ALLY_CREDS[:account_id]}/orders.xml"
67
+ # response = @access_token.post( path_order, xml )
68
+ # print! response.body
69
+ end
70
+
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+
77
+
78
+
79
+
80
+
81
+
82
+
83
+
data/lib/ish_models.rb CHANGED
@@ -33,16 +33,18 @@ require 'gameui/premium_purchase.rb'
33
33
 
34
34
  require 'ish/crawler.rb'
35
35
  require 'ish/gallery_name.rb'
36
+ require 'ish/iron_condor.rb'
37
+ require 'ish/iron_condor_watcher.rb'
36
38
  require 'ish/payment.rb'
37
39
  require 'ish/stock_action.rb'
38
40
  require 'ish/stock_option.rb'
39
41
  require 'ish/stock_watch.rb'
40
- require 'ish/yahoo_stockwatcher.rb'
41
42
  # require 'ish/alphavantage_stockwatcher.rb'
42
43
  require 'ish/invoice.rb'
43
44
  require 'ish/lead.rb'
44
45
  require 'ish/campaign.rb'
45
46
  require 'ish/issue.rb'
47
+ require 'ish/yahoo_stockwatcher.rb'
46
48
 
47
49
  # obsolete, use `ish` namespace now
48
50
  require 'ish_models/cache_key.rb' # this is really obsolete? _vp_ 20180123
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ish_models
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.33.108
4
+ version: 0.0.33.109
5
5
  platform: ruby
6
6
  authors:
7
7
  - piousbox
@@ -124,6 +124,8 @@ files:
124
124
  - lib/ish/crawler.rb
125
125
  - lib/ish/gallery_name.rb
126
126
  - lib/ish/invoice.rb
127
+ - lib/ish/iron_condor.rb
128
+ - lib/ish/iron_condor_watcher.rb
127
129
  - lib/ish/issue.rb
128
130
  - lib/ish/lead.rb
129
131
  - lib/ish/payment.rb