iron_warbler 2.0.7.39 → 2.0.7.41

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: 706bc42f34e116f0071a21611468365ac0a6a2b76fc722c812a9d0158380898b
4
- data.tar.gz: 670933ff9f081f0c7d31a32a1a99e4af6b933e4d1b019c51b5923d3efd244395
3
+ metadata.gz: 00d253e5183bd431fc4f47681007d9ce860d7ea71ec825247db81d3f56224d4f
4
+ data.tar.gz: 8600938ea2f61303da8f2eae2a4775e13b177cb976211a1911a4f5d9d09b1aba
5
5
  SHA512:
6
- metadata.gz: 7e3039883ab46c0a8231500f29fffba931f2ba8fb45529ea139464246c1657940d97279f1b4f61f9d8a563640384874096c87949cb617c0e96aa34c6e978d946
7
- data.tar.gz: b0b80caa5be42c0062836150043e89ef719df3caac02b4535887b17ea8e6b7d180073b2585db7195f83b0adec264ab4421f7f3fcc830fcf2394657081d2fde40
6
+ metadata.gz: 3867a03b4d259f27256a09eda9047b688f3410301429ea9d8a321875e9d753db9028cadf93fb02f2ea1617e0370ad6e920346d68ae5d673ebaacf8e953c389e2
7
+ data.tar.gz: 6cdc0b4e80653ae44fa231e18007a829f6216a348b4fb6a5279dbf13f88caa7b50ed8d3053344c20680463f3aa5d2d681c6aa0edea48fd3452b8e916ac6ddaf5
@@ -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
@@ -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
@@ -18,8 +18,14 @@ class Iro::Datapoint
18
18
  KIND_TREASURY = 'TREASURY'
19
19
 
20
20
  field :symbol ## ticker, but use 'symbol' here
21
- SYMBOL_BTC = 'BTC'
22
- SYMBOL_ETH = 'ETH'
21
+ ## crypto
22
+ SYMBOL_BTC = 'BTC'
23
+ SYMBOL_ETH = 'ETH'
24
+ ## currencies
25
+ SYMBOL_JPY = 'JPY'
26
+ SYMBOL_COP = 'COP'
27
+ SUMBOL_EUR = 'EUR'
28
+ ## treasuries
23
29
  SYMBOL_T1MO = 'T1MO'
24
30
  SYMBOL_T2MO = 'T2MO'
25
31
  SYMBOL_T3MO = 'T3MO'
@@ -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,7 +34,12 @@ class Iro::Priceitem
33
34
  field :exchangeName, type: String
34
35
  field :volatility, type: Float
35
36
 
36
- field :expires_on, type: :date
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
37
43
 
38
44
  def self.my_find props={}
39
45
  lookup = { '$lookup': {
@@ -35,23 +35,32 @@ class Tda::Option
35
35
  }
36
36
  path = "/chains"
37
37
  out = self.get path, {
38
- basic_auth: { username: SCHWAB_DATA[:key], password: SCHWAB_DATA[:secret] },
39
38
  headers: headers,
40
39
  query: query }
41
40
  timestamp = DateTime.parse out.headers['date']
42
- out = out.parsed_response.deep_symbolize_keys
41
+ out = out.parsed_response
43
42
 
44
- byebug
43
+ # byebug
45
44
 
46
45
  outs = []
47
46
  %w| put call |.each do |contractType|
48
- tmp_sym = "#{contractType}ExpDateMap".to_sym
49
- _out = out[tmp_sym]
47
+ _out = out["#{contractType}ExpDateMap"]
50
48
  _out.each do |date, vs| ## date="2023-02-10:5"
51
49
  vs.each do |strike, _v| ## strike="18.5"
52
- v = _v[0] ## v={} many attrs
53
- v = v.except( :lastSize, :optionDeliverablesList, :settlementType,
54
- :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
+ }
55
64
  v.each do |k, i|
56
65
  if i == 'NaN'
57
66
  v[k] = nil
@@ -66,11 +75,13 @@ class Tda::Option
66
75
  end
67
76
 
68
77
  outs.each do |out|
69
- opi = ::Iro::PriceItem.create( out )
78
+ opi = ::Iro::Priceitem.create( out )
70
79
  if !opi.persisted?
71
- puts! opi.errors.full_messages, "Cannot create OptionPriceItem"
80
+ puts! opi.errors.full_messages, "Cannot create PriceItem"
72
81
  end
73
82
  end
83
+
84
+ return out
74
85
  end
75
86
 
76
87
  ##
@@ -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
data/lib/iron_warbler.rb CHANGED
@@ -25,6 +25,35 @@ class Iro::Iro
25
25
  end
26
26
  end
27
27
 
28
+ def self.get_currencies
29
+ out = HTTParty.get "https://api.currencyfreaks.com/v2.0/rates/latest?apikey=#{CURRENCYFREAKS[:key]}&symbols=COP,EUR,JPY"
30
+ out = out.parsed_response.deep_symbolize_keys!
31
+ out[:rates].each do |currency, value|
32
+
33
+ # opi = OPI.new({
34
+ # putCall: 'CURRENCY',
35
+ # symbol: currency,
36
+ # ticker: currency,
37
+ # exchangeName: 'currencyfreaks',
38
+ # mark: value,
39
+ # lastPrice: value,
40
+ # timestamp: Time.now.to_date,
41
+ # })
42
+ # opi.save!
43
+
44
+ datapoint = Iro::Datapoint.new({
45
+ date: Time.now.to_date,
46
+ quote_at: Time.now,
47
+ kind: Iro::Datapoint::KIND_CURRENCY,
48
+ symbol: currency,
49
+ value: value,
50
+ })
51
+ datapoint.save!
52
+
53
+ print '^'
54
+ end
55
+ end
56
+
28
57
  def self.get_treasuries
29
58
  response = HTTParty.get( "https://home.treasury.gov/resource-center/data-chart-center/interest-rates/daily-treasury-rates.csv/all/#{Time.now.strftime('%Y%m')}?type=daily_treasury_yield_curve&field_tdr_date_value_month=#{Time.now.strftime('%Y%m')}&page&_format=csv")
30
59
  outs = CSV.parse( response.body, { headers: true })
@@ -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.39
4
+ version: 2.0.7.41
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-09 00:00:00.000000000 Z
11
+ date: 2024-08-21 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