nas-yahoo_stock 0.1.6 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -32,3 +32,8 @@
32
32
  * 1 addition:
33
33
  * adds convenience methods Quote#realtime, standard and extended to
34
34
  fetch relevant stock values
35
+
36
+ === 1.0.1 2009-09-10
37
+
38
+ * 1 addition:
39
+ * adds feature to retreive historical stock data
data/Manifest.txt CHANGED
@@ -6,6 +6,8 @@ lib/yahoo_stock.rb
6
6
  lib/yahoo_stock/quote.rb
7
7
  lib/yahoo_stock/interface.rb
8
8
  lib/yahoo_stock/scrip_symbol.rb
9
+ lib/yahoo_stock/history.rb
9
10
  spec/spec_helper.rb
10
11
  spec/yahoo_stock/quote_spec.rb
11
12
  spec/yahoo_stock/scrip_symbol_spec.rb
13
+ spec/yahoo_stock/history_spec.rb
@@ -0,0 +1,186 @@
1
+ =begin
2
+
3
+ base url = http://ichart.finance.yahoo.com/table.csv
4
+
5
+ params:
6
+ s=stock symbol
7
+ a=month-1
8
+ b=date
9
+ c=year
10
+ d=month-1
11
+ e=date
12
+ f=year
13
+ g=d or w or m
14
+ ignore=.csv
15
+
16
+ =end
17
+ require 'net/http'
18
+ module YahooStock
19
+ class History
20
+
21
+ class HistoryError < RuntimeError; end
22
+
23
+ attr_reader :stock_symbol, :start_date, :end_date, :interval
24
+
25
+ def initialize(options)
26
+ unless options.is_a?(Hash)
27
+ raise HistoryError, 'A hash of start_date, end_date and stock_symbol is expected as parameters'
28
+ end
29
+ validate_keys(options)
30
+
31
+ @stock_symbol = options[:stock_symbol]
32
+ @start_date = options[:start_date]
33
+ @end_date = options[:end_date]
34
+ @interval = options[:interval].nil? ? :daily : options[:interval].to_sym
35
+
36
+ validate_interval_values(options[:interval]) if options[:interval]
37
+ validate_stock_symbol(options)
38
+ validate_start_date(options)
39
+ validate_end_date(options)
40
+ validate_history_range
41
+ @base_url = "http://ichart.finance.yahoo.com/table.csv"
42
+ end
43
+
44
+ def stock_symbol=(stock_symbol)
45
+ validate_stock_symbol_attribute(stock_symbol)
46
+ @stock_symbol = stock_symbol
47
+ end
48
+
49
+ def start_date=(start_date)
50
+ validate_start_date_type(start_date)
51
+ validate_history_range(start_date)
52
+ @start_date = start_date
53
+ end
54
+
55
+ def end_date=(end_date)
56
+ validate_end_date_type(end_date)
57
+ validate_history_range(start_date, end_date)
58
+ @end_date = end_date
59
+ end
60
+
61
+ def interval=(interval)
62
+ validate_interval_values(interval)
63
+ @interval = interval
64
+ end
65
+
66
+ def send_request
67
+ if stock_symbol.nil? || start_date.nil? || end_date.nil?
68
+ raise HistoryError, 'Cannot send request unless all parameters, ie stock_symbol, start and end date are present'
69
+ end
70
+ if !(start_date.is_a?(Date) || end_date.is_a?(Date))
71
+ raise HistoryError, 'Start and end date should be of type Date'
72
+ end
73
+ response = Net::HTTP.get_response(URI.parse(uri))
74
+ if response.code == '200'
75
+ return response.body
76
+ else
77
+ raise "No historical data found for the stock symbol: #{stock_symbol}"
78
+ end
79
+ end
80
+
81
+ # Return an array of hashes with latest date first
82
+ # Each array element contains a hash of date, volume traded, opening, closing, high and low prices
83
+ def results
84
+ values = send_request.split(/\n/)
85
+ headers, daily_data = values.partition{|h| h==values[0]}
86
+ headings = headers.first.split(',')
87
+ data = []
88
+ daily_data.each do |datum|
89
+ daily_values = {}
90
+ datum.split(',').each_with_index do |item, i|
91
+ daily_values[headings[i]] = item
92
+ end
93
+ data << daily_values
94
+ end
95
+ data
96
+ end
97
+
98
+ private
99
+
100
+ def uri
101
+ frequency = case interval
102
+ when :daily : 'd'
103
+ when :weekly : 'w'
104
+ when :monthly : 'm'
105
+ end
106
+ start_date_param = "a=#{sprintf("%02d", start_date.month-1)}&b=#{start_date.day}&c=#{start_date.year}"
107
+ end_date_param = "d=#{sprintf("%02d", end_date.month-1)}&e=#{end_date.day}&f=#{end_date.year}"
108
+ params="s=#{stock_symbol}&#{start_date_param}&#{end_date_param}&g=#{frequency}&ignore=.csv"
109
+ "#{@base_url}?#{params}"
110
+ end
111
+
112
+ def validate_interval_values(interval_value=interval)
113
+ valid_values = [:daily, :weekly, :monthly]
114
+ unless valid_values.include?(interval_value)
115
+ raise HistoryError, "Allowed values for interval are #{valid_values.join(', ')}"
116
+ end
117
+ end
118
+
119
+ def validate_stock_symbol(options)
120
+ unless options.keys.include?(:stock_symbol)
121
+ raise HistoryError, ':stock_symbol key is not present in the parameter hash'
122
+ end
123
+ validate_stock_symbol_attribute
124
+ end
125
+
126
+ def validate_stock_symbol_attribute(symbol=stock_symbol)
127
+ if symbol.nil? || symbol.empty?
128
+ raise HistoryError, ':stock_symbol value cannot be nil or blank'
129
+ end
130
+ end
131
+
132
+ def validate_start_date(options)
133
+ validate_date_options(:start_date, options)
134
+ validate_start_date_type
135
+ end
136
+
137
+ def validate_end_date(options)
138
+ validate_date_options(:end_date, options)
139
+ validate_end_date_type
140
+ end
141
+
142
+ def validate_history_range(s_date = start_date, e_date = end_date)
143
+ if s_date >= Date.today
144
+ raise HistoryError, "Start date must be in the past"
145
+ end
146
+ if e_date >= Date.today
147
+ raise HistoryError, "End date must be in the past"
148
+ end
149
+ if e_date < s_date
150
+ raise HistoryError, "End date must be greater than the start date"
151
+ end
152
+ end
153
+
154
+ def validate_end_date_type(e_date=end_date)
155
+ unless e_date.is_a?(Date)
156
+ raise HistoryError, "End date must be of type Date"
157
+ end
158
+ end
159
+
160
+ def validate_start_date_type(s_date=start_date)
161
+ unless s_date.is_a?(Date)
162
+ raise HistoryError, "Start date must be of type Date"
163
+ end
164
+ end
165
+
166
+ def validate_date_options(date_type, options)
167
+ unless options.keys.include?(date_type)
168
+ raise HistoryError, ":#{date_type} key is not present in the parameter hash"
169
+ end
170
+
171
+ if options[date_type].nil? || options[date_type].to_s.empty?
172
+ raise HistoryError, ":#{date_type} value cannot be blank"
173
+ end
174
+ end
175
+
176
+ def validate_keys(options)
177
+ valid_keys = [:stock_symbol, :start_date, :end_date, :interval]
178
+ invalid_keys = []
179
+ options.keys.each{|key| invalid_keys << key unless valid_keys.include?(key) }
180
+ unless invalid_keys.length.zero?
181
+ raise HistoryError, "An invalid key '#{invalid_keys.join(',')}' is passed in the parameters. Allowed keys are #{valid_keys.join(', ')}"
182
+ end
183
+ end
184
+
185
+ end
186
+ end
@@ -129,9 +129,9 @@ module YahooStock
129
129
  if !stock_params_hash[:read_parameters] || stock_params_hash[:read_parameters].length.zero?
130
130
  raise InterfaceError, 'Dont know what data to get'
131
131
  end
132
- @stock_symbols = stock_params_hash[:stock_symbols]
133
- @yahoo_url_parameters = stock_params_hash[:read_parameters]
134
- @base_url = "http://download.finance.yahoo.com/d/quotes.csv"
132
+ @stock_symbols = stock_params_hash[:stock_symbols]
133
+ @yahoo_url_parameters = stock_params_hash[:read_parameters]
134
+ @base_url = "http://download.finance.yahoo.com/d/quotes.csv"
135
135
  end
136
136
 
137
137
  # Generate full url to be sent to yahoo
data/lib/yahoo_stock.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
+ require 'date'
4
5
  require 'yahoo_stock/scrip_symbol.rb'
5
6
  require 'yahoo_stock/interface.rb'
6
7
  require 'yahoo_stock/quote.rb'
8
+ require 'yahoo_stock/history.rb'
7
9
 
8
10
  module YahooStock
9
11
  VERSION = '0.1.3'
@@ -0,0 +1,190 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe YahooStock::History do
4
+
5
+ describe ".new" do
6
+
7
+ it "should raise error when no parameter is passed during object initialization" do
8
+ lambda { YahooStock::History.new
9
+ }.should raise_error(ArgumentError)
10
+ end
11
+
12
+ it "should raise error when the parameter is not a hash" do
13
+ lambda { YahooStock::History.new(nil)
14
+ }.should raise_error(YahooStock::History::HistoryError, 'A hash of start_date, end_date and stock_symbol is expected as parameters')
15
+ end
16
+
17
+ it "should raise an error if stock symbol key is not present in parameter hash" do
18
+ lambda { YahooStock::History.new(:start_date => Date.today-7)
19
+ }.should raise_error(YahooStock::History::HistoryError, ':stock_symbol key is not present in the parameter hash')
20
+ end
21
+
22
+ it "should raise error when stock_symbol value in hash is nil" do
23
+ lambda { YahooStock::History.new(:stock_symbol => nil)
24
+ }.should raise_error(YahooStock::History::HistoryError, ':stock_symbol value cannot be nil or blank')
25
+ end
26
+
27
+ it "should raise error when stock_symbol value in hash is blank" do
28
+ lambda { YahooStock::History.new(:stock_symbol => '')
29
+ }.should raise_error(YahooStock::History::HistoryError, ':stock_symbol value cannot be nil or blank')
30
+ end
31
+
32
+ it "should raise error when start date key is not present in parameter hash" do
33
+ lambda { YahooStock::History.new(:stock_symbol => 'd') }.should raise_error(YahooStock::History::HistoryError, ':start_date key is not present in the parameter hash')
34
+ end
35
+
36
+ it "should raise error when start_date value is nil" do
37
+ lambda { YahooStock::History.new(:stock_symbol => 'd', :start_date => nil) }.should raise_error(YahooStock::History::HistoryError, ':start_date value cannot be blank')
38
+ end
39
+
40
+ it "should raise error when start_date value is blank" do
41
+ lambda { YahooStock::History.new(:stock_symbol => 'd', :start_date => '') }.should raise_error(YahooStock::History::HistoryError, ':start_date value cannot be blank')
42
+ end
43
+
44
+ it "should raise error when start date value is not of type date" do
45
+ lambda { YahooStock::History.new(:stock_symbol => 'd', :start_date => '23/3/2009') }.should raise_error(YahooStock::History::HistoryError, 'Start date must be of type Date')
46
+ end
47
+
48
+ it "should raise error when end date key is not present in parameter hash" do
49
+ lambda { YahooStock::History.new(:stock_symbol => 'd', :start_date => Date.today-1) }.should raise_error(YahooStock::History::HistoryError, ':end_date key is not present in the parameter hash')
50
+ end
51
+
52
+ it "should raise error when end_date value is nil" do
53
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
54
+ :start_date => Date.today-1,
55
+ :end_date => nil) }.should raise_error(YahooStock::History::HistoryError, ':end_date value cannot be blank')
56
+ end
57
+
58
+ it "should raise error when end_date value is blank" do
59
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
60
+ :start_date => Date.today-1,
61
+ :end_date => '') }.should raise_error(YahooStock::History::HistoryError, ':end_date value cannot be blank')
62
+ end
63
+
64
+ it "should raise error when end date value is not of type date" do
65
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
66
+ :start_date => Date.today-1,
67
+ :end_date => 'sds') }.should raise_error(YahooStock::History::HistoryError, 'End date must be of type Date')
68
+ end
69
+
70
+ it "should raise error when start date is not less than today" do
71
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
72
+ :start_date => Date.today,
73
+ :end_date => Date.today)
74
+ }.should raise_error(YahooStock::History::HistoryError, 'Start date must be in the past')
75
+ end
76
+
77
+ it "should raise error when start date is greater than end date" do
78
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
79
+ :start_date => Date.today-7,
80
+ :end_date => Date.today-8)
81
+ }.should raise_error(YahooStock::History::HistoryError, 'End date must be greater than the start date')
82
+ end
83
+
84
+ it "should not raise error when start date is in the past, end date is greater than start date and all relevant keys are present with right type" do
85
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
86
+ :start_date => Date.today-7,
87
+ :end_date => Date.today-1)
88
+ }.should_not raise_error
89
+
90
+ end
91
+
92
+ it "should by default set interval to daily if no value provided for it" do
93
+ @history = YahooStock::History.new(:stock_symbol => 'd',
94
+ :start_date => Date.today-7,
95
+ :end_date => Date.today-1)
96
+ @history.interval.should eql(:daily)
97
+ end
98
+
99
+ it "should raise invalid keys error when an invalid key is passed in the parameter" do
100
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
101
+ :start_date => Date.today-7,
102
+ :end_date => Date.today-1, :boom => 1) }.should raise_error(YahooStock::History::HistoryError, "An invalid key 'boom' is passed in the parameters. Allowed keys are stock_symbol, start_date, end_date, interval")
103
+ end
104
+
105
+ it "should raise error when interval is neither :daily, :weekly or :monthly" do
106
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
107
+ :start_date => Date.today-7,
108
+ :end_date => Date.today-1,
109
+ :interval => :yearly)
110
+ }.should raise_error(YahooStock::History::HistoryError, "Allowed values for interval are daily, weekly, monthly")
111
+
112
+ end
113
+
114
+ it "should not raise error when interval is :daily" do
115
+ lambda { YahooStock::History.new(:stock_symbol => 'd',
116
+ :start_date => Date.today-7,
117
+ :end_date => Date.today-1,
118
+ :interval => :daily)
119
+ }.should_not raise_error
120
+
121
+ end
122
+ end
123
+
124
+ describe "setters" do
125
+ before(:each) do
126
+ @history = YahooStock::History.new(:stock_symbol => 'd',
127
+ :start_date => Date.today-7,
128
+ :end_date => Date.today-1)
129
+ end
130
+
131
+ it "should raise error when stock symbol is being set to nil" do
132
+ lambda { @history.stock_symbol = nil
133
+ }.should raise_error(YahooStock::History::HistoryError, ':stock_symbol value cannot be nil or blank')
134
+ end
135
+
136
+ it "should raise error when stock symbol is being set to an empty string" do
137
+ lambda { @history.stock_symbol = ''
138
+ }.should raise_error(YahooStock::History::HistoryError, ':stock_symbol value cannot be nil or blank')
139
+ end
140
+
141
+ it "should set the new stock symbol value when it is valid" do
142
+ @history.stock_symbol = 'new_val'
143
+ @history.stock_symbol.should eql('new_val')
144
+ end
145
+
146
+ it "should raise error when start date type is not a date" do
147
+ lambda { @history.start_date = '21/3/2009'
148
+ }.should raise_error(YahooStock::History::HistoryError, 'Start date must be of type Date')
149
+ end
150
+
151
+ it "should raise error when start date is not in the past" do
152
+ lambda { @history.start_date = Date.today
153
+ }.should raise_error(YahooStock::History::HistoryError, 'Start date must be in the past')
154
+ end
155
+
156
+ it "should set the start date when start date is valid" do
157
+ s_date = Date.today-1
158
+ @history.start_date = s_date
159
+ @history.start_date.should eql(s_date)
160
+ end
161
+
162
+ it "should raise error when end date type is not a date" do
163
+ lambda { @history.end_date = '21/3/2009'
164
+ }.should raise_error(YahooStock::History::HistoryError, 'End date must be of type Date')
165
+ end
166
+
167
+ it "should raise error when end date type is not in the past" do
168
+ lambda { @history.end_date = Date.today
169
+ }.should raise_error(YahooStock::History::HistoryError, 'End date must be in the past')
170
+ end
171
+
172
+ it "should raise error when end date type is not in the past" do
173
+ e_date = Date.today-1
174
+ @history.end_date = e_date
175
+ @history.end_date.should eql(e_date)
176
+ end
177
+
178
+ it "should raise error when settin interval other than :daily, :monthly or :weekly" do
179
+ lambda { @history.interval = :yearly }.should raise_error(YahooStock::History::HistoryError)
180
+ end
181
+
182
+ it "should set the interval" do
183
+ @history.interval = :daily
184
+ @history.interval.should eql(:daily)
185
+ end
186
+
187
+ end
188
+
189
+
190
+ end
@@ -6,7 +6,7 @@ describe YahooStock::Interface do
6
6
  @interface = YahooStock::Interface.new(:stock_symbols => ['MSFT'], :read_parameters => [:last_trade_price_only])
7
7
  end
8
8
 
9
- describe "initialize" do
9
+ describe ".new" do
10
10
 
11
11
  it "should raise InterfaceError when stock params hash is nil" do
12
12
  lambda { YahooStock::Interface.new(nil)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nas-yahoo_stock
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nasir Jamal
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-07 00:00:00 -07:00
12
+ date: 2009-09-10 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -49,12 +49,15 @@ files:
49
49
  - lib/yahoo_stock/quote.rb
50
50
  - lib/yahoo_stock/interface.rb
51
51
  - lib/yahoo_stock/scrip_symbol.rb
52
+ - lib/yahoo_stock/history.rb
52
53
  - spec/spec_helper.rb
53
54
  - spec/yahoo_stock/quote_spec.rb
54
55
  - spec/yahoo_stock/interface_spec.rb
55
56
  - spec/yahoo_stock/scrip_symbol_spec.rb
57
+ - spec/yahoo_stock/history_spec.rb
56
58
  has_rdoc: true
57
59
  homepage: http://github.com/nas/yahoo_stock
60
+ licenses:
58
61
  post_install_message:
59
62
  rdoc_options:
60
63
  - --inline-source
@@ -76,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
79
  requirements: []
77
80
 
78
81
  rubyforge_project:
79
- rubygems_version: 1.2.0
82
+ rubygems_version: 1.3.5
80
83
  signing_key:
81
84
  specification_version: 2
82
85
  summary: Yahoo Stock is a Ruby library for extracting information about stocks from yahoo finance.