The initial concept of Smart EDGAR was to provide the tools to download the data from the EDGAR website and
We have extended the funcitonality a little bit so that the Smart EDGAR Library can be used without having any data available locally. So we provide
We install the following libraries with the help of Maven
%classpath config resolver maven-public http://software.pschatzmann.ch/repository/maven-public/
%%classpath add mvn
ch.pschatzmann:smart-edgar:LATEST
ch.pschatzmann:jupyter-jdk-extensions:LATEST
Added new repo: maven-public
import ch.pschatzmann.display._
import ch.pschatzmann.edgar.base._
import ch.pschatzmann.edgar.reporting.company._
import ch.pschatzmann.edgar.dataload.rss.RSSDataSource
import ch.pschatzmann.edgar.utils.Utils
import ch.pschatzmann.edgar.base.Fact._
import ch.pschatzmann.edgar.dataload.online._
Displayers.setup
true
We provide an API to retrieve the Company information and the related filings.
We can pass a ticker symbol or a company number to the constructor of the CompanyInformation
%%time
val company = new CompanyInformation("AAPL")
CPU times: user 0 ns, sys: 398 µs, total: 398 µs Wall Time: 1 s
APPLE INC (0000320193)
Optionally we can indicate the form type in the constructor. If no form is indicated we retrieve all documents but this is taking quite some time.
%%time
val company = new CompanyInformation("320193","10-K")
CPU times: user 0 ns, sys: 288 µs, total: 288 µs Wall Time: 642 ms
APPLE INC (0000320193)
We can list all the available filings
%%time
company.entries
CPU times: user 0 ns, sys: 630 µs, total: 630 µs Wall Time: 1 s
[0000320193-18-000145:10-K, 0000320193-17-000070:10-K, 0001628280-16-020309:10-K, 0001193125-15-356351:10-K, 0001193125-14-383437:10-K, 0001193125-13-416534:10-K, 0001193125-12-444068:10-K, 0001193125-11-282113:10-K, 0001193125-10-238044:10-K, 0001193125-10-012091:10-K/A, 0001193125-09-214859:10-K, 0001193125-08-224958:10-K, 0001047469-07-009340:10-K, 0001104659-06-084288:10-K, 0001104659-05-058421:10-K, 0001047469-04-035975:10-K, 0001047469-03-041604:10-K, 0001047469-02-007674:10-K, 0000912057-01-544436:10-K405, 0000912057-00-053623:10-K, 0000912057-99-010244:10-K, 0001047469-98-044981:10-K405, 0001047469-98-001822:10-K/A, 0001047469-97-006960:10-K, 0000320193-96-000023:10-K, 0000320193-95-000016:10-K, 0000320193-94-000016:10-K]
We can also limit the enties with a Regex expression
%%time
var entries = company.entries("10-K")
CPU times: user 0 ns, sys: 284 µs, total: 284 µs Wall Time: 440 ms
[0000320193-18-000145:10-K, 0000320193-17-000070:10-K, 0001628280-16-020309:10-K, 0001193125-15-356351:10-K, 0001193125-14-383437:10-K, 0001193125-13-416534:10-K, 0001193125-12-444068:10-K, 0001193125-11-282113:10-K, 0001193125-10-238044:10-K, 0001193125-09-214859:10-K, 0001193125-08-224958:10-K, 0001047469-07-009340:10-K, 0001104659-06-084288:10-K, 0001104659-05-058421:10-K, 0001047469-04-035975:10-K, 0001047469-03-041604:10-K, 0001047469-02-007674:10-K, 0000912057-00-053623:10-K, 0000912057-99-010244:10-K, 0001047469-97-006960:10-K, 0000320193-96-000023:10-K, 0000320193-95-000016:10-K, 0000320193-94-000016:10-K]
We can get the XBRL object which contains the informaiton of all documents
%%time
var xbrl = company.getXBRL
xbrl.isEmpty
CPU times: user 0 ns, sys: 289 µs, total: 289 µs Wall Time: 21 s
false
On the level of the filing entry we provide the following:
var entry = entries.get(0)
0000320193-18-000145:10-K
We can e.g. display the Form or title ...
entry.getForm
10-K
entry.getTitle
10-K - Annual report [Section 13 and 15(d), not S-K Item 405]
entry.getLink
http://www.sec.gov/Archives/edgar/data/320193/000032019318000145/0000320193-18-000145-index.htm
Each link is pointing to a list of detailed documents:
import scala.collection.JavaConverters._
entry.getLinksToDocuments.iterator.asScala.toSeq.foreach(r => println(r))
/Archives/edgar/data/320193/000032019318000145/0000320193-18-000145-index-headers.html /Archives/edgar/data/320193/000032019318000145/0000320193-18-000145-index.html /Archives/edgar/data/320193/000032019318000145/0000320193-18-000145.txt /Archives/edgar/data/320193/000032019318000145/0000320193-18-000145-xbrl.zip /Archives/edgar/data/320193/000032019318000145/a10-k20189292018.htm /Archives/edgar/data/320193/000032019318000145/a10-k9_chartx38133a09.jpg /Archives/edgar/data/320193/000032019318000145/a10-kexhibit10172018.htm /Archives/edgar/data/320193/000032019318000145/a10-kexhibit10182018.htm /Archives/edgar/data/320193/000032019318000145/a10-kexhibit2112018.htm /Archives/edgar/data/320193/000032019318000145/a10-kexhibit2312018.htm /Archives/edgar/data/320193/000032019318000145/a10-kexhibit3112018.htm /Archives/edgar/data/320193/000032019318000145/a10-kexhibit3122018.htm /Archives/edgar/data/320193/000032019318000145/a10-kexhibit3212018.htm /Archives/edgar/data/320193/000032019318000145/aapl-20180929.xml /Archives/edgar/data/320193/000032019318000145/aapl-20180929.xsd /Archives/edgar/data/320193/000032019318000145/aapl-20180929_cal.xml /Archives/edgar/data/320193/000032019318000145/aapl-20180929_def.xml /Archives/edgar/data/320193/000032019318000145/aapl-20180929_lab.xml /Archives/edgar/data/320193/000032019318000145/aapl-20180929_pre.xml /Archives/edgar/data/320193/000032019318000145/FilingSummary.xml /Archives/edgar/data/320193/000032019318000145/Financial_Report.xlsx /Archives/edgar/data/320193/000032019318000145/g66145g66i24.jpg /Archives/edgar/data/320193/000032019318000145/R1.htm /Archives/edgar/data/320193/000032019318000145/R10.htm /Archives/edgar/data/320193/000032019318000145/R11.htm /Archives/edgar/data/320193/000032019318000145/R12.htm /Archives/edgar/data/320193/000032019318000145/R13.htm /Archives/edgar/data/320193/000032019318000145/R14.htm /Archives/edgar/data/320193/000032019318000145/R15.htm /Archives/edgar/data/320193/000032019318000145/R16.htm /Archives/edgar/data/320193/000032019318000145/R17.htm /Archives/edgar/data/320193/000032019318000145/R18.htm /Archives/edgar/data/320193/000032019318000145/R19.htm /Archives/edgar/data/320193/000032019318000145/R2.htm /Archives/edgar/data/320193/000032019318000145/R20.htm /Archives/edgar/data/320193/000032019318000145/R21.htm /Archives/edgar/data/320193/000032019318000145/R22.htm /Archives/edgar/data/320193/000032019318000145/R23.htm /Archives/edgar/data/320193/000032019318000145/R24.htm /Archives/edgar/data/320193/000032019318000145/R25.htm /Archives/edgar/data/320193/000032019318000145/R26.htm /Archives/edgar/data/320193/000032019318000145/R27.htm /Archives/edgar/data/320193/000032019318000145/R28.htm /Archives/edgar/data/320193/000032019318000145/R29.htm /Archives/edgar/data/320193/000032019318000145/R3.htm /Archives/edgar/data/320193/000032019318000145/R30.htm /Archives/edgar/data/320193/000032019318000145/R31.htm /Archives/edgar/data/320193/000032019318000145/R32.htm /Archives/edgar/data/320193/000032019318000145/R33.htm /Archives/edgar/data/320193/000032019318000145/R34.htm /Archives/edgar/data/320193/000032019318000145/R35.htm /Archives/edgar/data/320193/000032019318000145/R36.htm /Archives/edgar/data/320193/000032019318000145/R37.htm /Archives/edgar/data/320193/000032019318000145/R38.htm /Archives/edgar/data/320193/000032019318000145/R39.htm /Archives/edgar/data/320193/000032019318000145/R4.htm /Archives/edgar/data/320193/000032019318000145/R40.htm /Archives/edgar/data/320193/000032019318000145/R41.htm /Archives/edgar/data/320193/000032019318000145/R42.htm /Archives/edgar/data/320193/000032019318000145/R43.htm /Archives/edgar/data/320193/000032019318000145/R44.htm /Archives/edgar/data/320193/000032019318000145/R45.htm /Archives/edgar/data/320193/000032019318000145/R46.htm /Archives/edgar/data/320193/000032019318000145/R47.htm /Archives/edgar/data/320193/000032019318000145/R48.htm /Archives/edgar/data/320193/000032019318000145/R49.htm /Archives/edgar/data/320193/000032019318000145/R5.htm /Archives/edgar/data/320193/000032019318000145/R50.htm /Archives/edgar/data/320193/000032019318000145/R51.htm /Archives/edgar/data/320193/000032019318000145/R52.htm /Archives/edgar/data/320193/000032019318000145/R53.htm /Archives/edgar/data/320193/000032019318000145/R54.htm /Archives/edgar/data/320193/000032019318000145/R55.htm /Archives/edgar/data/320193/000032019318000145/R56.htm /Archives/edgar/data/320193/000032019318000145/R57.htm /Archives/edgar/data/320193/000032019318000145/R58.htm /Archives/edgar/data/320193/000032019318000145/R59.htm /Archives/edgar/data/320193/000032019318000145/R6.htm /Archives/edgar/data/320193/000032019318000145/R60.htm /Archives/edgar/data/320193/000032019318000145/R61.htm /Archives/edgar/data/320193/000032019318000145/R62.htm /Archives/edgar/data/320193/000032019318000145/R63.htm /Archives/edgar/data/320193/000032019318000145/R64.htm /Archives/edgar/data/320193/000032019318000145/R65.htm /Archives/edgar/data/320193/000032019318000145/R66.htm /Archives/edgar/data/320193/000032019318000145/R67.htm /Archives/edgar/data/320193/000032019318000145/R7.htm /Archives/edgar/data/320193/000032019318000145/R8.htm /Archives/edgar/data/320193/000032019318000145/R9.htm /Archives/edgar/data/320193/000032019318000145/report.css /Archives/edgar/data/320193/000032019318000145/Show.js
null
We can get the XBRL document link
entry.getLinkToXbrl
Optional[/Archives/edgar/data/320193/000032019318000145/0000320193-18-000145-xbrl.zip]
The base URL for the documents can be determied with
entry.getLinkBase
https://www.sec.gov
Or we can get the XBRL object
%%time
val xbrl = entry.getXBRL.get
xbrl.isEmpty
CPU times: user 0 ns, sys: 203 µs, total: 203 µs Wall Time: 573 ms
false
val values = xbrl.findValues("NetIncomeLoss")
values.size
20
Finally we display the xbrl values in a table
import scala.collection.JavaConverters._
values.asScala.map(factValue => factValue.getAttributes).asJava
We double check the existence of xbrl documents
import scala.collection.JavaConverters._
new CompanyInformation("320193","10-K").entries().asScala
.map(e => (e.getForm, e.getAccessionNumber, e.getLinkToXbrl) )
.foreach(t => println(t) )
(10-K,0000320193-18-000145,Optional[/Archives/edgar/data/320193/000032019318000145/0000320193-18-000145-xbrl.zip]) (10-K,0000320193-17-000070,Optional[/Archives/edgar/data/320193/000032019317000070/0000320193-17-000070-xbrl.zip]) (10-K,0001628280-16-020309,Optional[/Archives/edgar/data/320193/000162828016020309/0001628280-16-020309-xbrl.zip]) (10-K,0001193125-15-356351,Optional[/Archives/edgar/data/320193/000119312515356351/0001193125-15-356351-xbrl.zip]) (10-K,0001193125-14-383437,Optional[/Archives/edgar/data/320193/000119312514383437/0001193125-14-383437-xbrl.zip]) (10-K,0001193125-13-416534,Optional[/Archives/edgar/data/320193/000119312513416534/0001193125-13-416534-xbrl.zip]) (10-K,0001193125-12-444068,Optional[/Archives/edgar/data/320193/000119312512444068/0001193125-12-444068-xbrl.zip]) (10-K,0001193125-11-282113,Optional[/Archives/edgar/data/320193/000119312511282113/0001193125-11-282113-xbrl.zip]) (10-K,0001193125-10-238044,Optional[/Archives/edgar/data/320193/000119312510238044/0001193125-10-238044-xbrl.zip]) (10-K/A,0001193125-10-012091,Optional.empty) (10-K,0001193125-09-214859,Optional.empty) (10-K,0001193125-08-224958,Optional.empty) (10-K,0001047469-07-009340,Optional.empty) (10-K,0001104659-06-084288,Optional.empty) (10-K,0001104659-05-058421,Optional.empty) (10-K,0001047469-04-035975,Optional.empty) (10-K,0001047469-03-041604,Optional.empty) (10-K,0001047469-02-007674,Optional.empty) (10-K405,0000912057-01-544436,Optional.empty) (10-K,0000912057-00-053623,Optional.empty) (10-K,0000912057-99-010244,Optional.empty) (10-K405,0001047469-98-044981,Optional.empty) (10-K/A,0001047469-98-001822,Optional.empty) (10-K,0001047469-97-006960,Optional.empty) (10-K,0000320193-96-000023,Optional.empty) (10-K,0000320193-95-000016,Optional.empty) (10-K,0000320193-94-000016,Optional.empty)
null
We can retrieve the values from the XBRL filings
new CompanyInformation("320193","10-K")
.getXBRL.findValues("NetIncomeLoss").asScala
.map(factValue => factValue.getAttributes)
.asJava
The following example is providing KPIs directly from EDGAR
%%time
val values = new CompanyEdgarValuesEdgar(new CompanyInformation("320193"))
.setFilter(new FilterYearly())
.setParameterNames("NetIncomeLoss","OperatingIncomeLoss","ResearchAndDevelopmentExpense",
"CashAndCashEquivalentsAtCarryingValue","AvailableForSaleSecuritiesCurrent","AccountsReceivableNetCurrent",
"Revenues","SalesRevenueNet","InventoryNet","AssetsCurrent","LiabilitiesCurrent","Assets","EarningsPerShareBasic",
"StockholdersEquity")
.addFormula("Revenue","Edgar.coalesce('Revenues', 'SalesRevenueNet')")
.addFormula("QuickRatio","(CashAndCashEquivalentsAtCarryingValue + AccountsReceivableNetCurrent + AvailableForSaleSecuritiesCurrent) / LiabilitiesCurrent")
.addFormula("CurrentRatio","AssetsCurrent / LiabilitiesCurrent")
.addFormula("InventoryTurnover","Revenue / InventoryNet")
.addFormula("NetProfitMargin","NetIncomeLoss / Revenue")
.addFormula("SalesResearchRatio%","ResearchAndDevelopmentExpense / Revenue *100")
.addFormula("NetIncomeResearchRatio%","ResearchAndDevelopmentExpense / NetIncomeLoss * 100")
.addFormula("NetIncomeChange%", "NetIncomeLoss - Edgar.lag('NetIncomeLoss', -1) / Edgar.lag('NetIncomeLoss', -1) * 100 ")
.addFormula("RevenueChange%", "Edgar.percentChange('Revenue')" )
.addFormula("ResearchAndDevelopmentChange%","Edgar.percentChange('ResearchAndDevelopmentExpense')" )
.removeParameterNames("Revenues","SalesRevenueNet")
val table = values.getTable
CPU times: user 0 ns, sys: 250 µs, total: 250 µs Wall Time: 5 s
%%time
val values = new CompanyEdgarValuesRest(new CompanyInformation("320193"))
.setFilter(new FilterYearly())
.setParameterNames("NetIncomeLoss","OperatingIncomeLoss","ResearchAndDevelopmentExpense",
"CashAndCashEquivalentsAtCarryingValue","AvailableForSaleSecuritiesCurrent","AccountsReceivableNetCurrent",
"Revenues","SalesRevenueNet","InventoryNet","AssetsCurrent","LiabilitiesCurrent","Assets","EarningsPerShareBasic",
"StockholdersEquity")
.addFormula("Revenue","Edgar.coalesce('Revenues', 'SalesRevenueNet')")
.addFormula("QuickRatio","(CashAndCashEquivalentsAtCarryingValue + AccountsReceivableNetCurrent + AvailableForSaleSecuritiesCurrent) / LiabilitiesCurrent")
.addFormula("CurrentRatio","AssetsCurrent / LiabilitiesCurrent")
.addFormula("InventoryTurnover","Revenue / InventoryNet")
.addFormula("NetProfitMargin","NetIncomeLoss / Revenue")
.addFormula("SalesResearchRatio%","ResearchAndDevelopmentExpense / Revenue *100")
.addFormula("NetIncomeResearchRatio%","ResearchAndDevelopmentExpense / NetIncomeLoss * 100")
.addFormula("NetIncomeChange%", "NetIncomeLoss - Edgar.lag('NetIncomeLoss', -1) / Edgar.lag('NetIncomeLoss', -1) * 100 ")
.addFormula("RevenueChange%", "Edgar.percentChange('Revenue')" )
.addFormula("ResearchAndDevelopmentChange%","Edgar.percentChange('ResearchAndDevelopmentExpense')" )
.removeParameterNames("Revenues","SalesRevenueNet")
val table = values.getTable
CPU times: user 0 ns, sys: 215 µs, total: 215 µs Wall Time: 2 s