yahoo_finance_lib 0.7.1 → 0.7.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +6 -7
- data/README.md +30 -3
- data/lib/yahoo_finance.rb +1 -0
- data/lib/yahoo_finance/analyst_opinion.rb +2 -2
- data/lib/yahoo_finance/company_events.rb +3 -3
- data/lib/yahoo_finance/company_profile.rb +8 -3
- data/lib/yahoo_finance/financial_statement.rb +324 -0
- data/lib/yahoo_finance/key_statistics.rb +3 -2
- data/lib/yahoo_finance/stock.rb +55 -9
- data/lib/yahoo_finance/version.rb +1 -1
- data/spec/yahoo_company_events_spec.rb +4 -3
- data/spec/yahoo_financial_statement_spec.rb +124 -0
- metadata +25 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd71a533f1acc521ce2c0640edca3edf271d4839
|
4
|
+
data.tar.gz: b89733ecc5c7c3e96626b70efb7d83c6ba71318f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9c5122b36f66b8acd2d615c5824f458b9c71223f2827bd9036c3aa1f41f788a17e69c4edea0d0add7d7f1bfb6848bc49ef6707243de9a3f3f0b30ee9d5123b3
|
7
|
+
data.tar.gz: 8bd86c5c3eac252821d39074c624f53c0f1d2934d379a1f0cc920fa43baec4fa89e9696a0c6d8075cedb754e3a885733cf70df129df9db8c2b5a1e249d512b2b
|
data/History.md
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
|
1
|
+
## History of changes
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
Added company profile scraping :sector, and :industry
|
7
|
-
|
8
|
-
Added :website attribute in company profile; also added YahooFinance::StockHistory abstraction to nas/yahoo_finance
|
3
|
+
Version | Description
|
4
|
+
------- | -----------
|
5
|
+
0.6 | Original release, supporting key statistics, company events, and analyst opinion
|
6
|
+
0.7 | Added company profile scraping :sector, and :industry
|
7
|
+
0.7.1 |Added :website attribute in company profile; also added YahooFinance::StockHistory abstraction to nas/yahoo_finance
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# YahooFinance library
|
2
2
|
|
3
|
-
YahooFinance lib is a gem that fetches stock quotes, key statistics, company events, and analyst opinion from Yahoo (TM) API and financial HTML pages. The loading of stock quotes uses the excellent nas/yahoo_stock gem. This gem provides a 'unified' attribute based interface, and abstracts the source of the information, i.e. the user only needs to specify an attribute without the need to specify the page source of the attribute. This gem leverages to the highest extend possible the YahooStock (yahoo_stock_nas) gem for all the attributes provided by that gem, and fails over to HTML scraping when the data is unavailable there. Naturally, this has an implication on performance; YahooStock queries bundle 50 stocks in each query, whereas HTML scraping happens one page per stock at a time.
|
3
|
+
YahooFinance lib is a gem that fetches stock quotes, key statistics, company profile, company events, and analyst opinion from Yahoo (TM) API and financial HTML pages. Additionally, it has interfaces for historical data, and financial statements. The loading of stock quotes uses the excellent nas/yahoo_stock gem. This gem provides a 'unified' attribute based interface, and abstracts the source of the information, i.e. the user only needs to specify an attribute without the need to specify the page source of the attribute. This gem leverages to the highest extend possible the YahooStock (yahoo_stock_nas) gem for all the attributes provided by that gem, and fails over to HTML scraping when the data is unavailable there. Naturally, this has an implication on performance; YahooStock queries bundle 50 stocks in each query, whereas HTML scraping happens one page per stock at a time.
|
4
4
|
|
5
5
|
#####This gem is currently still in development. HTML scraping now supports many attributes from Key Statistics, supports earnings announcements from the Company Events page, and most attributes from Analyst Opinion -- additional pages will be added as I find time.
|
6
6
|
|
@@ -23,13 +23,20 @@ Or install it yourself as:
|
|
23
23
|
|
24
24
|
$ gem install yahoo_finance_lib
|
25
25
|
|
26
|
+
## Test Before You Use
|
27
|
+
Web pages get occasionally updated -- updates could break any or all of the classes in the gem. Do not use any classes that don't pass the RSpec tests. To test, run the rspec tests from the root directory:
|
28
|
+
```
|
29
|
+
rspec -c -f d
|
30
|
+
```
|
31
|
+
|
26
32
|
## Usage
|
27
33
|
|
28
34
|
|
29
35
|
|
30
36
|
Example:
|
37
|
+
|
38
|
+
```ruby
|
31
39
|
irb
|
32
|
-
require 'rubygems'
|
33
40
|
require 'yahoo_finance'
|
34
41
|
|
35
42
|
stock = YahooFinance::Stock.new(['AAPL', 'YHOO'], [:market_cap, :bid, :brokers_count, :upgrades_downgrades_history])
|
@@ -41,15 +48,35 @@ Example:
|
|
41
48
|
results = stock.fetch
|
42
49
|
aapl_bid = results["AAPL"][:bid]
|
43
50
|
yhoo_last = results["YHOO"][:last_trade_price_only]
|
51
|
+
```
|
44
52
|
|
45
53
|
A simple interface using yahoo_stock to fetch history. It returns history as an array of hashes, e.g.
|
54
|
+
|
55
|
+
```ruby
|
46
56
|
irb
|
47
57
|
require 'yahoo_finance'
|
48
58
|
require 'date'
|
49
59
|
|
50
60
|
start_date = Date.today - 30
|
51
|
-
history = YahooFinance::StockHistory.new('AAPL', start_date)
|
61
|
+
history = YahooFinance::StockHistory.new('AAPL', start_date) # when you don't specify end date, end date = today - 1
|
52
62
|
history.fetch
|
63
|
+
```
|
64
|
+
|
65
|
+
A simple interface to scrape financial statements - Income Statement, Balance Sheet, and Cash Flow. It can fetch either quarterly or annual data, and it returns the value in a hash. e.g.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
irb
|
69
|
+
require 'yahoo_finance'
|
70
|
+
|
71
|
+
income_stmt = YahooFinance::FinancialStatement::QuarterlyIncomeStatementPage.new 'YHOO'
|
72
|
+
result = income_stmt.fetch
|
73
|
+
most_recent_qtr = income_stmt.statement_periods[0]
|
74
|
+
available_fields = income_stmt.available_fields
|
75
|
+
|
76
|
+
puts "Net income for the most recent quarter ending on #{most_recent_qtr.to_s} is #{result[:net_income][0]}"
|
77
|
+
```
|
78
|
+
|
79
|
+
The classes for the financial statement are: QuarterlyIncomeStatementPage, AnnualIncomeStatementPage, AnnualBalanceSheetPage, QuarterlyBalanceSheetPage, QuarterlyCashFlowStatementPage, AnnualCashFlowStatementPage
|
53
80
|
|
54
81
|
!-- ## Contributing
|
55
82
|
|
data/lib/yahoo_finance.rb
CHANGED
@@ -11,9 +11,9 @@ module YahooFinance
|
|
11
11
|
end
|
12
12
|
|
13
13
|
class CompanyEventsPage
|
14
|
-
|
14
|
+
attr_accessor :symbol
|
15
15
|
|
16
|
-
def initialize symbol
|
16
|
+
def initialize symbol=nil
|
17
17
|
@symbol = symbol
|
18
18
|
end
|
19
19
|
|
@@ -38,4 +38,4 @@ module YahooFinance
|
|
38
38
|
|
39
39
|
end
|
40
40
|
end
|
41
|
-
end
|
41
|
+
end
|
@@ -6,16 +6,18 @@ module YahooFinance
|
|
6
6
|
COMPANY_PROFILE_STATS = {
|
7
7
|
:sector => ['Sector:', "Sector classification"],
|
8
8
|
:industry => ['Industry:', 'Industry classification'],
|
9
|
-
:website => ['Website:', 'Company website']
|
9
|
+
:website => ['Website:', 'Company website'],
|
10
|
+
:symbol => ['Symbol', 'Company Exchange Symbol'],
|
11
|
+
:company_name => ['Company Name', 'Company Name']
|
10
12
|
}
|
11
13
|
def CompanyProfile.key_events_available
|
12
14
|
return YahooFinance::CompanyProfile::COMPANY_PROFILE_STATS.keys;
|
13
15
|
end
|
14
16
|
|
15
17
|
class CompanyProfilePage
|
16
|
-
|
18
|
+
attr_accessor :symbol
|
17
19
|
|
18
|
-
def initialize symbol
|
20
|
+
def initialize symbol=nil
|
19
21
|
@symbol = symbol
|
20
22
|
end
|
21
23
|
|
@@ -34,6 +36,9 @@ module YahooFinance
|
|
34
36
|
if key_stat == :website
|
35
37
|
r = @doc.xpath("//td[contains(., \"#{YahooFinance::CompanyProfile::COMPANY_PROFILE_STATS[key_stat][0]}\")]")
|
36
38
|
return r.xpath("./a[contains(., 'http:')]").text
|
39
|
+
elsif key_stat == :company_name
|
40
|
+
name = @doc.xpath('//td[@class="yfnc_modtitlew1"]//b')[0].text
|
41
|
+
return name
|
37
42
|
elsif CompanyProfile::key_events_available.include? key_stat
|
38
43
|
begin
|
39
44
|
value = @doc.xpath("//td[text() = \"#{YahooFinance::CompanyProfile::COMPANY_PROFILE_STATS[key_stat][0]}\"]")[0].parent.children[1].text
|
@@ -0,0 +1,324 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'date'
|
4
|
+
|
5
|
+
module YahooFinance
|
6
|
+
module FinancialStatement
|
7
|
+
INCOME_STMT_FIELDS = {
|
8
|
+
:statement_periods => ['Period Ending', "Ending date per period"],
|
9
|
+
:total_revenue => ['Total Revenue', "Total Revenue (per period)"],
|
10
|
+
:cost_of_revenue => ['Cost of Revenue', 'Cost of Revenue (per period)'],
|
11
|
+
:gross_profit => ['Gross Profit', 'Gross profit (per period)'],
|
12
|
+
:research_development => ['Research Development', 'Research and Development (per period)'],
|
13
|
+
:selling_general_and_administrative => ['Selling General and Administrative', 'Selling General and Administrative (per period)'],
|
14
|
+
:non_recurring => ['Non Recurring', 'Non Recurring (per period)'],
|
15
|
+
:other_expenses => ['Others', 'Other expenses (per period)'],
|
16
|
+
:total_operating_expenses => ['Total Operating Expenses', 'Total Operating Expenses (per period)'],
|
17
|
+
:operating_income_or_loss => ['Operating Income or Loss', 'Operating Income or Loss (per period)'],
|
18
|
+
:total_other_income_expenses_net => ['Total Other Income/Expenses Net', 'Total Other Income/Expenses Net (per period)'],
|
19
|
+
:EBIT => ['Earnings Before Interest And Taxes', ' Earnings Before Interest And Taxes (per period)'],
|
20
|
+
:interest_expense => ['Interest Expense', 'Interest Expense (per period)'],
|
21
|
+
:income_before_tax => ['Income Before Tax', 'Income Before Tax (per period)'],
|
22
|
+
:income_tax_expense => ['Income Tax Expense', 'Income Tax Expense (per period)'],
|
23
|
+
:minority_interest => ['Minority Interest', 'Minority Interest (per period)'],
|
24
|
+
:net_income_from_continuing_operations => ['Net Income From Continuing Ops', 'Net Income From Continuing Ops (per period)'],
|
25
|
+
:discontinued_operations => ['Discontinued Operations', 'Discontinued Operations (per period)'],
|
26
|
+
:extraordinary_items =>['Extraordinary Items', 'Extraordinary Items (per period)'],
|
27
|
+
:effect_of_accounting_changes => ['Effect Of Accounting Changes', 'Effect Of Accounting Changes (per period)'],
|
28
|
+
:other_items => ['Other Items', 'Other Items (per period)'],
|
29
|
+
:net_income => ['Net Income', 'Net Income (per period)'],
|
30
|
+
:preferred_stock_and_other_adjustments => ['Preferred Stock And Other Adjustments', 'Preferred Stock And Other Adjustments (per period)'],
|
31
|
+
:net_income_applicable_to_common_shares => ['Net Income Applicable To Common Shares', 'Net Income Applicable To Common Shares (per period)']
|
32
|
+
}
|
33
|
+
|
34
|
+
BALANCE_SHEET_FIELDS = {
|
35
|
+
:statement_periods => ['Period Ending', "Ending date per period"],
|
36
|
+
:cash_and_cash_equivalents => ['Cash And Cash Equivalents', 'Cash And Cash Equivalents'],
|
37
|
+
:short_term_investments => ['Short Term Investments', ' Short Term Investments'],
|
38
|
+
:net_receivables => ['Net Receivables', 'Net Receivables'],
|
39
|
+
:inventory => ['Inventory', 'Inventory'],
|
40
|
+
:other_current_assets => ['Other Current Assets', 'Other Current Assets'],
|
41
|
+
:total_current_assets => ['Total Current Assets', 'Total Current Assets'],
|
42
|
+
:long_term_investments => ['Long Term Investments', 'Long Term Investments'],
|
43
|
+
:property_plant_and_equipment => ['Property Plant and Equipment', 'Property Plant and Equipment'],
|
44
|
+
:goodwill => ['Goodwill', 'Goodwill'],
|
45
|
+
:intagible_assets => ['Intangible Assets', 'Intangible Assets'],
|
46
|
+
:accumulated_amortization => ['Accumulated Amortization', 'Accumulated Amortization'],
|
47
|
+
:other_assets => ['Other Assets', 'Other Assets'],
|
48
|
+
:deferred_long_term_asset_charges => ['Deferred Long Term Asset Charges', 'Deferred Long Term Asset Charges'],
|
49
|
+
:total_assets => ['Total Assets', 'Total Assets'],
|
50
|
+
:accounts_payable => ['Accounts Payable', 'Accounts Payable'],
|
51
|
+
:short_current_long_term_debt => ['Short/Current Long Term Debt', 'Short/Current Long Term Debt'],
|
52
|
+
:other_current_liabilities => ['Other Current Liabilities', 'Other Current Liabilities'],
|
53
|
+
:total_current_liabilities => ['Total Current Liabilities', 'Total Current Liabilities'],
|
54
|
+
:long_term_debt => ['Long Term Debt', 'Long Term Debt'],
|
55
|
+
:other_liabilities => ['Other Liabilities', 'Other Liabilities'],
|
56
|
+
:deferred_long_term_liability_charges => ['Deferred Long Term Liability Charges', 'Deferred Long Term Liability Charges'],
|
57
|
+
:minority_interest => ['Minority Interest', 'Minority Interest'],
|
58
|
+
:negative_goodwill => ['Negative Goodwill', 'Negative Goodwill'],
|
59
|
+
:total_liabilities => ['Total Liabilities', 'Total Liabilities'],
|
60
|
+
:misc_stocks_options_warrants => ['Misc Stocks Options Warrants', 'Misc Stocks Options Warrants'],
|
61
|
+
:redeemable_preferred_stock => ['Redeemable Preferred Stock', 'Redeemable Preferred Stock'],
|
62
|
+
:preferred_stock => ['Preferred Stock', 'Preferred Stock'],
|
63
|
+
:common_stock => ['Common Stock', 'Common Stock'],
|
64
|
+
:retained_earnings => ['Retained Earnings', 'Retained Earnings'],
|
65
|
+
:treasury_stock => ['Treasury Stock', 'Treasury Stock'],
|
66
|
+
:capital_surplus => ['Capital Surplus', 'Capital Surplus'],
|
67
|
+
:other_stockholder_equity => ['Other Stockholder Equity', 'Other Stockholder Equity'],
|
68
|
+
:total_stockholder_equity => ['Total Stockholder Equity', 'Total Stockholder Equity'],
|
69
|
+
:net_tangible_assets => ['Net Tangible Assets', 'Net Tangible Assets']
|
70
|
+
}
|
71
|
+
|
72
|
+
CASH_FLOW_STMT_FIELDS = {
|
73
|
+
:statement_periods => ['Period Ending', "Ending date per period"],
|
74
|
+
:net_income => ['Net Income', 'Net Income'],
|
75
|
+
:depreciation => ['Depreciation', 'Depreciation'],
|
76
|
+
:adjustments_to_net_income => ['Adjustments To Net Income','Adjustments To Net Income'],
|
77
|
+
:changes_in_accounts_receivables => ['Changes In Accounts Receivables', 'Changes In Accounts Receivables'],
|
78
|
+
:changes_in_liabilities => ['Changes In Liabilities','Changes In Liabilities'],
|
79
|
+
:changes_in_inventories => ['Changes In Inventories', 'Changes In Inventories'],
|
80
|
+
:changes_in_other_operating_activities => ['Changes In Other Operating Activities', 'Changes In Other Operating Activities'],
|
81
|
+
:total_cash_flow_from_operating_activities => ['Total Cash Flow From Operating Activities', 'Total Cash Flow From Operating Activities'],
|
82
|
+
:capital_expenditures => ['Capital Expenditures', 'Capital Expenditures'],
|
83
|
+
:investments => ['Investments', 'Investments'],
|
84
|
+
:other_cash_flows_from_investing_activities => ['Other Cash flows from Investing Activities', 'Other Cash flows from Investing Activities'],
|
85
|
+
:total_cash_flows_from_investing_activities => ['Total Cash Flows From Investing Activities', 'Total Cash Flows From Investing Activities'],
|
86
|
+
:dividends_paid => ['Dividends Paid', 'Dividends Paid'],
|
87
|
+
:sale_purchase_of_stock => ['Sale Purchase of Stock', 'Sale Purchase of Stock'],
|
88
|
+
:net_borrowings => ['Net Borrowings', 'Net Borrowings'],
|
89
|
+
:other_cash_flows_from_financing_activities => ['Other Cash Flows from Financing Activities', 'Other Cash Flows from Financing Activities'],
|
90
|
+
:total_cash_flows_from_financing_activities => ['Total Cash Flows From Financing Activities', 'Total Cash Flows From Financing Activities'],
|
91
|
+
:effect_of_exchange_rate_changes => ['Effect Of Exchange Rate Changes', 'Effect Of Exchange Rate Changes'],
|
92
|
+
:change_in_cash_and_cash_equivalents => ['Change In Cash and Cash Equivalents', 'Change In Cash and Cash Equivalents']
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
# Quarterly Data
|
97
|
+
class FinancialStatementPage
|
98
|
+
attr_accessor :symbol
|
99
|
+
|
100
|
+
def initialize symbol=nil
|
101
|
+
@symbol = symbol
|
102
|
+
@term = :quarterly
|
103
|
+
@periods = []
|
104
|
+
@number_multiplier = 1000.00 # all numbers in the statements are in thousands... I need to verify whether I need to parse that
|
105
|
+
@financial_statement = {}
|
106
|
+
@data_columns = 4
|
107
|
+
@type="is"
|
108
|
+
@field_defs = YahooFinance::FinancialStatement::INCOME_STMT_FIELDS
|
109
|
+
end
|
110
|
+
|
111
|
+
def term= aValue
|
112
|
+
if term == :quarterly || term == :annual
|
113
|
+
@term = term
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def available_fields
|
118
|
+
return @field_defs.keys;
|
119
|
+
end
|
120
|
+
|
121
|
+
def fetch
|
122
|
+
url = "http://finance.yahoo.com/q/#{@type}?s=#{@symbol}&#{@term.to_s}"
|
123
|
+
doc = nil
|
124
|
+
tries = 0
|
125
|
+
begin
|
126
|
+
# SINCE YAHOO HAS SOME TIMES THE TENDENCY TO RETURN AN OOPS PAGE RATHER THAN A HTTP FAILURE
|
127
|
+
# WE ARE USING A TEST OF A HEADER FIELD AS A CONDITION OF A CORRECTLY FETCHED PAGE
|
128
|
+
fetched_ok = false
|
129
|
+
fetch_tries = 1
|
130
|
+
while (fetched_ok == false) && (fetch_tries <= 3)
|
131
|
+
open(url) do |stream|
|
132
|
+
doc = Nokogiri::HTML(stream)
|
133
|
+
end
|
134
|
+
search_field = ((@type == "is") ? "Income Statement" : ((@type == "bs") ? "Balance Sheet" : "Cash Flow") )
|
135
|
+
fetched_test = doc.xpath("//b[text()[contains(., '" + search_field +"')]]")
|
136
|
+
if fetched_test && fetched_test.size > 0
|
137
|
+
# THERE IS STILL A CHANCE THAT YAHOO WILL NOT HAVE THE DATA FOR THIS STOCK, IN WHICH CASE, IT WILL DISPLAY
|
138
|
+
# a PAGE WITH A STATEMENT LIKE: 'There is no Income Statement data available for AMBR.' --- WE SEARCH FOR THAT AND RETURN NIL IF FOUND
|
139
|
+
nodata_path_search_expr = "//p[text()[contains(., 'There is no "+ search_field + " data available for #{symbol}.')]]"
|
140
|
+
no_statement = doc.xpath(nodata_path_search_expr)
|
141
|
+
# puts "EXPR: #{nodata_path_search_expr} NO STATEMENT: #{no_statement} AND SIZE: #{no_statement.size}"
|
142
|
+
if (no_statement && (no_statement.size > 0))
|
143
|
+
puts "WARNING: FOUND There is no #{search_field} data available for #{symbol}. -- RETURNING NIL"
|
144
|
+
return nil # YAHOO DOESN'T HAVE THE DATA...
|
145
|
+
else
|
146
|
+
fetched_ok = true
|
147
|
+
end
|
148
|
+
else
|
149
|
+
puts "Fetching URL #{url} again - previous one failed. Trying #{fetch_tries} of 3"
|
150
|
+
sleep (1)
|
151
|
+
fetch_tries += 1
|
152
|
+
end
|
153
|
+
end
|
154
|
+
rescue
|
155
|
+
tries += 1
|
156
|
+
if fetch_tries <= 3
|
157
|
+
puts "Exception: #{$!.inspect} -- Retrying symbol #{@symbol} time: #{fetch_tries.to_s} (total 3)"
|
158
|
+
sleep(2)
|
159
|
+
retry
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
#
|
164
|
+
# %%% OK, WE MUST MAKE THIS MORE ROBUST TO HANDLE FEWER REPORTING PERIODS, e.g. ACT Actavis has 3 quarters reported
|
165
|
+
#
|
166
|
+
# let's initialize periods: by finding 'Period Endinng
|
167
|
+
got_periods = true
|
168
|
+
begin
|
169
|
+
row = doc.xpath("//span[text() = 'Period Ending']")[0].parent.parent.parent
|
170
|
+
period = []
|
171
|
+
1.upto(@data_columns) do |i|
|
172
|
+
begin
|
173
|
+
pd = Date.parse(row.children[i].text)
|
174
|
+
@periods << pd
|
175
|
+
rescue
|
176
|
+
break; # end of the line here
|
177
|
+
end
|
178
|
+
end
|
179
|
+
@financial_statement[:statement_periods] = @periods
|
180
|
+
rescue
|
181
|
+
puts "Exception: #{$!.inspect} -- Skipping symbol #{@symbol} URL: #{url}"
|
182
|
+
# puts "DOC: #{doc}"
|
183
|
+
got_periods = false
|
184
|
+
end
|
185
|
+
|
186
|
+
return nil if !got_periods
|
187
|
+
|
188
|
+
# YahooFinance.parse_financial_statement_field field, multiplier
|
189
|
+
# let's fetch everything here & store in the income statement
|
190
|
+
@field_defs.keys.each do |incst_key|
|
191
|
+
next if incst_key == :statement_periods
|
192
|
+
path_expr = "//td[text()[contains(., '" + @field_defs[incst_key][0] + "')]]"
|
193
|
+
row = nil
|
194
|
+
elem = doc.xpath(path_expr)
|
195
|
+
index = 1
|
196
|
+
regex = "\\s\*#{@field_defs[incst_key][0]}\\s\*"
|
197
|
+
if elem && elem.size == 0
|
198
|
+
# this is because we have a strong type; let's try again
|
199
|
+
path_expr = "//td/strong[text()[contains(., '" + @field_defs[incst_key][0] +"')]]"
|
200
|
+
elem = doc.xpath(path_expr)
|
201
|
+
if elem.size > 0
|
202
|
+
elem.each do |e|
|
203
|
+
if e.text.match regex
|
204
|
+
# we found it
|
205
|
+
row = e.parent.parent
|
206
|
+
end
|
207
|
+
end
|
208
|
+
if !row
|
209
|
+
# wasn't found
|
210
|
+
puts "#{@field_defs[incst_key][0]} was not found!"
|
211
|
+
next
|
212
|
+
end
|
213
|
+
index = row.children.index(elem[0].parent)
|
214
|
+
end
|
215
|
+
else
|
216
|
+
elem.each do |e|
|
217
|
+
# puts "Checking #{e}: class #{e.text.class.name} with text <<#{e.text}>> and regex #{regex}"
|
218
|
+
if e.text.match regex
|
219
|
+
# we found it
|
220
|
+
row = e.parent
|
221
|
+
break
|
222
|
+
end
|
223
|
+
end
|
224
|
+
if !row
|
225
|
+
# wasn't found
|
226
|
+
puts "#{@field_defs[incst_key][0]} was not found!"
|
227
|
+
next
|
228
|
+
end
|
229
|
+
index = row.children.index(elem[0])
|
230
|
+
end
|
231
|
+
if elem && elem.size > 0
|
232
|
+
# puts "\tFOUND!!!! PATH EXPRESSION IS #{path_expr} "
|
233
|
+
# puts "\t\tROW: #{row}"
|
234
|
+
rstbl = []
|
235
|
+
1.upto(@periods.size) do |i|
|
236
|
+
field = row.children[index+i].text.tr('^[0-9\,\.\-\(\)]', '')
|
237
|
+
rs = YahooFinance.parse_financial_statement_field(field, @number_multiplier)
|
238
|
+
rstbl << rs
|
239
|
+
end
|
240
|
+
|
241
|
+
@financial_statement[incst_key] = rstbl
|
242
|
+
# puts "\tPARSED #{incst_key}"
|
243
|
+
else
|
244
|
+
puts "\tNOT FOUND!!!! #{incst_key}"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
@financial_statement
|
248
|
+
end
|
249
|
+
|
250
|
+
def statement_periods
|
251
|
+
@periods
|
252
|
+
end
|
253
|
+
|
254
|
+
def value_for key_stat
|
255
|
+
begin
|
256
|
+
return @financial_statement[key_stat]
|
257
|
+
rescue
|
258
|
+
end
|
259
|
+
return nil
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
class QuarterlyIncomeStatementPage < FinancialStatementPage
|
264
|
+
def initialize symbol = nil
|
265
|
+
super symbol
|
266
|
+
@term = :quarterly
|
267
|
+
@data_columns = 4
|
268
|
+
@type="is"
|
269
|
+
@field_defs = YahooFinance::FinancialStatement::INCOME_STMT_FIELDS
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class AnnualIncomeStatementPage < FinancialStatementPage
|
274
|
+
def initialize symbol = nil
|
275
|
+
super symbol
|
276
|
+
@term = :annual
|
277
|
+
@data_columns = 3
|
278
|
+
@type="is"
|
279
|
+
@field_defs = YahooFinance::FinancialStatement::INCOME_STMT_FIELDS
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
class QuarterlyBalanceSheetPage < FinancialStatementPage
|
284
|
+
def initialize symbol = nil
|
285
|
+
super symbol
|
286
|
+
@term = :quarterly
|
287
|
+
@data_columns = 4
|
288
|
+
@type="bs"
|
289
|
+
@field_defs = YahooFinance::FinancialStatement::BALANCE_SHEET_FIELDS
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
class AnnualBalanceSheetPage < FinancialStatementPage
|
294
|
+
def initialize symbol = nil
|
295
|
+
super symbol
|
296
|
+
@term = :annual
|
297
|
+
@data_columns = 3
|
298
|
+
@type="bs"
|
299
|
+
@field_defs = YahooFinance::FinancialStatement::BALANCE_SHEET_FIELDS
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
class QuarterlyCashFlowStatementPage < FinancialStatementPage
|
304
|
+
def initialize symbol = nil
|
305
|
+
super symbol
|
306
|
+
@term = :quarterly
|
307
|
+
@data_columns = 4
|
308
|
+
@type="cf"
|
309
|
+
@field_defs = YahooFinance::FinancialStatement::CASH_FLOW_STMT_FIELDS
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
class AnnualCashFlowStatementPage < FinancialStatementPage
|
314
|
+
def initialize symbol = nil
|
315
|
+
super symbol
|
316
|
+
@term = :annual
|
317
|
+
@data_columns = 3
|
318
|
+
@type="cf"
|
319
|
+
@field_defs = YahooFinance::FinancialStatement::CASH_FLOW_STMT_FIELDS
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
end
|
324
|
+
end
|
data/lib/yahoo_finance/stock.rb
CHANGED
@@ -72,6 +72,18 @@ module YahooFinance
|
|
72
72
|
return dt if dt
|
73
73
|
end
|
74
74
|
|
75
|
+
m=aField.match /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[\s]+([\d]{1,2})\s*\-\s*(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[\s]+([\d]{1,2})\,[\s]*([\d]{4})/
|
76
|
+
if m && (m.size == 6)
|
77
|
+
# we found it, and it is a date range
|
78
|
+
dt1 = dt2 = nil
|
79
|
+
begin
|
80
|
+
dt1 = Date.strptime "#{m[1]} #{m[2]}, #{m[5]}", '%b %d, %Y'
|
81
|
+
dt2 = Date.strptime "#{m[3]} #{m[4]}, #{m[5]}", '%b %d, %Y'
|
82
|
+
rescue
|
83
|
+
end
|
84
|
+
return [dt1, dt2]
|
85
|
+
end
|
86
|
+
|
75
87
|
#else make an attempt to parse as date
|
76
88
|
dt = nil
|
77
89
|
begin
|
@@ -83,16 +95,42 @@ module YahooFinance
|
|
83
95
|
aField
|
84
96
|
end
|
85
97
|
|
98
|
+
# this really parses numeric fields only
|
99
|
+
def YahooFinance.parse_financial_statement_field aField, multiplier = 1000.0
|
100
|
+
aField = aField.strip
|
101
|
+
|
102
|
+
multiplier = 1000.00 if !multiplier # just in case a nil is forced...
|
103
|
+
|
104
|
+
if aField.match /^([\d\,])*(\.[\d]+)*$/
|
105
|
+
# it's a number as far as we care; let's strip the commas....
|
106
|
+
return aField.tr('\,', '').to_f * multiplier
|
107
|
+
end
|
108
|
+
|
109
|
+
# process the accounting negative field -- parentheses
|
110
|
+
m = aField.match /^\(([\d\,])*(\.[\d]+)*\)$/
|
111
|
+
if m
|
112
|
+
# it's a number as far as we care; let's strip the commas....
|
113
|
+
aField = aField.tr('\(\)\,', '')
|
114
|
+
return aField.to_f * multiplier * -1.0
|
115
|
+
end
|
116
|
+
|
117
|
+
# anything else becomes zero by definition
|
118
|
+
return 0.0
|
119
|
+
|
120
|
+
end
|
121
|
+
|
86
122
|
class Stock
|
87
|
-
|
88
|
-
@@
|
89
|
-
@@
|
123
|
+
attr_reader :results_hash, :print_progress
|
124
|
+
@@available_fields = (AVL_FIELDS[:YAHOO_STOCK_FIELDS] + AVL_FIELDS[:KEY_STATISTICS] + AVL_FIELDS[:COMPANY_EVENTS] + AVL_FIELDS[:ANALYST_OPINION] + AVL_FIELDS[:COMPANY_PROFILE])
|
125
|
+
@@insert_variable_delays = false
|
126
|
+
@@insert_variable_delay = 2
|
90
127
|
@@retry_times = 3
|
91
128
|
@@retry_variable_delay = 30
|
92
129
|
@symbols = []
|
93
130
|
@fields = []
|
94
131
|
@fields_hash = {}
|
95
132
|
@results_hash = {}
|
133
|
+
@print_progress = false
|
96
134
|
|
97
135
|
def self.insert_variable_delays
|
98
136
|
@@insert_variable_delays
|
@@ -188,13 +226,16 @@ module YahooFinance
|
|
188
226
|
end
|
189
227
|
# Then we fetch fields from KEY STATISTICS
|
190
228
|
DRIVERS.keys.each do |driver|
|
191
|
-
# puts "CHECKING #{driver.to_s}"
|
192
229
|
if @fields_hash[driver].size > 0
|
193
|
-
|
230
|
+
puts "FETCHING FIELDS FOR #{driver.to_s}" if @print_progress
|
231
|
+
stp = DRIVERS[driver].new # will overwrite symbol below
|
194
232
|
@symbols.each do |aSymbol|
|
195
233
|
tries = 0
|
234
|
+
now = Time.now
|
235
|
+
stp.symbol = aSymbol
|
236
|
+
puts "#{now.hour}:#{now.min}:#{now.sec}\tWorking on symbol #{aSymbol}" if @print_progress
|
196
237
|
begin
|
197
|
-
stp = DRIVERS[driver].new(aSymbol)
|
238
|
+
# stp = DRIVERS[driver].new(aSymbol) # will overwrite symbol below
|
198
239
|
stp.fetch
|
199
240
|
@fields_hash[driver].each do |aField|
|
200
241
|
value = stp.value_for(aField) # this already parses the numbers
|
@@ -203,12 +244,17 @@ module YahooFinance
|
|
203
244
|
sleep(Random.new(Random.new_seed).rand*@@insert_variable_delay) if @@insert_variable_delays
|
204
245
|
rescue
|
205
246
|
tries += 1
|
206
|
-
|
207
|
-
|
247
|
+
puts "Exception: #{$!.inspect} -- Retrying symbol #{aSymbol} time: #{tries.to_s}"
|
248
|
+
if tries <= @@retry_times
|
249
|
+
sleep(@@retry_variable_delay)
|
250
|
+
retry
|
251
|
+
end
|
208
252
|
end
|
209
253
|
end
|
210
254
|
end
|
255
|
+
puts "DONE witn #{driver.to_s}" if @print_progress
|
211
256
|
end
|
257
|
+
# puts "RIGHT BEFORE I RETURN THE BIG HASH: #{@results_hash}"
|
212
258
|
@results_hash
|
213
259
|
end
|
214
260
|
|
@@ -230,7 +276,7 @@ module YahooFinance
|
|
230
276
|
end
|
231
277
|
end
|
232
278
|
end
|
233
|
-
|
279
|
+
end
|
234
280
|
end
|
235
281
|
|
236
282
|
class StockHistory
|
@@ -10,13 +10,14 @@ describe YahooFinance::CompanyEvents do
|
|
10
10
|
it "available stats should include things like :next_earnings_announcement_date" do
|
11
11
|
YahooFinance::CompanyEvents.key_events_available.include?(:next_earnings_announcement_date).should == true
|
12
12
|
end
|
13
|
-
it "should fetch a stat like :next_earnings_announcement_date for AAPL and should be either Date or String" do
|
13
|
+
it "should fetch a stat like :next_earnings_announcement_date for AAPL and should be either Date, and Array of two dates, or String" do
|
14
14
|
pg = YahooFinance::CompanyEvents::CompanyEventsPage.new('AAPL')
|
15
15
|
pg.fetch
|
16
16
|
aapl_next_earnings_date = pg.value_for :next_earnings_announcement_date
|
17
17
|
case aapl_next_earnings_date.class.name
|
18
|
-
|
19
|
-
|
18
|
+
when "Date" then aapl_next_earnings_date.class.name.should == "Date"
|
19
|
+
when "Array" then aapl_next_earnings_date.size.should == 2 && aapl_next_earnings_date[0].class.name.should == "Date" && aapl_next_earnings_date[1].class.name.should == "Date"
|
20
|
+
when "String" then aapl_next_earnings_date.class.name.should == "String"
|
20
21
|
else
|
21
22
|
aapl_next_earnings_date.class.name.should == "Date" #force a failure
|
22
23
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
# really more like a quick sample, more concerned about connectivity -- a better test needs to be developed to exhaustively
|
4
|
+
# test all fields to make sure Yahoo hasn't changed the format...
|
5
|
+
# %%%%%%
|
6
|
+
describe YahooFinance::FinancialStatement do
|
7
|
+
# before(:each) do
|
8
|
+
# @tsymbols = ['AAPL', 'DDD']
|
9
|
+
# @page = YahooFinance::Page.new(@tsymbols)
|
10
|
+
# end
|
11
|
+
|
12
|
+
describe "Financial Statement" do
|
13
|
+
it "Income Statement should include things like :next_earnings_announcement_date" do
|
14
|
+
YahooFinance::FinancialStatement::INCOME_STMT_FIELDS.include?(:operating_income_or_loss).should == true
|
15
|
+
end
|
16
|
+
it "Balance Sheet should include things like :intagible_assets" do
|
17
|
+
YahooFinance::FinancialStatement::BALANCE_SHEET_FIELDS.include?(:intagible_assets).should == true
|
18
|
+
end
|
19
|
+
it "Cash Flow Statement should include things like :total_cash_flow_from_operating_activities" do
|
20
|
+
YahooFinance::FinancialStatement::CASH_FLOW_STMT_FIELDS.include?(:total_cash_flow_from_operating_activities).should == true
|
21
|
+
end
|
22
|
+
it "should fetch all fields for e.g. AAPL quarterly Income statement and all values should be float (except for :statement_periods)-- valid values" do
|
23
|
+
is = YahooFinance::FinancialStatement::QuarterlyIncomeStatementPage.new 'AAPL'
|
24
|
+
rs = is.fetch
|
25
|
+
YahooFinance::FinancialStatement::INCOME_STMT_FIELDS.keys.each do |attr|
|
26
|
+
fields = rs[attr]
|
27
|
+
fields.class.name.should == "Array"
|
28
|
+
fields.size.should == 4
|
29
|
+
fields.each do |field|
|
30
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
it "should fetch all fields for e.g. AAPL annual Income statement and all values should be float (except for :statement_periods)-- valid values" do
|
35
|
+
is = YahooFinance::FinancialStatement::AnnualIncomeStatementPage.new 'AAPL'
|
36
|
+
rs = is.fetch
|
37
|
+
YahooFinance::FinancialStatement::INCOME_STMT_FIELDS.keys.each do |attr|
|
38
|
+
fields = rs[attr]
|
39
|
+
fields.class.name.should == "Array"
|
40
|
+
fields.size.should == 3
|
41
|
+
fields.each do |field|
|
42
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
it "should fetch all fields for e.g. AAPL quarterly Balance Sheet statement and all values should be float (except for :statement_periods)-- valid values" do
|
47
|
+
is = YahooFinance::FinancialStatement::QuarterlyBalanceSheetPage.new 'AAPL'
|
48
|
+
rs = is.fetch
|
49
|
+
YahooFinance::FinancialStatement::BALANCE_SHEET_FIELDS.keys.each do |attr|
|
50
|
+
fields = rs[attr]
|
51
|
+
fields.class.name.should == "Array"
|
52
|
+
fields.size.should == 4
|
53
|
+
fields.each do |field|
|
54
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
it "should fetch all fields for e.g. AAPL annual Balance Sheet statement and all values should be float (except for :statement_periods)-- valid values" do
|
59
|
+
is = YahooFinance::FinancialStatement::AnnualBalanceSheetPage.new 'AAPL'
|
60
|
+
rs = is.fetch
|
61
|
+
YahooFinance::FinancialStatement::BALANCE_SHEET_FIELDS.keys.each do |attr|
|
62
|
+
fields = rs[attr]
|
63
|
+
fields.class.name.should == "Array"
|
64
|
+
fields.size.should == 3
|
65
|
+
fields.each do |field|
|
66
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
it "should fetch all fields for e.g. AAPL quarterly Cash Flow statement and all values should be float (except for :statement_periods)-- valid values" do
|
71
|
+
is = YahooFinance::FinancialStatement::QuarterlyCashFlowStatementPage.new 'AAPL'
|
72
|
+
rs = is.fetch
|
73
|
+
YahooFinance::FinancialStatement::CASH_FLOW_STMT_FIELDS.keys.each do |attr|
|
74
|
+
fields = rs[attr]
|
75
|
+
fields.class.name.should == "Array"
|
76
|
+
fields.size.should == 4
|
77
|
+
fields.each do |field|
|
78
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
it "should fetch all fields for e.g. AAPL annual Cash Flow statement and all values should be float (except for :statement_periods)-- valid values" do
|
83
|
+
is = YahooFinance::FinancialStatement::AnnualCashFlowStatementPage.new 'AAPL'
|
84
|
+
rs = is.fetch
|
85
|
+
YahooFinance::FinancialStatement::CASH_FLOW_STMT_FIELDS.keys.each do |attr|
|
86
|
+
fields = rs[attr]
|
87
|
+
fields.class.name.should == "Array"
|
88
|
+
fields.size.should == 3
|
89
|
+
fields.each do |field|
|
90
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
it "should fetch all fields for e.g. ACT (3 quarters only on 11/19/14) quarterly Cash Flow statement and all values should be float (except for :statement_periods)-- valid values" do
|
95
|
+
is = YahooFinance::FinancialStatement::QuarterlyCashFlowStatementPage.new 'ACT'
|
96
|
+
rs = is.fetch
|
97
|
+
YahooFinance::FinancialStatement::CASH_FLOW_STMT_FIELDS.keys.each do |attr|
|
98
|
+
fields = rs[attr]
|
99
|
+
fields.class.name.should == "Array"
|
100
|
+
fields.size.should == 3
|
101
|
+
fields.each do |field|
|
102
|
+
attr == :statement_periods ? field.class.name.should == "Date" : field.class.name.should == "Float"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
it "should return a nil hash if yahoo doesn't have the statement, e.g. for AMBR" do
|
107
|
+
is = YahooFinance::FinancialStatement::QuarterlyCashFlowStatementPage.new 'AMBR'
|
108
|
+
rs = is.fetch
|
109
|
+
rs.should == nil
|
110
|
+
end
|
111
|
+
|
112
|
+
# pg = YahooFinance::CompanyEvents::CompanyEventsPage.new('AAPL')
|
113
|
+
# pg.fetch
|
114
|
+
# aapl_next_earnings_date = pg.value_for :next_earnings_announcement_date
|
115
|
+
# case aapl_next_earnings_date.class.name
|
116
|
+
# when "Date" then aapl_next_earnings_date.class.name.should == "Date"
|
117
|
+
# when "Array" then aapl_next_earnings_date.size.should == 2 && aapl_next_earnings_date[0].class.name.should == "Date" && aapl_next_earnings_date[1].class.name.should == "Date"
|
118
|
+
# when "String" then aapl_next_earnings_date.class.name.should == "String"
|
119
|
+
# else
|
120
|
+
# aapl_next_earnings_date.class.name.should == "Date" #force a failure
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
end
|
124
|
+
end
|
metadata
CHANGED
@@ -1,101 +1,101 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yahoo_finance_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.9.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takis Mercouris
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nas-yahoo_stock
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.0.8
|
20
|
-
- -
|
20
|
+
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 1.0.8
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - ~>
|
27
|
+
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 1.0.8
|
30
|
-
- -
|
30
|
+
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: 1.0.8
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: nokogiri
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
|
-
- - ~>
|
37
|
+
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: 1.6.1
|
40
|
-
- -
|
40
|
+
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
42
|
version: 1.6.1
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
|
-
- - ~>
|
47
|
+
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
49
|
version: 1.6.1
|
50
|
-
- -
|
50
|
+
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
52
|
version: 1.6.1
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: bundler
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
|
-
- - ~>
|
57
|
+
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
59
|
version: '1.3'
|
60
60
|
type: :development
|
61
61
|
prerelease: false
|
62
62
|
version_requirements: !ruby/object:Gem::Requirement
|
63
63
|
requirements:
|
64
|
-
- - ~>
|
64
|
+
- - "~>"
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: '1.3'
|
67
67
|
- !ruby/object:Gem::Dependency
|
68
68
|
name: rake
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
70
70
|
requirements:
|
71
|
-
- - ~>
|
71
|
+
- - "~>"
|
72
72
|
- !ruby/object:Gem::Version
|
73
73
|
version: '0'
|
74
74
|
type: :development
|
75
75
|
prerelease: false
|
76
76
|
version_requirements: !ruby/object:Gem::Requirement
|
77
77
|
requirements:
|
78
|
-
- - ~>
|
78
|
+
- - "~>"
|
79
79
|
- !ruby/object:Gem::Version
|
80
80
|
version: '0'
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: rspec
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
|
-
- - ~>
|
85
|
+
- - "~>"
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: 2.14.1
|
88
|
-
- -
|
88
|
+
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: 2.14.1
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- - ~>
|
95
|
+
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: 2.14.1
|
98
|
-
- -
|
98
|
+
- - ">="
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: 2.14.1
|
101
101
|
description: Unified library to stock quotes and various pages in yahoo finance, including
|
@@ -106,7 +106,7 @@ executables: []
|
|
106
106
|
extensions: []
|
107
107
|
extra_rdoc_files: []
|
108
108
|
files:
|
109
|
-
- .gitignore
|
109
|
+
- ".gitignore"
|
110
110
|
- Gemfile
|
111
111
|
- History.md
|
112
112
|
- LICENSE.txt
|
@@ -116,6 +116,7 @@ files:
|
|
116
116
|
- lib/yahoo_finance/analyst_opinion.rb
|
117
117
|
- lib/yahoo_finance/company_events.rb
|
118
118
|
- lib/yahoo_finance/company_profile.rb
|
119
|
+
- lib/yahoo_finance/financial_statement.rb
|
119
120
|
- lib/yahoo_finance/key_statistics.rb
|
120
121
|
- lib/yahoo_finance/stock.rb
|
121
122
|
- lib/yahoo_finance/version.rb
|
@@ -124,6 +125,7 @@ files:
|
|
124
125
|
- spec/yahoo_company_events_spec.rb
|
125
126
|
- spec/yahoo_company_profile_spec.rb
|
126
127
|
- spec/yahoo_finance_spec.rb
|
128
|
+
- spec/yahoo_financial_statement_spec.rb
|
127
129
|
- spec/yahoo_key_stats_spec.rb
|
128
130
|
- yahoo_finance.gemspec
|
129
131
|
homepage: http://polymechanus.com/yahoo_finance-ruby-gem-tutorial/
|
@@ -136,17 +138,17 @@ require_paths:
|
|
136
138
|
- lib
|
137
139
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
140
|
requirements:
|
139
|
-
- -
|
141
|
+
- - ">="
|
140
142
|
- !ruby/object:Gem::Version
|
141
143
|
version: '0'
|
142
144
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
145
|
requirements:
|
144
|
-
- -
|
146
|
+
- - ">="
|
145
147
|
- !ruby/object:Gem::Version
|
146
148
|
version: '0'
|
147
149
|
requirements: []
|
148
150
|
rubyforge_project:
|
149
|
-
rubygems_version: 2.4.
|
151
|
+
rubygems_version: 2.4.2
|
150
152
|
signing_key:
|
151
153
|
specification_version: 4
|
152
154
|
summary: Fetch stock information from yahoo finance API and HTML pages
|
@@ -156,4 +158,5 @@ test_files:
|
|
156
158
|
- spec/yahoo_company_events_spec.rb
|
157
159
|
- spec/yahoo_company_profile_spec.rb
|
158
160
|
- spec/yahoo_finance_spec.rb
|
161
|
+
- spec/yahoo_financial_statement_spec.rb
|
159
162
|
- spec/yahoo_key_stats_spec.rb
|