y_fi 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8a1743769b54ef3fe88f6e697ed8f6fd13b86197
4
+ data.tar.gz: 15efa974fffa26653de3a8b9173bcd7bfbd94b98
5
+ SHA512:
6
+ metadata.gz: 0d65e50fb52c51bbe8deeea4441489128e56ab30534a756534f2e298d11cb10d38a488ba0d45134950da7588267c1ed8d4d86c98642ba1f839e60c7b96c4ffe7
7
+ data.tar.gz: e3a92ddde289e1c45e77395d3e3ed71c3da4d5d2bebccf1cb0a99b3edf2744fa729ebd7e6675eaadb5220cd841ea2b92ee4303066108556acf6a66253f7b65c7
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Jeff Ramer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # YFi
2
+ This is a Ruby implementation for fetching stock/fund prices from the Yahoo Finance API with YQL: https://developer.yahoo.com/yql/faq/
3
+
4
+ ## Usage
5
+ To get a collection of quotes (Enumerable object):
6
+ ```
7
+ YFi::QuoteCollection.new(['vbtlx', 'vigrx'])
8
+ ```
9
+
10
+ To get an individual quote:
11
+ ```
12
+ quote = YFi::Quote.find('aapl')
13
+ puts quote.price
14
+ puts quote.updated_at
15
+ puts quote.issuer_name
16
+ puts quote.ticker
17
+ ```
18
+
19
+ ## Installation
20
+ ```gem install y_fi```
21
+
22
+ ```ruby
23
+ gem 'y_fi'
24
+ ```
25
+
26
+ And then execute:
27
+ ```bash
28
+ $ bundle
29
+ ```
30
+
31
+ Or install it yourself as:
32
+ ```bash
33
+ $ gem install y_fi
34
+ ```
35
+
36
+ Set up the logger:
37
+ ```
38
+ YFi.configure do |config|
39
+ config.logger = ::Logger.new("#{Rails.root}/log/yahoo_finance.log")
40
+ end
41
+ ```
42
+
43
+ ## Contributing
44
+ Feel free to create a pull request on a feature branch.
45
+
46
+ ## License
47
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'YFi'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+
33
+ task default: :test
data/lib/y_fi/quote.rb ADDED
@@ -0,0 +1,22 @@
1
+ module YFi
2
+ class Quote
3
+ attr_accessor :price,
4
+ :updated_at,
5
+ :issuer_name,
6
+ :ticker
7
+
8
+ def initialize(args)
9
+ args.each do |key, val|
10
+ self.public_send("#{key}=", val)
11
+ end
12
+ self.ticker = self.ticker.to_s.upcase
13
+ end
14
+
15
+ # @param ticker [String]
16
+ # @example Api::ExternalFund.find_by_ticker('AAPL')
17
+ # @return [Api::ExternalFund]
18
+ def self.find_by_ticker(ticker)
19
+ QuoteCollection.new([ticker]).first
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,98 @@
1
+ # Uses YAHOO's API service for fetching fund prices.
2
+ # Example:
3
+ # YFi::QuoteCollection.new(['vbtlx', 'vigrx'])
4
+ # Will call the following URL:
5
+ # http://finance.yahoo.com/webservice/v1/symbols/VBTLX,VIGRX/quote?format=json&view=detail
6
+ require "httparty"
7
+
8
+ module YFi
9
+ class QuoteCollection
10
+ include Enumerable
11
+ include HTTParty
12
+ attr_accessor :tickers, :raw_quotes
13
+
14
+ base_uri 'http://query.yahooapis.com/v1/public/yql'
15
+
16
+ logger begin
17
+ YFi.configuration.logger
18
+ end
19
+ debug_output YFi.configuration.logger
20
+
21
+ # @param [Array<String>] - An array of tickers, such as ['AAPL']
22
+ # @return [YFi::Quote, #to_a, #find, #each] - an array of Api::ExteralFunds
23
+ def initialize(tickers)
24
+ validate_ticker_format(tickers)
25
+ self.tickers = tickers
26
+ self.raw_quotes = self.class.get("", url_query_options)
27
+ end
28
+
29
+ # @return [Array] - an array of YFi::Quote
30
+ def to_a
31
+ response_array.each_with_object([]) do |raw_quote, arr|
32
+ next unless valid_quote?(raw_quote)
33
+ arr << Quote.new(
34
+ ticker: raw_quote.fetch("symbol"),
35
+ price: raw_quote["LastTradePriceOnly"].to_f,
36
+ updated_at: parse_updated_at(raw_quote.fetch("LastTradeDate")),
37
+ issuer_name: raw_quote.fetch("Name")
38
+ )
39
+ end
40
+ end
41
+
42
+ # @return [YFi::Quote]
43
+ def find(ticker)
44
+ to_a.find{|ef| ef.ticker == ticker.to_s.upcase}
45
+ end
46
+
47
+ def each(&block)
48
+ to_a.each(&block)
49
+ end
50
+
51
+ private
52
+ def yql_query_string
53
+ funds = self.tickers.map{|f| "\"#{f}\""}.join(',')
54
+ "select * from yahoo.finance.quotes where symbol in(#{funds})"
55
+ end
56
+
57
+ def response_array
58
+ arr = raw_quotes.fetch("query", {}).fetch("results", {}).fetch("quote", {})
59
+ arr = [arr] unless arr.is_a?(Array)
60
+ arr
61
+ end
62
+
63
+ def parse_updated_at(updated_at)
64
+ Date.strptime(updated_at, '%m/%d/%Y')
65
+ rescue
66
+ YFi.configuration.logger("Unable to parse date: #{updated_at}")
67
+ Date.new(1976,1,1)
68
+ end
69
+
70
+ def validate_ticker_format(tickers)
71
+ unless tickers.is_a?(Array) && tickers.all?{|f| f.is_a?(String)} && tickers.size
72
+ raise(ArgumentError, "Please provide an array of tickers")
73
+ end
74
+ end
75
+
76
+ def url_query_options
77
+ {
78
+ query: {
79
+ format: 'json',
80
+ q: yql_query_string,
81
+ env: "store://datatables.org/alltableswithkeys"
82
+ }
83
+ }
84
+ end
85
+
86
+ def valid_quote?(raw_quote)
87
+ unless raw_quote.is_a?(Hash)
88
+ YFi.configuration.logger.error("Expected a hash but got: #{raw_quote}")
89
+ return false
90
+ end
91
+ unless raw_quote["LastTradePriceOnly"]
92
+ YFi.configuration.logger.error("Unable to fetch a price from #{raw_quote}")
93
+ return false
94
+ end
95
+ true
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,3 @@
1
+ module YFi
2
+ VERSION = '0.1.0'
3
+ end
data/lib/y_fi.rb ADDED
@@ -0,0 +1,30 @@
1
+ require "logger"
2
+
3
+ module YFi
4
+ class Configuration
5
+ attr_accessor :logger
6
+
7
+ def initialize
8
+ @logger ||= Logger.new(STDOUT)
9
+ end
10
+ end
11
+
12
+ class << self
13
+ attr_accessor :configuration
14
+ end
15
+
16
+ def self.configuration
17
+ @configuration ||= Configuration.new
18
+ end
19
+
20
+ def self.reset
21
+ @configuration = Configuration.new
22
+ end
23
+
24
+ def self.configure
25
+ yield(configuration)
26
+ end
27
+ end
28
+
29
+ require 'y_fi/quote.rb'
30
+ require 'y_fi/quote_collection.rb'
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: y_fi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Ramer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-06-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.13'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.5'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: vcr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.1'
69
+ description: https://developer.yahoo.com/yql/faq/
70
+ email:
71
+ - jeffery.ramer@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - MIT-LICENSE
77
+ - README.md
78
+ - Rakefile
79
+ - lib/y_fi.rb
80
+ - lib/y_fi/quote.rb
81
+ - lib/y_fi/quote_collection.rb
82
+ - lib/y_fi/version.rb
83
+ homepage:
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.6.8
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Gem for fetching quotes from the Yahoo Finance API
107
+ test_files: []