edgar-stocks 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NDMzODMwZGU3YTQxNDQ5MzIzZTRkYTg3YTEyNWVjOWViZTI0NGU4NQ==
5
+ data.tar.gz: !binary |-
6
+ MGEwODcyYTBkYjY1MTNkYTM4ZDllODk3NzhiZjBkZWNiNTJiN2ZlMw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZTU5YmMzODE2OWVjZWI3N2YwYTE0ZjRkYWMwNzM5N2NjNzczMDdmOGQ5NzQz
10
+ MGQ4MmRjN2YyNDlkMjI1NmZhZDQzYjViMmY3YjYwYWI0MzM5ODRmMGJlMThl
11
+ NDI3NDIxZDNlODIxNzQyNmUzZDhjN2U4NWE1MDQ2OTVlMjA0Njc=
12
+ data.tar.gz: !binary |-
13
+ MDIxNDk0MjU3YjIzOGJlZGVkNTg0ZDQzYzI4OWNmNjUzOWUxYTI2NmM1YWRm
14
+ MDZkZjFmOWVhN2JhM2RlMzhjZTdiMWRmZmNjMDQ5NGQ3YTQwNmIxZWNmMTVh
15
+ NTM5ZDAwYjBiNTYzZDUxMjM1YWY1YTY3ZGM1NTBlNmZjYWYzNDA=
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .idea/
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in edgar.gemspec
4
+ gemspec
5
+
6
+ gem 'rspec'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Andy Schrage
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,55 @@
1
+ # Edgar-Stocks
2
+
3
+ Edgar-Stocks is a Ruby gem that provides access to historical stock data in a simple, configurable way.
4
+
5
+ Edgar provides the following info for a stock:
6
+ - Opening price
7
+ - Closing price
8
+ - Daily high
9
+ - Daily low
10
+ - Adjusted close
11
+ - Volume
12
+
13
+ In addition to the above, Edgar can calculate the rolling average for a given date for a particular stock.
14
+
15
+ Have more ideas how I can improve the gem? Leave me a message!
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's Gemfile:
20
+
21
+ gem 'edgar'
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install edgar
30
+
31
+ ## Usage
32
+
33
+ Simply create a new Edgar object for each stock you care about:
34
+
35
+ stock = Edgar::Edgar.new('INTU')
36
+
37
+ Then query it!
38
+
39
+ stock.closing_price # Returns today's closing price
40
+
41
+ Or ask for a date in the past.
42
+
43
+ stock.closing_price(DateTime.yesterday) # Obviously get yesterday's closing price
44
+
45
+ You can even get running averages
46
+
47
+ stock.closing_price(DateTime.now, 5) # Get the five day average closing price starting with today's closing.
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'edgar/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "edgar-stocks"
8
+ spec.version = Edgar::VERSION
9
+ spec.authors = ["Andy Schrage"]
10
+ spec.email = ["ajschrag@mtu.edu"]
11
+ spec.description = %q{Edgar-Stocks is a Ruby gem that provides access to historical stock data in a simple, configurable way.}
12
+ spec.summary = %q{Stock data since the beginning of time!}
13
+ spec.homepage = "https://github.com/Swimminschrage/edgar"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency 'rspec'
24
+ end
@@ -0,0 +1,116 @@
1
+ require 'edgar/version'
2
+ require 'net/http'
3
+ require 'csv'
4
+ require 'time'
5
+
6
+ module Edgar
7
+
8
+ class Edgar
9
+ attr_reader :symbol
10
+
11
+ # Configuration defaults
12
+ @@config = {
13
+ :lookup_offset => -1,
14
+ :round_to => 2
15
+ }
16
+
17
+ @@valid_config_keys = @@config.keys
18
+
19
+ def self.configure(opts = {})
20
+ opts.each {|k,v| @@config[k.to_sym] = v if @@valid_config_keys.include? k.to_sym}
21
+ end
22
+
23
+ def self.config
24
+ @@config
25
+ end
26
+
27
+ def initialize(symbol)
28
+ @symbol = symbol
29
+
30
+ # Perform the actual lookup of historical data and parse it into arrays that
31
+ # are cached in memory
32
+ @data = CSV.parse(lookup)
33
+ end
34
+
35
+ def closing_price(date = DateTime.now, running = 1)
36
+ lookup_by_column(running, date, 4)
37
+ end
38
+
39
+ def opening_price(date = DateTime.now, running = 1)
40
+ lookup_by_column(running, date, 1)
41
+ end
42
+
43
+ def high_price(date = DateTime.now, running = 1)
44
+ lookup_by_column(running, date, 2)
45
+ end
46
+
47
+ def low_price(date = DateTime.now, running = 1)
48
+ lookup_by_column(running, date, 3)
49
+ end
50
+
51
+ def volume(date = DateTime.now, running = 1)
52
+ lookup_by_column(running, date, 5)
53
+ end
54
+
55
+ private
56
+
57
+ def lookup
58
+ @content ||= get_historical_data
59
+ end
60
+
61
+ def get_historical_data
62
+ uri = URI("http://ichart.finance.yahoo.com/table.csv?s=#{@symbol}")
63
+ response = Net::HTTP.get_response(uri)
64
+
65
+ raise InvalidSymbolError.new("Unable to lookup '#{symbol}'") unless response.code == "200"
66
+ response.body
67
+ end
68
+
69
+ def lookup_by_column(running, date, column)
70
+ return nil if date > DateTime.now()
71
+
72
+ running = 1 if running < 1
73
+
74
+ formatted_date = date.strftime('%Y-%m-%d')
75
+
76
+ @data[1..@data.size].each_index do |index|
77
+ row = @data[index+1]
78
+
79
+ return sum_and_average(index+1, running, column) if row[0] == formatted_date
80
+
81
+ if DateTime.parse(row[0]) < date
82
+ if Edgar.config[:lookup_offset] < 0
83
+ return sum_and_average(index+1, running, column)
84
+ else
85
+ return sum_and_average(index, running, column)
86
+ end
87
+ end
88
+
89
+ end
90
+ return nil
91
+ end
92
+
93
+ def sum_and_average(start, days, column)
94
+ total = @data[start, days].inject(0) do |sum, row|
95
+ sum + row[column.to_i].to_f
96
+ end
97
+
98
+ # Round off to at most two digits
99
+ round_to = Edgar.config[:round_to]
100
+ round_to = 2 if round_to < 0
101
+
102
+ denom = @data[start, days].size
103
+ (total / denom).round(round_to)
104
+ end
105
+ end
106
+
107
+ class InvalidSymbolError < ArgumentError
108
+ def initialize(message)
109
+ @message = message
110
+ end
111
+
112
+ def to_s
113
+ @message
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,3 @@
1
+ module Edgar
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+ require_relative '../lib/edgar'
3
+
4
+ describe 'Edgar' do
5
+ let(:stock) {Edgar::Edgar.new('INTU')}
6
+ let(:firstday) {DateTime.new(2013,10,1)}
7
+ let(:weekend_day) {DateTime.new(2013,9,21)}
8
+ let(:future_day) {DateTime.new(2020,1,1)}
9
+ subject {stock}
10
+
11
+ it 'should have a reference to the symbol' do
12
+ expect(stock.symbol).to eq('INTU')
13
+ end
14
+
15
+ it 'should be able to lookup valid stock symbols' do
16
+ expect{Edgar::Edgar.new('INTU')}.to_not raise_error Edgar::InvalidSymbolError
17
+ end
18
+
19
+ it 'should not be able to lookup invalid stock symbols' do
20
+ expect{Edgar::Edgar.new('LALALALALA')}.to raise_error(Edgar::InvalidSymbolError)
21
+ end
22
+
23
+ it 'can get closing price for October 1, 2013' do
24
+ expect(stock.closing_price(firstday)).to eq(66.45)
25
+ end
26
+
27
+ it 'can get the opening price for October 1, 2013' do
28
+ expect(stock.opening_price(firstday)).to eq(66.53)
29
+ end
30
+
31
+ it 'can get the high price for October 1, 2013' do
32
+ expect(stock.high_price(firstday)).to eq(67.09)
33
+ end
34
+
35
+ it 'can get the low price for a stock' do
36
+ expect(stock.low_price(firstday)).to eq(66.19)
37
+ end
38
+
39
+ it 'can get the volume traded for a stock' do
40
+ expect(stock.volume(firstday)).to eq(2095700)
41
+ end
42
+
43
+ describe 'when configured to look to the next day' do
44
+ before (:all) do
45
+ Edgar::Edgar.configure({:lookup_offset => 1})
46
+ end
47
+
48
+ it 'should go to monday when a weekend date is specified' do
49
+ expect(stock.opening_price(weekend_day)).to eq(66.59)
50
+ end
51
+ end
52
+
53
+ describe 'when configured to look to the prev day' do
54
+ before (:all) do
55
+ Edgar::Edgar.configure({:lookup_offset => -1})
56
+ end
57
+
58
+ it 'should go to friday when a weekend date is specified' do
59
+ expect(stock.opening_price(weekend_day)).to eq(66.64)
60
+ end
61
+ end
62
+
63
+ describe 'when a future date is provided' do
64
+ let(:future_day) {DateTime.new(2020,1,1)}
65
+ it 'should return nil' do
66
+ expect(stock.opening_price(future_day)).to be_nil
67
+ end
68
+ end
69
+
70
+ describe 'when an old date is provided' do
71
+ let(:past_day) {DateTime.new(1919,1,1)}
72
+ it 'should return nil' do
73
+ expect(stock.opening_price(past_day)).to be_nil
74
+ end
75
+
76
+ it 'should return the average using any valid dates when all are valid' do
77
+ expect(stock.opening_price(DateTime.new(1993, 3, 23), 2)).to eq(29.50)
78
+ end
79
+
80
+ it 'should return the average using any valid dates when some are invalid' do
81
+ expect(stock.opening_price(DateTime.new(1993, 3, 23), 6)).to eq(29.50)
82
+ end
83
+ end
84
+
85
+ describe 'when providing a range' do
86
+ let(:firstday) {DateTime.new(2013, 9, 27)}
87
+ it 'should return the running avg for opening price' do
88
+ expect(stock.opening_price(firstday, 10)).to eq(66.28)
89
+ end
90
+
91
+ describe 'and rounding to 4 decimal points' do
92
+ it 'should return the running avg to 4 decimal points' do
93
+ Edgar::Edgar.configure({:round_to => 4})
94
+ expect(stock.opening_price(firstday, 10)).to eq(66.278)
95
+ end
96
+
97
+ it 'should return the running avg to 0 decimal points' do
98
+ Edgar::Edgar.configure({:round_to => 0})
99
+ expect(stock.opening_price(firstday, 10)).to eq(66)
100
+ end
101
+
102
+ it 'should return the running avg to 3 decimal points' do
103
+ Edgar::Edgar.configure({:round_to => 3})
104
+ expect(stock.opening_price(firstday, 10)).to eq(66.278)
105
+ end
106
+ end
107
+ end
108
+
109
+ end
@@ -0,0 +1,17 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+
12
+ # Run specs in random order to surface order dependencies. If you find an
13
+ # order dependency and want to debug it, you can fix the order by providing
14
+ # the seed, which is printed after each run.
15
+ # --seed 1234
16
+ config.order = 'random'
17
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: edgar-stocks
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andy Schrage
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Edgar-Stocks is a Ruby gem that provides access to historical stock data
56
+ in a simple, configurable way.
57
+ email:
58
+ - ajschrag@mtu.edu
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - edgar.gemspec
69
+ - lib/edgar.rb
70
+ - lib/edgar/version.rb
71
+ - spec/edgar_spec.rb
72
+ - spec/spec_helper.rb
73
+ homepage: https://github.com/Swimminschrage/edgar
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.1.8
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Stock data since the beginning of time!
97
+ test_files:
98
+ - spec/edgar_spec.rb
99
+ - spec/spec_helper.rb