栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

美国证券交易委员会EDGAR系统财务报表获取及文本清洗(I)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

美国证券交易委员会EDGAR系统财务报表获取及文本清洗(I)

最近在跟着一个NLP的项目,爬取了EDGAR上2021Q1到2022Q2的所有10-Q、10-K和8-K报表并清洗出特定Item的内容。做到现在半个月,总结了大致流程、遇到的问题和解决方法,希望能帮助到有同样需求的朋友们。完整内容大概会拆成3个部分,第一部分先介绍爬取报表的方法。

1. INTRO

关于美国证券交易委员会(SEC)的EDGAR系统,请参考:其中包含EDGAR系统的访问权限、访问方法、报表类型等常见问题。由于之后使用的爬取方法不需要自己设置请求间隔,此处仅作了解即可。常用的报表类型包括10-K(annual report)、10-Q(quarterly report)和8-K(current report),具体说明可参考:

SEC.gov | Forms Listhttps://www.sec.gov/forms关于报表的编成,简单来说, EDGAR系统给予每个编写报表的人员一个独特的索引码,称为CIK(central index key),我们查找报表也是基于CIK码而不是公司名称。如果想了解更多EDGAR系统中报表类型及索引问题,可参考论文:

  • García, D., & Norli, Ø. (2012). Crawling EDGAR. The spanish review of financial economics, 10(1), 1-10.
2. 获取季度报表主索引(Quarterly Master Index)

每个季度SEC会给出该季度内上传到EDGAR系统的报表的信息,包括CIK、公司名称、编成日期及文件名等等,称为quarterly master index。获取QMI可以帮助我们了解该季度内报表的编成情况,比如对QMI根据CIK进一步筛选来了解某个公司在一段时间内各类报表的编成数量。

很多基于Python、R的packages都能帮助我们获取QMI信息,我使用的是一个近两年新发布的R package,edgar。之后爬取特定时间段内的特定类型的报表也将用到这个包。使用这个包不需要很进阶的爬虫搭建技巧,只要求基本的R语言使用知识,可以说是非常便捷的一个黑箱。该R包与其他更早发布的Python及其他R包的功能对比可以参考原始论文:

  • Lonare, G., Patil, B., & Raut, N. (2021). edgar: An R package for the US SEC EDGAR retrieval and parsing of corporate filings. SoftwareX, 16, 100865.

论文中也介绍了部分函数的参数和功能。下文介绍我使用到的部分函数,有其他需求的朋友可自行参考帮助文档(有空的话我会考虑翻译一遍)。

2.1 爬取准备

以下内容全部基于R语言。首先安装并导入edgar包:

install.packages('edgar')
library(edgar)

接着设置working directory,之后爬取到的所有内容将默认保存到该wd中。然后是爬虫的常规操作,user agent。该包需要提交的user-agent格式为: 姓名 邮箱,将其作为字符串赋值即可。

setwd("F:/EDGAR")
myid <- 'GOTO Ryusuke niccolologne@gmail.com'
2.2 下载QMI信息

我的任务是下载2021Q1到2022Q2的所有10-K、10-Q及8-K报表,所以需要的QMI为六个季度。在edgar中,我们先使用getMasterIndex函数来下载QMI信息到本地路径:

getMasterIndex(c(2021,2022),myid)

其中第一个参数为想要获取的年份,第二个参数为user-agent。执行操作后会自动创建一个名为“Master Indexes”的文件夹,其中包含指定年份内.idx文件的压缩包及.Rda文件。先导入2021、2022年的.Rda文件:

load("F:/EDGAR/Master Indexes/2021master.Rda")
edgarR3 <- year.master
load("F:/EDGAR/Master Indexes/2022master.Rda")
edgarR4 <- year.master

结果得到edgarR3、edgarR4两个dateframe,具体结构如下图:

 

可以看到所有信息已经以非常organised的形式包含在这个dataframe里了,我们只要根据需求筛选所需报表的类型、找出对应CIK即可。

以获取6个季度内所有8-K报表信息为例。首先筛选出两年内所有的8-K表格:

ind.R3.8K <- which(edgarR3$form.type=='8-K')
ind.R4.8K <- which(edgarR4$form.type=='8-K')
f8k <- rbind(edgarR3[ind.R3.8K,],edgarR4[ind.R4.8K,])

接着看看各个季度的8-K报表编成情况:

> nrow(f8k)
[1] 98050

可见6个季度内一共有近10万份8-K报表被上传到EDGAR系统中。如果想要知道这些报表来自多少个CIK,可以直接调用f8k中的CIK变量:

> cik.8K <- as.integer(unique(f8k$cik))
> length(cik.8K)
[1] 8140

这9.8万份8-K由8140个独特的编写人员编写并上传完成。如果需要进一步查看公司名称、筛选某些公司的8-K报表进行爬取,可以直接对f8k的name变量进行筛选操作。

3. 爬取报表

edgar包提供了非常便利的函数来帮助爬取报表,因此我们不需要考虑访问间隔(若自己搭建爬虫而不注意设置间隔,1秒内访问超过10次会导致封IP)和路径等复杂的问题。仍以爬取8-K报表为例,我们使用getFilings函数来获取txt格式的8-K报表。该函数的参数如下:

  • cik.no: 由目标公司CIK码组成的整数型向量。若要获取来自所有CIK的报表,则需输入字符串 'ALL';
  • form.type: 目标报表类型。与cik,no类似,若要获取所有类型的报表,输入字符串 'ALL';
  • filing.year: 由目标年份组成的四位数整数型向量;
  • quarter: 由目标季度组成的一位数整数型向量。默认为4个季度。
  • downl.permit: 爬取前是否需要二次确认。默认为需要。个人建议最好不要设置为 'False',有时候会莫名其妙的导致爬取无法进行,而且二次确认也不会花费多少时间,只需在给出提示后输入 'y'即可。
  • useragent

由于我的任务是所有8-K报表,参数输入如下:

> get.8K <- getFilings('ALL',
+                      '8-K',
+                      c(2021,2022),
+                      useragent = myid)
Total number of filings to be downloaded = 98050. Do you want to download (y/n)? 

出现二次确认后输入 'y'即可开始下载。此处将结果返回给get.8K,有助于后期导出统计表格。该函数的返回类型也是一个dataframe,包含以下变量:

同时所有下载好的txt格式的报表也可在wd的 'Edgar filings_full textForm 8-K' 下找到,并且已经按照CIK分好文件夹。老板要求给出一个Excel大表来列出CIK、编成日期、公司名、本地路径及文件名等信息,这个表格也有利于之后提取文本内容并进行清洗,所以又加了以下代码来输出包含所需信息的Excel表格:

exl.8k <- get.8K[,1:4]
names(exl.8k) <- c('CIK','CompanyName','FormType','FilingDate')

FileName <- c()
for (i in 1:nrow(get.8K)) {
  main.file <- 'F:/EDGAR/Edgar filings_full text/Form 8-K'
  child.file <- get.8K$cik[i]
  parent.address <- paste(main.file,child.file, sep = '/')
  
  temp.name <- paste(get.8K$accession.number[i],
                     '.txt',
                     sep = '')
  
  full.name <- paste(get.8K$cik[i],
                     get.8K$form.type[i],
                     get.8K$date.filed[i],
                     temp.name,
                     sep = '_')
  
  local.address <- paste(parent.address,'/',full.name,sep = '')
  
  FileName[i] <- local.address
}

 可以查看得到的本地路径向量:

> FileName[1:10]
 [1] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-01-25_0001564590-21-002004.txt"
 [2] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-02-03_0001564590-21-003940.txt"
 [3] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-03-08_0001564590-21-011365.txt"
 [4] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-06-02_0001564590-21-031267.txt"
 [5] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-06-11_0001564590-21-032560.txt"
 [6] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-06-29_0001564590-21-034885.txt"
 [7] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-07-30_0001564590-21-039333.txt"
 [8] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-09-02_0000950170-21-001640.txt"
 [9] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-09-02_0000950170-21-001647.txt"
[10] "F:/EDGAR/Edgar filings_full text/Form 8-K/1000045/1000045_8-K_2021-09-30_0000950170-21-001953.txt"

最后将本地路径作为新变量加入exl.8k,并输出为Excel即可:

exl.8k$FileName <- FileName
write_xlsx(exl.8k,"2021Q1-2022Q2_8-K_AllFirms(WithLocalAddress).xlsx")

 

下一部分的内容:

使用Python对10-Q、8-K报表进行初步清洗;获取各个item的起始、结束位置。

 

 

 

 

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/920270.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号