ish_models 0.0.33.108 → 0.0.33.109

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 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