Class: SecQuery::Filing

Inherits:
Object
  • Object
show all
Defined in:
lib/sec_query/filing.rb

Overview

> SecQuery::Filing

SecQuery::Filing requests and parses filings for any given SecQuery::Entity

Constant Summary collapse

COLUMNS =
[:cik, :title, :summary, :link, :term, :date, :file_id]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filing) ⇒ Filing

Returns a new instance of Filing.



11
12
13
14
15
# File 'lib/sec_query/filing.rb', line 11

def initialize(filing)
  COLUMNS.each do |column|
    instance_variable_set("@#{ column }", filing[column])
  end
end

Class Method Details

.fetch(uri, &blk) ⇒ Object



21
22
23
24
25
# File 'lib/sec_query/filing.rb', line 21

def self.fetch(uri, &blk)
  RestClient::Request.execute(method: :get, url: uri.to_s, timeout: 10) do |response, request, result, &block|
    parse_rss(response.body, &blk)
  end
end

.filing_for_index_row(row) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/sec_query/filing.rb', line 71

def self.filing_for_index_row(row)
  data = row.split(/   /).reject(&:blank?).map(&:strip)
  data = row.split(/  /).reject(&:blank?).map(&:strip) if data.count == 4
  return nil unless data[0] and data[1] and data[2] and data[3] and data[4]
  data.delete_at(1) if data[1][0] == '/'
  return nil unless Regexp.new(/\d{8}/).match(data[3])
  return nil if data[4] == nil
  unless data[4][0..3] == 'http'
    data[4] = "https://www.sec.gov/Archives/#{ data[4] }"
  end
  begin
    Date.parse(data[3])
  rescue ArgumentError
    return nil
  end
  Filing.new(
    term: data[1],
    cik: data[2],
    date: Date.parse(data[3]),
    link: data[4]
  )
end

.filings_for_index(index) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/sec_query/filing.rb', line 59

def self.filings_for_index(index)
  [].tap do |filings|
    content_section = false
    index.each_line do |row|
      content_section = true if row.include?('-------------')
      next if !content_section || row.include?('------------')
      filing = filing_for_index_row(row)
      filings << filing unless filing.nil?
    end
  end
end

.find(cik, start = 0, count = 80, args = {}) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/sec_query/filing.rb', line 131

def self.find(cik, start = 0, count = 80, args={})
  temp = {}
  temp[:url] = SecURI.browse_edgar_uri({cik: cik})
  temp[:url][:action] = :getcompany
  temp[:url][:start] = start
  temp[:url][:count] = count
  args.each {|k,v| temp[:url][k]=v }
  
  response = Entity.query(temp[:url].output_atom.to_s)
  document = Nokogiri::HTML(response)
  parse(cik, document)
end

.for_cik(cik, options = {}, &blk) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/sec_query/filing.rb', line 40

def self.for_cik(cik, options = {}, &blk)
  start = options.fetch(:start, 0)
  count = options.fetch(:count, 100)
  limit = options.fetch(:limit, 100)
  fetch(uri_for_cik(cik, start, count), &blk)
  start += count
  return if start >= limit
  for_cik(cik, { start: start, count: count, limit: limit }, &blk)
rescue OpenURI::HTTPError
  return
end

.for_date(date, &blk) ⇒ Object



52
53
54
55
56
57
# File 'lib/sec_query/filing.rb', line 52

def self.for_date(date, &blk)
  url = SecURI.for_date(date).to_s
  RestClient::Request.execute(method: :get, url: url, timeout: 10) do |response, request, result, &block|
    filings_for_index(response.body).each(&blk)
  end
end

.last(cik, args = {}) ⇒ Object



144
145
146
147
# File 'lib/sec_query/filing.rb', line 144

def self.last(cik, args = {})
  filings = find(cik, 0, 1, args)
  filings.is_a?(Array) ? filings.first : nil
end

.parse(cik, document) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/sec_query/filing.rb', line 149

def self.parse(cik, document)
  filings = []
  if document.xpath('//content').to_s.length > 0
    document.xpath('//content').each do |e|
      if e.xpath('//content/accession-number').to_s.length > 0
        content = Hash.from_xml(e.to_s)['content']
        content[:cik] = cik
        content[:file_id] = content.delete('accession_nunber')
        content[:date] = content.delete('filing_date')
        content[:link] = content.delete('filing_href')
        content[:term] = content.delete('filing_type')
        content[:title] = content.delete('form_name')
        filings << Filing.new(content)
      end
    end
  end
  filings
end

.parse_rss(rss, &blk) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/sec_query/filing.rb', line 115

def self.parse_rss(rss, &blk)
  feed = RSS::Parser.parse(rss, false)
  feed.entries.each do |entry|
    filing = Filing.new(
      cik: entry.title.content.match(/\((\w{10})\)/)[1],
      file_id: entry.id.content.split('=').last,
      term:  entry.category.term,
      title: entry.title.content,
      summary: entry.summary.content,
      date: DateTime.parse(entry.updated.content.to_s),
      link: entry.link.href.gsub('-index.htm', '.txt')
    )
    blk.call(filing)
  end
end

.recent(options = {}, &blk) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/sec_query/filing.rb', line 27

def self.recent(options = {}, &blk)
  start = options.fetch(:start, 0)
  count = options.fetch(:count, 100)
  limit = options.fetch(:limit, 100)
  limited_count = [limit - start, count].min
  fetch(uri_for_recent(start, limited_count), &blk)
  start += count
  return if start >= limit
  recent({ start: start, count: count, limit: limit }, &blk)
rescue OpenURI::HTTPError
  return
end

.uri_for_cik(cik, start = 0, count = 100) ⇒ Object



104
105
106
107
108
109
110
111
112
113
# File 'lib/sec_query/filing.rb', line 104

def self.uri_for_cik(cik, start = 0, count = 100)
  SecURI.browse_edgar_uri(
    action: :getcompany,
    owner: :include,
    output: :atom,
    start: start,
    count: count,
    CIK: cik
  )
end

.uri_for_recent(start = 0, count = 100) ⇒ Object



94
95
96
97
98
99
100
101
102
# File 'lib/sec_query/filing.rb', line 94

def self.uri_for_recent(start = 0, count = 100)
  SecURI.browse_edgar_uri(
    action: :getcurrent,
    owner: :include,
    output: :atom,
    start: start,
    count: count
  )
end

Instance Method Details

#content(&error_blk) ⇒ Object



168
169
170
171
172
173
174
175
176
177
# File 'lib/sec_query/filing.rb', line 168

def content(&error_blk)
  @content ||= RestClient.get(self.link)
rescue RestClient::ResourceNotFound => e
  puts "404 Resource Not Found: Bad link #{ self.link }"
  if block_given?
    error_blk.call(e, self)
  else
    raise e
  end
end

#detailObject



17
18
19
# File 'lib/sec_query/filing.rb', line 17

def detail
  @detail ||= FilingDetail.fetch(@link)
end