iron_warbler 2.0.7.38 → 2.0.7.40

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: c3d26b42528adce8dcac715a0dc3296c6a7dfe8aa69deae868baa38f207d9140
4
- data.tar.gz: c947418c85ee93024ff05d64207ae159b852db6746b3104d5b14174d83dfd575
3
+ metadata.gz: 9f3f78d3df3906d30951b5cb346a7fbe4e04f4b4e3585cd2aab6b71de0f734e3
4
+ data.tar.gz: 5054b253d6f7e944ffdfd09575b3401f2bd6371a5ea90190c9ba8dcfd16a3e58
5
5
  SHA512:
6
- metadata.gz: b5b4e030572f6781add522f5fb1b8bebdfdeffdc871153b8b408882f998de6be0069544eecfa58e14b4e8357877fd5a84ab2d153ffa8a463bda86fdab2783633
7
- data.tar.gz: 707028e50d3b1aa4a5522765226ea09b5e5e81e397c1b1541432d46231355ab462569295d5375db958d8c41e6bf475340b073591a18b5a547a5488b0db1039b5
6
+ metadata.gz: d117e27f37ed366fe1fde852da5d7083d757e917d4badf9e1af4419885d4ea8a906571518572ca39842b6f34347dd010ea8e2e735cc63dcf194c3988246ff05a
7
+ data.tar.gz: 9e87de47b40b4ae05197ad764f5e8f0c9d941798dfff736553d579d1eba06f5552de354e5b21cd5cc4446897646168eb1fd846f7c8ae5f02646fe192970f021f
data/README.txt CHANGED
@@ -10,3 +10,8 @@ From: https://docs.galpy.org/en/latest/installation.html
10
10
  calculator: https://www.omnicalculator.com/finance/black-scholes
11
11
 
12
12
  From: https://pythoninoffice.com/calculate-black-scholes-option-price-in-python/
13
+
14
+ = schwab =
15
+ == swagger ==
16
+
17
+ * https://developer.schwab.com/products/trader-api--individual
@@ -1,6 +1,6 @@
1
1
 
2
2
  class Iro::Api::StocksController < Iro::ApiController
3
- before_action :set_stock, only: [:show, :edit, :update, :destroy]
3
+ before_action :set_stock, only: [:destroy, :edit, :max_pain, :show, :update ]
4
4
 
5
5
  def index
6
6
  @stocks = Iro::Stock.active
@@ -12,6 +12,21 @@ class Iro::Api::StocksController < Iro::ApiController
12
12
  end
13
13
  end
14
14
 
15
+ def max_pain
16
+ authorize! :max_pain, @stock
17
+
18
+ hash = Tda::Option.get_chains({ ticker: @stock.ticker })
19
+ # hash = JSON.parse File.read './trash.json'
20
+ @max_pain = Iro::Option.max_pain hash
21
+
22
+ respond_to do |format|
23
+ format.html
24
+ format.json do
25
+ render layout: false
26
+ end
27
+ end
28
+ end
29
+
15
30
  def show
16
31
  authorize! :show, @stock
17
32
  end_on = Time.now.to_date.in_time_zone('UTC')
@@ -49,4 +49,14 @@ class Iro::ApiController < ActionController::Base
49
49
  sign_in user
50
50
  end
51
51
 
52
+ def set_stock
53
+ begin
54
+ @stock = Iro::Stock.find(params[:id])
55
+ rescue Mongoid::Errors::DocumentNotFound => e
56
+ @stock = Iro::Stock.find_by ticker: params[:id]
57
+ end
58
+ @stocks_list = Iro::Stock.tickers_list
59
+ end
60
+
61
+
52
62
  end
@@ -34,7 +34,7 @@ class Iro::ApplicationController < Wco::ApplicationController
34
34
  },
35
35
  })
36
36
  out = out.parsed_response
37
- puts! out, 'out'
37
+ # puts! out, 'out'
38
38
 
39
39
  attrs = {
40
40
  schwab_access_token: out['access_token'],
@@ -43,10 +43,12 @@ class Iro::ApplicationController < Wco::ApplicationController
43
43
  }
44
44
  # puts! attrs, 'attrs'
45
45
 
46
- profile.update(attrs)
47
- profile.save!
46
+ if attrs[:schwab_refresh_token]
47
+ profile.update(attrs)
48
+ profile.save!
49
+ end
48
50
 
49
- render json: { status: :ok }
51
+ render json: { attrs: attrs, out: out }
50
52
  end
51
53
 
52
54
  ##
@@ -3,7 +3,7 @@
3
3
  ## https://www.macrotrends.net/stocks/charts/META/meta-platforms/stock-price-history
4
4
  ##
5
5
  class Iro::StocksController < Iro::ApplicationController
6
- before_action :set_stock, only: [:show, :edit, :update, :destroy]
6
+ before_action :set_stock, only: [:destroy, :edit, :show, :update ]
7
7
 
8
8
  def create
9
9
  @stock = Iro::Stock.new(stock_params)
@@ -38,6 +38,8 @@ class Iro::StocksController < Iro::ApplicationController
38
38
  end
39
39
  end
40
40
 
41
+
42
+
41
43
  def new
42
44
  @stock = Iro::Stock.new
43
45
  authorize! :new, @stock
@@ -64,6 +66,25 @@ class Iro::StocksController < Iro::ApplicationController
64
66
  symbol: @stock.ticker,
65
67
  }).order_by({ date: :desc }).limit(100)
66
68
 
69
+ filename = "./data/schwab/#{Time.now.to_date.to_s}-#{@stock.ticker}-chains.json"
70
+ if File.exists? filename
71
+ hash = JSON.parse File.read filename
72
+ else
73
+ hash = Tda::Option.get_chains({ ticker: @stock.ticker })
74
+ File.write filename, hash.to_json
75
+ end
76
+ @max_pain = Iro::Option.max_pain hash
77
+ @max_pain_summary = {}
78
+ @max_pain.each do |date, types|
79
+ all = types['all']
80
+ @max_pain_summary[date] = all.keys[0]
81
+ all.each do |strike, amount|
82
+ if amount < all[@max_pain_summary[date]]
83
+ @max_pain_summary[date] = strike
84
+ end
85
+ end
86
+ end
87
+
67
88
  respond_to do |format|
68
89
  format.html
69
90
  format.json do
@@ -73,6 +73,7 @@ class Iro::Option
73
73
  self[:symbol]
74
74
  end
75
75
 
76
+ before_save :sync, if: ->() { !Rails.env.test? } ## do not sync in test
76
77
  def sync
77
78
  out = Tda::Option.get_quote({
78
79
  contractType: put_call,
@@ -86,6 +87,53 @@ class Iro::Option
86
87
  # self.save
87
88
  end
88
89
 
89
- before_save :sync, if: ->() { !Rails.env.test? } ## do not sync in test
90
+ def self.max_pain hash
91
+ outs = {}
92
+
93
+ %w| put call |.each do |contractType|
94
+ dates = hash["#{contractType}ExpDateMap"]
95
+ dates.each do |_date, strikes| ## _date="2023-02-10:5"
96
+ date = _date.split(':')[0].to_date.to_s
97
+ outs[date] ||= {
98
+ 'all' => {},
99
+ 'put' => {},
100
+ 'call' => {},
101
+ }
102
+
103
+ strikes.each do |_strike, _v| ## _strike="18.5"
104
+ strike = _strike.to_f
105
+
106
+ ## calls
107
+ mem_c = 0
108
+ strikes.keys.reverse.each do |_key|
109
+ if _key == _strike
110
+ break
111
+ end
112
+ key = _key.to_f
113
+ tmp = hash["callExpDateMap"][_date][_key][0]['openInterest'] * ( key - strike )
114
+ mem_c += tmp
115
+ end
116
+ outs[date]['call'][_strike] = mem_c
117
+
118
+ ## puts
119
+ mem_p = 0
120
+ strikes.keys.each do |_key|
121
+ if _key == _strike
122
+ break
123
+ end
124
+ key = _key.to_f
125
+ tmp = hash["putExpDateMap"][_date][_key][0]['openInterest'] * ( strike - key )
126
+ mem_p += tmp
127
+ end
128
+ outs[date]['put'][_strike] = mem_p
129
+ outs[date]['all'][_strike] = mem_c + mem_p
130
+
131
+ end
132
+ end
133
+ end
134
+
135
+ return outs
136
+ end
137
+
90
138
 
91
139
  end
@@ -11,6 +11,7 @@ class Iro::Priceitem
11
11
  ## PUT, CALL, STOCK
12
12
  field :putCall, type: String ## kind
13
13
  field :symbol, type: String
14
+ field :description, type: String
14
15
  field :ticker, type: String
15
16
  # belongs_to :stock, inverse_of: :priceitems
16
17
 
@@ -33,6 +34,13 @@ class Iro::Priceitem
33
34
  field :exchangeName, type: String
34
35
  field :volatility, type: Float
35
36
 
37
+ field :expirationDate, type: :date
38
+ field :delta, type: Float
39
+ field :gamma, type: Float
40
+ field :theta, type: Float
41
+ field :openInterest, type: Integer
42
+ field :strikePrice, type: Float
43
+
36
44
  def self.my_find props={}
37
45
  lookup = { '$lookup': {
38
46
  'from': 'iro_price_items',
@@ -18,28 +18,49 @@ class Tda::Option
18
18
 
19
19
 
20
20
  ##
21
- ## 2023-02-05 _vp_ :: Gets the entire chain
21
+ ## Get entire chains for a ticker
22
+ ## params: { ticker, }
22
23
  ##
23
- def self.get_chain params
24
- opts = { symbol: params[:ticker] } ## use 'GME' as symbol here even though a symbol is eg 'GME_021023P2.5'
25
- query = { apikey: ::TD_AMERITRADE[:apiKey] }.merge opts
26
- puts! query, 'input opts'
24
+ ## 2024-08-09 :: Continue
25
+ ##
26
+ def self.get_chains params
27
+ profile = Wco::Profile.find_by email: 'piousbox@gmail.com'
27
28
 
28
- path = "/v1/marketdata/chains"
29
- out = self.get path, { query: query }
29
+ query = { symbol: params[:ticker] } ## use 'GME' as symbol here even though a symbol is eg 'GME_021023P2.5'
30
+ puts! query, 'query'
31
+
32
+ headers = {
33
+ accept: 'application/json',
34
+ Authorization: "Bearer #{profile[:schwab_access_token]}",
35
+ }
36
+ path = "/chains"
37
+ out = self.get path, {
38
+ headers: headers,
39
+ query: query }
30
40
  timestamp = DateTime.parse out.headers['date']
31
- out = out.parsed_response.deep_symbolize_keys
41
+ out = out.parsed_response
32
42
 
43
+ # byebug
33
44
 
34
45
  outs = []
35
46
  %w| put call |.each do |contractType|
36
- tmp_sym = "#{contractType}ExpDateMap".to_sym
37
- _out = out[tmp_sym]
47
+ _out = out["#{contractType}ExpDateMap"]
38
48
  _out.each do |date, vs| ## date="2023-02-10:5"
39
49
  vs.each do |strike, _v| ## strike="18.5"
40
- v = _v[0] ## v={} many attrs
41
- v = v.except( :lastSize, :optionDeliverablesList, :settlementType,
42
- :deliverableNote, :pennyPilot, :mini )
50
+ _v = _v[0] ## weird, keep
51
+ # puts! _v, '_v'
52
+
53
+ v = {
54
+ putCall: _v['putCall'],
55
+ symbol: _v['symbol'],
56
+ bid: _v['bid'],
57
+ ask: _v['ask'],
58
+ last: _v['last'],
59
+ totalVolume: _v['totalVolume'],
60
+ openInterest: _v['openInterest'],
61
+ strikePrice: _v['strikePrice'],
62
+ expirationDate: _v['expirationDate'],
63
+ }
43
64
  v.each do |k, i|
44
65
  if i == 'NaN'
45
66
  v[k] = nil
@@ -53,12 +74,14 @@ class Tda::Option
53
74
  end
54
75
  end
55
76
 
56
- outs.each do |x|
57
- opi = ::Iro::OptionPriceItem.create( x )
77
+ outs.each do |out|
78
+ opi = ::Iro::Priceitem.create( out )
58
79
  if !opi.persisted?
59
- puts! opi.errors.full_messages, "Cannot create OptionPriceItem"
80
+ puts! opi.errors.full_messages, "Cannot create PriceItem"
60
81
  end
61
82
  end
83
+
84
+ return out
62
85
  end
63
86
 
64
87
  ##
@@ -125,7 +148,6 @@ class Tda::Option
125
148
  }
126
149
  puts! out, 'out'
127
150
  timestamp = DateTime.parse out.headers['date']
128
- # out = HTTParty.get "https://api.tdameritrade.com#{path}", { query: query }
129
151
  out = out.parsed_response.deep_symbolize_keys
130
152
 
131
153
 
@@ -0,0 +1,18 @@
1
+
2
+ json.ticker @stock.ticker
3
+ json.last @stock.last
4
+
5
+ json.max_pain do
6
+ @max_pain.each do |date, maps|
7
+ json.set! date do
8
+ json.all do
9
+ json.array! maps['all'] do |strike, value|
10
+ json.strike strike
11
+ json.value value
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+
@@ -24,4 +24,6 @@
24
24
  %b 1 yr volatility <br />
25
25
  = @stock.volatility
26
26
 
27
- %h4 Max Pain
27
+ %h4 Max Pain
28
+ %pre
29
+ = JSON.pretty_generate @max_pain_summary
data/config/routes.rb CHANGED
@@ -35,13 +35,14 @@ Iro::Engine.routes.draw do
35
35
 
36
36
  get 'api/oauth2-redirect.html', to: 'api#oauth2_redirect'
37
37
  namespace :api do
38
- get 'stocks', to: 'stocks#index'
39
- get 'stocks/:ticker', to: 'stocks#show'
40
- get 'stocks/:ticker/period/:period', to: 'stocks#show'
41
- get 'stocks/:ticker/from/:begin_on', to: 'stocks#show'
42
- get 'stocks/:ticker/begin_on/:begin_on', to: 'stocks#show'
43
- get 'stocks/:ticker/from/:begin_on/to/:end_on', to: 'stocks#show'
38
+ get 'stocks', to: 'stocks#index'
39
+ get 'stocks/:ticker', to: 'stocks#show'
40
+ get 'stocks/:ticker/begin_on/:begin_on', to: 'stocks#show'
44
41
  get 'stocks/:ticker/begin_on/:begin_on/end_on/:end_on', to: 'stocks#show'
42
+ get 'stocks/:ticker/from/:begin_on', to: 'stocks#show'
43
+ get 'stocks/:ticker/from/:begin_on/to/:end_on', to: 'stocks#show'
44
+ get 'stocks/:ticker/max-pain', to: 'stocks#max_pain'
45
+ get 'stocks/:ticker/period/:period', to: 'stocks#show'
45
46
  end
46
47
 
47
48
  end
@@ -1,6 +1,14 @@
1
1
 
2
2
  namespace :test do
3
3
 
4
+ desc 'max pain'
5
+ task max_pain: :environment do
6
+ hash = JSON.parse File.read './trash.json'
7
+ puts! hash.keys, '+++ +++ parsed hash'
8
+ outs = Iro::Option.max_pain hash
9
+ byebug
10
+ end
11
+
4
12
  desc 'stock#volatility_mo'
5
13
  task stock_vol_mo: :environment do
6
14
  out = Iro::Stock.find_by( ticker: 'NVDA' ).volatility_from_mo
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iron_warbler
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.7.38
4
+ version: 2.0.7.40
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Pudeyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-08 00:00:00.000000000 Z
11
+ date: 2024-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: business_time
@@ -260,6 +260,7 @@ files:
260
260
  - app/views/iro/alerts/_form.haml
261
261
  - app/views/iro/alerts/index.haml
262
262
  - app/views/iro/api/stocks/index.json.jbuilder
263
+ - app/views/iro/api/stocks/max_pain.json.jbuilder
263
264
  - app/views/iro/api/stocks/show.json.jbuilder
264
265
  - app/views/iro/api/stocks/show.json.jbuilder-bk
265
266
  - app/views/iro/application/home.haml