sec_query 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/lib/sec_query.rb +1 -1
- data/lib/sec_query/entity.rb +31 -188
- data/lib/sec_query/filing.rb +29 -25
- data/lib/sec_query/sec_uri.rb +0 -1
- data/lib/sec_query/transaction.rb +1 -1
- data/lib/sec_query/version.rb +1 -1
- data/sec_query.gemspec +2 -1
- data/spec/sec_query/entity_spec.rb +73 -0
- data/spec/sec_query/filing_spec.rb +44 -1
- data/spec/sec_query/transaction_spec.rb +39 -0
- data/spec/spec_helper.rb +23 -0
- metadata +38 -26
- data/spec/sec_query/sec_query_spec.rb +0 -129
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YTQ1MThkMWUwYzFlYTFiMDMxMzVhMDVhMTIwMGVlZDlkNWU1OWFiYQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0d2dde810ce6cded495db60a0e15cf12db156d9d
|
4
|
+
data.tar.gz: dfe37e5437bc0ec14d526c404700287023494101
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
YmE2YjI1Mjg5MTBhMjI5ODkwMGY1MGRjNjkyZDdkN2E3ZDg5M2E2MDU0MDA2
|
11
|
-
ZGU5MmFkOGEyOGZiNGNjMTU5YzNjMDdlZTFlYWU5N2RkODg1ZmE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NWY4MzFmZjJlYmE1YTMyYWViNzY1MzgxOTExMjkyZWY4ZjdmZDJlOGRiNGVh
|
14
|
-
MWEyODVhMTdiYmM4MTk1M2U3ZGE1Yzk5MTI4MjA3MGFkYmQ3MTU0OGEzMTJh
|
15
|
-
ZDcwMjU1MDliNzFiNDU2OTA0Y2U4YzYxNGE3ODYwZTA0NjA2ZmE=
|
6
|
+
metadata.gz: c9ae3373495a35a87f297ca8fbba54d15eadf7013273ac98c22ef5c4a64a8015feab56bfe1b531dd56fcd2fed98a761aee4346ba80e91438e6fafdebab4b1beb
|
7
|
+
data.tar.gz: e09c380cdcaf40ccff9deac2a5f24d7db825434d77f849993ced6396928b6df2a346fefa0546ea695876ce67fb8487e1e0414fa17e72e98eeff785ce1d9e0cf6
|
data/lib/sec_query.rb
CHANGED
data/lib/sec_query/entity.rb
CHANGED
@@ -1,52 +1,30 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
3
2
|
module SecQuery
|
4
3
|
# => SecQuery::Entity
|
5
4
|
# SecQuery::Entity is the root class which is responsible for requesting,
|
6
5
|
# parsing and initializing SecQuery::Entity intances from SEC Edgar.
|
7
6
|
class Entity
|
8
|
-
COLUMNS = [:
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
COLUMNS = [:cik, :name, :mailing_address, :business_address,
|
8
|
+
:assigned_sic, :assigned_sic_desc, :assigned_sic_href, :assitant_director, :cik_href,
|
9
|
+
:formerly_names, :state_location, :state_location_href, :state_of_incorporation]
|
12
10
|
attr_accessor(*COLUMNS)
|
13
11
|
|
14
12
|
def initialize(entity)
|
15
13
|
COLUMNS.each do |column|
|
16
|
-
instance_variable_set("@#{ column }", entity[column])
|
14
|
+
instance_variable_set("@#{ column }", entity[column.to_s])
|
17
15
|
end
|
18
16
|
end
|
19
17
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
temp[:url][:action] = :getcompany
|
24
|
-
temp[:cik] = Entity.cik(temp[:url], entity_args)
|
25
|
-
|
26
|
-
if !temp[:cik] || temp[:cik] == ''
|
27
|
-
puts "No Entity found for query: #{ temp[:url] }"
|
28
|
-
return false
|
29
|
-
end
|
30
|
-
|
31
|
-
### Get Document and Entity Type
|
32
|
-
doc = Entity.document(temp[:cik])
|
33
|
-
temp = Entity.parse_document(temp, doc)
|
34
|
-
|
35
|
-
### Get Additional Arguments and Query Additional Details
|
36
|
-
unless options.empty?
|
37
|
-
temp[:transactions] = []
|
38
|
-
temp[:filings] = []
|
39
|
-
options = Entity.options(temp, options)
|
40
|
-
temp = Entity.details(temp, options)
|
41
|
-
end
|
18
|
+
def filings
|
19
|
+
Filing.find(@cik)
|
20
|
+
end
|
42
21
|
|
43
|
-
|
44
|
-
|
45
|
-
@entity
|
22
|
+
def transactions
|
23
|
+
Transaction.find(@cik)
|
46
24
|
end
|
47
25
|
|
48
26
|
def self.query(url)
|
49
|
-
RestClient.get(url
|
27
|
+
RestClient.get(url) do |response, request, result, &block|
|
50
28
|
case response.code
|
51
29
|
when 200
|
52
30
|
return response
|
@@ -56,166 +34,31 @@ module SecQuery
|
|
56
34
|
end
|
57
35
|
end
|
58
36
|
|
59
|
-
def self.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
tbl.each do |tr|
|
68
|
-
td = tr.search('td')
|
69
|
-
if td[1] && entity[:middle] && td[1].innerHTML.downcase == ("#{entity[:last]} #{entity[:first]} #{entity[:middle]}").downcase || td[1] && td[1].innerHTML.downcase == ("#{ entity[:last] } #{ entity[:first] }").downcase
|
70
|
-
cik = td[0].search('a').innerHTML
|
71
|
-
return cik
|
72
|
-
end
|
73
|
-
end
|
74
|
-
else
|
75
|
-
return false
|
76
|
-
end
|
77
|
-
else
|
78
|
-
cik = data.inner_text.scan(/\(([^)]+)\)/).to_s
|
79
|
-
cik = cik.gsub('[["', '').gsub('"]]', '')
|
80
|
-
return cik
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def self.document(cik)
|
85
|
-
url = SecURI.ownership_display_uri(action: :getissuer, CIK: cik)
|
86
|
-
response = query(url)
|
87
|
-
doc = Hpricot(response)
|
88
|
-
text = 'Ownership Reports from:'
|
89
|
-
type = 'issuer'
|
90
|
-
entity = doc.search('//table').search('//td').search("b[text()*='#{text}']")
|
91
|
-
if entity.empty?
|
92
|
-
url = SecURI.ownership_display_uri(action: :getowner, CIK: cik)
|
93
|
-
response = query(url)
|
94
|
-
doc = Hpricot(response)
|
95
|
-
text = 'Ownership Reports for entitys:'
|
96
|
-
type = 'owner'
|
97
|
-
entity = doc.search('//table').search('//td').search("b[text()*='#{text}']")
|
98
|
-
end
|
99
|
-
[doc, type]
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.parse_document(temp, doc)
|
103
|
-
info = Entity.info(doc[0])
|
104
|
-
temp[:type] = doc[1]
|
105
|
-
temp[:name] = info[:name]
|
106
|
-
temp[:location] = info[:location]
|
107
|
-
temp[:sic] = info[:sic]
|
108
|
-
temp[:state_of_inc] = info[:state_of_inc]
|
109
|
-
temp[:formerly] = info[:formerly]
|
110
|
-
|
111
|
-
### Get Mailing Address
|
112
|
-
temp[:mailing_address] = Entity.mailing_address(doc[0])
|
113
|
-
|
114
|
-
### Get Business Address
|
115
|
-
temp[:business_address] = Entity.business_address(doc[0])
|
116
|
-
|
117
|
-
temp
|
118
|
-
end
|
119
|
-
|
120
|
-
def self.info(doc)
|
121
|
-
info = {}
|
122
|
-
lines = doc.search("//td[@bgcolor='#E6E6E6']")[0].parent.parent.search('//tr')
|
123
|
-
td = lines[0].search('//td//b').innerHTML
|
124
|
-
info[:name] = td.gsub(td.scan(/\(([^)]+)\)/).to_s, '').gsub('()', '').gsub('\n', '')
|
125
|
-
lines = lines[1].search('//table')[0].search('//tr//td')
|
126
|
-
|
127
|
-
if lines[0].search('a')[0]
|
128
|
-
info[:sic] = lines[0].search('a')[0].innerHTML
|
129
|
-
end
|
130
|
-
|
131
|
-
if lines[0].search('a')[1]
|
132
|
-
info[:location] = lines[0].search('a')[1].innerHTML
|
133
|
-
end
|
134
|
-
|
135
|
-
if lines[0].search('b')[0] && lines[0].search('b')[0].innerHTML.squeeze(' ') != ' '
|
136
|
-
info[:state_of_inc] = lines[0].search('b')[0].innerHTML
|
137
|
-
end
|
138
|
-
|
139
|
-
if lines[1] && lines[1].search('font')
|
140
|
-
info[:formerly] = lines[1].search('font').innerHTML
|
141
|
-
.gsub('formerly: ', '').gsub('<br />', '').gsub('\n', '; ')
|
142
|
-
end
|
143
|
-
|
144
|
-
info
|
145
|
-
end
|
146
|
-
|
147
|
-
def self.business_address(doc)
|
148
|
-
addie = doc.search('//table').search('//td')
|
149
|
-
.search("b[text()*='Business Address']")
|
150
|
-
if !addie.empty?
|
151
|
-
business_address = addie[0].parent.innerHTML
|
152
|
-
.gsub('<b class="blue">Business Address</b>', '').gsub('<br />', ' ')
|
153
|
-
return business_address
|
154
|
-
else
|
155
|
-
return false
|
156
|
-
end
|
37
|
+
def self.find(entity_args)
|
38
|
+
temp = {}
|
39
|
+
temp[:url] = SecURI.browse_edgar_uri(entity_args)
|
40
|
+
temp[:url][:action] = :getcompany
|
41
|
+
response = query(temp[:url].output_atom.to_s)
|
42
|
+
document = Nokogiri::HTML(response)
|
43
|
+
xml = document.xpath("//feed/company-info")
|
44
|
+
Entity.new(parse(xml))
|
157
45
|
end
|
158
46
|
|
159
|
-
def self.
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
47
|
+
def self.parse(xml)
|
48
|
+
content = Hash.from_xml(xml.to_s)
|
49
|
+
if content['company_info'].present?
|
50
|
+
content = content['company_info']
|
51
|
+
content['name'] = content.delete('conformed_name')
|
52
|
+
if content['formerly_names'].present?
|
53
|
+
content['formerly_names'] = content.delete('formerly_names')['names']
|
54
|
+
end
|
55
|
+
content['addresses']['address'].each do |address|
|
56
|
+
content["#{address['type']}_address"] = address
|
57
|
+
end
|
58
|
+
return content
|
166
59
|
else
|
167
|
-
return
|
60
|
+
return {}
|
168
61
|
end
|
169
62
|
end
|
170
|
-
|
171
|
-
def self.options(temp, options)
|
172
|
-
args = {}
|
173
|
-
if options.is_a?(Array) && options.length == 1 && options[0] == true
|
174
|
-
args[:relationships] = true
|
175
|
-
args[:transactions] = true
|
176
|
-
args[:filings] = true
|
177
|
-
elsif options.is_a?(Array) && options.length > 1
|
178
|
-
args[:relationships] = options[0]
|
179
|
-
args[:transactions] = options[1]
|
180
|
-
args[:filings] = options[2]
|
181
|
-
elsif options[0].is_a?(Hash)
|
182
|
-
args[:relationships] = options[0][:relationships]
|
183
|
-
args[:transactions] = options[0][:transactions]
|
184
|
-
args[:filings] = options[0][:filings]
|
185
|
-
end
|
186
|
-
args
|
187
|
-
end
|
188
|
-
|
189
|
-
def self.details(temp, options)
|
190
|
-
## Get Relationships for entity
|
191
|
-
if options[:relationships] == true
|
192
|
-
relationships = Relationship.find(temp)
|
193
|
-
temp[:relationships] = relationships
|
194
|
-
end
|
195
|
-
|
196
|
-
## Get Transactions for entity
|
197
|
-
if options[:transactions] && options[:transactions].is_a?(Hash)
|
198
|
-
temp = Transaction.find(
|
199
|
-
temp,
|
200
|
-
options[:transactions][:start],
|
201
|
-
options[:transactions][:count],
|
202
|
-
options[:transactions][:limit])
|
203
|
-
elsif options[:transactions] && options[:transactions] == true
|
204
|
-
temp = Transaction.find(temp, nil, nil, nil)
|
205
|
-
end
|
206
|
-
|
207
|
-
## Get Filings for entity
|
208
|
-
if options[:filings] && options[:filings].is_a?(Hash)
|
209
|
-
temp = Filing.find(
|
210
|
-
temp,
|
211
|
-
options[:filings][:start],
|
212
|
-
options[:filings][:count],
|
213
|
-
options[:filings][:limit])
|
214
|
-
elsif options[:filings] && options[:filings] == true
|
215
|
-
temp = Filing.find(temp, nil, nil, nil)
|
216
|
-
end
|
217
|
-
|
218
|
-
temp
|
219
|
-
end
|
220
63
|
end
|
221
64
|
end
|
data/lib/sec_query/filing.rb
CHANGED
@@ -4,7 +4,8 @@ module SecQuery
|
|
4
4
|
# => SecQuery::Filing
|
5
5
|
# SecQuery::Filing requests and parses filings for any given SecQuery::Entity
|
6
6
|
class Filing
|
7
|
-
COLUMNS = :cik, :title, :summary, :link, :term, :date, :file_id
|
7
|
+
COLUMNS = [:cik, :title, :summary, :link, :term, :date, :file_id]
|
8
|
+
|
8
9
|
attr_accessor(*COLUMNS)
|
9
10
|
|
10
11
|
def initialize(filing)
|
@@ -81,31 +82,34 @@ module SecQuery
|
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
84
|
-
def self.find(
|
85
|
-
|
86
|
-
|
87
|
-
url
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
85
|
+
def self.find(cik, start = 0, count = 80)
|
86
|
+
temp = {}
|
87
|
+
temp[:url] = SecURI.browse_edgar_uri({cik: cik})
|
88
|
+
temp[:url][:action] = :getcompany
|
89
|
+
temp[:url][:start] = start
|
90
|
+
temp[:url][:count] = count
|
91
|
+
response = Entity.query(temp[:url].output_atom.to_s)
|
92
|
+
document = Nokogiri::HTML(response)
|
93
|
+
parse(cik, document)
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.parse(cik, document)
|
97
|
+
filings = []
|
98
|
+
if document.xpath('//content').to_s.length > 0
|
99
|
+
document.xpath('//content').each do |e|
|
100
|
+
if e.xpath('//content/accession-nunber').to_s.length > 0
|
101
|
+
content = Hash.from_xml(e.to_s)['content']
|
102
|
+
content[:cik] = cik
|
103
|
+
content[:file_id] = content.delete('accession_nunber')
|
104
|
+
content[:date] = content.delete('filing_date')
|
105
|
+
content[:link] = content.delete('filing_href')
|
106
|
+
content[:term] = content.delete('filing_type')
|
107
|
+
content[:title] = content.delete('form_name')
|
108
|
+
filings << Filing.new(content)
|
109
|
+
end
|
110
|
+
end
|
108
111
|
end
|
112
|
+
filings
|
109
113
|
end
|
110
114
|
end
|
111
115
|
end
|
data/lib/sec_query/sec_uri.rb
CHANGED
data/lib/sec_query/version.rb
CHANGED
data/sec_query.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
s.add_development_dependency 'vcr', '~> 2.9'
|
25
25
|
s.add_development_dependency 'webmock', '~> 1.17'
|
26
26
|
s.add_development_dependency 'rubocop', '~> 0.20'
|
27
|
+
s.add_development_dependency 'addressable', '~> 2.3'
|
27
28
|
s.add_runtime_dependency 'rest-client', '~> 1.6'
|
28
|
-
s.add_runtime_dependency '
|
29
|
+
s.add_runtime_dependency 'nokogiri', '~> 1.6'
|
29
30
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
include SecQuery
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
# Note: Shared Methods are available in spec_helper.rb
|
5
|
+
|
6
|
+
describe SecQuery::Entity do
|
7
|
+
|
8
|
+
describe "Company Queries", vcr: { cassette_name: "aapl"} do
|
9
|
+
|
10
|
+
let(:query){{name: "APPLE INC", sic: "3571", symbol: "aapl", cik:"0000320193"}}
|
11
|
+
|
12
|
+
[:symbol, :cik, :name].each do |key|
|
13
|
+
context "when quering by #{key}" do
|
14
|
+
describe "as hash" do
|
15
|
+
|
16
|
+
let(:entity){ SecQuery::Entity.find({ key => query[key] }) }
|
17
|
+
|
18
|
+
it "should be valid" do
|
19
|
+
is_valid?(entity)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should have a valid mailing address" do
|
23
|
+
is_valid_address?(entity.mailing_address)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have a valid business address" do
|
27
|
+
is_valid_address?(entity.business_address)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "as string" do
|
32
|
+
it "should be valid" do
|
33
|
+
entity = SecQuery::Entity.find(query[key])
|
34
|
+
is_valid?(entity)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "People Queries", vcr: { cassette_name: "Steve Jobs"} do
|
42
|
+
|
43
|
+
let(:query){ { name: "JOBS STEVEN P", :cik => "0001007844" } }
|
44
|
+
|
45
|
+
[:cik, :name].each do |key|
|
46
|
+
context "when quering by #{key}" do
|
47
|
+
describe "as hash" do
|
48
|
+
|
49
|
+
let(:entity){ SecQuery::Entity.find({ key => query[key] }) }
|
50
|
+
|
51
|
+
it "should be valid" do
|
52
|
+
is_valid?(entity)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should have a valid mailing address" do
|
56
|
+
is_valid_address?(entity.mailing_address)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should have a valid business address" do
|
60
|
+
is_valid_address?(entity.business_address)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "as string" do
|
65
|
+
it "should be valid" do
|
66
|
+
entity = SecQuery::Entity.find(query[key])
|
67
|
+
is_valid?(entity)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
2
|
include SecQuery
|
4
3
|
require 'spec_helper'
|
5
4
|
|
@@ -38,4 +37,48 @@ describe SecQuery::Filing do
|
|
38
37
|
end
|
39
38
|
end
|
40
39
|
end
|
40
|
+
|
41
|
+
describe "::find" do
|
42
|
+
let(:query){{
|
43
|
+
name: "JOBS STEVEN P", :cik => "0001007844",
|
44
|
+
relationships:[
|
45
|
+
{cik: "0000320193", name: "APPLE INC"},
|
46
|
+
{cik: "0001001039", name: "WALT DISNEY CO/"},
|
47
|
+
{cik: "0001002114", name: "PIXAR \\CA\\"}
|
48
|
+
],
|
49
|
+
transactions:[
|
50
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares:120000.0},
|
51
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares: 40000.0},
|
52
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares: 40000.0},
|
53
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares: 40000.0},
|
54
|
+
{filing_number: "0001181431-06-028746", reporting_owner: "WALT DISNEY CO/", shares: 138000004.0},
|
55
|
+
{filing_number: "0001356184-06-000008", reporting_owner: "PIXAR \\CA\\", shares: 60000002.0},
|
56
|
+
{filing_number: "0001181431-06-019230", reporting_owner: "APPLE COMPUTER INC", shares: 4573553.0},
|
57
|
+
{filing_number: "0001181431-06-028747", reporting_owner: "WALT DISNEY CO/", shares: 0.0}
|
58
|
+
],
|
59
|
+
filings:[
|
60
|
+
{cik: "0001007844", file_id: "0001181431-07-052839"},
|
61
|
+
{cik: "0001007844", file_id: "0001356184-06-000008"},
|
62
|
+
{cik: "0001007844", file_id: "0001193125-06-103741"},
|
63
|
+
{cik: "0001007844", file_id: "0001181431-06-028747"},
|
64
|
+
{cik: "0001007844", file_id: "0001181431-06-028746"},
|
65
|
+
{cik: "0001007844", file_id: "0001181431-06-019230"},
|
66
|
+
{cik: "0001007844", file_id: "0001193125-06-019727"},
|
67
|
+
{cik: "0001007844", file_id: "0001104659-03-004723"}
|
68
|
+
]
|
69
|
+
}}
|
70
|
+
|
71
|
+
let(:entity) {SecQuery::Entity.find(query[:cik])}
|
72
|
+
|
73
|
+
describe "Filings", vcr: { cassette_name: "Steve Jobs"} do
|
74
|
+
it "should respond to filings" do
|
75
|
+
entity.should respond_to(:filings)
|
76
|
+
entity.filings.should be_kind_of(Array)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should be valid filing" do
|
80
|
+
is_valid_filing?(entity.filings.first)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
41
84
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
include SecQuery
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe SecQuery::Filing do
|
5
|
+
context "Owner" do
|
6
|
+
describe "Transactions", vcr: { cassette_name: "Steve Jobs"} do
|
7
|
+
let(:query){{
|
8
|
+
name: "JOBS STEVEN P", :cik => "0001007844",
|
9
|
+
transactions:[
|
10
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares:120000.0},
|
11
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares: 40000.0},
|
12
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares: 40000.0},
|
13
|
+
{filing_number: "0001181431-07-052839", reporting_owner: "APPLE INC", shares: 40000.0},
|
14
|
+
{filing_number: "0001181431-06-028746", reporting_owner: "WALT DISNEY CO/", shares: 138000004.0},
|
15
|
+
{filing_number: "0001356184-06-000008", reporting_owner: "PIXAR \\CA\\", shares: 60000002.0},
|
16
|
+
{filing_number: "0001181431-06-019230", reporting_owner: "APPLE COMPUTER INC", shares: 4573553.0},
|
17
|
+
{filing_number: "0001181431-06-028747", reporting_owner: "WALT DISNEY CO/", shares: 0.0}
|
18
|
+
]
|
19
|
+
}}
|
20
|
+
|
21
|
+
let(:entity) {SecQuery::Entity.find(query[:cik])}
|
22
|
+
|
23
|
+
# it "should respond to transactions" do
|
24
|
+
# entity.should respond_to(:transactions)
|
25
|
+
# entity.filings.should be_kind_of(Array)
|
26
|
+
# end
|
27
|
+
|
28
|
+
# it "should be valid transaction" do
|
29
|
+
# entity.transactions.first.inspect
|
30
|
+
# #is_valid_filing?(entity.filings.first)
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# it "should respond to content" do
|
34
|
+
# entity.filings.first.should respond_to(:content)
|
35
|
+
# puts entity.filings.first.content
|
36
|
+
# end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,3 +4,26 @@ require 'rubygems'
|
|
4
4
|
require 'bundler/setup'
|
5
5
|
require 'sec_query'
|
6
6
|
require 'support/vcr'
|
7
|
+
|
8
|
+
def is_valid?(entity)
|
9
|
+
entity.should_not be_nil
|
10
|
+
entity.name.should == query[:name]
|
11
|
+
entity.cik.should == query[:cik]
|
12
|
+
entity.instance_variables.each do |key|
|
13
|
+
SecQuery::Entity::COLUMNS.should include(key[1..-1].to_sym)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def is_valid_address?(address)
|
18
|
+
address.should_not be_nil
|
19
|
+
address.keys.each do |key|
|
20
|
+
['city', 'state', 'street1', 'street2', 'type', 'zip', 'phone'].should include(key)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def is_valid_filing?(filing)
|
25
|
+
filing.should_not be_nil
|
26
|
+
filing.instance_variables.each do |key|
|
27
|
+
SecQuery::Filing::COLUMNS.should include(key[1..-1].to_sym)
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,99 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sec_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ty Rauber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2.14'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.14'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: vcr
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '2.9'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.9'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: webmock
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.17'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.17'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rubocop
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0.20'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0.20'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: addressable
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.3'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.3'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rest-client
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- - ~>
|
87
|
+
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '1.6'
|
76
90
|
type: :runtime
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- - ~>
|
94
|
+
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '1.6'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
98
|
+
name: nokogiri
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- - ~>
|
101
|
+
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
103
|
+
version: '1.6'
|
90
104
|
type: :runtime
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- - ~>
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
110
|
+
version: '1.6'
|
97
111
|
description: Search for company or person, by name, symbol or Central Index Key (CIK),
|
98
112
|
and retrieve relationships, transactions and filings.
|
99
113
|
email:
|
@@ -102,7 +116,7 @@ executables: []
|
|
102
116
|
extensions: []
|
103
117
|
extra_rdoc_files: []
|
104
118
|
files:
|
105
|
-
- .gitignore
|
119
|
+
- ".gitignore"
|
106
120
|
- Gemfile
|
107
121
|
- README.md
|
108
122
|
- Rakefile
|
@@ -113,13 +127,11 @@ files:
|
|
113
127
|
- lib/sec_query/sec_uri.rb
|
114
128
|
- lib/sec_query/transaction.rb
|
115
129
|
- lib/sec_query/version.rb
|
116
|
-
- pkg/sec_query-1.0.1.gem
|
117
|
-
- pkg/sec_query-1.0.2.gem
|
118
|
-
- pkg/sec_query-1.0.3.gem
|
119
130
|
- sec_query.gemspec
|
131
|
+
- spec/sec_query/entity_spec.rb
|
120
132
|
- spec/sec_query/filing_spec.rb
|
121
|
-
- spec/sec_query/sec_query_spec.rb
|
122
133
|
- spec/sec_query/sec_uri_spec.rb
|
134
|
+
- spec/sec_query/transaction_spec.rb
|
123
135
|
- spec/spec_helper.rb
|
124
136
|
- spec/support/vcr.rb
|
125
137
|
homepage: https://github.com/tyrauber/sec_query
|
@@ -132,12 +144,12 @@ require_paths:
|
|
132
144
|
- lib
|
133
145
|
required_ruby_version: !ruby/object:Gem::Requirement
|
134
146
|
requirements:
|
135
|
-
- -
|
147
|
+
- - ">="
|
136
148
|
- !ruby/object:Gem::Version
|
137
149
|
version: '0'
|
138
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
151
|
requirements:
|
140
|
-
- -
|
152
|
+
- - ">="
|
141
153
|
- !ruby/object:Gem::Version
|
142
154
|
version: '0'
|
143
155
|
requirements: []
|
@@ -148,9 +160,9 @@ specification_version: 4
|
|
148
160
|
summary: A ruby gem for querying the United States Securities and Exchange Commission
|
149
161
|
Edgar System.
|
150
162
|
test_files:
|
163
|
+
- spec/sec_query/entity_spec.rb
|
151
164
|
- spec/sec_query/filing_spec.rb
|
152
|
-
- spec/sec_query/sec_query_spec.rb
|
153
165
|
- spec/sec_query/sec_uri_spec.rb
|
166
|
+
- spec/sec_query/transaction_spec.rb
|
154
167
|
- spec/spec_helper.rb
|
155
168
|
- spec/support/vcr.rb
|
156
|
-
has_rdoc:
|
@@ -1,129 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
include SecQuery
|
4
|
-
require 'spec_helper'
|
5
|
-
|
6
|
-
describe SecQuery::Entity do
|
7
|
-
|
8
|
-
describe 'Company Queries', vcr: { cassette_name: 'aapl' } do
|
9
|
-
|
10
|
-
let(:apple) do
|
11
|
-
{ name: 'APPLE INC', sic: '3571', symbol: 'aapl', cik: '0000320193' }
|
12
|
-
end
|
13
|
-
|
14
|
-
context 'when quering by stock symbol' do
|
15
|
-
it 'lazely' do
|
16
|
-
entity = SecQuery::Entity.find(apple[:symbol])
|
17
|
-
entity.cik.should eql(apple[:cik])
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'explicitly' do
|
21
|
-
entity = SecQuery::Entity.find(symbol: apple[:symbol])
|
22
|
-
entity.cik.should eql(apple[:cik])
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'when querying by entity name' do
|
27
|
-
it 'lazely' do
|
28
|
-
entity = SecQuery::Entity.find(apple[:name])
|
29
|
-
entity.cik.should eql(apple[:cik])
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'explicitly' do
|
33
|
-
entity = SecQuery::Entity.find(name: apple[:name])
|
34
|
-
entity.cik.should eql(apple[:cik])
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context 'when querying by cik' do
|
39
|
-
it 'lazely' do
|
40
|
-
entity = SecQuery::Entity.find(apple[:cik])
|
41
|
-
entity.name.should match(apple[:name])
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'explicitly' do
|
45
|
-
entity = SecQuery::Entity.find(cik: apple[:cik])
|
46
|
-
entity.name.should match(apple[:name])
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'People Queries', vcr: { cassette_name: 'Steve Jobs' } do
|
52
|
-
let(:jobs) do
|
53
|
-
{ first: 'Steve', middle: 'P', last: 'Jobs', cik: '0001007844' }
|
54
|
-
end
|
55
|
-
|
56
|
-
context 'when querying by name' do
|
57
|
-
it 'first, middle and last name' do
|
58
|
-
entity = SecQuery::Entity.find(
|
59
|
-
first: jobs[:first],
|
60
|
-
middle: jobs[:middle],
|
61
|
-
last: jobs[:last])
|
62
|
-
entity.cik.should eql(jobs[:cik])
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
describe 'Relationships, Transactions and Filings', vcr: { cassette_name: 'Steve Jobs' } do
|
68
|
-
## Using Steve, because data should not change in the future. RIP.
|
69
|
-
|
70
|
-
let(:jobs) do
|
71
|
-
{ first: 'Steve', middle: 'P', last: 'Jobs', cik: '0001007844',
|
72
|
-
relationships: [
|
73
|
-
{ cik: '0000320193', name: 'APPLE INC' },
|
74
|
-
{ cik: '0001001039', name: 'WALT DISNEY CO/' },
|
75
|
-
{ cik: '0001002114', name: 'PIXAR \\CA\\' }
|
76
|
-
],
|
77
|
-
transactions: [
|
78
|
-
{ filing_number: '0001181431-07-052839', reporting_owner: 'APPLE INC', shares: 120000.0 },
|
79
|
-
{ filing_number: '0001181431-07-052839', reporting_owner: 'APPLE INC', shares: 40000.0 },
|
80
|
-
{ filing_number: '0001181431-07-052839', reporting_owner: 'APPLE INC', shares: 40000.0 },
|
81
|
-
{ filing_number: '0001181431-07-052839', reporting_owner: 'APPLE INC', shares: 40000.0 },
|
82
|
-
{ filing_number: '0001181431-06-028746', reporting_owner: 'WALT DISNEY CO/', shares: 138000004.0 },
|
83
|
-
{ filing_number: '0001356184-06-000008', reporting_owner: 'PIXAR \\CA\\', shares: 60000002.0 },
|
84
|
-
{ filing_number: '0001181431-06-019230', reporting_owner: 'APPLE COMPUTER INC', shares: 4573553.0 },
|
85
|
-
{ filing_number: '0001181431-06-028747', reporting_owner: 'WALT DISNEY CO/', shares: 0.0 }
|
86
|
-
],
|
87
|
-
filings: [
|
88
|
-
{ cik: '0001007844', file_id: '0001181431-07-052839' },
|
89
|
-
{ cik: '0001007844', file_id: '0001356184-06-000008' },
|
90
|
-
{ cik: '0001007844', file_id: '0001193125-06-103741' },
|
91
|
-
{ cik: '0001007844', file_id: '0001181431-06-028747' },
|
92
|
-
{ cik: '0001007844', file_id: '0001181431-06-028746' },
|
93
|
-
{ cik: '0001007844', file_id: '0001181431-06-019230' },
|
94
|
-
{ cik: '0001007844', file_id: '0001193125-06-019727' },
|
95
|
-
{ cik: '0001007844', file_id: '0001104659-03-004723' }
|
96
|
-
]
|
97
|
-
}
|
98
|
-
end
|
99
|
-
|
100
|
-
let(:entity) do
|
101
|
-
SecQuery::Entity.find(
|
102
|
-
{ first: 'Steve',
|
103
|
-
middle: 'P',
|
104
|
-
last: 'Jobs',
|
105
|
-
cik: '0001007844' },
|
106
|
-
true)
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'when quering entities with option "true"' do
|
110
|
-
it 'should provide relationships' do
|
111
|
-
entity.relationships.each_with_index do |r, i|
|
112
|
-
r.cik.should eql(jobs[:relationships][i][:cik])
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should provide transactions' do
|
117
|
-
entity.transactions.each_with_index do |t, i|
|
118
|
-
t.filing_number.should eql(jobs[:transactions][i][:filing_number])
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'should provide filings' do
|
123
|
-
entity.filings.each_with_index do |f, i|
|
124
|
-
f.file_id.should eql(jobs[:filings][i][:file_id])
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|