yfinrb 0.1.0

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 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
@@ -0,0 +1,13 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Style/StringLiterals:
5
+ Enabled: true
6
+ EnforcedStyle: double_quotes
7
+
8
+ Style/StringLiteralsInInterpolation:
9
+ Enabled: true
10
+ EnforcedStyle: double_quotes
11
+
12
+ Layout/LineLength:
13
+ Max: 120
data/CHANGELOG.rst ADDED
File without changes
@@ -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
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in yfinrb.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rubocop", "~> 1.21"
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,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rubocop/rake_task"
5
+
6
+ RuboCop::RakeTask.new
7
+
8
+ task default: :rubocop
@@ -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