yfinrb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.rst +0 -0
- data/CODE_OF_CONDUCT.md +15 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +144 -0
- data/Rakefile +8 -0
- data/lib/yfinrb/analysis.rb +68 -0
- data/lib/yfinrb/financials.rb +302 -0
- data/lib/yfinrb/fundamentals.rb +54 -0
- data/lib/yfinrb/holders.rb +260 -0
- data/lib/yfinrb/multi.rb +238 -0
- data/lib/yfinrb/price_history.rb +2037 -0
- data/lib/yfinrb/quote.rb +342 -0
- data/lib/yfinrb/ticker.rb +381 -0
- data/lib/yfinrb/tickers.rb +52 -0
- data/lib/yfinrb/utils.rb +359 -0
- data/lib/yfinrb/version.rb +5 -0
- data/lib/yfinrb/yf_connection.rb +300 -0
- data/lib/yfinrb/yfinance_exception.rb +16 -0
- data/lib/yfinrb.rb +17 -0
- data/sig/yfinrb.rbs +4 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ae85dede3894ef988f67e2ad11cbade387915950c3387e4f593c34eb172e4d27
|
4
|
+
data.tar.gz: ff90bb244a371653b94696e1137cdeecc2a955f1acd0f355c54068073c439f06
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a5be1264d728ab72e778062b430162a27e6bf40b970893495e2db61c1760434401440b6bda8ca982088c2e9254e9452a2585d5a6e9dd5ad6d3b8157da03d0000
|
7
|
+
data.tar.gz: f40d51d8164b62fb3edcd04f98011f9450c8523460e22abfe1e052cedaa11c7edc9c8a5ce94a44602acc421e8eec822dc50c763e4a04aa43a90c02c28422f941
|
data/.rubocop.yml
ADDED
data/CHANGELOG.rst
ADDED
File without changes
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Code of Conduct
|
2
|
+
|
3
|
+
## Submitting a new issue
|
4
|
+
|
5
|
+
* Search through existing Issues and Discussions, in case your issue already exists and a solution is being developed.
|
6
|
+
* Ensure you read & follow the template form.
|
7
|
+
* Consider you may be the best person to investigate and fix.
|
8
|
+
|
9
|
+
## Contributing to an existing Issue
|
10
|
+
|
11
|
+
* Read the entire thread.
|
12
|
+
* Ensure your comment is contributing something new/useful. Remember you can simply react to other comments.
|
13
|
+
* Be concise:
|
14
|
+
- use the formatting options
|
15
|
+
- if replying to a big comment, instead of quoting it, link to it
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 TODO: Write your name
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
# Yfinrb
|
2
|
+
|
3
|
+
# Download market data from Yahoo! Finance's API
|
4
|
+
|
5
|
+
<table border=1 cellpadding=10><tr><td>
|
6
|
+
|
7
|
+
#### \*\*\* IMPORTANT LEGAL DISCLAIMER \*\*\*
|
8
|
+
|
9
|
+
---
|
10
|
+
|
11
|
+
**Yahoo!, Y!Finance, and Yahoo! finance are registered trademarks of
|
12
|
+
Yahoo, Inc.**
|
13
|
+
|
14
|
+
yfinrb is **not** affiliated, endorsed, or vetted by Yahoo, Inc. It is
|
15
|
+
an open-source tool that uses Yahoo's publicly available APIs, and is
|
16
|
+
intended for research and educational purposes.
|
17
|
+
|
18
|
+
**You should refer to Yahoo!'s terms of use**
|
19
|
+
([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm),
|
20
|
+
[here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and
|
21
|
+
[here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) **for
|
22
|
+
details on your rights to use the actual data downloaded. Remember - the
|
23
|
+
Yahoo! finance API is intended for personal use only.**
|
24
|
+
|
25
|
+
</td></tr></table>
|
26
|
+
|
27
|
+
---
|
28
|
+
|
29
|
+
## Quick Start
|
30
|
+
|
31
|
+
### The Ticker module
|
32
|
+
|
33
|
+
The `Ticker` class, which allows you to access ticker data:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
|
37
|
+
msft = Yfinrb::Ticker("MSFT")
|
38
|
+
|
39
|
+
# get all stock info
|
40
|
+
msft.info
|
41
|
+
|
42
|
+
# get historical market data
|
43
|
+
hist = msft.history(period: "1mo")
|
44
|
+
hist2 = msft.history(start: '2020-01-01', fin: '2021-12-31')
|
45
|
+
|
46
|
+
# show meta information about the history (requires history() to be called first)
|
47
|
+
msft.history_metadata
|
48
|
+
|
49
|
+
# show actions (dividends, splits, capital gains)
|
50
|
+
msft.actions
|
51
|
+
msft.dividends
|
52
|
+
msft.splits
|
53
|
+
msft.capital_gains # only for mutual funds & etfs
|
54
|
+
|
55
|
+
# show share count
|
56
|
+
msft.shares_full(start: "2022-01-01", fin: nil)
|
57
|
+
|
58
|
+
# show financials:
|
59
|
+
# - income statement
|
60
|
+
msft.income_stmt
|
61
|
+
msft.quarterly_income_stmt
|
62
|
+
# - balance sheet
|
63
|
+
msft.balance_sheet
|
64
|
+
msft.quarterly_balance_sheet
|
65
|
+
# - cash flow statement
|
66
|
+
msft.cashflow
|
67
|
+
msft.quarterly_cashflow
|
68
|
+
|
69
|
+
# show holders
|
70
|
+
msft.major_holders
|
71
|
+
msft.institutional_holders
|
72
|
+
msft.mutualfund_holders
|
73
|
+
msft.insider_transactions
|
74
|
+
msft.insider_purchases
|
75
|
+
msft.insider_roster_holders
|
76
|
+
|
77
|
+
# show recommendations
|
78
|
+
msft.recommendations
|
79
|
+
msft.recommendations_summary
|
80
|
+
msft.upgrades_downgrades
|
81
|
+
|
82
|
+
# Show future and historic earnings dates, returns at most next 4 quarters and last 8 quarters by default.
|
83
|
+
msft.earnings_dates
|
84
|
+
|
85
|
+
# show ISIN code
|
86
|
+
# ISIN = International Securities Identification Number
|
87
|
+
msft.isin
|
88
|
+
|
89
|
+
# show options expirations
|
90
|
+
msft.options
|
91
|
+
|
92
|
+
# show news
|
93
|
+
msft.news
|
94
|
+
|
95
|
+
# get option chain for specific expiration
|
96
|
+
opt = msft.option_chain('2026-12-18')
|
97
|
+
# data available via: opt.calls, opt.puts
|
98
|
+
```
|
99
|
+
|
100
|
+
---
|
101
|
+
|
102
|
+
## Installation
|
103
|
+
|
104
|
+
Add this line to your application's Gemfile:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
gem 'yfinrb'
|
108
|
+
```
|
109
|
+
|
110
|
+
And then execute:
|
111
|
+
|
112
|
+
$ bundle install
|
113
|
+
|
114
|
+
Or install it yourself as:
|
115
|
+
|
116
|
+
$ gem install yfinrb
|
117
|
+
|
118
|
+
---
|
119
|
+
|
120
|
+
## Development
|
121
|
+
|
122
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
123
|
+
|
124
|
+
## Contributing
|
125
|
+
|
126
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bmck/yfinrb.
|
127
|
+
|
128
|
+
---
|
129
|
+
|
130
|
+
### Legal Stuff
|
131
|
+
|
132
|
+
The **yfinrb** gem is available as open source under the **MIT Software License** (https://opensource.org/licenses/MIT). See
|
133
|
+
the [LICENSE.txt](./LICENSE.txt) file in the release for details.
|
134
|
+
|
135
|
+
|
136
|
+
AGAIN - yfinrb is **not** affiliated, endorsed, or vetted by Yahoo, Inc. It's
|
137
|
+
an open-source tool that uses Yahoo's publicly available APIs, and is
|
138
|
+
intended for research and educational purposes. You should refer to Yahoo!'s terms of use
|
139
|
+
([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm),
|
140
|
+
[here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and
|
141
|
+
[here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) for
|
142
|
+
details on your rights to use the actual data downloaded.
|
143
|
+
|
144
|
+
---
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
class Yfin
|
2
|
+
module Analysis
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
# attr_accessor :ticker
|
6
|
+
|
7
|
+
def self.included(base) # built-in Ruby hook for modules
|
8
|
+
base.class_eval do
|
9
|
+
original_method = instance_method(:initialize)
|
10
|
+
define_method(:initialize) do |*args, &block|
|
11
|
+
original_method.bind(self).call(*args, &block)
|
12
|
+
initialize_analysis # (your module code here)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize_analysis
|
18
|
+
@earnings_trend = nil
|
19
|
+
@analyst_trend_details = nil
|
20
|
+
@analyst_price_target = nil
|
21
|
+
@ev_est = nil
|
22
|
+
@ps_est = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def earnings_trend #(self)
|
27
|
+
raise YFNotImplementedError.new('earnings_trend') if @earnings_trend.nil?
|
28
|
+
return earnings_trend
|
29
|
+
end
|
30
|
+
|
31
|
+
def analyst_trend_details #(self)
|
32
|
+
raise YFNotImplementedError.new('analyst_trend_details') if @analyst_trend_details.nil?
|
33
|
+
return analyst_trend_details
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method :trend_details, :analyst_trend_details
|
37
|
+
|
38
|
+
def analyst_price_target #(self)
|
39
|
+
raise YFNotImplementedError.new('analyst_price_target') if @analyst_price_target.nil?
|
40
|
+
return analyst_price_target
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :price_targets, :analyst_price_target
|
44
|
+
|
45
|
+
def rev_est #(self)
|
46
|
+
raise YFNotImplementedError.new('rev_est') if @rev_est.nil?
|
47
|
+
return rev_est
|
48
|
+
end
|
49
|
+
|
50
|
+
alias_method :rev_forecast, :rev_est
|
51
|
+
|
52
|
+
def eps_est #(self)
|
53
|
+
raise YFNotImplementedError.new('eps_est') if @eps_est.nil?
|
54
|
+
return eps_est
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :earnings_forecast, :eps_est
|
58
|
+
|
59
|
+
# analysis_methods = [:earnings_trend, :analyst_trend_details, :trend_details, \
|
60
|
+
# :price_targets, :analyst_price_target, :rev_est, \
|
61
|
+
# :rev_forecast, :eps_est, :earnings_forecast ]
|
62
|
+
# analysis_methods.each do |meth|
|
63
|
+
# # delegate meth, to: :analysis
|
64
|
+
# alias_method "get_#{meth}".to_sym, meth
|
65
|
+
# end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,302 @@
|
|
1
|
+
class Yfin
|
2
|
+
module Financials
|
3
|
+
include ActiveSupport::Inflector
|
4
|
+
|
5
|
+
def self.included(base) # built-in Ruby hook for modules
|
6
|
+
base.class_eval do
|
7
|
+
original_method = instance_method(:initialize)
|
8
|
+
define_method(:initialize) do |*args, &block|
|
9
|
+
original_method.bind(self).call(*args, &block)
|
10
|
+
initialize_financials # (your module code here)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize_financials
|
16
|
+
@income_time_series = {}
|
17
|
+
@balance_sheet_time_series = {}
|
18
|
+
@cash_flow_time_series = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def income_stmt; _get_income_stmt(pretty: true); end
|
22
|
+
def quarterly_income_stmt; _get_income_stmt(pretty: true, freq: 'quarterly'); end
|
23
|
+
alias_method :quarterly_incomestmt, :quarterly_income_stmt
|
24
|
+
alias_method :quarterly_financials, :quarterly_income_stmt
|
25
|
+
alias_method :annual_incomestmt, :income_stmt
|
26
|
+
alias_method :annual_income_stmt, :income_stmt
|
27
|
+
alias_method :annual_financials, :income_stmt
|
28
|
+
|
29
|
+
def balance_sheet; _get_balance_sheet(pretty: true); end
|
30
|
+
def quarterly_balance_sheet; _get_balance_sheet(pretty: true, freq: 'quarterly'); end
|
31
|
+
alias_method :quarterly_balancesheet, :quarterly_balance_sheet
|
32
|
+
alias_method :annual_balance_sheet, :balance_sheet
|
33
|
+
alias_method :annual_balancesheet, :balance_sheet
|
34
|
+
|
35
|
+
def cash_flow; _get_cash_flow(pretty: true, freq: 'yearly'); end
|
36
|
+
alias_method :cashflow, :cash_flow
|
37
|
+
def quarterly_cash_flow; _get_cash_flow(pretty: true, freq: 'quarterly'); end
|
38
|
+
alias_method :quarterly_cashflow, :quarterly_cash_flow
|
39
|
+
alias_method :annual_cashflow, :cash_flow
|
40
|
+
alias_method :annual_cash_flow, :cash_flow
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def _get_cash_flow(as_dict: false, pretty: false, freq: "yearly")
|
53
|
+
data = _get_cash_flow_time_series(freq)
|
54
|
+
|
55
|
+
if pretty
|
56
|
+
# data = data.dup
|
57
|
+
# data.index = Utils.camel2title(data.index, sep: ' ', acronyms: ["PPE"])
|
58
|
+
end
|
59
|
+
|
60
|
+
as_dict ? data.to_h : data
|
61
|
+
end
|
62
|
+
|
63
|
+
def _get_income_stmt(as_dict: false, pretty: false, freq: "yearly")
|
64
|
+
data = _get_income_time_series(freq)
|
65
|
+
|
66
|
+
if pretty
|
67
|
+
# data = data.dup
|
68
|
+
# data.index = Utils.camel2title(data.index, sep: ' ', acronyms: ["EBIT", "EBITDA", "EPS", "NI"])
|
69
|
+
end
|
70
|
+
|
71
|
+
as_dict ? data.to_h : data
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def _get_balance_sheet(as_dict: false, pretty: false, freq: "yearly")
|
76
|
+
data = _get_balance_sheet_time_series(freq)
|
77
|
+
|
78
|
+
if pretty
|
79
|
+
# data = data.dup
|
80
|
+
# data.index = Utils.camel2title(data.index, sep: ' ', acronyms: ["PPE"])
|
81
|
+
end
|
82
|
+
|
83
|
+
as_dict ? data.to_h : data
|
84
|
+
end
|
85
|
+
|
86
|
+
def _get_income_time_series(freq = "yearly")
|
87
|
+
res = @income_time_series
|
88
|
+
res[freq] ||= _fetch_time_series("income", freq)
|
89
|
+
res[freq]
|
90
|
+
end
|
91
|
+
|
92
|
+
def _get_balance_sheet_time_series(freq = "yearly")
|
93
|
+
res = @balance_sheet_time_series
|
94
|
+
res[freq] ||= _fetch_time_series("balancesheet", freq)
|
95
|
+
res[freq]
|
96
|
+
end
|
97
|
+
|
98
|
+
def _get_cash_flow_time_series(freq = "yearly")
|
99
|
+
res = @cash_flow_time_series
|
100
|
+
res[freq] ||= _fetch_time_series("cashflow", freq)
|
101
|
+
res[freq]
|
102
|
+
end
|
103
|
+
|
104
|
+
def _get_financials_time_series(timescale, ts_keys)
|
105
|
+
Polars::Config.set_tbl_rows(-1)
|
106
|
+
timescale_translation = { "yearly" => "annual", "quarterly" => "quarterly" }
|
107
|
+
timescale = timescale_translation[timescale]
|
108
|
+
|
109
|
+
ts_url_base = "https://query2.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/#{symbol}?symbol=#{symbol}"
|
110
|
+
url = ts_url_base + "&type=" + ts_keys.map { |k| "#{timescale}#{k}" }.join(",")
|
111
|
+
start_dt = DateTime.new(2016, 12, 31)
|
112
|
+
end_dt = DateTime.now.tomorrow.midnight
|
113
|
+
url += "&period1=#{start_dt.to_i}&period2=#{end_dt.to_i}"
|
114
|
+
|
115
|
+
json_str = get(url).parsed_response
|
116
|
+
data_raw = json_str["timeseries"]["result"]
|
117
|
+
data_raw.each { |d| d.delete("meta") }
|
118
|
+
|
119
|
+
timestamps = data_raw.map{|d| d['timestamp']}.flatten.uniq.compact.uniq.sort.reverse
|
120
|
+
|
121
|
+
cols = [ :metric ] + timestamps.map{|ts| Time.at(ts).utc.to_date.to_s }
|
122
|
+
df = {}; cols.each {|c| df[c] = [] }
|
123
|
+
ts_keys.each { |k| df[:metric] << k.gsub(/([A-Z]+)/,' \1').strip }
|
124
|
+
|
125
|
+
timestamps.each do |ts|
|
126
|
+
ts_date = Time.at(ts).utc.to_date.to_s
|
127
|
+
|
128
|
+
ts_keys.each_with_index do |k, ndex|
|
129
|
+
l = "#{timescale}#{k}"
|
130
|
+
d = data_raw.detect{|dd| dd.key?(l) }
|
131
|
+
if d.nil?
|
132
|
+
df[ts_date] << ''
|
133
|
+
next
|
134
|
+
end
|
135
|
+
tv = d[l].detect{|dd| dd['asOfDate'] == ts_date }
|
136
|
+
df[ts_date] << (tv.nil? ? '' : tv['reportedValue']['raw'].to_s)
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
df = Polars::DataFrame.new(df)
|
142
|
+
timestamps.map{|ts| Time.at(ts).utc.to_date.to_s }.each do |t|
|
143
|
+
puts t
|
144
|
+
df.replace(t, Polars::Series.new(df[t].cast(Polars::String)))
|
145
|
+
end
|
146
|
+
df
|
147
|
+
end
|
148
|
+
|
149
|
+
def _fetch_time_series(nam, timescale)
|
150
|
+
# Rails.logger.info { "#{__FILE__}:#{__LINE__}"}
|
151
|
+
allowed_names = FUNDAMENTALS_KEYS.keys + [:income]
|
152
|
+
allowed_timescales = ["yearly", "quarterly"]
|
153
|
+
|
154
|
+
raise ArgumentError, "Illegal argument: name (#{nam}) must be one of: #{allowed_names}" unless allowed_names.include?(nam.to_sym)
|
155
|
+
raise ArgumentError, "Illegal argument: timescale (#{timescale}) must be one of: #{allowed_timescales}" unless allowed_timescales.include?(timescale)
|
156
|
+
|
157
|
+
begin
|
158
|
+
statement = _create_financials_table(nam, timescale)
|
159
|
+
return statement unless statement.nil?
|
160
|
+
rescue Yfin::YfinDataException => e
|
161
|
+
Rails.logger.error {"#{@symbol}: Failed to create #{nam} financials table for reason: #{e}"}
|
162
|
+
end
|
163
|
+
Polars::DataFrame.new()
|
164
|
+
end
|
165
|
+
|
166
|
+
def _create_financials_table(nam, timescale)
|
167
|
+
nam = "financials" if nam == "income"
|
168
|
+
|
169
|
+
keys = FUNDAMENTALS_KEYS[nam.to_sym]
|
170
|
+
begin
|
171
|
+
_get_financials_time_series(timescale, keys)
|
172
|
+
rescue StandardError
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
FUNDAMENTALS_KEYS = {
|
180
|
+
financials: [
|
181
|
+
"TaxEffectOfUnusualItems", "TaxRateForCalcs", "NormalizedEBITDA", "NormalizedDilutedEPS",
|
182
|
+
"NormalizedBasicEPS", "TotalUnusualItems", "TotalUnusualItemsExcludingGoodwill",
|
183
|
+
"NetIncomeFromContinuingOperationNetMinorityInterest", "ReconciledDepreciation",
|
184
|
+
"ReconciledCostOfRevenue", "EBITDA", "EBIT", "NetInterestIncome", "InterestExpense",
|
185
|
+
"InterestIncome", "ContinuingAndDiscontinuedDilutedEPS", "ContinuingAndDiscontinuedBasicEPS",
|
186
|
+
"NormalizedIncome", "NetIncomeFromContinuingAndDiscontinuedOperation", "TotalExpenses",
|
187
|
+
"RentExpenseSupplemental", "ReportedNormalizedDilutedEPS", "ReportedNormalizedBasicEPS",
|
188
|
+
"TotalOperatingIncomeAsReported", "DividendPerShare", "DilutedAverageShares", "BasicAverageShares",
|
189
|
+
"DilutedEPS", "DilutedEPSOtherGainsLosses", "TaxLossCarryforwardDilutedEPS",
|
190
|
+
"DilutedAccountingChange", "DilutedExtraordinary", "DilutedDiscontinuousOperations",
|
191
|
+
"DilutedContinuousOperations", "BasicEPS", "BasicEPSOtherGainsLosses", "TaxLossCarryforwardBasicEPS",
|
192
|
+
"BasicAccountingChange", "BasicExtraordinary", "BasicDiscontinuousOperations",
|
193
|
+
"BasicContinuousOperations", "DilutedNIAvailtoComStockholders", "AverageDilutionEarnings",
|
194
|
+
"NetIncomeCommonStockholders", "OtherunderPreferredStockDividend", "PreferredStockDividends",
|
195
|
+
"NetIncome", "MinorityInterests", "NetIncomeIncludingNoncontrollingInterests",
|
196
|
+
"NetIncomeFromTaxLossCarryforward", "NetIncomeExtraordinary", "NetIncomeDiscontinuousOperations",
|
197
|
+
"NetIncomeContinuousOperations", "EarningsFromEquityInterestNetOfTax", "TaxProvision",
|
198
|
+
"PretaxIncome", "OtherIncomeExpense", "OtherNonOperatingIncomeExpenses", "SpecialIncomeCharges",
|
199
|
+
"GainOnSaleOfPPE", "GainOnSaleOfBusiness", "OtherSpecialCharges", "WriteOff",
|
200
|
+
"ImpairmentOfCapitalAssets", "RestructuringAndMergernAcquisition", "SecuritiesAmortization",
|
201
|
+
"EarningsFromEquityInterest", "GainOnSaleOfSecurity", "NetNonOperatingInterestIncomeExpense",
|
202
|
+
"TotalOtherFinanceCost", "InterestExpenseNonOperating", "InterestIncomeNonOperating",
|
203
|
+
"OperatingIncome", "OperatingExpense", "OtherOperatingExpenses", "OtherTaxes",
|
204
|
+
"ProvisionForDoubtfulAccounts", "DepreciationAmortizationDepletionIncomeStatement",
|
205
|
+
"DepletionIncomeStatement", "DepreciationAndAmortizationInIncomeStatement", "Amortization",
|
206
|
+
"AmortizationOfIntangiblesIncomeStatement", "DepreciationIncomeStatement", "ResearchAndDevelopment",
|
207
|
+
"SellingGeneralAndAdministration", "SellingAndMarketingExpense", "GeneralAndAdministrativeExpense",
|
208
|
+
"OtherGandA", "InsuranceAndClaims", "RentAndLandingFees", "SalariesAndWages", "GrossProfit",
|
209
|
+
"CostOfRevenue", "TotalRevenue", "ExciseTaxes", "OperatingRevenue"
|
210
|
+
],
|
211
|
+
balancesheet: [
|
212
|
+
"TreasurySharesNumber", "PreferredSharesNumber", "OrdinarySharesNumber", "ShareIssued", "NetDebt",
|
213
|
+
"TotalDebt", "TangibleBookValue", "InvestedCapital", "WorkingCapital", "NetTangibleAssets",
|
214
|
+
"CapitalLeaseObligations", "CommonStockEquity", "PreferredStockEquity", "TotalCapitalization",
|
215
|
+
"TotalEquityGrossMinorityInterest", "MinorityInterest", "StockholdersEquity",
|
216
|
+
"OtherEquityInterest", "GainsLossesNotAffectingRetainedEarnings", "OtherEquityAdjustments",
|
217
|
+
"FixedAssetsRevaluationReserve", "ForeignCurrencyTranslationAdjustments",
|
218
|
+
"MinimumPensionLiabilities", "UnrealizedGainLoss", "TreasuryStock", "RetainedEarnings",
|
219
|
+
"AdditionalPaidInCapital", "CapitalStock", "OtherCapitalStock", "CommonStock", "PreferredStock",
|
220
|
+
"TotalPartnershipCapital", "GeneralPartnershipCapital", "LimitedPartnershipCapital",
|
221
|
+
"TotalLiabilitiesNetMinorityInterest", "TotalNonCurrentLiabilitiesNetMinorityInterest",
|
222
|
+
"OtherNonCurrentLiabilities", "LiabilitiesHeldforSaleNonCurrent", "RestrictedCommonStock",
|
223
|
+
"PreferredSecuritiesOutsideStockEquity", "DerivativeProductLiabilities", "EmployeeBenefits",
|
224
|
+
"NonCurrentPensionAndOtherPostretirementBenefitPlans", "NonCurrentAccruedExpenses",
|
225
|
+
"DuetoRelatedPartiesNonCurrent", "TradeandOtherPayablesNonCurrent",
|
226
|
+
"NonCurrentDeferredLiabilities", "NonCurrentDeferredRevenue",
|
227
|
+
"NonCurrentDeferredTaxesLiabilities", "LongTermDebtAndCapitalLeaseObligation",
|
228
|
+
"LongTermCapitalLeaseObligation", "LongTermDebt", "LongTermProvisions", "CurrentLiabilities",
|
229
|
+
"OtherCurrentLiabilities", "CurrentDeferredLiabilities", "CurrentDeferredRevenue",
|
230
|
+
"CurrentDeferredTaxesLiabilities", "CurrentDebtAndCapitalLeaseObligation",
|
231
|
+
"CurrentCapitalLeaseObligation", "CurrentDebt", "OtherCurrentBorrowings", "LineOfCredit",
|
232
|
+
"CommercialPaper", "CurrentNotesPayable", "PensionandOtherPostRetirementBenefitPlansCurrent",
|
233
|
+
"CurrentProvisions", "PayablesAndAccruedExpenses", "CurrentAccruedExpenses", "InterestPayable",
|
234
|
+
"Payables", "OtherPayable", "DuetoRelatedPartiesCurrent", "DividendsPayable", "TotalTaxPayable",
|
235
|
+
"IncomeTaxPayable", "AccountsPayable", "TotalAssets", "TotalNonCurrentAssets",
|
236
|
+
"OtherNonCurrentAssets", "DefinedPensionBenefit", "NonCurrentPrepaidAssets",
|
237
|
+
"NonCurrentDeferredAssets", "NonCurrentDeferredTaxesAssets", "DuefromRelatedPartiesNonCurrent",
|
238
|
+
"NonCurrentNoteReceivables", "NonCurrentAccountsReceivable", "FinancialAssets",
|
239
|
+
"InvestmentsAndAdvances", "OtherInvestments", "InvestmentinFinancialAssets",
|
240
|
+
"HeldToMaturitySecurities", "AvailableForSaleSecurities",
|
241
|
+
"FinancialAssetsDesignatedasFairValueThroughProfitorLossTotal", "TradingSecurities",
|
242
|
+
"LongTermEquityInvestment", "InvestmentsinJointVenturesatCost",
|
243
|
+
"InvestmentsInOtherVenturesUnderEquityMethod", "InvestmentsinAssociatesatCost",
|
244
|
+
"InvestmentsinSubsidiariesatCost", "InvestmentProperties", "GoodwillAndOtherIntangibleAssets",
|
245
|
+
"OtherIntangibleAssets", "Goodwill", "NetPPE", "AccumulatedDepreciation", "GrossPPE", "Leases",
|
246
|
+
"ConstructionInProgress", "OtherProperties", "MachineryFurnitureEquipment",
|
247
|
+
"BuildingsAndImprovements", "LandAndImprovements", "Properties", "CurrentAssets",
|
248
|
+
"OtherCurrentAssets", "HedgingAssetsCurrent", "AssetsHeldForSaleCurrent", "CurrentDeferredAssets",
|
249
|
+
"CurrentDeferredTaxesAssets", "RestrictedCash", "PrepaidAssets", "Inventory",
|
250
|
+
"InventoriesAdjustmentsAllowances", "OtherInventories", "FinishedGoods", "WorkInProcess",
|
251
|
+
"RawMaterials", "Receivables", "ReceivablesAdjustmentsAllowances", "OtherReceivables",
|
252
|
+
"DuefromRelatedPartiesCurrent", "TaxesReceivable", "AccruedInterestReceivable", "NotesReceivable",
|
253
|
+
"LoansReceivable", "AccountsReceivable", "AllowanceForDoubtfulAccountsReceivable",
|
254
|
+
"GrossAccountsReceivable", "CashCashEquivalentsAndShortTermInvestments",
|
255
|
+
"OtherShortTermInvestments", "CashAndCashEquivalents", "CashEquivalents", "CashFinancial"
|
256
|
+
],
|
257
|
+
cashflow: [
|
258
|
+
"ForeignSales", "DomesticSales", "AdjustedGeographySegmentData", "FreeCashFlow",
|
259
|
+
"RepurchaseOfCapitalStock", "RepaymentOfDebt", "IssuanceOfDebt", "IssuanceOfCapitalStock",
|
260
|
+
"CapitalExpenditure", "InterestPaidSupplementalData", "IncomeTaxPaidSupplementalData",
|
261
|
+
"EndCashPosition", "OtherCashAdjustmentOutsideChangeinCash", "BeginningCashPosition",
|
262
|
+
"EffectOfExchangeRateChanges", "ChangesInCash", "OtherCashAdjustmentInsideChangeinCash",
|
263
|
+
"CashFlowFromDiscontinuedOperation", "FinancingCashFlow", "CashFromDiscontinuedFinancingActivities",
|
264
|
+
"CashFlowFromContinuingFinancingActivities", "NetOtherFinancingCharges", "InterestPaidCFF",
|
265
|
+
"ProceedsFromStockOptionExercised", "CashDividendsPaid", "PreferredStockDividendPaid",
|
266
|
+
"CommonStockDividendPaid", "NetPreferredStockIssuance", "PreferredStockPayments",
|
267
|
+
"PreferredStockIssuance", "NetCommonStockIssuance", "CommonStockPayments", "CommonStockIssuance",
|
268
|
+
"NetIssuancePaymentsOfDebt", "NetShortTermDebtIssuance", "ShortTermDebtPayments",
|
269
|
+
"ShortTermDebtIssuance", "NetLongTermDebtIssuance", "LongTermDebtPayments", "LongTermDebtIssuance",
|
270
|
+
"InvestingCashFlow", "CashFromDiscontinuedInvestingActivities",
|
271
|
+
"CashFlowFromContinuingInvestingActivities", "NetOtherInvestingChanges", "InterestReceivedCFI",
|
272
|
+
"DividendsReceivedCFI", "NetInvestmentPurchaseAndSale", "SaleOfInvestment", "PurchaseOfInvestment",
|
273
|
+
"NetInvestmentPropertiesPurchaseAndSale", "SaleOfInvestmentProperties",
|
274
|
+
"PurchaseOfInvestmentProperties", "NetBusinessPurchaseAndSale", "SaleOfBusiness",
|
275
|
+
"PurchaseOfBusiness", "NetIntangiblesPurchaseAndSale", "SaleOfIntangibles", "PurchaseOfIntangibles",
|
276
|
+
"NetPPEPurchaseAndSale", "SaleOfPPE", "PurchaseOfPPE", "CapitalExpenditureReported",
|
277
|
+
"OperatingCashFlow", "CashFromDiscontinuedOperatingActivities",
|
278
|
+
"CashFlowFromContinuingOperatingActivities", "TaxesRefundPaid", "InterestReceivedCFO",
|
279
|
+
"InterestPaidCFO", "DividendReceivedCFO", "DividendPaidCFO", "ChangeInWorkingCapital",
|
280
|
+
"ChangeInOtherWorkingCapital", "ChangeInOtherCurrentLiabilities", "ChangeInOtherCurrentAssets",
|
281
|
+
"ChangeInPayablesAndAccruedExpense", "ChangeInAccruedExpense", "ChangeInInterestPayable",
|
282
|
+
"ChangeInPayable", "ChangeInDividendPayable", "ChangeInAccountPayable", "ChangeInTaxPayable",
|
283
|
+
"ChangeInIncomeTaxPayable", "ChangeInPrepaidAssets", "ChangeInInventory", "ChangeInReceivables",
|
284
|
+
"ChangesInAccountReceivables", "OtherNonCashItems", "ExcessTaxBenefitFromStockBasedCompensation",
|
285
|
+
"StockBasedCompensation", "UnrealizedGainLossOnInvestmentSecurities", "ProvisionandWriteOffofAssets",
|
286
|
+
"AssetImpairmentCharge", "AmortizationOfSecurities", "DeferredTax", "DeferredIncomeTax",
|
287
|
+
"DepreciationAmortizationDepletion", "Depletion", "DepreciationAndAmortization",
|
288
|
+
"AmortizationCashFlow", "AmortizationOfIntangibles", "Depreciation", "OperatingGainsLosses",
|
289
|
+
"PensionAndEmployeeBenefitExpense", "EarningsLossesFromEquityInvestments",
|
290
|
+
"GainLossOnInvestmentSecurities", "NetForeignCurrencyExchangeGainLoss", "GainLossOnSaleOfPPE",
|
291
|
+
"GainLossOnSaleOfBusiness", "NetIncomeFromContinuingOperations",
|
292
|
+
"CashFlowsfromusedinOperatingActivitiesDirect", "TaxesRefundPaidDirect", "InterestReceivedDirect",
|
293
|
+
"InterestPaidDirect", "DividendsReceivedDirect", "DividendsPaidDirect", "ClassesofCashPayments",
|
294
|
+
"OtherCashPaymentsfromOperatingActivities", "PaymentsonBehalfofEmployees",
|
295
|
+
"PaymentstoSuppliersforGoodsandServices", "ClassesofCashReceiptsfromOperatingActivities",
|
296
|
+
"OtherCashReceiptsfromOperatingActivities", "ReceiptsfromGovernmentGrants", "ReceiptsfromCustomers"
|
297
|
+
]
|
298
|
+
}
|
299
|
+
|
300
|
+
|
301
|
+
end
|
302
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
class Yfin
|
3
|
+
module Fundamentals
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def self.included(base) # built-in Ruby hook for modules
|
7
|
+
base.class_eval do
|
8
|
+
attr_reader :financials, :earnings, :shares, :ticker
|
9
|
+
|
10
|
+
original_method = instance_method(:initialize)
|
11
|
+
define_method(:initialize) do |*args, &block|
|
12
|
+
original_method.bind(self).call(*args, &block)
|
13
|
+
initialize_fundamentals # (your module code here)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize_fundamentals
|
19
|
+
@earnings = nil
|
20
|
+
@financials = nil
|
21
|
+
@shares = nil
|
22
|
+
|
23
|
+
@financials_data = nil
|
24
|
+
@fin_data_quote = nil
|
25
|
+
@basics_already_scraped = false
|
26
|
+
end
|
27
|
+
|
28
|
+
# delegate :proxy, :tz, to: :ticker
|
29
|
+
|
30
|
+
def earnings
|
31
|
+
raise YFNotImplementedError.new('earnings') if @earnings.nil?
|
32
|
+
@earnings
|
33
|
+
end
|
34
|
+
|
35
|
+
def shares
|
36
|
+
raise YFNotImplementedError.new('shares') if @shares.nil?
|
37
|
+
@shares
|
38
|
+
end
|
39
|
+
|
40
|
+
# financials_methods = [:income_stmt, :incomestmt, :financials, :balance_sheet, :balancesheet, :cash_flow, :cashflow]
|
41
|
+
# financials_methods.each do |meth|
|
42
|
+
# delegate "get_#{meth}".to_sym, meth, to: :financials
|
43
|
+
# end
|
44
|
+
|
45
|
+
# fundamentals_methods = [:earnings, :shares]
|
46
|
+
# fundamentals_methods.each do |meth|
|
47
|
+
# alias_method "get_#{meth}".to_sym, meth
|
48
|
+
# end
|
49
|
+
|
50
|
+
# def quarterly_earnings
|
51
|
+
# earnings(freq: 'quarterly')
|
52
|
+
# end
|
53
|
+
end
|
54
|
+
end
|