yahoofinance 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +30 -0
- data/README +15 -0
- data/lib/yahoofinance.rb +570 -0
- metadata +48 -0
data/ChangeLog
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
2006-08-01 Nicholas Rahn <nick@mobiledude.com>
|
2
|
+
* lib/yahoofinance.rb: Internal cleanups and optimizations so we don't return or create big arrays if not necessary in the historical quote API.
|
3
|
+
|
4
|
+
2006-07-31 Nicholas Rahn <nick@mobiledude.com>
|
5
|
+
* Reorganize directory layout for gem.
|
6
|
+
* Rakefile: New rakefile for building a gem.
|
7
|
+
* lib/yahoofinance.rb: Add command line usage for historical quotes.
|
8
|
+
|
9
|
+
2006-05-04 Nicholas Rahn <nick@mobiledude.com>
|
10
|
+
* yahoofinance.rb: Re-organize the method names for historical quotes. Upgrade the downloading of historical data so that "international" market data that are available only in 200 data point chunks are completely downloaded (in multiple chunks).
|
11
|
+
|
12
|
+
2006-03-13 Nicholas Rahn <nick@mobiledude.com>
|
13
|
+
* yahoofinance.rb: Play around with timeouts in an attempt to find why requests will sometimes hang. Added a bit of error checking to get method. Probably can remove extra stuff later.
|
14
|
+
|
15
|
+
2006-01-01 Nicholas Rahn <nick@mobiledude.com>
|
16
|
+
* yahoofinance.rb: Start work on historical quote data retrieval. Mostly for use in Grism (www.grism.org).
|
17
|
+
|
18
|
+
2005-09-05 Nicholas Rahn <nick@mobiledude.com>
|
19
|
+
|
20
|
+
* yahoofinance.rb: add proper value conversion methods to some
|
21
|
+
extended quote variables.
|
22
|
+
|
23
|
+
2005-08-31 Nicholas Rahn <nick@mobiledude.com>
|
24
|
+
|
25
|
+
* yahoofinance.rb: Allow passing arrays of symbols as well as
|
26
|
+
comma delimited strings.
|
27
|
+
|
28
|
+
2005-08-30 Nicholas Rahn <nick@mobiledude.com>
|
29
|
+
|
30
|
+
* Release 1.0.0
|
data/README
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
YahooFinance ruby module
|
2
|
+
|
3
|
+
Homepage: http://www.mobiledude.com/projects/yahoofinance
|
4
|
+
|
5
|
+
Ruby module for getting stock quote information from the
|
6
|
+
finance.yahoo.com website.
|
7
|
+
|
8
|
+
This module can be "required" and used as a library. Or it can be
|
9
|
+
run from the command-line as a script.
|
10
|
+
|
11
|
+
|
12
|
+
Please see the homepage for more details.
|
13
|
+
|
14
|
+
Please send any comments or bug reports to "nick lives-here mobiledude
|
15
|
+
pixel-grouping com".
|
data/lib/yahoofinance.rb
ADDED
@@ -0,0 +1,570 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# YahooFinance ruby module.
|
4
|
+
# Homepage: http://www.mobiledude.com/projects/yahoofinance
|
5
|
+
#
|
6
|
+
# Ruby module for getting stock quote information from the
|
7
|
+
# finance.yahoo.com website.
|
8
|
+
#
|
9
|
+
# This module can be "required" and used as a library. Or it can be
|
10
|
+
# run from the command-line as a script.
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# Copyright (c) 2006 Nicholas Rahn <nick at mobiledude.com>
|
14
|
+
#
|
15
|
+
# This software may be freely redistributed under the terms of the GNU
|
16
|
+
# public license version 2.
|
17
|
+
#
|
18
|
+
# This package is distributed in the hope that it will be useful,
|
19
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
20
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
21
|
+
#
|
22
|
+
# See the "GNU General Public License" for more detail.
|
23
|
+
#
|
24
|
+
|
25
|
+
require 'net/http'
|
26
|
+
require 'csv'
|
27
|
+
require 'date'
|
28
|
+
require 'optparse'
|
29
|
+
require 'ostruct'
|
30
|
+
|
31
|
+
# Was using this to test a theory about why requests would hang
|
32
|
+
# randomly, but since upgrading to ruby 1.8.4, I haven't had many
|
33
|
+
# hangs. I also tend to think that Yahoo has improved the reliability
|
34
|
+
# of this service a bit. My guess is that most of the hangs were due
|
35
|
+
# to dropped requests.
|
36
|
+
#
|
37
|
+
#require 'timeout'
|
38
|
+
|
39
|
+
|
40
|
+
#
|
41
|
+
# Module for retrieving quote data ('live' and 'historical') from
|
42
|
+
# YahooFinance!
|
43
|
+
#
|
44
|
+
# This module is made up of 2 parts:
|
45
|
+
# 1. Retrieving 'live' quote data. 'Live' quotes are the current
|
46
|
+
# data available for a given stock. Most often delayed 20mins.
|
47
|
+
# 2. Retrieving 'historical' quote data. 'Historical' quotes are
|
48
|
+
# for past pricings of a given stock.
|
49
|
+
#
|
50
|
+
module YahooFinance
|
51
|
+
|
52
|
+
#
|
53
|
+
# 'Live' quote data retrieval.
|
54
|
+
#
|
55
|
+
|
56
|
+
STDHASH = {
|
57
|
+
"s" => [ "symbol", "val" ],
|
58
|
+
"n" => [ "name", "val" ],
|
59
|
+
"l1" => [ "lastTrade", "val.to_f" ],
|
60
|
+
"d1" => [ "date", "val" ],
|
61
|
+
"t1" => [ "time", "val" ],
|
62
|
+
"c" => [ "change", "val" ],
|
63
|
+
"c1" => [ "changePoints", "val.to_f" ],
|
64
|
+
"p2" => [ "changePercent", "val.to_f" ],
|
65
|
+
"p" => [ "previousClose", "val.to_f" ],
|
66
|
+
"o" => [ "open", "val.to_f" ],
|
67
|
+
"h" => [ "dayHigh", "val.to_f" ],
|
68
|
+
"g" => [ "dayLow", "val.to_f" ],
|
69
|
+
"v" => [ "volume", "val.to_i" ],
|
70
|
+
"m" => [ "dayRange", "val" ],
|
71
|
+
"l" => [ "lastTradeWithTime", "val" ],
|
72
|
+
"t7" => [ "tickerTrend", "convert(val)" ],
|
73
|
+
"a2" => [ "averageDailyVolume", "val.to_i" ],
|
74
|
+
"b" => [ "bid", "val.to_f" ],
|
75
|
+
"a" => [ "ask", "val.to_f" ]
|
76
|
+
# These return integers like "1,000". The CVS parser gets confused by this
|
77
|
+
# so I've removed them for the time being.
|
78
|
+
# "b6" => [ "bidSize", "val" ],
|
79
|
+
# "a5" => [ "askSize", "val" ]
|
80
|
+
# "k3" => [ "lastTradeSize", "convert(val)" ],
|
81
|
+
}
|
82
|
+
|
83
|
+
EXTENDEDHASH = {
|
84
|
+
"s" => [ "symbol", "val" ],
|
85
|
+
"n" => [ "name", "val" ],
|
86
|
+
"w" => [ "weeks52Range", "val" ],
|
87
|
+
"j5" => [ "weeks52ChangeFromLow", "val.to_f" ],
|
88
|
+
"j6" => [ "weeks52ChangePercentFromLow", "val" ],
|
89
|
+
"k4" => [ "weeks52ChangeFromHigh", "val.to_f" ],
|
90
|
+
"k5" => [ "weeks52ChangePercentFromHigh", "val" ],
|
91
|
+
"e" => [ "earningsPerShare", "val.to_f" ],
|
92
|
+
"r" => [ "peRatio", "val.to_f" ],
|
93
|
+
"s7" => [ "shortRatio", "val" ],
|
94
|
+
"r1" => [ "dividendPayDate", "val" ],
|
95
|
+
"q" => [ "exDividendDate", "val" ],
|
96
|
+
"d" => [ "dividendPerShare", "convert(val)" ],
|
97
|
+
"y" => [ "dividendYield", "convert(val)" ],
|
98
|
+
"j1" => [ "marketCap", "convert(val)" ],
|
99
|
+
"t8" => [ "oneYearTargetPrice", "val" ],
|
100
|
+
"e7" => [ "epsEstimateCurrentYear", "val" ],
|
101
|
+
"e8" => [ "epsEstimateNextYear", "val" ],
|
102
|
+
"e9" => [ "epsEstimateNextQuarter", "val" ],
|
103
|
+
"r6" => [ "pricePerEPSEstimateCurrentYear", "val" ],
|
104
|
+
"r7" => [ "pricePerEPSEstimateNextYear", "val" ],
|
105
|
+
"r5" => [ "pegRatio", "val.to_f" ],
|
106
|
+
"b4" => [ "bookValue", "val.to_f" ],
|
107
|
+
"p6" => [ "pricePerBook", "val.to_f" ],
|
108
|
+
"p5" => [ "pricePerSales", "val.to_f" ],
|
109
|
+
"j4" => [ "ebitda", "val" ],
|
110
|
+
"m3" => [ "movingAve50days", "val" ],
|
111
|
+
"m7" => [ "movingAve50daysChangeFrom", "val" ],
|
112
|
+
"m8" => [ "movingAve50daysChangePercentFrom", "val" ],
|
113
|
+
"m4" => [ "movingAve200days", "val" ],
|
114
|
+
"m5" => [ "movingAve200daysChangeFrom", "val" ],
|
115
|
+
"m6" => [ "movingAve200daysChangePercentFrom", "val" ],
|
116
|
+
"s1" => [ "sharesOwned", "val" ],
|
117
|
+
"p1" => [ "pricePaid", "val" ],
|
118
|
+
"c3" => [ "commission", "val" ],
|
119
|
+
"v1" => [ "holdingsValue", "val" ],
|
120
|
+
"w1" => [ "dayValueChange", "val" ],
|
121
|
+
"g1" => [ "holdingsGainPercent", "val" ],
|
122
|
+
"g4" => [ "holdingsGain", "val" ],
|
123
|
+
"d2" => [ "tradeDate", "val" ],
|
124
|
+
"g3" => [ "annualizedGain", "val" ],
|
125
|
+
"l2" => [ "highLimit", "val" ],
|
126
|
+
"l3" => [ "lowLimit", "val" ],
|
127
|
+
"n4" => [ "notes", "val" ],
|
128
|
+
"x" => [ "stockExchange", "val" ]
|
129
|
+
# This returns an integer like "1,000,000".
|
130
|
+
# The CVS parser gets confused by this
|
131
|
+
# so I've removed it for the time being.
|
132
|
+
# "f6" => [ "floatShares", "val" ],
|
133
|
+
}
|
134
|
+
|
135
|
+
REALTIMEHASH = {
|
136
|
+
"s" => [ "symbol", "val" ],
|
137
|
+
"n" => [ "name" , "val" ],
|
138
|
+
"b2" => [ "ask", "val.to_f" ],
|
139
|
+
"b3" => [ "bid", "val.to_f" ],
|
140
|
+
"k2" => [ "change", "val" ],
|
141
|
+
"k1" => [ "lastTradeWithTime", "val" ],
|
142
|
+
"c6" => [ "changePoints", "val.to_f" ],
|
143
|
+
"m2" => [ "dayRange", "val" ],
|
144
|
+
"j3" => [ "marketCap", "convert(val)" ],
|
145
|
+
# "v7" => [ "holdingsValue", "val" ],
|
146
|
+
# "w4" => [ "dayValueChange", "val" ],
|
147
|
+
# "g5" => [ "holdingsGainPercent", "val" ],
|
148
|
+
# "g6" => [ "holdingsGain", "val" ],
|
149
|
+
# "r2" => [ "pe", "val" ],
|
150
|
+
# "c8" => [ "afterHoursChange", "val" ],
|
151
|
+
# "i5" => [ "orderBook", "val" ],
|
152
|
+
}
|
153
|
+
|
154
|
+
DEFAULT_READ_TIMEOUT = 5
|
155
|
+
|
156
|
+
def YahooFinance.get( symbols, format, timeout=DEFAULT_READ_TIMEOUT )
|
157
|
+
return "" if symbols == nil
|
158
|
+
symbols = symbols.join( "," ) if symbols.class == Array
|
159
|
+
symbols.strip!
|
160
|
+
return "" if symbols == ""
|
161
|
+
|
162
|
+
Net::HTTP.start( "finance.yahoo.com", 80 ) { |http|
|
163
|
+
http.read_timeout = timeout
|
164
|
+
response = nil
|
165
|
+
|
166
|
+
begin
|
167
|
+
#Timeout::timeout( 1 ) {
|
168
|
+
response = http.get( "/d/quotes.csv?s=#{symbols}&f=#{format}&e=.csv" )
|
169
|
+
#}
|
170
|
+
rescue
|
171
|
+
response = nil
|
172
|
+
end
|
173
|
+
|
174
|
+
return "" if !response
|
175
|
+
|
176
|
+
response.body.chomp
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
def YahooFinance.get_quotes( quote_class, symbols, &block )
|
181
|
+
if quote_class == YahooFinance::StandardQuote
|
182
|
+
return get_standard_quotes( symbols, &block )
|
183
|
+
elsif quote_class == YahooFinance::ExtendedQuote
|
184
|
+
return get_extended_quotes( symbols, &block )
|
185
|
+
elsif quote_class == YahooFinance::RealTimeQuote
|
186
|
+
return get_realtime_quotes( symbols, &block )
|
187
|
+
else
|
188
|
+
# Use the standard quote if the given quote_class was not recoginized.
|
189
|
+
return get_standard_quotes( symbols, &block )
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def YahooFinance.get_realtime_quotes( symbols )
|
194
|
+
csvquotes = YahooFinance::get( symbols, REALTIMEHASH.keys.join )
|
195
|
+
ret = Hash.new
|
196
|
+
CSV.parse( csvquotes ) do |row|
|
197
|
+
qt = RealTimeQuote.new( row )
|
198
|
+
if block_given?
|
199
|
+
yield qt
|
200
|
+
end
|
201
|
+
ret[qt.symbol] = qt
|
202
|
+
end
|
203
|
+
ret
|
204
|
+
end
|
205
|
+
def YahooFinance.get_extended_quotes( symbols )
|
206
|
+
csvquotes = YahooFinance::get( symbols, EXTENDEDHASH.keys.join )
|
207
|
+
ret = Hash.new
|
208
|
+
CSV.parse( csvquotes ) do |row|
|
209
|
+
qt = ExtendedQuote.new( row )
|
210
|
+
if block_given?
|
211
|
+
yield qt
|
212
|
+
end
|
213
|
+
ret[qt.symbol] = qt
|
214
|
+
end
|
215
|
+
ret
|
216
|
+
end
|
217
|
+
def YahooFinance.get_standard_quotes( symbols )
|
218
|
+
csvquotes = YahooFinance::get( symbols, STDHASH.keys.join )
|
219
|
+
ret = Hash.new
|
220
|
+
CSV.parse( csvquotes ) do |row|
|
221
|
+
qt = StandardQuote.new( row )
|
222
|
+
if block_given?
|
223
|
+
yield qt
|
224
|
+
end
|
225
|
+
ret[qt.symbol] = qt
|
226
|
+
end
|
227
|
+
ret
|
228
|
+
end
|
229
|
+
|
230
|
+
class BaseQuote
|
231
|
+
def initialize( hash, valarray=nil )
|
232
|
+
@formathash = hash
|
233
|
+
@formathash.each_key { |elem|
|
234
|
+
# Create a getter method for each format element.
|
235
|
+
instance_eval( "def #{@formathash[elem][0]}() " +
|
236
|
+
"@#{@formathash[elem][0]} " +
|
237
|
+
"end" )
|
238
|
+
# Create a setter method for each format element.
|
239
|
+
instance_eval( "def #{@formathash[elem][0]}=(val) " +
|
240
|
+
"@#{@formathash[elem][0]}=#{@formathash[elem][1]} " +
|
241
|
+
"end" )
|
242
|
+
}
|
243
|
+
|
244
|
+
parse( valarray ) if valarray
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
def load_quote( symbol )
|
249
|
+
csv = YahooFinance.get( symbol, @formathash.keys.join )
|
250
|
+
parse( CSV.parse_line( csv ) )
|
251
|
+
end
|
252
|
+
|
253
|
+
def get_info()
|
254
|
+
"#{symbol} : #{name}"
|
255
|
+
end
|
256
|
+
|
257
|
+
def to_s()
|
258
|
+
ret = String.new
|
259
|
+
ret << self.class.name << "\n"
|
260
|
+
@formathash.each_value { |val|
|
261
|
+
ret << "#{val[0]} = "
|
262
|
+
ret << send( val[0] ).to_s unless send( val[0] ) == nil
|
263
|
+
ret << "\n"
|
264
|
+
}
|
265
|
+
return ret
|
266
|
+
end
|
267
|
+
|
268
|
+
protected
|
269
|
+
|
270
|
+
def parse( results )
|
271
|
+
begin
|
272
|
+
ctr = 0
|
273
|
+
results.each { |elem|
|
274
|
+
# Call the setter method for this element.
|
275
|
+
send "#{@formathash[@formathash.keys[ctr]][0]}=", elem
|
276
|
+
ctr += 1
|
277
|
+
}
|
278
|
+
rescue
|
279
|
+
puts "yfparse:#{$!}"
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def convert( value )
|
284
|
+
if ( value == "N/A" )
|
285
|
+
return value
|
286
|
+
elsif ( value =~ /.*\..*B/ )
|
287
|
+
return value
|
288
|
+
else
|
289
|
+
return value
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
end
|
294
|
+
|
295
|
+
class RealTimeQuote < YahooFinance::BaseQuote
|
296
|
+
def initialize( valarray=nil )
|
297
|
+
super( YahooFinance::REALTIMEHASH, valarray )
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
class ExtendedQuote < YahooFinance::BaseQuote
|
302
|
+
def initialize( valarray=nil )
|
303
|
+
super( YahooFinance::EXTENDEDHASH, valarray )
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class StandardQuote < YahooFinance::BaseQuote
|
308
|
+
def initialize( valarray=nil )
|
309
|
+
super( YahooFinance::STDHASH, valarray )
|
310
|
+
end
|
311
|
+
|
312
|
+
def get_info()
|
313
|
+
"#{symbol} : #{lastTrade} : #{changePoints} (#{changePercent})"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
#
|
318
|
+
# 'Historical' quote retrieval.
|
319
|
+
#
|
320
|
+
|
321
|
+
class HistoricalQuote
|
322
|
+
attr_accessor :recno, :symbol, :date, :open
|
323
|
+
attr_accessor :high, :low, :close, :adjClose, :volume
|
324
|
+
|
325
|
+
def initialize( sym, valarray=nil, &block )
|
326
|
+
@symbol = sym.upcase
|
327
|
+
if valarray
|
328
|
+
|
329
|
+
@date = HistoricalQuote.parse_date( valarray[0] )
|
330
|
+
@open = valarray[1].to_f
|
331
|
+
@high = valarray[2].to_f
|
332
|
+
@low = valarray[3].to_f
|
333
|
+
@close = valarray[4].to_f
|
334
|
+
@volume = valarray[5].to_i
|
335
|
+
@adjClose = valarray[6].to_f
|
336
|
+
@recno = valarray[7].to_i if valarray.size >= 8
|
337
|
+
end
|
338
|
+
if block_given?
|
339
|
+
instance_eval( &block )
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
@@date_re = /([0-9]{1,2})-([A-Za-z]+)-([0-9]{1,2})/
|
344
|
+
@@months = %w( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )
|
345
|
+
def HistoricalQuote.parse_date( date )
|
346
|
+
md = @@date_re.match( date )
|
347
|
+
if md
|
348
|
+
if md[3].to_i > 30
|
349
|
+
year = "19#{md[3]}"
|
350
|
+
else
|
351
|
+
year = "20#{md[3]}"
|
352
|
+
end
|
353
|
+
return "#{year}-%02d-%02d" % [(@@months.index(md[2]) + 1), md[1].to_i]
|
354
|
+
else
|
355
|
+
return date
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
def HistoricalQuote.parse_date_to_Date( date )
|
360
|
+
return Date.parse( parse_date( date ) )
|
361
|
+
end
|
362
|
+
|
363
|
+
def to_s
|
364
|
+
return "#{symbol},#{date},#{open},#{high},#{low},#{close},#{volume},#{adjClose}"
|
365
|
+
end
|
366
|
+
|
367
|
+
def to_a
|
368
|
+
return [] << symbol << date << open << high <<
|
369
|
+
low << close << volume << adjClose
|
370
|
+
end
|
371
|
+
|
372
|
+
def date_to_Date
|
373
|
+
return Date.parse( @date )
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
|
378
|
+
def YahooFinance.retrieve_raw_historical_quotes( symbol, startDate, endDate )
|
379
|
+
|
380
|
+
# Don't try to download anything if the starting date is before
|
381
|
+
# the end date.
|
382
|
+
return [] if startDate > endDate
|
383
|
+
|
384
|
+
Net::HTTP.start( "itable.finance.yahoo.com", 80 ) { |http|
|
385
|
+
query = "/table.csv?s=#{symbol}&g=d" +
|
386
|
+
"&a=#{startDate.month-1}&b=#{startDate.mday}&c=#{startDate.year}" +
|
387
|
+
"&d=#{endDate.month-1}&e=#{endDate.mday}&f=#{endDate.year.to_s}"
|
388
|
+
#puts "#{query}"
|
389
|
+
response = http.get( query )
|
390
|
+
#puts "#{response.body}"
|
391
|
+
body = response.body.chomp
|
392
|
+
|
393
|
+
# If we don't get the first line like this, there was something
|
394
|
+
# wrong with the data (404 error, new data formet, etc).
|
395
|
+
return [] if body !~ /Date,Open,High,Low,Close,Volume,Adj. Close\*/
|
396
|
+
|
397
|
+
# Parse into an array of arrays.
|
398
|
+
rows = CSV.parse( body )
|
399
|
+
# Remove the first array since it is just the field headers.
|
400
|
+
rows.shift
|
401
|
+
#puts "#{rows.length}"
|
402
|
+
|
403
|
+
return rows
|
404
|
+
}
|
405
|
+
end
|
406
|
+
|
407
|
+
def YahooFinance.get_historical_quotes( symbol, startDate, endDate )
|
408
|
+
rows = []
|
409
|
+
rowct = 0
|
410
|
+
gotchunk = false
|
411
|
+
|
412
|
+
#
|
413
|
+
# Yahoo is only able to provide 200 data points at a time for Some
|
414
|
+
# "international" markets. We want to download all of the data
|
415
|
+
# points between the startDate and endDate, regardless of how many
|
416
|
+
# 200 data point chunks it comes in. In this section we download
|
417
|
+
# as many chunks as needed to get all of the data points.
|
418
|
+
#
|
419
|
+
begin
|
420
|
+
gotchunk = false
|
421
|
+
r = YahooFinance.retrieve_raw_historical_quotes( symbol,
|
422
|
+
startDate, endDate )
|
423
|
+
if block_given?
|
424
|
+
# If we were given a block, yield to it for every row of data
|
425
|
+
# downloaded.
|
426
|
+
r.each { |row| yield row }
|
427
|
+
else
|
428
|
+
rows += r
|
429
|
+
end
|
430
|
+
|
431
|
+
# Is this a chunk?
|
432
|
+
if r.length == 200
|
433
|
+
# Adjust the endDate for when we retrieve the next chunk.
|
434
|
+
endDate = HistoricalQuote.parse_date_to_Date( r.last[0] ) - 1
|
435
|
+
# Marke this as a chunk so do the download again with the new endDate.
|
436
|
+
gotchunk = true
|
437
|
+
end
|
438
|
+
|
439
|
+
end while gotchunk
|
440
|
+
|
441
|
+
if block_given?
|
442
|
+
# If we have already yielded to every row, just return nil.
|
443
|
+
return nil
|
444
|
+
else
|
445
|
+
# Otherwise return the big array of arrays.
|
446
|
+
rows
|
447
|
+
end
|
448
|
+
|
449
|
+
end
|
450
|
+
|
451
|
+
def YahooFinance.get_historical_quotes_days( symbol, days, &block )
|
452
|
+
endDate = Date.today()
|
453
|
+
startDate = Date.today() - days
|
454
|
+
YahooFinance.get_historical_quotes( symbol, startDate, endDate, &block )
|
455
|
+
end
|
456
|
+
|
457
|
+
def YahooFinance.get_HistoricalQuotes( symbol, startDate, endDate )
|
458
|
+
ret = []
|
459
|
+
YahooFinance.get_historical_quotes( symbol, startDate, endDate ) { |row|
|
460
|
+
if block_given?
|
461
|
+
yield HistoricalQuote.new( symbol, row )
|
462
|
+
else
|
463
|
+
ret << HistoricalQuote.new( symbol, row )
|
464
|
+
end
|
465
|
+
}
|
466
|
+
if block_given?
|
467
|
+
return nil
|
468
|
+
else
|
469
|
+
return ret
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
def YahooFinance.get_HistoricalQuotes_days( symbol, days, &block )
|
474
|
+
endDate = Date.today()
|
475
|
+
startDate = Date.today() - days
|
476
|
+
YahooFinance.get_HistoricalQuotes( symbol, startDate, endDate, &block )
|
477
|
+
end
|
478
|
+
|
479
|
+
end
|
480
|
+
|
481
|
+
|
482
|
+
|
483
|
+
if $0 == __FILE__
|
484
|
+
|
485
|
+
class CLIOpts
|
486
|
+
def self.help( options, opts )
|
487
|
+
puts "ERROR: #{options.helpMsg}" if options.helpMsg
|
488
|
+
puts opts
|
489
|
+
exit
|
490
|
+
end
|
491
|
+
|
492
|
+
# Return a structure describing the options.
|
493
|
+
def self.parse( args, options )
|
494
|
+
|
495
|
+
opts = OptionParser.new do |opts|
|
496
|
+
opts.banner = "Usage: yahoofinance.rb [options] <symbol>"
|
497
|
+
|
498
|
+
opts.separator ""
|
499
|
+
|
500
|
+
opts.on( "-s", "Retrieve standard quotes (default)." ) {
|
501
|
+
options.quote_class = YahooFinance::StandardQuote
|
502
|
+
}
|
503
|
+
opts.on( "-x", "Retrieve extended quotes." ) {
|
504
|
+
options.quote_class = YahooFinance::ExtendedQuote
|
505
|
+
}
|
506
|
+
opts.on( "-r", "Retrieve real-time quotes." ) {
|
507
|
+
options.quote_class = YahooFinance::RealTimeQuote
|
508
|
+
}
|
509
|
+
opts.on( '-z', "Retrieve historical quotes." ) {
|
510
|
+
options.quote_class = nil
|
511
|
+
}
|
512
|
+
opts.on( "-d", "--days N", Integer, "Number of days of historical " +
|
513
|
+
"quotes to retrieve. Default is 90." ) { |days|
|
514
|
+
options.historical_days = days
|
515
|
+
}
|
516
|
+
opts.on( "-h", "--help", "Show this message" ) do
|
517
|
+
options.help = true
|
518
|
+
end
|
519
|
+
|
520
|
+
end
|
521
|
+
|
522
|
+
begin
|
523
|
+
opts.parse!(args)
|
524
|
+
rescue OptionParser::InvalidOption
|
525
|
+
options.help = true
|
526
|
+
options.helpMsg = $!.message
|
527
|
+
help( options, opts )
|
528
|
+
end
|
529
|
+
|
530
|
+
if options.help
|
531
|
+
help( options, opts )
|
532
|
+
end
|
533
|
+
|
534
|
+
if args.length > 0 && options.help != true
|
535
|
+
options.symbol = args[0]
|
536
|
+
else
|
537
|
+
options.help = true
|
538
|
+
options.helpMsg = "Missing Symbol!"
|
539
|
+
help( options, opts )
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
$options = OpenStruct.new
|
545
|
+
$options.help = false
|
546
|
+
$options.helpMsg = nil
|
547
|
+
$options.symbol = nil
|
548
|
+
$options.quote_class = YahooFinance::StandardQuote
|
549
|
+
$options.historical_days = 90
|
550
|
+
|
551
|
+
CLIOpts.parse( ARGV, $options )
|
552
|
+
puts "Retrieving quotes for: #{$options.symbol}"
|
553
|
+
|
554
|
+
if $options.quote_class
|
555
|
+
YahooFinance::get_quotes( $options.quote_class, $options.symbol ) do |qt|
|
556
|
+
puts "QUOTING: #{qt.symbol}"
|
557
|
+
#puts "#{qt.get_info}"
|
558
|
+
puts qt.to_s
|
559
|
+
end
|
560
|
+
else
|
561
|
+
$options.symbol.split( ',' ).each do |s|
|
562
|
+
YahooFinance::get_historical_quotes_days( s,
|
563
|
+
$options.historical_days ) do
|
564
|
+
|row|
|
565
|
+
puts "#{s},#{row.join(',')}"
|
566
|
+
end
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: yahoofinance
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.2.0
|
7
|
+
date: 2006-08-01 00:00:00 +02:00
|
8
|
+
summary: A package for retrieving stock quote information from Yahoo! Finance.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: nick @nospam@ mobiledude.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: yahoofinance
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Nicholas Rahn
|
31
|
+
files:
|
32
|
+
- lib/yahoofinance.rb
|
33
|
+
- README
|
34
|
+
- ChangeLog
|
35
|
+
test_files: []
|
36
|
+
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
extra_rdoc_files: []
|
40
|
+
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
requirements: []
|
46
|
+
|
47
|
+
dependencies: []
|
48
|
+
|