yahoo-finance 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/HISTORY +4 -0
- data/README.md +42 -8
- data/lib/yahoo-finance.rb +172 -1
- data/lib/yahoo-finance/finance-utils.rb +28 -0
- data/lib/yahoo-finance/version.rb +4 -0
- metadata +5 -4
- data/lib/yahoo_finance.rb +0 -231
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0f9d32ecd47a310bd70df430526a855153ea006
|
4
|
+
data.tar.gz: 3a416023015934a5f5129fb3e074ffa4cddc522f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78010a4b901285e85116bb2ab01801028fed4a456801af994b75906b23230659c69760b6deb2573f6e0c6f053d76f979a2a90b4a16272130dd31d4154a35bb18
|
7
|
+
data.tar.gz: 98e08a4fc5919b6841605be60c4397379939648f92ef49d0582950199044400d03fede1d8bb302bba96dd134d43f8dad1504b8b1e7e3c383caecce34c5bbdeb9
|
data/HISTORY
CHANGED
data/README.md
CHANGED
@@ -4,10 +4,13 @@ A dead simple wrapper for yahoo finance quotes end-point.
|
|
4
4
|
## Installation:
|
5
5
|
|
6
6
|
`gem install 'yahoo-finance'`
|
7
|
-
`require '
|
7
|
+
`require 'yahoo-finance'`
|
8
8
|
|
9
9
|
If using bundler:
|
10
|
-
|
10
|
+
|
11
|
+
`gem 'yahoo-finance', git: 'https://github.com/herval/yahoo-finance.git'`
|
12
|
+
|
13
|
+
`require: 'yahoo-finance'`
|
11
14
|
|
12
15
|
## Usage:
|
13
16
|
|
@@ -16,7 +19,8 @@ If using bundler:
|
|
16
19
|
Pass an array of valid symbols (stock names, indexes, exchange rates) and a list of fields you want:
|
17
20
|
|
18
21
|
```ruby
|
19
|
-
|
22
|
+
yahoo_client = YahooFinance::Client.new
|
23
|
+
data = yahoo_client.quotes(["BVSP", "NATU3.SA", "USDJPY=X"], [:ask, :bid, :last_trade_date])
|
20
24
|
```
|
21
25
|
|
22
26
|
Data is now an array of results. You now have accessor methods to retrieve the data, with the return results being strings:
|
@@ -28,7 +32,8 @@ puts data[0].symbol + " value is: " + data[0].ask
|
|
28
32
|
Passing `raw: false` will return numerical values
|
29
33
|
|
30
34
|
```ruby
|
31
|
-
|
35
|
+
yahoo_client = YahooFinance::Client.new
|
36
|
+
data = yahoo_client.quotes(["BVSP", "NATU3.SA", "USDJPY=X"], [:ask, :bid, :last_trade_date], { raw: false } )
|
32
37
|
data[0].ask # This is now a float
|
33
38
|
```
|
34
39
|
|
@@ -123,6 +128,30 @@ The full list of fields follows:
|
|
123
128
|
:weeks_range_52
|
124
129
|
```
|
125
130
|
|
131
|
+
### Getting symbols by stock market (beta)
|
132
|
+
|
133
|
+
Create a YahooFinance::Client instance
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
yahoo_client = YahooClient::Client.new
|
137
|
+
```
|
138
|
+
|
139
|
+
Calling symbols_by_market method (symbols_by_market(country, stock_market))
|
140
|
+
|
141
|
+
Note: Can only be called with US Stock Markets for now.
|
142
|
+
|
143
|
+
*Important: This data comes directly from NASDAQ's CSV endpoints, NOT Yahoo Finance*. It might be extracted into a different Gem in the future.
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
yahoo_client.symbols_by('us', 'nyse') # Only US Stock Markets For Now
|
147
|
+
```
|
148
|
+
|
149
|
+
This method returns an array of symbols that can be used with the quotes method
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
data = yahoo_client.quotes(yahoo_client.symbols_by_market('us', 'nyse'), [:ask, :bid, :last_trade_date])
|
153
|
+
```
|
154
|
+
|
126
155
|
### Getting historical quotes
|
127
156
|
|
128
157
|
Here you can specify a date range and a symbol, and retrieve historical data for it.
|
@@ -130,19 +159,22 @@ The last parameter (options) can include, besides the "raw" option, a "period" o
|
|
130
159
|
The period can be specified as :daily, :monthly, :weekly or :dividends_only
|
131
160
|
|
132
161
|
```ruby
|
133
|
-
|
162
|
+
yahoo_client = YahooFinance::Client.new
|
163
|
+
data = yahoo_client.historical_quotes("AAPL") # entire historical data
|
134
164
|
```
|
135
165
|
|
136
166
|
or
|
137
167
|
|
138
168
|
```ruby
|
139
|
-
|
169
|
+
yahoo_client = YahooFinance::Client.new
|
170
|
+
data = yahoo_client.historical_quotes("AAPL", { start_date: Time::now-(24*60*60*10), end_date: Time::now }) # 10 days worth of data
|
140
171
|
```
|
141
172
|
|
142
173
|
or
|
143
174
|
|
144
175
|
``` ruby
|
145
|
-
|
176
|
+
yahoo_client = YahooFinance::Client.new
|
177
|
+
data = yahoo_client.historical_quotes("AAPL", { raw: false, period: :monthly })
|
146
178
|
```
|
147
179
|
|
148
180
|
### Getting splits
|
@@ -150,7 +182,8 @@ data = YahooFinance.historical_quotes("AAPL", { raw: false, period: :monthly })
|
|
150
182
|
You can also retrieve split data.
|
151
183
|
|
152
184
|
```ruby
|
153
|
-
|
185
|
+
yahoo_client = YahooFinance::Client.new
|
186
|
+
data = yahoo_client.splits('AAPL', :start_date => Date.today - 10*365)
|
154
187
|
data[0].date # Date<2014-06-09>
|
155
188
|
data[0].before # 1
|
156
189
|
data[0].after # 7
|
@@ -160,3 +193,4 @@ data[0].after # 7
|
|
160
193
|
Enjoy! :-)
|
161
194
|
|
162
195
|
- Herval (hervalfreire@gmail.com)
|
196
|
+
- Eric D. Santos Sosa (eric.santos@cometa.works)
|
data/lib/yahoo-finance.rb
CHANGED
@@ -1 +1,172 @@
|
|
1
|
-
require
|
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
|
+
|
8
|
+
module YahooFinance
|
9
|
+
# Client for Yahoo Finance Queries
|
10
|
+
class Client
|
11
|
+
include YahooFinance::FinanceUtils
|
12
|
+
|
13
|
+
COLUMNS = {
|
14
|
+
ask: "a", average_daily_volume: "a2", ask_size: "a5", bid: "b",
|
15
|
+
ask_real_time: "b2", bid_real_time: "b3", book_value: "b4",
|
16
|
+
bid_size: "b6", change_and_percent_change: "c", change: "c1",
|
17
|
+
comission: "c3", change_real_time: "c6",
|
18
|
+
after_hours_change_real_time: "c8", dividend_per_share: "d",
|
19
|
+
last_trade_date: "d1", trade_date: "d2", earnings_per_share: "e",
|
20
|
+
error_indicator: "e1", eps_estimate_current_year: "e7",
|
21
|
+
eps_estimate_next_year: "e8", eps_estimate_next_quarter: "e9",
|
22
|
+
float_shares: "f6", low: "g", high: "h", low_52_weeks: "j",
|
23
|
+
high_52_weeks: "k", holdings_gain_percent: "g1", annualized_gain: "g3",
|
24
|
+
holdings_gain: "g4", holdings_gain_percent_realtime: "g5",
|
25
|
+
holdings_gain_realtime: "g6", more_info: "i", order_book: "i5",
|
26
|
+
market_capitalization: "j1", market_cap_realtime: "j3", ebitda: "j4",
|
27
|
+
change_From_52_week_low: "j5", percent_change_from_52_week_low: "j6",
|
28
|
+
last_trade_realtime_withtime: "k1", change_percent_realtime: "k2",
|
29
|
+
last_trade_size: "k3", change_from_52_week_high: "k4",
|
30
|
+
percent_change_from_52_week_high: "k5", last_trade_with_time: "l",
|
31
|
+
last_trade_price: "l1", close: "l1", high_limit: "l2", low_limit: "l3",
|
32
|
+
days_range: "m", days_range_realtime: "m2", moving_average_50_day: "m3",
|
33
|
+
moving_average_200_day: "m4", change_from_200_day_moving_average: "m5",
|
34
|
+
percent_change_from_200_day_moving_average: "m6",
|
35
|
+
change_from_50_day_moving_average: "m7",
|
36
|
+
percent_change_from_50_day_moving_average: "m8", name: "n", notes: "n4",
|
37
|
+
open: "o", previous_close: "p", price_paid: "p1", change_in_percent: "p2",
|
38
|
+
price_per_sales: "p5", price_per_book: "p6", ex_dividend_date: "q",
|
39
|
+
pe_ratio: "r", dividend_pay_date: "r1", pe_ratio_realtime: "r2",
|
40
|
+
peg_ratio: "r5", price_eps_estimate_current_year: "r6",
|
41
|
+
price_eps_Estimate_next_year: "r7", symbol: "s", shares_owned: "s1",
|
42
|
+
short_ratio: "s7", last_trade_time: "t1", trade_links: "t6",
|
43
|
+
ticker_trend: "t7", one_year_target_price: "t8", volume: "v",
|
44
|
+
holdings_value: "v1", holdings_value_realtime: "v7", weeks_range_52: "w",
|
45
|
+
day_value_change: "w1", day_value_change_realtime: "w4",
|
46
|
+
stock_exchange: "x", dividend_yield: "y", adjusted_close: nil
|
47
|
+
# only in historical quotes ^
|
48
|
+
}
|
49
|
+
|
50
|
+
HISTORICAL_MODES = {
|
51
|
+
daily: "d", weekly: "w", monthly: "m", dividends_only: "v"
|
52
|
+
}
|
53
|
+
|
54
|
+
SYMBOLS_PER_REQUEST = 50
|
55
|
+
|
56
|
+
# retrieve the quote data (an OpenStruct per quote)
|
57
|
+
# the options param can be used to specify the following attributes:
|
58
|
+
# :raw - if true, each column will be converted (to numbers, dates, etc)
|
59
|
+
def quotes(symbols_array, columns_array = [
|
60
|
+
:symbol, :last_trade_price, :last_trade_date,
|
61
|
+
:change, :previous_close], options = {})
|
62
|
+
|
63
|
+
options[:raw] ||= true
|
64
|
+
ret = []
|
65
|
+
symbols_array.each_slice(SYMBOLS_PER_REQUEST) do |symbols|
|
66
|
+
read_quotes(symbols.join("+"), columns_array).map do |row|
|
67
|
+
ret << OpenStruct.new(row.to_hash)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
ret
|
71
|
+
end
|
72
|
+
|
73
|
+
def quote(symbol, columns_array = [
|
74
|
+
:symbol, :last_trade_price, :last_trade_date,
|
75
|
+
:change, :previous_close], options = {})
|
76
|
+
|
77
|
+
options[:raw] ||= true
|
78
|
+
quotes([symbol], columns_array, options).first
|
79
|
+
end
|
80
|
+
|
81
|
+
def historical_quotes(symbol, options = {})
|
82
|
+
options[:raw] ||= true
|
83
|
+
options[:period] ||= :daily
|
84
|
+
read_historical(symbol, options).map do |row|
|
85
|
+
OpenStruct.new(row.to_hash.merge(symbol: symbol))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def symbols(query)
|
90
|
+
ret = []
|
91
|
+
read_symbols(query).each do |row|
|
92
|
+
ret << OpenStruct.new(row)
|
93
|
+
end
|
94
|
+
ret
|
95
|
+
end
|
96
|
+
|
97
|
+
def splits(symbol, options = {})
|
98
|
+
rows = read_splits(symbol, options).select { |row| row[0] == "SPLIT" }
|
99
|
+
rows.map do |row|
|
100
|
+
type, date, value = row
|
101
|
+
after, before = value.split(":")
|
102
|
+
OpenStruct.new(
|
103
|
+
symbol: symbol, date: Date.strptime(date.strip, "%Y%m%d"),
|
104
|
+
before: before.to_i, after: after.to_i)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def read_quotes(symb_str, cols)
|
111
|
+
columns = "#{cols.map { |col| COLUMNS[col] }.join("")}"
|
112
|
+
conn = open("http://download.finance.yahoo.com/d/quotes.csv?s=#{URI.escape(symb_str)}&f=#{columns}")
|
113
|
+
CSV.parse(conn.read, headers: cols)
|
114
|
+
end
|
115
|
+
|
116
|
+
def read_historical(symbol, options)
|
117
|
+
params = {
|
118
|
+
s: URI.escape(symbol), g: HISTORICAL_MODES[options[:period]],
|
119
|
+
ignore: ".csv" }
|
120
|
+
if options[:start_date]
|
121
|
+
params[:a] = options[:start_date].month-1
|
122
|
+
params[:b] = options[:start_date].day
|
123
|
+
params[:c] = options[:start_date].year
|
124
|
+
end
|
125
|
+
if options[:end_date]
|
126
|
+
params[:d] = options[:end_date].month-1
|
127
|
+
params[:e] = options[:end_date].day
|
128
|
+
params[:f] = options[:end_date].year
|
129
|
+
end
|
130
|
+
|
131
|
+
url = "http://ichart.finance.yahoo.com/table.csv?#{params.map{|k, v| "#{k}=#{v}"}.join("&")}"
|
132
|
+
conn = open(url)
|
133
|
+
cols = if options[:period] == :dividends_only
|
134
|
+
[:dividend_pay_date, :dividend_yield]
|
135
|
+
else
|
136
|
+
[:trade_date, :open, :high, :low,
|
137
|
+
:close, :volume, :adjusted_close]
|
138
|
+
end
|
139
|
+
result = CSV.parse(conn.read, headers: cols)
|
140
|
+
#:first_row, :header_converters => :symbol)
|
141
|
+
result.delete(0) # drop returned header
|
142
|
+
result
|
143
|
+
end
|
144
|
+
|
145
|
+
def read_splits(symbol, options)
|
146
|
+
params = {
|
147
|
+
s: URI.escape(symbol), g: "v" }
|
148
|
+
if options[:start_date]
|
149
|
+
params[:a] = options[:start_date].month-1
|
150
|
+
params[:b] = options[:start_date].day
|
151
|
+
params[:c] = options[:start_date].year
|
152
|
+
end
|
153
|
+
if options[:end_date]
|
154
|
+
params[:d] = options[:end_date].month-1
|
155
|
+
params[:e] = options[:end_date].day
|
156
|
+
params[:f] = options[:end_date].year
|
157
|
+
end
|
158
|
+
|
159
|
+
url = "http://ichart.finance.yahoo.com/x?#{params.map{|k, v| "#{k}=#{v}"}.join("&")}"
|
160
|
+
conn = open(url)
|
161
|
+
CSV.parse(conn.read)
|
162
|
+
end
|
163
|
+
|
164
|
+
def read_symbols(query)
|
165
|
+
conn = open("http://d.yimg.com/autoc.finance.yahoo.com/autoc?query=#{query}&callback=YAHOO.Finance.SymbolSuggest.ssCallback")
|
166
|
+
result = conn.read
|
167
|
+
result.sub!("YAHOO.Finance.SymbolSuggest.ssCallback(", "").chomp!(")")
|
168
|
+
json_result = JSON.parse(result)
|
169
|
+
json_result["ResultSet"]["Result"]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,28 @@
|
|
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
|
+
return symbols unless MARKETS[country][market]
|
21
|
+
CSV.foreach(open(MARKETS[country][market].url)) do |row|
|
22
|
+
next if row.first == "Symbol"
|
23
|
+
symbols.push(row.first.gsub(" ", ""))
|
24
|
+
end
|
25
|
+
symbols
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yahoo-finance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Herval Freire
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: herval@hervalicio.us
|
@@ -21,7 +21,8 @@ files:
|
|
21
21
|
- HISTORY
|
22
22
|
- README.md
|
23
23
|
- lib/yahoo-finance.rb
|
24
|
-
- lib/
|
24
|
+
- lib/yahoo-finance/finance-utils.rb
|
25
|
+
- lib/yahoo-finance/version.rb
|
25
26
|
homepage: http://hervalicio.us/blog
|
26
27
|
licenses: []
|
27
28
|
metadata: {}
|
@@ -41,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
42
|
version: '0'
|
42
43
|
requirements: []
|
43
44
|
rubyforge_project:
|
44
|
-
rubygems_version: 2.
|
45
|
+
rubygems_version: 2.4.8
|
45
46
|
signing_key:
|
46
47
|
specification_version: 4
|
47
48
|
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
|