market_beat 0.1.1 → 0.2.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.
data/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ 0.2.0
2
+ - Added support for fetching historical stock quotes.
3
+
1
4
  0.1.1
2
5
  - Include YAML files when building the gem.
3
6
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- market_beat (0.1.0)
4
+ market_beat (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 Michael Dvorkin
1
+ Copyright (c) 2011-12 Michael Dvorkin
2
2
  twitter.com/mid
3
3
  %w(mike dvorkin.net) * "@" || %w(mike fatfreecrm.com) * "@"
4
4
 
data/README.md CHANGED
@@ -31,6 +31,15 @@ Some methods return multiple values:
31
31
  >> MarketBeat.last_trade_with_time :IBM
32
32
  ["4:02pm", "181.47"]
33
33
 
34
+ Fetching historical quotes returns array of hashes where each hash represents
35
+ stock data for a given date:
36
+
37
+ >> MarketBeat.quotes(:AAPL, "2011-12-21", "2011-12-22")
38
+ [{:date=>#<Date: 2011-12-22 (4911835/2,0,2299161)>, :open=>"397.00",
39
+ :high=>"399.13", :low=>"396.10", :close=>"398.55", :volume=>"7227016"},
40
+ {:date=>#<Date: 2011-12-21 (4911833/2,0,2299161)>, :open=>"396.69",
41
+ :high=>"397.30", :low=>"392.01", :close=>"396.44", :volume=>"9390954"}]
42
+
34
43
  ### Available Methods (Real Time Data) ###
35
44
 
36
45
  MarketBeat.after_hours_change_real_time
@@ -133,6 +142,7 @@ Some methods return multiple values:
133
142
  MarketBeat.price_to_eps_estimate_current_year
134
143
  MarketBeat.price_to_eps_estimate_next_year
135
144
  MarketBeat.price_to_sales
145
+ MarketBeat.quotes
136
146
  MarketBeat.range_52_week
137
147
  MarketBeat.shares_owned
138
148
  MarketBeat.short_ratio
@@ -164,7 +174,7 @@ Some methods return multiple values:
164
174
  * Send me a pull request.
165
175
 
166
176
  ### License ###
167
- Copyright (c) 2011 Michael Dvorkin
177
+ Copyright (c) 2011-12 Michael Dvorkin
168
178
 
169
179
  twitter.com/mid
170
180
 
@@ -1,31 +1,42 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
5
  #------------------------------------------------------------------------------
6
6
  require File.dirname(__FILE__) + '/market_beat/yahoo'
7
7
  require File.dirname(__FILE__) + '/market_beat/google'
8
+ require File.dirname(__FILE__) + '/market_beat/historical'
8
9
  require File.dirname(__FILE__) + "/market_beat/version"
9
10
 
10
11
  module MarketBeat
11
12
  # Pre-cache available methods so we could use them within
12
13
  # method_missing where respond_to? gives false positives.
14
+ @@methods = { :historical => [ :quotes ] }
13
15
  if RUBY_VERSION < '1.9.0'
14
- @@yahoo = (Yahoo.methods - Object.methods).map { |m| m.to_sym }
15
- @@google = (Google.methods - Object.methods).map { |m| m.to_sym }
16
+ @@methods[:yahoo] = (Yahoo.methods - Object.methods).map { |m| m.to_sym }
17
+ @@methods[:google] = (Google.methods - Object.methods).map { |m| m.to_sym }
16
18
  else
17
- @@yahoo = Yahoo.methods - Object.methods
18
- @@google = Google.methods - Object.methods
19
+ @@methods[:yahoo] = Yahoo.methods - Object.methods
20
+ @@methods[:google] = Google.methods - Object.methods
19
21
  end
20
22
 
21
23
  # Proxy MarketBeat methods to either Google or Yahoo providers.
22
24
  def self.method_missing(method, *args, &blk)
23
- if @@google.include?(method)
25
+ if @@methods[:google].include?(method)
24
26
  Google.send(method, *args)
25
- elsif @@yahoo.include?(method)
27
+ elsif @@methods[:yahoo].include?(method)
26
28
  Yahoo.send(method, *args)
29
+ elsif @@methods[:historical].include?(method)
30
+ Historical.send(method, *args)
27
31
  else
28
32
  super
29
33
  end
30
34
  end
35
+
36
+ if RUBY_VERSION > '1.9'
37
+ # Make MarketBeat.respond_to? return true for all the methods above.
38
+ def self.respond_to_missing?(method, include_private)
39
+ super(method, include_private) || @@methods.values.flatten.include?(method)
40
+ end
41
+ end
31
42
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
+ #
3
+ # Market Beat is freely distributable under the terms of MIT license.
4
+ # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
+ #------------------------------------------------------------------------------
6
+ require "csv"
7
+ require "date"
8
+
9
+ module MarketBeat
10
+ class Historical
11
+ URL = "http://www.google.com/finance/historical?q=%s&startdate=%s&enddate=%s&output=csv"
12
+
13
+ class << self
14
+ private
15
+ #
16
+ # Fetch historical quotes. Return nil on error or an array of hashes
17
+ # representing stock data. Empty array means no data is available.
18
+ # Start and end date parameters should be either YYYY-MM-DD strings
19
+ # or Date objects.
20
+ #
21
+ def quotes(ticker, start_date, end_date = Date.today)
22
+ csv = fetch(ticker, start_date, end_date)
23
+ return nil unless csv
24
+
25
+ quotes = CSV.parse(csv) # Parse comma-delimited data.
26
+ quotes[1..-1].map do |col| # Skip header line.
27
+ #
28
+ # I guess Google finance folks are tight on data so they return year
29
+ # as two digits, ex: 23-Dec-11 or Apr-26-99. With the tweak below we
30
+ # should be good till year 2042 ;-)
31
+ #
32
+ date = *col[0].split("-")
33
+ date[2] = ((date[2] <= "42" ? "20" : "19") + date[2]) if date[2].size == 2
34
+ { :date => Date.parse(date.join("-")),
35
+ :open => col[1],
36
+ :high => col[2],
37
+ :low => col[3],
38
+ :close => col[4],
39
+ :volume => col[5]
40
+ }
41
+ end
42
+ end
43
+ #
44
+ # Format the URL and fetch stock data.
45
+ #
46
+ def fetch(ticker, start_date, end_date)
47
+ uri = URI.parse(URL % [ ticker, start_date.to_s, end_date.to_s ])
48
+ response = Net::HTTP.get_response(uri)
49
+ response.body
50
+ rescue Exception => e
51
+ $stderr.puts "market_beat: error fetching quotes\n#{e.inspect}"
52
+ nil
53
+ end
54
+ end
55
+ end
56
+ end
@@ -1,10 +1,10 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
5
  #------------------------------------------------------------------------------
6
6
  module MarketBeat
7
7
  def self.version
8
- '0.1.1'
8
+ '0.2.0'
9
9
  end
10
10
  end
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -0,0 +1,65 @@
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
+ #
3
+ # Market Beat is freely distributable under the terms of MIT license.
4
+ # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
5
+ #------------------------------------------------------------------------------
6
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
7
+ require "stringio"
8
+ require "date"
9
+
10
+ describe "MarketBeat::Historical" do
11
+ before(:all) do
12
+ @csv = File.read(File.dirname(__FILE__) + '/fixtures/AAPL.csv')
13
+ end
14
+
15
+ it "should return correct data when using strings as start/end dates" do
16
+ response = mock(:body => @csv)
17
+ Net::HTTP.should_receive(:get_response).once.and_return(response)
18
+ quotes = MarketBeat.quotes(:aapl, "2011-12-21", "2011-12-23")
19
+ quotes.size.should == 3
20
+ quotes[0].keys.map(&:to_s).sort.should == %w(close date high low open volume)
21
+ quotes[0][:open].should == "403.43"
22
+ quotes[0][:high].should == "403.43"
23
+ quotes[0][:low].should == "403.43"
24
+ quotes[0][:close].should == "403.43"
25
+ quotes[0][:volume].should == "0"
26
+ quotes[0][:date].to_s.should == "2011-12-23"
27
+ quotes[1][:date].to_s.should == "2011-12-22"
28
+ quotes[2][:date].to_s.should == "2011-12-21"
29
+ end
30
+
31
+ it "should return correct data when using Date as start/end dates" do
32
+ response = mock(:body => @csv)
33
+ Net::HTTP.should_receive(:get_response).once.and_return(response)
34
+ quotes = MarketBeat.quotes(:aapl, Date.parse("2011-12-21"), Date.parse("2011-12-23"))
35
+ quotes.size.should == 3
36
+ quotes[2].keys.map(&:to_s).sort.should == %w(close date high low open volume)
37
+ quotes[2][:open].should == "396.69"
38
+ quotes[2][:high].should == "397.30"
39
+ quotes[2][:low].should == "392.01"
40
+ quotes[2][:close].should == "396.44"
41
+ quotes[2][:volume].should == "9390954"
42
+ quotes[2][:date].to_s.should == "2011-12-21"
43
+ quotes[1][:date].to_s.should == "2011-12-22"
44
+ quotes[0][:date].to_s.should == "2011-12-23"
45
+ end
46
+
47
+ it "should return empty array when no data is available" do
48
+ response = mock(:body => @csv.split.first) # Just the header row.
49
+ Net::HTTP.should_receive(:get_response).once.and_return(response)
50
+ MarketBeat.quotes(:aapl, "2011-12-21", "2011-12-23").should == []
51
+ end
52
+
53
+ it "should return nil on error" do
54
+ begin
55
+ stderr, $stderr = $stderr, StringIO.new
56
+ response = mock(:body => "")
57
+ Net::HTTP.should_receive(:get_response).once.and_raise(SocketError)
58
+ MarketBeat.quotes(:aapl, "2011-12-21", "2011-12-23").should == nil
59
+ $stderr.string.should =~ /^market_beat: error fetching quotes/m
60
+ ensure
61
+ $stderr = stderr
62
+ end
63
+ end
64
+ end
65
+
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -9,6 +9,12 @@ require 'yaml'
9
9
  describe "MarketBeat Google Proxy" do
10
10
  metrics = YAML.load_file(File.dirname(__FILE__) + '/../lib/market_beat/google.yml')
11
11
  metrics.values.each do |method|
12
+ if RUBY_VERSION > '1.9'
13
+ it "MarketBeat should respond to :#{method}" do
14
+ MarketBeat.respond_to?(method).should == true
15
+ end
16
+ end
17
+
12
18
  it "Google.#{method}" do
13
19
  MarketBeat::Google.should_receive(method).once
14
20
  MarketBeat::Yahoo.should_not_receive(method)
@@ -21,6 +27,12 @@ describe "MarketBeat Yahoo Proxy" do
21
27
  yahoo_metrics = YAML.load_file(File.dirname(__FILE__) + '/../lib/market_beat/yahoo.yml')
22
28
  google_metrics = YAML.load_file(File.dirname(__FILE__) + '/../lib/market_beat/google.yml')
23
29
  yahoo_metrics.values.each do |method|
30
+ if RUBY_VERSION > '1.9'
31
+ it "MarketBeat should respond to :#{method}" do
32
+ MarketBeat.respond_to?(method).should == true
33
+ end
34
+ end
35
+
24
36
  it "Yahoo.#{method}" do # If Yahoo and Google have the same method Google takes precedence.
25
37
  if google_metrics.values.include?(method)
26
38
  MarketBeat::Google.should_receive(method).once
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
@@ -1,4 +1,4 @@
1
- # Copyright (c) 2011 Michael Dvorkin
1
+ # Copyright (c) 2011-12 Michael Dvorkin
2
2
  #
3
3
  # Market Beat is freely distributable under the terms of MIT license.
4
4
  # See LICENSE file or http://www.opensource.org/licenses/mit-license.php
metadata CHANGED
@@ -1,34 +1,37 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: market_beat
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.1
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.2.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Michael Dvorkin
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-21 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2012-01-15 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
15
16
  name: rspec
16
- requirement: &70119385118060 !ruby/object:Gem::Requirement
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
17
19
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
21
23
  version: 2.6.0
22
24
  type: :development
23
- prerelease: false
24
- version_requirements: *70119385118060
25
- description: Fetch real-time and delayed stock quotes and 100+ other financial and
26
- market indicaors from publicly available sources.
25
+ version_requirements: *id001
26
+ description: Fetch real-time and delayed stock quotes and 100+ other financial and market indicaors from publicly available sources.
27
27
  email: mike@dvorkin.net
28
28
  executables: []
29
+
29
30
  extensions: []
31
+
30
32
  extra_rdoc_files: []
31
- files:
33
+
34
+ files:
32
35
  - CHANGELOG
33
36
  - Gemfile
34
37
  - Gemfile.lock
@@ -36,42 +39,48 @@ files:
36
39
  - Rakefile
37
40
  - README.md
38
41
  - lib/market_beat/google.rb
42
+ - lib/market_beat/historical.rb
39
43
  - lib/market_beat/version.rb
40
44
  - lib/market_beat/yahoo.rb
41
45
  - lib/market_beat.rb
42
46
  - lib/market_beat/google.yml
43
47
  - lib/market_beat/yahoo.yml
44
48
  - spec/google_spec.rb
49
+ - spec/historical_spec.rb
45
50
  - spec/market_beat_spec.rb
46
51
  - spec/spec_helper.rb
47
52
  - spec/yahoo_spec.rb
48
53
  - .gitignore
49
54
  homepage: http://github.com/michaeldv/market_beat
50
55
  licenses: []
56
+
51
57
  post_install_message:
52
58
  rdoc_options: []
53
- require_paths:
59
+
60
+ require_paths:
54
61
  - lib
55
- required_ruby_version: !ruby/object:Gem::Requirement
62
+ required_ruby_version: !ruby/object:Gem::Requirement
56
63
  none: false
57
- requirements:
58
- - - ! '>='
59
- - !ruby/object:Gem::Version
60
- version: '0'
61
- required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
69
  none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
67
74
  requirements: []
75
+
68
76
  rubyforge_project: market_beat
69
- rubygems_version: 1.8.11
77
+ rubygems_version: 1.8.5
70
78
  signing_key:
71
79
  specification_version: 3
72
80
  summary: Fetch up-to-date stock quotes and 100+ financial and market indicators.
73
- test_files:
81
+ test_files:
74
82
  - spec/google_spec.rb
83
+ - spec/historical_spec.rb
75
84
  - spec/market_beat_spec.rb
76
85
  - spec/spec_helper.rb
77
86
  - spec/yahoo_spec.rb