ruby-edgar 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 +7 -0
- data/README.md +120 -0
- data/lib/edgar/attachment.rb +69 -0
- data/lib/edgar/attachments.rb +75 -0
- data/lib/edgar/company.rb +217 -0
- data/lib/edgar/config.rb +62 -0
- data/lib/edgar/data_objects.rb +521 -0
- data/lib/edgar/entity.rb +98 -0
- data/lib/edgar/entity_data.rb +189 -0
- data/lib/edgar/entity_facts.rb +322 -0
- data/lib/edgar/filing.rb +170 -0
- data/lib/edgar/filing_facts.rb +312 -0
- data/lib/edgar/filing_header.rb +124 -0
- data/lib/edgar/filing_homepage.rb +118 -0
- data/lib/edgar/filing_index.rb +87 -0
- data/lib/edgar/filing_sections.rb +43 -0
- data/lib/edgar/filings.rb +216 -0
- data/lib/edgar/financials.rb +361 -0
- data/lib/edgar/http_client.rb +116 -0
- data/lib/edgar/ttm_calculator.rb +185 -0
- data/lib/edgar/version.rb +5 -0
- data/lib/edgar/xbrl/xbrl.rb +134 -0
- data/lib/edgar.rb +83 -0
- metadata +164 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edgar
|
|
4
|
+
# Form-type dispatching: maps filing forms to specialized data objects.
|
|
5
|
+
module DataObjects
|
|
6
|
+
# Base class for form-specific data wrappers.
|
|
7
|
+
class Base
|
|
8
|
+
attr_reader :filing
|
|
9
|
+
|
|
10
|
+
def initialize(filing)
|
|
11
|
+
@filing = filing
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def form_type
|
|
15
|
+
@filing.form
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def company_name
|
|
19
|
+
@filing.company
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def filing_date
|
|
23
|
+
@filing.filing_date
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def accession_number
|
|
27
|
+
@filing.accession_number
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_s
|
|
31
|
+
"#<#{self.class.name.split('::').last} #{form_type} #{company_name}>"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Wraps a 10-K annual filing with section accessors.
|
|
36
|
+
class TenK < Base
|
|
37
|
+
def items
|
|
38
|
+
@filing.sections
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def business
|
|
42
|
+
items["1"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def risk_factors
|
|
46
|
+
items["1A"]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def financial_statements
|
|
50
|
+
items["8"]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def exhibits
|
|
54
|
+
@filing.exhibits
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Wraps a 10-Q quarterly filing with section accessors.
|
|
59
|
+
class TenQ < Base
|
|
60
|
+
def items
|
|
61
|
+
@filing.sections
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def financial_statements
|
|
65
|
+
items["1"]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def legal_proceedings
|
|
69
|
+
items["1"]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Wraps a Form 4 insider trading filing.
|
|
74
|
+
class Form4 < Base
|
|
75
|
+
def transactions
|
|
76
|
+
@filing.xbrl&.financial_concepts || []
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def issuer_cik
|
|
80
|
+
@filing.cik
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Wraps an 8-K current report filing.
|
|
85
|
+
class Form8K < Base
|
|
86
|
+
def items
|
|
87
|
+
@filing.sections
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def exhibit_list
|
|
91
|
+
@filing.exhibits
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Wraps a Schedule 13D beneficial ownership filing.
|
|
96
|
+
class Schedule13D < Base
|
|
97
|
+
def beneficial_owner
|
|
98
|
+
@filing.header.filers.first
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Wraps a Schedule 13G beneficial ownership filing.
|
|
103
|
+
class Schedule13G < Base
|
|
104
|
+
def beneficial_owner
|
|
105
|
+
@filing.header.filers.first
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Wraps an NPORT-P portfolio holding filing.
|
|
110
|
+
class FormNport < Base
|
|
111
|
+
def report_date
|
|
112
|
+
@filing.header.period_of_report
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def fund_name
|
|
116
|
+
@filing.header.filer_company
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Wraps a Form 13F institutional holdings filing.
|
|
121
|
+
class Form13F < Base
|
|
122
|
+
def report_date
|
|
123
|
+
@filing.header.period_of_report
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def filing_manager
|
|
127
|
+
@filing.header.filer_company
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def holdings
|
|
131
|
+
xml = @filing.xml
|
|
132
|
+
return [] if xml.empty?
|
|
133
|
+
|
|
134
|
+
doc = Nokogiri::XML(xml)
|
|
135
|
+
doc.remove_namespaces!
|
|
136
|
+
entries = []
|
|
137
|
+
doc.xpath("//infoTable").each do |table|
|
|
138
|
+
entry = {
|
|
139
|
+
name_of_issuer: table.at_xpath("nameOfIssuer")&.text,
|
|
140
|
+
title_of_class: table.at_xpath("titleOfClass")&.text,
|
|
141
|
+
cusip: table.at_xpath("cusip")&.text,
|
|
142
|
+
value: table.at_xpath("value")&.text&.to_i,
|
|
143
|
+
shares: table.at_xpath("shrsOrPrnAmt/shrsPrnAmt")&.text&.to_i,
|
|
144
|
+
put_call: table.at_xpath("putCall")&.text,
|
|
145
|
+
investment_discretion: table.at_xpath("investmentDiscretion")&.text,
|
|
146
|
+
voting_authority_sole: table.at_xpath("votingAuthority/sole")&.text&.to_i,
|
|
147
|
+
voting_authority_shared: table.at_xpath("votingAuthority/shared")&.text&.to_i,
|
|
148
|
+
voting_authority_none: table.at_xpath("votingAuthority/none")&.text&.to_i
|
|
149
|
+
}
|
|
150
|
+
entries << entry
|
|
151
|
+
end
|
|
152
|
+
entries
|
|
153
|
+
rescue StandardError
|
|
154
|
+
[]
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Wraps a filing summary report.
|
|
159
|
+
class FilingSummary < Base
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Wraps a Form 3 initial insider ownership filing.
|
|
163
|
+
class Form3 < Base
|
|
164
|
+
def issuer_cik
|
|
165
|
+
@filing.cik
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Wraps a Form 5 annual insider ownership filing.
|
|
170
|
+
class Form5 < Base
|
|
171
|
+
def issuer_cik
|
|
172
|
+
@filing.cik
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Wraps a proxy statement (DEF 14A, etc.).
|
|
177
|
+
class ProxyStatement < Base
|
|
178
|
+
def items
|
|
179
|
+
@filing.sections
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def proposals
|
|
183
|
+
items
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Wraps an S-1 IPO registration filing.
|
|
188
|
+
class S1 < Base
|
|
189
|
+
def items
|
|
190
|
+
@filing.sections
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def business
|
|
194
|
+
items["1"]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def risk_factors
|
|
198
|
+
items["1A"]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def financial_statements
|
|
202
|
+
items["8"]
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Wraps a Form 20-F foreign filer annual report.
|
|
207
|
+
class Form20F < Base
|
|
208
|
+
def items
|
|
209
|
+
@filing.sections
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Wraps a Form 6-K foreign filer current report.
|
|
214
|
+
class Form6K < Base
|
|
215
|
+
def items
|
|
216
|
+
@filing.sections
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Wraps an N-CSR fund annual report.
|
|
221
|
+
class FormNCSR < Base
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Wraps a Form 144 restricted stock filing.
|
|
225
|
+
class Form144 < Base
|
|
226
|
+
def securities_sold
|
|
227
|
+
@filing.header.fields["SECURITIES SOLD"] || []
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def issuer
|
|
231
|
+
@filing.header.filer_company
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# Wraps a Form C crowdfunding filing.
|
|
236
|
+
class FormC < Base
|
|
237
|
+
def offering_amount
|
|
238
|
+
@filing.header.fields["TOTAL OFFERING AMOUNT"]&.first
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def issuer
|
|
242
|
+
@filing.header.filer_company
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Wraps a Form D offering filing.
|
|
247
|
+
class FormD < Base
|
|
248
|
+
def offering_amount
|
|
249
|
+
@filing.header.fields["TOTAL OFFERING AMOUNT"]&.first
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def issuer
|
|
253
|
+
@filing.header.filer_company
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
# Wraps an S-3 shelf registration filing.
|
|
258
|
+
class RegistrationS3 < Base
|
|
259
|
+
def items
|
|
260
|
+
@filing.sections
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def risk_factors
|
|
264
|
+
items["1A"]
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Wraps a 424B prospectus filing.
|
|
269
|
+
class Prospectus424B < Base
|
|
270
|
+
def items
|
|
271
|
+
@filing.sections
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
# Wraps a SEC correspondence filing.
|
|
276
|
+
class Correspondence < Base
|
|
277
|
+
def subject
|
|
278
|
+
@filing.header.fields["SUBJECT"]&.first
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# Wraps an SEC Effect filing.
|
|
283
|
+
class Effect < Base
|
|
284
|
+
def effect_type
|
|
285
|
+
@filing.header.fields["EFFECT"]&.first
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Wraps an Alternative Trading System filing.
|
|
290
|
+
class AlternativeTradingSystem < Base
|
|
291
|
+
def ats_name
|
|
292
|
+
@filing.header.filer_company
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
# Wraps a Draft Registration Statement filing.
|
|
297
|
+
class DraftRegistrationStatement < Base
|
|
298
|
+
def items
|
|
299
|
+
@filing.sections
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Wraps a 40-F Canadian MJDS annual report.
|
|
304
|
+
class FortyF < Form20F
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Wraps an F-1 foreign registration statement.
|
|
308
|
+
class RegistrationS1 < S1
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# Wraps a Fund portfolio holdings report (NPORT-P).
|
|
312
|
+
class FundReport < FormNport
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Wraps a Fund shareholder report (N-CSR / N-CSRS).
|
|
316
|
+
class FundShareholderReport < FormNCSR
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Wraps a Money Market Fund report (N-MFP2 / N-MFP3).
|
|
320
|
+
class MoneyMarketFund < Base
|
|
321
|
+
def report_date
|
|
322
|
+
@filing.header.period_of_report
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def fund_name
|
|
326
|
+
@filing.header.filer_company
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Wraps a Fund census report (N-CEN).
|
|
331
|
+
class FundCensus < Base
|
|
332
|
+
def report_date
|
|
333
|
+
@filing.header.period_of_report
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def fund_name
|
|
337
|
+
@filing.header.filer_company
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Wraps an N-PX proxy voting record.
|
|
342
|
+
class NPX < Base
|
|
343
|
+
def report_date
|
|
344
|
+
@filing.header.period_of_report
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def fund_name
|
|
348
|
+
@filing.header.filer_company
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Wraps a 497K summary prospectus.
|
|
353
|
+
class Prospectus497K < Base
|
|
354
|
+
def fund_name
|
|
355
|
+
@filing.header.filer_company
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Wraps a 24F-2NT fund fee notice.
|
|
360
|
+
class FundFeeNotice < Base
|
|
361
|
+
def fund_name
|
|
362
|
+
@filing.header.filer_company
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Wraps a Municipal Advisor Form (MA-I).
|
|
367
|
+
class MunicipalAdvisorForm < Base
|
|
368
|
+
def firm_name
|
|
369
|
+
@filing.header.filer_company
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Wraps an ABS distribution report (10-D).
|
|
374
|
+
class TenD < Base
|
|
375
|
+
def items
|
|
376
|
+
@filing.sections
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def distribution_data
|
|
380
|
+
@filing.attachments.select { |a| a.document_type == "EX-102" }
|
|
381
|
+
end
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Generic wrapper for XML-based SEC filings (X-17A-5, TA-1, TA-2, etc.).
|
|
385
|
+
class XmlFiling < Base
|
|
386
|
+
def xml_data
|
|
387
|
+
@filing.xml
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
def parsed_xml
|
|
391
|
+
return nil if xml_data.empty?
|
|
392
|
+
|
|
393
|
+
Nokogiri::XML(xml_data)
|
|
394
|
+
rescue StandardError
|
|
395
|
+
nil
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# Wraps an Alternative Trading System Cessation filing (ATS-N-C).
|
|
400
|
+
class AtsCessation < Base
|
|
401
|
+
def ats_name
|
|
402
|
+
@filing.header.filer_company
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Python-compatible alias classes
|
|
407
|
+
EightK = Form8K
|
|
408
|
+
SixK = Form6K
|
|
409
|
+
TwentyF = Form20F
|
|
410
|
+
|
|
411
|
+
FORM_MAP = {
|
|
412
|
+
"10-K" => TenK,
|
|
413
|
+
"10-K/A" => TenK,
|
|
414
|
+
"10-Q" => TenQ,
|
|
415
|
+
"10-Q/A" => TenQ,
|
|
416
|
+
"4" => Form4,
|
|
417
|
+
"4/A" => Form4,
|
|
418
|
+
"8-K" => EightK,
|
|
419
|
+
"8-K/A" => EightK,
|
|
420
|
+
"6-K" => SixK,
|
|
421
|
+
"6-K/A" => SixK,
|
|
422
|
+
"20-F" => TwentyF,
|
|
423
|
+
"20-F/A" => TwentyF,
|
|
424
|
+
"40-F" => FortyF,
|
|
425
|
+
"40-F/A" => FortyF,
|
|
426
|
+
"SC 13D" => Schedule13D,
|
|
427
|
+
"SC 13D/A" => Schedule13D,
|
|
428
|
+
"SC 13G" => Schedule13G,
|
|
429
|
+
"SC 13G/A" => Schedule13G,
|
|
430
|
+
"NPORT-P" => FundReport,
|
|
431
|
+
"NPORT-P/A" => FundReport,
|
|
432
|
+
"NPORT-EX" => FundReport,
|
|
433
|
+
"13F-HR" => Form13F,
|
|
434
|
+
"13F-HR/A" => Form13F,
|
|
435
|
+
"3" => Form3,
|
|
436
|
+
"3/A" => Form3,
|
|
437
|
+
"5" => Form5,
|
|
438
|
+
"5/A" => Form5,
|
|
439
|
+
"144" => Form144,
|
|
440
|
+
"144/A" => Form144,
|
|
441
|
+
"DEF 14A" => ProxyStatement,
|
|
442
|
+
"DEFA 14A" => ProxyStatement,
|
|
443
|
+
"DEFM 14A" => ProxyStatement,
|
|
444
|
+
"DEFC 14A" => ProxyStatement,
|
|
445
|
+
"DEFN 14A" => ProxyStatement,
|
|
446
|
+
"DFAN 14A" => ProxyStatement,
|
|
447
|
+
"DEFR 14A" => ProxyStatement,
|
|
448
|
+
"DFRN 14A" => ProxyStatement,
|
|
449
|
+
"PRE 14A" => ProxyStatement,
|
|
450
|
+
"PREC 14A" => ProxyStatement,
|
|
451
|
+
"PREN 14A" => ProxyStatement,
|
|
452
|
+
"PREM 14A" => ProxyStatement,
|
|
453
|
+
"S-1" => RegistrationS1,
|
|
454
|
+
"S-1/A" => RegistrationS1,
|
|
455
|
+
"F-1" => RegistrationS1,
|
|
456
|
+
"F-1/A" => RegistrationS1,
|
|
457
|
+
"S-3" => RegistrationS3,
|
|
458
|
+
"S-3/A" => RegistrationS3,
|
|
459
|
+
"S-3ASR" => RegistrationS3,
|
|
460
|
+
"S-3ASR/A" => RegistrationS3,
|
|
461
|
+
"S-3D" => RegistrationS3,
|
|
462
|
+
"S-3DPOS" => RegistrationS3,
|
|
463
|
+
"F-3" => RegistrationS3,
|
|
464
|
+
"F-3/A" => RegistrationS3,
|
|
465
|
+
"F-3ASR" => RegistrationS3,
|
|
466
|
+
"F-3ASR/A" => RegistrationS3,
|
|
467
|
+
"424B1" => Prospectus424B,
|
|
468
|
+
"424B2" => Prospectus424B,
|
|
469
|
+
"424B3" => Prospectus424B,
|
|
470
|
+
"424B4" => Prospectus424B,
|
|
471
|
+
"424B5" => Prospectus424B,
|
|
472
|
+
"424B7" => Prospectus424B,
|
|
473
|
+
"424B8" => Prospectus424B,
|
|
474
|
+
"497K" => Prospectus497K,
|
|
475
|
+
"N-CSR" => FundShareholderReport,
|
|
476
|
+
"N-CSRS" => FundShareholderReport,
|
|
477
|
+
"N-CEN" => FundCensus,
|
|
478
|
+
"N-MFP2" => MoneyMarketFund,
|
|
479
|
+
"N-MFP3" => MoneyMarketFund,
|
|
480
|
+
"N-PX" => NPX,
|
|
481
|
+
"10-D" => TenD,
|
|
482
|
+
"10-D/A" => TenD,
|
|
483
|
+
"24F-2NT" => FundFeeNotice,
|
|
484
|
+
"MA-I" => MunicipalAdvisorForm,
|
|
485
|
+
"MA" => XmlFiling,
|
|
486
|
+
"MA-W" => XmlFiling,
|
|
487
|
+
"C" => FormC,
|
|
488
|
+
"C/A" => FormC,
|
|
489
|
+
"C-U" => FormC,
|
|
490
|
+
"C-AR" => FormC,
|
|
491
|
+
"C-TR" => FormC,
|
|
492
|
+
"D" => FormD,
|
|
493
|
+
"D/A" => FormD,
|
|
494
|
+
"CORRESP" => Correspondence,
|
|
495
|
+
"UPLOAD" => Correspondence,
|
|
496
|
+
"EFFECT" => Effect,
|
|
497
|
+
"ATS-N" => AlternativeTradingSystem,
|
|
498
|
+
"ATS-N/A" => AlternativeTradingSystem,
|
|
499
|
+
"ATS-N-W" => AlternativeTradingSystem,
|
|
500
|
+
"DRS" => DraftRegistrationStatement,
|
|
501
|
+
"DRS/A" => DraftRegistrationStatement,
|
|
502
|
+
"X-17A-5" => XmlFiling,
|
|
503
|
+
"TA-1" => XmlFiling,
|
|
504
|
+
"TA-2" => XmlFiling,
|
|
505
|
+
"TA-W" => XmlFiling,
|
|
506
|
+
"CFPORTAL" => XmlFiling,
|
|
507
|
+
"SBSE" => XmlFiling,
|
|
508
|
+
"SBSE-A" => XmlFiling,
|
|
509
|
+
"SBSE-W" => XmlFiling,
|
|
510
|
+
"ATS-N-C" => AtsCessation
|
|
511
|
+
}.freeze
|
|
512
|
+
|
|
513
|
+
def self.for(filing)
|
|
514
|
+
form = filing.form
|
|
515
|
+
klass = FORM_MAP[form]
|
|
516
|
+
klass ||= FORM_MAP[form.sub(%r{/A$}, "")]
|
|
517
|
+
klass ||= Base
|
|
518
|
+
klass.new(filing)
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
end
|
data/lib/edgar/entity.rb
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Edgar
|
|
4
|
+
# Base class wrapping SEC submissions API data for a CIK entity.
|
|
5
|
+
class Entity
|
|
6
|
+
attr_reader :cik
|
|
7
|
+
|
|
8
|
+
def initialize(cik:, name: nil)
|
|
9
|
+
@cik = cik.to_i
|
|
10
|
+
@name = name
|
|
11
|
+
@entity_data = nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def name
|
|
15
|
+
@name || data.name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def data
|
|
19
|
+
@data ||= EntityData.new(cik: @cik)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def display_name
|
|
23
|
+
data.name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def company?
|
|
27
|
+
data.company?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def individual?
|
|
31
|
+
data.individual?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def not_found?
|
|
35
|
+
data.not_found?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def mailing_address
|
|
39
|
+
data.mailing_address
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def business_address
|
|
43
|
+
data.business_address
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def get_filings(form: nil, year: nil, quarter: nil, accession_number: nil,
|
|
47
|
+
filing_date: nil, date: nil,
|
|
48
|
+
amendments: nil, date_start: nil, date_end: nil)
|
|
49
|
+
filings = if year && quarter
|
|
50
|
+
Filings.from_quarter(year, quarter)
|
|
51
|
+
else
|
|
52
|
+
build_filings_from_submissions
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
filings = filings.filter(
|
|
56
|
+
form: form,
|
|
57
|
+
filing_date: filing_date || date,
|
|
58
|
+
cik: @cik,
|
|
59
|
+
amendments: amendments,
|
|
60
|
+
date_start: date_start,
|
|
61
|
+
date_end: date_end
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if accession_number
|
|
65
|
+
filing = filings.find { |f| f.accession_number == accession_number }
|
|
66
|
+
return filing ? Filings.new([filing]) : Filings.new([])
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
filings
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def to_s
|
|
73
|
+
"#<Entity #{@cik}>"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def build_filings_from_submissions
|
|
79
|
+
all = data.all_filings
|
|
80
|
+
forms = all["form"] || []
|
|
81
|
+
dates = all["filingDate"] || []
|
|
82
|
+
accs = all["accessionNumber"] || []
|
|
83
|
+
companies = all["company"] || []
|
|
84
|
+
|
|
85
|
+
entries = forms.each_with_index.map do |f, i|
|
|
86
|
+
{
|
|
87
|
+
cik: @cik,
|
|
88
|
+
company: companies[i] || display_name,
|
|
89
|
+
form: f,
|
|
90
|
+
filing_date: dates[i],
|
|
91
|
+
accession_number: accs[i]
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
Filings.new(entries)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|