they-yahoo_stock 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/History.txt +98 -0
  2. data/Manifest.txt +37 -0
  3. data/README.rdoc +151 -0
  4. data/Rakefile +12 -0
  5. data/features/history.feature +23 -0
  6. data/features/quotes.feature +23 -0
  7. data/features/script_symbol.feature +23 -0
  8. data/features/step_definitions/history_steps.rb +44 -0
  9. data/features/step_definitions/quotes_steps.rb +45 -0
  10. data/features/step_definitions/script_symbol_steps.rb +40 -0
  11. data/lib/yahoo_stock.rb +21 -0
  12. data/lib/yahoo_stock/base.rb +37 -0
  13. data/lib/yahoo_stock/history.rb +32 -0
  14. data/lib/yahoo_stock/interface.rb +71 -0
  15. data/lib/yahoo_stock/interface/history.rb +187 -0
  16. data/lib/yahoo_stock/interface/quote.rb +287 -0
  17. data/lib/yahoo_stock/interface/scrip_symbol.rb +74 -0
  18. data/lib/yahoo_stock/quote.rb +158 -0
  19. data/lib/yahoo_stock/result.rb +21 -0
  20. data/lib/yahoo_stock/result/array_format.rb +23 -0
  21. data/lib/yahoo_stock/result/hash_format.rb +37 -0
  22. data/lib/yahoo_stock/result/xml_format.rb +37 -0
  23. data/lib/yahoo_stock/scrip_symbol.rb +61 -0
  24. data/spec/spec_helper.rb +4 -0
  25. data/spec/yahoo_stock/base_spec.rb +48 -0
  26. data/spec/yahoo_stock/history_spec.rb +75 -0
  27. data/spec/yahoo_stock/interface/history_spec.rb +317 -0
  28. data/spec/yahoo_stock/interface/quote_spec.rb +414 -0
  29. data/spec/yahoo_stock/interface/scrip_symbol_spec.rb +120 -0
  30. data/spec/yahoo_stock/interface_spec.rb +112 -0
  31. data/spec/yahoo_stock/quote_spec.rb +258 -0
  32. data/spec/yahoo_stock/result/array_format_spec.rb +14 -0
  33. data/spec/yahoo_stock/result/hash_format_spec.rb +65 -0
  34. data/spec/yahoo_stock/result/xml_format_spec.rb +54 -0
  35. data/spec/yahoo_stock/result_spec.rb +33 -0
  36. data/spec/yahoo_stock/scrip_symbol_spec.rb +46 -0
  37. metadata +114 -0
@@ -0,0 +1,74 @@
1
+ module YahooStock
2
+ # ==DESCRIPTION:
3
+ #
4
+ # Class to generate the right url and interface with yahoo to get Scrip / Stock Symbols
5
+ #
6
+ class Interface::ScripSymbol < Interface
7
+
8
+ class ScripSymbolError < RuntimeError ; end
9
+
10
+ attr_reader :company
11
+ # Scrapes the resulting page and gets data in between two points
12
+ def initialize(company)
13
+ @base_url = BASE_URLS[:scrip_symbol]
14
+ @company = remove_any_space(company)
15
+ @before_element = 'yfi_sym_results'
16
+ @after_element = 'yfi_fp_left_bottom'
17
+ add_observer(self)
18
+ end
19
+
20
+ # Generate full uri with the help of uri method of the superclass
21
+ def uri
22
+ @uri_parameters = {:s => @company}
23
+ super()
24
+ end
25
+
26
+ # Get uri content with the help of get method of the super class
27
+ def get
28
+ uri
29
+ super()
30
+ end
31
+
32
+ def values
33
+ @values ||= get_values
34
+ end
35
+
36
+ def company=(company)
37
+ old_company = @company
38
+ @company = remove_any_space(company)
39
+ old_company != @company ? changed : changed(false)
40
+ notify_observers
41
+ end
42
+
43
+ private
44
+
45
+ def remove_any_space(words)
46
+ words.gsub(/\s/,'+')
47
+ end
48
+ # returns only the text among two points
49
+ def text_range
50
+ body = get.gsub!(/\s*/,'')
51
+ pattern = /#{@before_element}.*#{@after_element}/
52
+ results = pattern.match(body)
53
+ return results[0] if results
54
+ end
55
+
56
+ # Returns all possible values in a single string
57
+ def get_values
58
+ data = []
59
+ rows = text_range.to_s.split(/\<\/tr>/)
60
+ rows.each_with_index do |row, row_i|
61
+ cells = row.split(/\<\/td>/)
62
+ row_data = []
63
+ cells.each_with_index do |cell, cell_i|
64
+ datum = cell.sub('</a>','').gsub(/\<.*\>/,'').strip
65
+ row_data << datum if !datum.nil? || datum.empty?
66
+ end
67
+ data << row_data.join(',') if row_data.length > 1
68
+ end
69
+ data.join("\r\n")
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,158 @@
1
+ module YahooStock
2
+ # == DESCRIPTION:
3
+ #
4
+ # Provides the stock related current data.
5
+ #
6
+ # Uses YahooStock::Interface to connect to yahoo and get relevant data.
7
+ #
8
+ # == USAGE:
9
+ #
10
+ # * Initialize quote object
11
+ #
12
+ # quote = YahooStock::Quote.new(:stock_symbols => ['YHOO', 'GOOG'],
13
+ # :read_parameters => [:last_trade_price_only, :last_trade_date])
14
+ #
15
+ # If read_parameters are not provided then by default the above two parameters are used.
16
+ #
17
+ # * To get data for all stocks
18
+ #
19
+ # quote.get
20
+ #
21
+ # * To get data with real time values
22
+ #
23
+ # quote.realtime
24
+ #
25
+ # * To get data with standard values
26
+ #
27
+ # quote.standard
28
+ #
29
+ # * To get data with extra parameter values
30
+ #
31
+ # quote.extended
32
+ #
33
+ # * To view the valid parameters that can be passed
34
+ #
35
+ # quote.valid_parameters
36
+ #
37
+ # * To view the current parameters used
38
+ #
39
+ # quote.current_parameters
40
+ #
41
+ # * To view the current stock symbols used
42
+ #
43
+ # quote.current_symbols
44
+ #
45
+ # * To add more stocks to the list
46
+ #
47
+ # quote.add_symbols('MSFT', 'AAPL')
48
+ #
49
+ # * To remove stocks from list
50
+ #
51
+ # quote.remove_symbols('MSFT', 'AAPL')
52
+ #
53
+ class Quote < Base
54
+ class QuoteException < RuntimeError; end
55
+
56
+ # The options parameter expects a hash with two key value pairs
57
+ #
58
+ # :stock_symbols => 'Array of stock symbols' or a single symbol
59
+ #
60
+ # e.g. :stock_symbols => ['MSFT','YHOO'] or :stock_symbols => 'YHOO'
61
+ #
62
+ # another hash :read_parameters => 'array of values'
63
+ #
64
+ # e.g. :read_parameters => [:last_trade_price_only, :last_trade_date]
65
+ def initialize(options)
66
+ if options.nil? || !options.is_a?(Hash)
67
+ raise QuoteException, "You must provide a hash of stock symbols to fetch data"
68
+ end
69
+ if options[:stock_symbols].nil? || options[:stock_symbols].empty?
70
+ raise QuoteException, "You must provide atleast one stock symbol to fetch data"
71
+ end
72
+ if !(options[:read_parameters] && options[:read_parameters].any?)
73
+ options[:read_parameters] = [:last_trade_price_only, :last_trade_date]
74
+ end
75
+ options[:stock_symbols] = Array.new << options[:stock_symbols] unless options[:stock_symbols].is_a?(Array)
76
+ @interface = YahooStock::Interface::Quote.new(options)
77
+ end
78
+
79
+ # Create methods:
80
+ # def realtime
81
+ # - To get realtime stock values
82
+ # def extended
83
+ # - To get values for extra parameters
84
+ # def standard
85
+ # - To get standard values for stocks
86
+ %w{realtime extended standard}.each do |quote_type|
87
+ self.send(:define_method, "#{quote_type}".to_sym) do
88
+ @interface.send("add_#{quote_type}_params".to_sym)
89
+ return self
90
+ end
91
+ end
92
+
93
+ # Adds more stock symbols to the existing instance.
94
+ # One or more stock symbols can be passed as parameter.
95
+ def add_symbols(*symbols)
96
+ @interface.add_symbols(*symbols)
97
+ end
98
+
99
+ # Removes stock symbols from the existing instance.
100
+ # One of more stock symbols can be passed to remove.
101
+ def remove_symbols(*symbols)
102
+ @interface.remove_symbols(*symbols)
103
+ end
104
+
105
+ # Clear all existing stock symbols from the current instance.
106
+ def clear_symbols
107
+ @interface.clear_symbols
108
+ end
109
+
110
+ # Show all stock symbols in the current instance that will be used to get results.
111
+ def current_symbols
112
+ @interface.stock_symbols
113
+ end
114
+
115
+ # Adds more parameters for the stock symbols to the existing instance for getting data.
116
+ # One or more parameters can be passed as argument.
117
+ def add_parameters(*parameters)
118
+ @interface.add_parameters(*parameters)
119
+ end
120
+
121
+ # Removes parameters for the stock symbols to get values for from the existing instance.
122
+ # One of more parameters can be passed to remove.
123
+ def remove_parameters(*parameters)
124
+ @interface.remove_parameters(*parameters)
125
+ end
126
+
127
+ # Shows all parameters in the current instance that will be used to get results.
128
+ def current_parameters
129
+ @interface.yahoo_url_parameters
130
+ end
131
+
132
+ alias :data_attributes :current_parameters
133
+
134
+ # Set current instance to use all parameters to fetch values for current symbols.
135
+ def use_all_parameters
136
+ params = valid_parameters.each {|parameter| add_parameters(parameter)}
137
+ sort_symbols(params)
138
+ end
139
+
140
+ # Clear all existing parameters from the current instance.
141
+ def clear_parameters
142
+ @interface.clear_parameters
143
+ current_parameters
144
+ end
145
+
146
+ # Returns an array of all allowed parameters that can be used.
147
+ def valid_parameters
148
+ sort_symbols(@interface.allowed_parameters)
149
+ end
150
+
151
+ private
152
+
153
+ def sort_symbols(array_of_symbols)
154
+ array_of_symbols.map(&:id2name).sort.map(&:to_sym)
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,21 @@
1
+ module YahooStock
2
+ class Result
3
+
4
+ def initialize(context)
5
+ @context = context
6
+ end
7
+
8
+ def output
9
+ return @context if @context.is_a?(String)
10
+ @context.output
11
+ end
12
+
13
+ def store(filename)
14
+ File.open(filename, 'a') do |f|
15
+ f.write(output)
16
+ f.write("\n")
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module YahooStock
2
+
3
+ # == DESCRIPTION:
4
+ # Parse results to show in an array form
5
+ #
6
+ # == USAGE
7
+ # YahooStock::Result::ArrayFormat.new("data as commma separated values").output
8
+ #
9
+ # Mostly will be used as a separate strategy for formatting results
10
+ class Result::ArrayFormat < Result
11
+
12
+ def initialize(data)
13
+ @data = data
14
+ super(self)
15
+ end
16
+
17
+ def output
18
+ CSV.parse @data
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,37 @@
1
+ module YahooStock
2
+ # == DESCRIPTION:
3
+ # Convert results as an array of key value pairs
4
+ #
5
+ # == USAGE
6
+ # YahooStock::Result::HashFormat.new("data as string"){['array', 'of', 'keys']}.output
7
+ # The number of keys in the block array must be equal to the values expected to be returned
8
+ #
9
+ # Mostly will be used as a separate strategy for formatting results
10
+ class Result::HashFormat < Result
11
+
12
+ def initialize(data, &block)
13
+ @data = YahooStock::Result::ArrayFormat.new(data).output
14
+ @keys = yield
15
+ super(self)
16
+ end
17
+
18
+ def output
19
+ data = []
20
+ @data.each do |datum|
21
+ row_values = {}
22
+ datum.each_with_index do |item, i|
23
+ row_values[keys[i]] = item
24
+ end
25
+ data << row_values
26
+ end
27
+ data
28
+ end
29
+
30
+ def keys
31
+ @keys.collect{|key| key.to_s.gsub(/\s/,'_').downcase.to_sym}
32
+ end
33
+
34
+ end
35
+
36
+
37
+ end
@@ -0,0 +1,37 @@
1
+ require 'rubygems'
2
+ require 'builder'
3
+
4
+ module YahooStock
5
+ # == DESCRIPTION:
6
+ # Convert results to xml
7
+ #
8
+ # == USAGE
9
+ # YahooStock::Result::XmlFormat.new("data as string"){[:keys => :values]}.output
10
+ #
11
+ # Mostly will be used as a separate strategy for formatting results to xml
12
+
13
+ class Result::XmlFormat < Result
14
+ def initialize(data, &block)
15
+ @hash_format = YahooStock::Result::HashFormat.new(data){yield}
16
+ @data = @hash_format.output
17
+ super(self)
18
+ end
19
+
20
+ def output
21
+ builder = Builder::XmlMarkup.new(:indent=>2)
22
+ builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
23
+ builder.items do |items|
24
+ @data.each do |data|
25
+ builder.item do |b|
26
+ data.each_pair do |key, value|
27
+ next if key.nil?
28
+ eval("b.#{key}(value)")
29
+ end
30
+ end
31
+ end
32
+ end
33
+ builder
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,61 @@
1
+ module YahooStock
2
+ # == DESCRIPTION:
3
+ #
4
+ # This class provides the ability to find out the stock /scrip symbols for a company used in stock exchanges.
5
+ #
6
+ # It uses Yahoo http://finance.yahoo.com/lookup page to find, screen scrape / parse the returned results.
7
+ #
8
+ # == USAGE:
9
+ #
10
+ # * If you want to use the symbols in your existing code then:
11
+ #
12
+ # symbol = YahooStock::ScripSymbol.new('company name')
13
+ #
14
+ # symbol.find #will return a string
15
+ #
16
+ # symbol.results :to_array, #will return an array of values instead of a string
17
+ #
18
+ # will give you an array of arrays where each outer array is the different option for the company name
19
+ # you provided and the inner array includes stock symbol, full company name, stock price, exchange symbol
20
+ # so that you can decide easily what symbol you can use.
21
+ #
22
+ # * If you just want to print the results on your console screen
23
+ #
24
+ # YahooStock::ScripSymbol.print_options('company name')
25
+ #
26
+ # * If you just want to store the results in file to use it later
27
+ #
28
+ # You can pass in any number of companies in the parameter
29
+ #
30
+ # YahooStock::ScripSymbol.save_options_to_file('path/to/filename','company1', 'company2')
31
+ #
32
+ class ScripSymbol < Base
33
+ # Initialize with the name of the company as parameter for which stock symbol is needed
34
+ #
35
+ # symbol = YahooStock::ScripSymbol.new('company name')
36
+ #
37
+ # symbol.find
38
+
39
+ attr_reader :company
40
+
41
+ def initialize(company_name)
42
+ @company = company_name
43
+ @interface = YahooStock::Interface::ScripSymbol.new(@company)
44
+ end
45
+
46
+ def company=(company)
47
+ @company = @interface.company = company
48
+ end
49
+
50
+ def data_attributes
51
+ ['Symbol', 'Name', 'Last Trade', 'Type', 'Industry Category', 'Exchange']
52
+ end
53
+
54
+ # get stock symbols for multilple companies
55
+ def self.results(*companies)
56
+ res = companies.inject('') { |options, company| options + new(company).results.output + "\n" }
57
+ YahooStock::Result.new(res)
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,4 @@
1
+ $: << File.join(File.dirname(__FILE__), "/../lib")
2
+
3
+ require 'rspec'
4
+ require 'yahoo_stock'
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe YahooStock::Base do
4
+ before(:each) do
5
+ @interface = stub!('Base')
6
+ @base = YahooStock::Base.new(@interface)
7
+ end
8
+
9
+ describe "find" do
10
+
11
+ it "should get the values from interface" do
12
+ @interface.should_receive(:values)
13
+ @base.find
14
+ end
15
+ end
16
+
17
+ describe "results" do
18
+
19
+ it "should return the results using find" do
20
+ @base.should_receive(:find)
21
+ @base.results
22
+ end
23
+
24
+ it "should yield the block if a block is given" do
25
+ @base.results {"Block to pass, probably, a class with result output method"
26
+ }.should eql('Block to pass, probably, a class with result output method')
27
+ end
28
+
29
+ it "should use the ArrayFormat class for results when :to_array is passed to the results param" do
30
+ @base.stub!(:find)
31
+ YahooStock::Result::ArrayFormat.should_receive(:new)
32
+ @base.results(:to_array)
33
+ end
34
+
35
+ it "should create the YahooStock::Result object when no formatting option is provided" do
36
+ find = stub('find')
37
+ @base.stub!(:find).and_return(find)
38
+ YahooStock::Result.should_receive(:new).with(find)
39
+ @base.results
40
+ end
41
+
42
+ end
43
+ describe "data_attributes" do
44
+ it "should raise an error if the data_attributes is called as this is an abstract method" do
45
+ lambda { @base.data_attributes }.should raise_error(RuntimeError, 'Abstract method called. Use the subclass data_attributes method')
46
+ end
47
+ end
48
+ end