yahoo-finance 0.2.0 → 1.2.1

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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c6a015a18c3319e26d41dbacde9bf2d76c5db9bf
4
- data.tar.gz: 9cde1310a1f8aa6585f1907a5300b732a3177410
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjBkYTA4YjE1ZDQ5ODNhMTJiYmQ5YWM2ZDRhMTdkOTlhMmJkYzY5Yw==
5
+ data.tar.gz: !binary |-
6
+ NDAyNTI1YWQ5ZWNhNDJhMTAyYjNjMzQ5OWJmZWI5MTdjMWE2NGQ2NQ==
5
7
  SHA512:
6
- metadata.gz: 451ea63a655451a65a446c4d8596b32907140d9b01fbfd83353fbf1c401bc334e521eaa873caff4defdaae6348ecac853c959796efb4ff6270d0e4a8548fa4ce
7
- data.tar.gz: 95647240723348756960cab2ecd423b9df7f98f50b5414fba507a17b1c7bb876bf1c77c0f17943abdd927f6d66221167dd3f8c87eb136f55586fe09bbfca4c65
8
+ metadata.gz: !binary |-
9
+ ODUwYTM3YjI3OGNhYzFmZjRiZjFjMDYyMGU5N2M3YmJjMDZjNGQxZTc5OTg3
10
+ NDM2ZjRiNWI5YjNiYjU0ODRiZDRlZTkwMzJiNzM2ZmQ4MWI4M2I1ZTRhODM5
11
+ NzAxYmJiZGU1ZTJmZGMzZDA3OTFlYzZhN2ZmZTRjMDJiNDE1Njg=
12
+ data.tar.gz: !binary |-
13
+ NjFjZWY4MTc5YzMxNTIyMDU2ZGJhODc1ZTE2NDQ0ZDc2NzQ5NTU4MmJjNTA1
14
+ Y2FjZDFjMzYyYWRhZWM5YzBiZDFkYmUyNTFlNWQ2NDQ1NjJmNWI5YzEzYjAz
15
+ NjFjYWM0ZWQ1M2Q3ODIwMDZjZGVhZTI1YTk4MDBjMDk2YWZlODM=
data/HISTORY CHANGED
@@ -1,3 +1,13 @@
1
+ 1.2.0 - Feb 04, 2017
2
+ ====================
3
+ * Fixed support for { raw: false }
4
+ * Symbols that are not found will now not return (instead of returning a struct with an empty :symbol field and a bunch of "N/A"s)
5
+ * The returned quotes now will always include the :symbol name
6
+
7
+ 0.3.0 - Aug 16, 2015
8
+ ====================
9
+ * Refactorings & support for US companies data (via NASDAQ's Apis) - by Eric D. Santos Sosa
10
+
1
11
  0.2.0 - Nov 24, 2014
2
12
  ====================
3
13
  * Allow fetching a single symbol with the `quote` method
@@ -16,4 +26,4 @@
16
26
 
17
27
  0.0.1 - Aug 04, 2007
18
28
  ===============================
19
- * Initial implementation - no bells, no whristles :)
29
+ * Initial implementation - no bells, no whistles :)
data/README.md CHANGED
@@ -3,11 +3,10 @@ A dead simple wrapper for yahoo finance quotes end-point.
3
3
 
4
4
  ## Installation:
5
5
 
6
- `gem install 'yahoo-finance'`
7
- `require 'yahoo_finance'`
6
+ Just add it to your `Gemfile`:
7
+
8
+ `gem 'yahoo-finance'`
8
9
 
9
- If using bundler:
10
- `gem 'yahoo-finance', require: 'yahoo_finance'`
11
10
 
12
11
  ## Usage:
13
12
 
@@ -16,7 +15,8 @@ If using bundler:
16
15
  Pass an array of valid symbols (stock names, indexes, exchange rates) and a list of fields you want:
17
16
 
18
17
  ```ruby
19
- data = YahooFinance.quotes(["BVSP", "NATU3.SA", "USDJPY=X"], [:ask, :bid, :last_trade_date])
18
+ yahoo_client = YahooFinance::Client.new
19
+ data = yahoo_client.quotes(["BVSP", "NATU3.SA", "USDJPY=X"], [:ask, :bid, :last_trade_date])
20
20
  ```
21
21
 
22
22
  Data is now an array of results. You now have accessor methods to retrieve the data, with the return results being strings:
@@ -28,13 +28,28 @@ puts data[0].symbol + " value is: " + data[0].ask
28
28
  Passing `raw: false` will return numerical values
29
29
 
30
30
  ```ruby
31
- data = YahooFinance.quotes(["BVSP", "NATU3.SA", "USDJPY=X"], [:ask, :bid, :last_trade_date], { raw: false } )
32
- data[0].ask # This is now a float
31
+ yahoo_client = YahooFinance::Client.new
32
+ data = yahoo_client.quotes(["BVSP", "NATU3.SA", "USDJPY=X"], [:ask, :bid, :last_trade_date], { raw: false } )
33
+ data[0].ask # This is now a BigDecimal
34
+ ```
35
+
36
+ Passing `na_as_nil: true` will convert "N/A" responses to `nil`
37
+
38
+ ```ruby
39
+ yahoo_client = YahooFinance::Client.new
40
+
41
+ data = yahoo_client.quotes(["BVSP"], [:ask] )
42
+ data[0].ask
43
+ > "N/A"
44
+
45
+ data = yahoo_client.quotes(["BVSP"], [:ask], { na_as_nil: true } )
46
+ data[0].ask
47
+ > nil
33
48
  ```
34
49
 
35
50
  The full list of fields follows:
36
51
 
37
- ``` ruby
52
+ ```ruby
38
53
  :after_hours_change_real_time
39
54
  :annualized_gain
40
55
  :ask
@@ -112,6 +127,8 @@ The full list of fields follows:
112
127
  :price_paid
113
128
  :price_per_book
114
129
  :price_per_sales
130
+ :revenue
131
+ :shares_outstanding
115
132
  :shares_owned
116
133
  :short_ratio
117
134
  :stock_exchange
@@ -123,6 +140,30 @@ The full list of fields follows:
123
140
  :weeks_range_52
124
141
  ```
125
142
 
143
+ ### Getting symbols by stock market (beta)
144
+
145
+ Create a YahooFinance::Client instance
146
+
147
+ ```ruby
148
+ yahoo_client = YahooFinance::Client.new
149
+ ```
150
+
151
+ Calling symbols_by_market method (symbols_by_market(country, stock_market))
152
+
153
+ Note: Can only be called with US Stock Markets for now.
154
+
155
+ *Important: This data comes directly from NASDAQ's CSV endpoints, NOT Yahoo Finance*. It might be extracted into a different Gem in the future.
156
+
157
+ ```ruby
158
+ yahoo_client.symbols_by_market('us', 'nyse') # Only US Stock Markets For Now
159
+ ```
160
+
161
+ This method returns an array of symbols that can be used with the quotes method
162
+
163
+ ```ruby
164
+ data = yahoo_client.quotes(yahoo_client.symbols_by_market('us', 'nyse'), [:ask, :bid, :last_trade_date])
165
+ ```
166
+
126
167
  ### Getting historical quotes
127
168
 
128
169
  Here you can specify a date range and a symbol, and retrieve historical data for it.
@@ -130,19 +171,22 @@ The last parameter (options) can include, besides the "raw" option, a "period" o
130
171
  The period can be specified as :daily, :monthly, :weekly or :dividends_only
131
172
 
132
173
  ```ruby
133
- data = YahooFinance.historical_quotes("AAPL") # entire historical data
174
+ yahoo_client = YahooFinance::Client.new
175
+ data = yahoo_client.historical_quotes("AAPL") # entire historical data
134
176
  ```
135
177
 
136
178
  or
137
179
 
138
180
  ```ruby
139
- data = YahooFinance.historical_quotes("AAPL", { start_date: Time::now-(24*60*60*10), end_date: Time::now }) # 10 days worth of data
181
+ yahoo_client = YahooFinance::Client.new
182
+ data = yahoo_client.historical_quotes("AAPL", { start_date: Time::now-(24*60*60*10), end_date: Time::now }) # 10 days worth of data
140
183
  ```
141
184
 
142
185
  or
143
186
 
144
187
  ``` ruby
145
- data = YahooFinance.historical_quotes("AAPL", { raw: false, period: :monthly })
188
+ yahoo_client = YahooFinance::Client.new
189
+ data = yahoo_client.historical_quotes("AAPL", { raw: false, period: :monthly })
146
190
  ```
147
191
 
148
192
  ### Getting splits
@@ -150,7 +194,8 @@ data = YahooFinance.historical_quotes("AAPL", { raw: false, period: :monthly })
150
194
  You can also retrieve split data.
151
195
 
152
196
  ```ruby
153
- data = YahooFinance.splits('AAPL', :start_date => Date.today - 10*365)
197
+ yahoo_client = YahooFinance::Client.new
198
+ data = yahoo_client.splits('AAPL', :start_date => Date.today - 10*365)
154
199
  data[0].date # Date<2014-06-09>
155
200
  data[0].before # 1
156
201
  data[0].after # 7
@@ -160,3 +205,4 @@ data[0].after # 7
160
205
  Enjoy! :-)
161
206
 
162
207
  - Herval (hervalfreire@gmail.com)
208
+ - Eric D. Santos Sosa (eric.santos@cometa.works)
@@ -0,0 +1,29 @@
1
+ # YahooFinance Module for YahooFinance gem
2
+ module YahooFinance
3
+ # FinanceUtils Module
4
+ module FinanceUtils
5
+ def self.included(base)
6
+ base.extend(self)
7
+ end
8
+
9
+ MARKETS = OpenStruct.new(
10
+ us: OpenStruct.new(
11
+ nasdaq: OpenStruct.new(
12
+ url: "http://www.nasdaq.com/screening/companies-by-name.aspx?letter=0&exchange=nasdaq&render=download"),
13
+ nyse: OpenStruct.new(
14
+ url: "http://www.nasdaq.com/screening/companies-by-name.aspx?letter=0&exchange=nyse&render=download"),
15
+ amex: OpenStruct.new(
16
+ url: "http://www.nasdaq.com/screening/companies-by-name.aspx?letter=0&exchange=amex&render=download")))
17
+
18
+ def symbols_by_market(country, market)
19
+ symbols = []
20
+ market = MARKETS.send(country).send(market)
21
+ return symbols if market.nil?
22
+ CSV.foreach(open(market.url)) do |row|
23
+ next if row.first == "Symbol"
24
+ symbols.push(row.first.gsub(" ", ""))
25
+ end
26
+ symbols
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,4 @@
1
+ # Version Variable for Yahoo Finance Gem
2
+ module YahooFinance
3
+ VERSION = '1.2.1'
4
+ end
data/lib/yahoo-finance.rb CHANGED
@@ -1 +1,245 @@
1
- require 'yahoo_finance'
1
+ require "open-uri"
2
+ require "ostruct"
3
+ require "json"
4
+ require "yahoo-finance/version"
5
+ require "yahoo-finance/finance-utils"
6
+ require "csv"
7
+ require 'bigdecimal'
8
+
9
+ module YahooFinance
10
+ # Client for Yahoo Finance Queries
11
+ class Client
12
+ include YahooFinance::FinanceUtils
13
+
14
+ COLUMNS = {
15
+ :ask => ["a", BigDecimal],
16
+ :average_daily_volume => ["a2", BigDecimal],
17
+ :ask_size => ["a5", BigDecimal],
18
+ :bid => ["b", BigDecimal],
19
+ :ask_real_time => ["b2", Time],
20
+ :bid_real_time => ["b3", BigDecimal],
21
+ :book_value => ["b4", BigDecimal],
22
+ :bid_size => ["b6", BigDecimal],
23
+ :chance_and_percent_change => ["c", String],
24
+ :change => ["c1", BigDecimal],
25
+ :comission => ["c3", String],
26
+ :change_real_time => ["c6", BigDecimal],
27
+ :after_hours_change_real_time => ["c8", String],
28
+ :dividend_per_share => ["d", BigDecimal],
29
+ :last_trade_date => ["d1", DateTime],
30
+ :trade_date => ["d2", String],
31
+ :earnings_per_share => ["e", BigDecimal],
32
+ :error_indicator => ["e1", String],
33
+ :eps_estimate_current_year => ["e7", BigDecimal],
34
+ :eps_estimate_next_year => ["e8", BigDecimal],
35
+ :eps_estimate_next_quarter => ["e9", BigDecimal],
36
+ :float_shares => ["f6", BigDecimal],
37
+ :low => ["g", BigDecimal],
38
+ :high => ["h", BigDecimal],
39
+ :low_52_weeks => ["j", BigDecimal],
40
+ :high_52_weeks => ["k", BigDecimal],
41
+ :holdings_gain_percent => ["g1", BigDecimal],
42
+ :annualized_gain => ["g3", BigDecimal],
43
+ :holdings_gain => ["g4", BigDecimal],
44
+ :holdings_gain_percent_realtime => ["g5", BigDecimal],
45
+ :holdings_gain_realtime => ["g6", BigDecimal],
46
+ :more_info => ["i", String],
47
+ :order_book => ["i5", BigDecimal],
48
+ :market_capitalization => ["j1", BigDecimal],
49
+ :shares_outstanding => ["j2", BigDecimal],
50
+ :market_cap_realtime => ["j3", BigDecimal],
51
+ :ebitda => ["j4", BigDecimal],
52
+ :change_From_52_week_low => ["j5", BigDecimal],
53
+ :percent_change_from_52_week_low => ["j6", BigDecimal],
54
+ :last_trade_realtime_withtime => ["k1", String],
55
+ :change_percent_realtime => ["k2", String],
56
+ :last_trade_size => ["k3", BigDecimal],
57
+ :change_from_52_week_high => ["k4", BigDecimal],
58
+ :percent_change_from_52_week_high => ["k5", BigDecimal],
59
+ :last_trade_with_time => ["l", String],
60
+ :last_trade_price => ["l1", BigDecimal],
61
+ :close => ["l1", BigDecimal], # same as :last_trade_price
62
+ :high_limit => ["l2", BigDecimal],
63
+ :low_limit => ["l3", BigDecimal],
64
+ :days_range => ["m", BigDecimal],
65
+ :days_range_realtime => ["m2", BigDecimal],
66
+ :moving_average_50_day => ["m3", BigDecimal],
67
+ :moving_average_200_day => ["m4", BigDecimal],
68
+ :change_from_200_day_moving_average => ["m5", BigDecimal],
69
+ :percent_change_from_200_day_moving_average => ["m6", BigDecimal],
70
+ :change_from_50_day_moving_average => ["m7", BigDecimal],
71
+ :percent_change_from_50_day_moving_average => ["m8", BigDecimal],
72
+ :name => ["n", String],
73
+ :notes => ["n4", String],
74
+ :open => ["o", BigDecimal],
75
+ :previous_close => ["p", BigDecimal],
76
+ :price_paid => ["p1", BigDecimal],
77
+ :change_in_percent => ["p2", BigDecimal],
78
+ :price_per_sales => ["p5", BigDecimal],
79
+ :price_per_book => ["p6", BigDecimal],
80
+ :ex_dividend_date => ["q", DateTime],
81
+ :pe_ratio => ["p5", BigDecimal],
82
+ :dividend_pay_date => ["r1", String],
83
+ :pe_ratio_realtime => ["r2", BigDecimal],
84
+ :peg_ratio => ["r5", BigDecimal],
85
+ :price_eps_estimate_current_year => ["r6", BigDecimal],
86
+ :price_eps_Estimate_next_year => ["r7", BigDecimal],
87
+ :symbol => ["s", String],
88
+ :shares_owned => ["s1", BigDecimal],
89
+ :revenue => ["s6", BigDecimal],
90
+ :short_ratio => ["s7", BigDecimal],
91
+ :last_trade_time => ["t1", Time],
92
+ :trade_links => ["t6", String],
93
+ :ticker_trend => ["t7", String],
94
+ :one_year_target_price => ["t8", BigDecimal],
95
+ :volume => ["v", BigDecimal],
96
+ :holdings_value => ["v1", String],
97
+ :holdings_value_realtime => ["v7", String],
98
+ :weeks_range_52 => ["w", BigDecimal],
99
+ :day_value_change => ["w1", BigDecimal],
100
+ :day_value_change_realtime => ["w4", String],
101
+ :stock_exchange => ["x", String],
102
+ :dividend_yield => ["y", BigDecimal],
103
+ :adjusted_close => [nil, BigDecimal] # this one only comes in historical quotes
104
+ }
105
+
106
+ HISTORICAL_MODES = {
107
+ daily: "d",
108
+ weekly: "w",
109
+ monthly: "m",
110
+ dividends_only: "v"
111
+ }
112
+
113
+ SYMBOLS_PER_REQUEST = 50
114
+
115
+ # retrieve the quote data (an OpenStruct per quote)
116
+ # the options param can be used to specify the following attributes:
117
+ # :raw - if true, each column will be converted (to numbers, dates, etc)
118
+ def quotes(symbols_array, columns_array = [:symbol, :last_trade_price, :last_trade_date, :change, :previous_close], options = {})
119
+ # remove invalid keys
120
+ columns_array.reject! { |c| !COLUMNS.key?(c) }
121
+ columns_array << :symbol if columns_array.index(:symbol).nil?
122
+
123
+ # "N/A" is never present if { raw = false }
124
+ options[:na_as_nil] = true if options[:raw] == false
125
+
126
+ ret = []
127
+ symbols_array.each_slice(SYMBOLS_PER_REQUEST) do |symbols|
128
+ read_quotes(symbols.join("+"), columns_array).map do |row|
129
+ data = row.to_hash
130
+ if options[:na_as_nil]
131
+ data.each { |key, value| data[key] = nil if value == 'N/A' }
132
+ end
133
+ if options[:raw] == false
134
+ data.each { |key, value| data[key] = format(value, COLUMNS[key][1]) }
135
+ end
136
+ ret << OpenStruct.new(data)
137
+ end
138
+ end
139
+ ret
140
+ end
141
+
142
+ def quote(symbol, columns_array = [:symbol, :last_trade_price, :last_trade_date, :change, :previous_close], options = {})
143
+ options[:raw] ||= true
144
+ quotes([symbol], columns_array, options).first
145
+ end
146
+
147
+ def historical_quotes(symbol, options = {})
148
+ options[:raw] ||= true
149
+ options[:period] ||= :daily
150
+ read_historical(symbol, options).map do |row|
151
+ OpenStruct.new(row.to_hash.merge(symbol: symbol))
152
+ end
153
+ end
154
+
155
+ def symbols(query)
156
+ ret = []
157
+ read_symbols(query).each do |row|
158
+ ret << OpenStruct.new(row)
159
+ end
160
+ ret
161
+ end
162
+
163
+ def splits(symbol, options = {})
164
+ rows = read_splits(symbol, options).select { |row| row[0] == "SPLIT" }
165
+ rows.map do |type, date, value|
166
+ after, before = value.split(":")
167
+ OpenStruct.new(symbol: symbol, date: Date.strptime(date.strip, "%Y%m%d"), before: before.to_i, after: after.to_i)
168
+ end
169
+ end
170
+
171
+ def format(str, type)
172
+ if str.nil?
173
+ str
174
+ elsif type == BigDecimal
175
+ BigDecimal.new(str)
176
+ elsif type == DateTime
177
+ DateTime.parse(str)
178
+ elsif type == Time
179
+ Time.parse(str)
180
+ else
181
+ str
182
+ end
183
+ end
184
+
185
+ private
186
+
187
+ def read_quotes(symb_str, cols)
188
+ columns = "#{cols.map { |col| COLUMNS[col][0] }.join("")}"
189
+ conn = open("https://download.finance.yahoo.com/d/quotes.csv?s=#{URI.escape(symb_str)}&f=#{columns}")
190
+ CSV.parse(conn.read, headers: cols)
191
+ end
192
+
193
+ def read_historical(symbol, options)
194
+ params = { s: URI.escape(symbol), g: HISTORICAL_MODES[options[:period]], ignore: ".csv" }
195
+ if options[:start_date]
196
+ params[:a] = options[:start_date].month-1
197
+ params[:b] = options[:start_date].day
198
+ params[:c] = options[:start_date].year
199
+ end
200
+ if options[:end_date]
201
+ params[:d] = options[:end_date].month-1
202
+ params[:e] = options[:end_date].day
203
+ params[:f] = options[:end_date].year
204
+ end
205
+
206
+ url = "https://ichart.finance.yahoo.com/table.csv?#{params.map{|k, v| "#{k}=#{v}"}.join("&")}"
207
+ conn = open(url)
208
+ cols = if options[:period] == :dividends_only
209
+ [:dividend_pay_date, :dividend_yield]
210
+ else
211
+ [:trade_date, :open, :high, :low, :close, :volume, :adjusted_close]
212
+ end
213
+ result = CSV.parse(conn.read, headers: cols)
214
+ #:first_row, :header_converters => :symbol)
215
+ result.delete(0) # drop returned header
216
+ result
217
+ end
218
+
219
+ def read_splits(symbol, options)
220
+ params = { s: URI.escape(symbol), g: "v" }
221
+ if options[:start_date]
222
+ params[:a] = options[:start_date].month-1
223
+ params[:b] = options[:start_date].day
224
+ params[:c] = options[:start_date].year
225
+ end
226
+ if options[:end_date]
227
+ params[:d] = options[:end_date].month-1
228
+ params[:e] = options[:end_date].day
229
+ params[:f] = options[:end_date].year
230
+ end
231
+
232
+ url = "https://ichart.finance.yahoo.com/x?#{params.map{|k, v| "#{k}=#{v}"}.join("&")}"
233
+ conn = open(url)
234
+ CSV.parse(conn.read)
235
+ end
236
+
237
+ def read_symbols(query)
238
+ conn = open("http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=#{query}&region=US&lang=en-US&callback=YAHOO.Finance.SymbolSuggest.ssCallback")
239
+ result = conn.read
240
+ result.sub!("YAHOO.Finance.SymbolSuggest.ssCallback(", "").chomp!(");")
241
+ json_result = JSON.parse(result)
242
+ json_result["ResultSet"]["Result"]
243
+ end
244
+ end
245
+ end
metadata CHANGED
@@ -1,15 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yahoo-finance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Herval Freire
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-24 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2017-02-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
13
69
  description:
14
70
  email: herval@hervalicio.us
15
71
  executables: []
@@ -21,7 +77,8 @@ files:
21
77
  - HISTORY
22
78
  - README.md
23
79
  - lib/yahoo-finance.rb
24
- - lib/yahoo_finance.rb
80
+ - lib/yahoo-finance/finance-utils.rb
81
+ - lib/yahoo-finance/version.rb
25
82
  homepage: http://hervalicio.us/blog
26
83
  licenses: []
27
84
  metadata: {}
@@ -31,17 +88,17 @@ require_paths:
31
88
  - lib
32
89
  required_ruby_version: !ruby/object:Gem::Requirement
33
90
  requirements:
34
- - - ">="
91
+ - - ! '>='
35
92
  - !ruby/object:Gem::Version
36
93
  version: '0'
37
94
  required_rubygems_version: !ruby/object:Gem::Requirement
38
95
  requirements:
39
- - - ">="
96
+ - - ! '>='
40
97
  - !ruby/object:Gem::Version
41
98
  version: '0'
42
99
  requirements: []
43
100
  rubyforge_project:
44
- rubygems_version: 2.2.2
101
+ rubygems_version: 2.4.8
45
102
  signing_key:
46
103
  specification_version: 4
47
104
  summary: A wrapper to Yahoo! Finance market data (quotes and exchange rates) feed
data/lib/yahoo_finance.rb DELETED
@@ -1,231 +0,0 @@
1
- require 'open-uri'
2
- require 'ostruct'
3
- require 'json'
4
-
5
- if RUBY_VERSION >= "1.9"
6
- require 'csv'
7
- else
8
- require 'rubygems'
9
- require 'fastercsv'
10
- class Object
11
- CSV = FCSV
12
- alias_method :CSV, :FCSV
13
- end
14
- end
15
-
16
- class YahooFinance
17
-
18
- VERSION = '0.2.0'
19
-
20
- COLUMNS = {
21
- :ask => "a",
22
- :average_daily_volume => "a2",
23
- :ask_size => "a5",
24
- :bid => "b",
25
- :ask_real_time => "b2",
26
- :bid_real_time => "b3",
27
- :book_value => "b4",
28
- :bid_size => "b6",
29
- :change_and_percent_change => "c",
30
- :change => "c1",
31
- :comission => "c3",
32
- :change_real_time => "c6",
33
- :after_hours_change_real_time => "c8",
34
- :dividend_per_share => "d",
35
- :last_trade_date => "d1",
36
- :trade_date => "d2",
37
- :earnings_per_share => "e",
38
- :error_indicator => "e1",
39
- :eps_estimate_current_year => "e7",
40
- :eps_estimate_next_year => "e8",
41
- :eps_estimate_next_quarter => "e9",
42
- :float_shares => "f6",
43
- :low => "g",
44
- :high => "h",
45
- :low_52_weeks => "j",
46
- :high_52_weeks => "k",
47
- :holdings_gain_percent => "g1",
48
- :annualized_gain => "g3",
49
- :holdings_gain => "g4",
50
- :holdings_gain_percent_realtime => "g5",
51
- :holdings_gain_realtime => "g6",
52
- :more_info => "i",
53
- :order_book => "i5",
54
- :market_capitalization => "j1",
55
- :market_cap_realtime => "j3",
56
- :ebitda => "j4",
57
- :change_From_52_week_low => "j5",
58
- :percent_change_from_52_week_low => "j6",
59
- :last_trade_realtime_withtime => "k1",
60
- :change_percent_realtime => "k2",
61
- :last_trade_size => "k3",
62
- :change_from_52_week_high => "k4",
63
- :percent_change_from_52_week_high => "k5",
64
- :last_trade_with_time => "l",
65
- :last_trade_price => "l1",
66
- :close => "l1",
67
- :high_limit => "l2",
68
- :low_limit => "l3",
69
- :days_range => "m",
70
- :days_range_realtime => "m2",
71
- :moving_average_50_day => "m3",
72
- :moving_average_200_day => "m4",
73
- :change_from_200_day_moving_average => "m5",
74
- :percent_change_from_200_day_moving_average => "m6",
75
- :change_from_50_day_moving_average => "m7",
76
- :percent_change_from_50_day_moving_average => "m8",
77
- :name => "n",
78
- :notes => "n4",
79
- :open => "o",
80
- :previous_close => "p",
81
- :price_paid => "p1",
82
- :change_in_percent => "p2",
83
- :price_per_sales => "p5",
84
- :price_per_book => "p6",
85
- :ex_dividend_date => "q",
86
- :pe_ratio => "r",
87
- :dividend_pay_date => "r1",
88
- :pe_ratio_realtime => "r2",
89
- :peg_ratio => "r5",
90
- :price_eps_estimate_current_year => "r6",
91
- :price_eps_Estimate_next_year => "r7",
92
- :symbol => "s",
93
- :shares_owned => "s1",
94
- :short_ratio => "s7",
95
- :last_trade_time => "t1",
96
- :trade_links => "t6",
97
- :ticker_trend => "t7",
98
- :one_year_target_price => "t8",
99
- :volume => "v",
100
- :holdings_value => "v1",
101
- :holdings_value_realtime => "v7",
102
- :weeks_range_52 => "w",
103
- :day_value_change => "w1",
104
- :day_value_change_realtime => "w4",
105
- :stock_exchange => "x",
106
- :dividend_yield => "y",
107
- :adjusted_close => nil # this one only comes in historical quotes
108
- }
109
-
110
- HISTORICAL_MODES = {
111
- :daily => "d",
112
- :weekly => "w",
113
- :monthly => "m",
114
- :dividends_only => "v"
115
- }
116
-
117
- SYMBOLS_PER_REQUEST = 50
118
-
119
- # retrieve the quote data (an OpenStruct per quote)
120
- # the options param can be used to specify the following attributes:
121
- # :raw - if true, each column will be converted (to numbers, dates, etc)
122
- def self.quotes(symbols_array, columns_array = [:symbol, :last_trade_price, :last_trade_date, :change, :previous_close], options = { })
123
- options[:raw] ||= true
124
-
125
- ret = []
126
- symbols_array.each_slice(SYMBOLS_PER_REQUEST) do |symbols|
127
- read_quotes(symbols.join("+"), columns_array).map do |row|
128
- ret << OpenStruct.new(row.to_hash)
129
- end
130
- end
131
- ret
132
- end
133
-
134
- def self.quote(symbol, columns_array = [:symbol, :last_trade_price, :last_trade_date, :change, :previous_close], options = { })
135
- options[:raw] ||= true
136
- quotes([symbol], columns_array, options).first
137
- end
138
-
139
- def self.historical_quotes(symbol, options = {})
140
- options[:raw] ||= true
141
- options[:period] ||= :daily
142
- read_historical(symbol, options).map do |row|
143
- OpenStruct.new(row.to_hash.merge(:symbol => symbol))
144
- end
145
- end
146
-
147
- def self.symbols(query)
148
- ret = []
149
- read_symbols(query).each do |row|
150
- ret << OpenStruct.new(row)
151
- end
152
- ret
153
- end
154
-
155
- def self.splits(symbol, options = {})
156
- rows = read_splits(symbol, options).select{|row| row[0] == 'SPLIT'}
157
- rows.map do |row|
158
- type, date, value = row
159
- after, before = value.split(':')
160
- OpenStruct.new(:symbol => symbol, :date => Date.strptime(date.strip, '%Y%m%d'), :before => before.to_i, :after => after.to_i)
161
- end
162
- end
163
-
164
- private
165
-
166
- def self.read_quotes(symb_str, cols)
167
- columns = "#{cols.map {|col| COLUMNS[col] }.join('')}"
168
- conn = open("http://download.finance.yahoo.com/d/quotes.csv?s=#{URI.escape(symb_str)}&f=#{columns}")
169
- CSV.parse(conn.read, :headers => cols)
170
- end
171
-
172
- def self.read_historical(symbol, options)
173
- params = {
174
- :s => URI.escape(symbol),
175
- :g => HISTORICAL_MODES[options[:period]],
176
- :ignore => '.csv',
177
- }
178
- if options[:start_date]
179
- params[:a] = options[:start_date].month-1
180
- params[:b] = options[:start_date].day
181
- params[:c] = options[:start_date].year
182
- end
183
- if options[:end_date]
184
- params[:d] = options[:end_date].month-1
185
- params[:e] = options[:end_date].day
186
- params[:f] = options[:end_date].year
187
- end
188
-
189
- url = "http://ichart.finance.yahoo.com/table.csv?#{params.map{|k, v| "#{k}=#{v}"}.join('&')}"
190
- conn = open(url)
191
- cols =
192
- if options[:period] == :dividends_only
193
- [:dividend_pay_date, :dividend_yield]
194
- else
195
- [:trade_date, :open, :high, :low, :close, :volume, :adjusted_close]
196
- end
197
- result = CSV.parse(conn.read, :headers => cols) #:first_row, :header_converters => :symbol)
198
- result.delete(0) # drop returned header
199
- result
200
- end
201
-
202
- def self.read_splits(symbol, options)
203
- params = {
204
- :s => URI.escape(symbol),
205
- :g => 'v'
206
- }
207
- if options[:start_date]
208
- params[:a] = options[:start_date].month-1
209
- params[:b] = options[:start_date].day
210
- params[:c] = options[:start_date].year
211
- end
212
- if options[:end_date]
213
- params[:d] = options[:end_date].month-1
214
- params[:e] = options[:end_date].day
215
- params[:f] = options[:end_date].year
216
- end
217
-
218
- url = "http://ichart.finance.yahoo.com/x?#{params.map{|k, v| "#{k}=#{v}"}.join('&')}"
219
- conn = open(url)
220
- CSV.parse(conn.read)
221
- end
222
-
223
- def self.read_symbols(query)
224
- conn = open("http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=#{query}&callback=YAHOO.Finance.SymbolSuggest.ssCallback")
225
- result = conn.read
226
- result.sub!('YAHOO.Finance.SymbolSuggest.ssCallback(', '').chomp!(')')
227
- json_result = JSON.parse(result)
228
- json_result["ResultSet"]["Result"]
229
- end
230
-
231
- end