public IFilingParserResult Parse(IFilingParserParams parserParams) { ResetState(); SECParserParams secParams = parserParams as SECParserParams; SECParserResult result = new SECParserResult(); try { ValidateFile(secParams, result); if (result.Success) { var doc = OpenDocument(secParams); if (doc != null) { ExtractCompanyData(doc, result); ExtractFilingData(doc, result); ExtractReportingOwnerData(doc, result); ExtractNonDerivaties(doc, result, result.PeriodEnd); ExtractDerivaties(doc, result); } } } catch (Exception ex) { result.Success = false; result.AddError(EErrorCodes.ParserError, EErrorType.Error, ex.Message); } return(result); }
public IFilingParserResult Parse(IFilingParserParams parserParams) { SECParserParams secParams = parserParams as SECParserParams; SECParserResult result = new SECParserResult(); try { ValidateFiles(secParams, result); if (result.Success) { XmlDocument docPrimary = OpenDocument(secParams, "primary_doc.xml"); XmlDocument docInfoTable = OpenDocument(secParams, "form13fInfoTable.xml"); ExtractFilingData(docPrimary, result); ExtractGeneralData(docPrimary, result); ExtractManagersData(docPrimary, result); ExtractHoldingsData(docInfoTable, result); } } catch (Exception ex) { result.Success = false; result.AddError(EErrorCodes.ParserError, EErrorType.Error, ex.Message); } return(result); }
protected void ValidateFile(SECParserParams secParams, SECParserResult secResult) { if (secParams.FileContent == null || !secParams.FileContent.Values.ElementAt(0).CanRead) { secResult.Success = false; secResult.AddError(EErrorCodes.FileNotFound, EErrorType.Error, "Stream is unaccessable"); } }
protected void ExtractXmlData(XmlDocument doc, SECParserResult secResult, string[][] tags, Dictionary <string, string> values) { foreach (var pair in tags) { XmlNodeList nodes = doc.GetElementsByTagName(pair[0]); if (nodes != null && nodes.Count > 0) { values.Add(pair[1], nodes[0].InnerText); } } }
void ExtractFilingData(XmlDocument doc, SECParserResult secResult) { string[][] tags = { new string[] { "periodOfReport", "DocumentPeriodStartDate" }, new string[] { "periodOfReport", "DocumentPeriodEndDate" }, new string[] { "documentType", "DocumentType" }, }; ExtractXmlData(doc, secResult, tags, secResult.FilingData); }
void ExtractCompanyData(XmlDocument doc, SECParserResult secResult) { string[][] tags = { new string[] { "issuerName", "EntityRegistrantName" }, new string[] { "issuerTradingSymbol", "TradingSymbol" }, new string[] { "issuerCik", "EntityCentralIndexKey" } }; ExtractXmlData(doc, secResult, tags, secResult.CompanyData); }
void ExtractReportingOwnerData(XmlDocument doc, SECParserResult secResult) { string[][] tags = { new string[] { "rptOwnerName", "OwnerName" }, new string[] { "rptOwnerCik", "OwnerCentralIndexKey" }, new string[] { "rptOwnerStreet1", "OwnerAddressStreet1" }, new string[] { "rptOwnerStreet2", "OwnerAddressStreet2" }, new string[] { "rptOwnerCity", "OwnerAddressCity" }, new string[] { "rptOwnerState", "OwnerAddressState" }, new string[] { "rptOwnerZipCode", "OwnerAddressZipCode" }, new string[] { "rptOwnerStateDescription", "OwnerAddressStateDesc" }, new string[] { "isDirector", "OwnerIsDirector" }, new string[] { "isOfficer", "OwnerIsOfficer" }, new string[] { "isTenPercentOwner", "Owner10PercentHolder" }, new string[] { "isOther", "OwnerOther" }, new string[] { "officerTitle", "OwnerOfficerTitle" }, new string[] { "otherText", "OwnerOtherText" }, }; Dictionary <string, string> values = new Dictionary <string, string>(); ExtractXmlData(doc, secResult, tags, values); string factId = GenerateMultivalueFactId(); Statement statementSection = new Statement("ReportingOwner"); foreach (var k in values.Keys) { decimal decValue = 0; StatementRecord record = new StatementRecord( k, Decimal.TryParse(values[k], out decValue) ? (object)decValue : values[k], null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId ); if (!statementSection.Records.Contains(record)) { statementSection.Records.Add(record); } } secResult.Statements.Add(statementSection); }
void ExtractFilingData(XmlDocument doc, SECParserResult secResult) { XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(doc.NameTable); xmlnsManager.AddNamespace("def", "http://www.sec.gov/edgar/thirteenffiler"); XmlNode nType = doc.SelectSingleNode("//def:submissionType", xmlnsManager); XmlNode nPeriodEnd = doc.SelectSingleNode("//def:edgarSubmission//def:headerData//def:filerInfo//def:periodOfReport", xmlnsManager); string documentType = nType.InnerText; DateTime periodEnd = DateTime.ParseExact(nPeriodEnd.InnerText, "MM-dd-yyyy", CultureInfo.InvariantCulture); DateTime periodStart = periodEnd; // TODO: need to figure out whether there are any difference in annual/quarterly reporting secResult.FilingData.Add("DocumentType", documentType); secResult.FilingData.Add("DocumentPeriodStartDate", periodStart.ToString()); secResult.FilingData.Add("DocumentPeriodEndDate", periodEnd.ToString()); }
private void ValidateFiles(SECParserParams secParams, SECParserResult secResult) { if (secParams.FileContent != null && secParams.FileContent.Count > 0) { foreach (var s in secParams.FileContent) { if (!s.Value.CanRead) { secResult.Success = false; secResult.AddError(EErrorCodes.FileNotFound, EErrorType.Error, string.Format("Stream {0} is unaccessable", s.Key)); } } } else { secResult.Success = false; secResult.AddError(EErrorCodes.FileNotFound, EErrorType.Error, "Streams were not provided"); } }
void ExtractGeneralData(XmlDocument doc, SECParserResult secResult) { XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(doc.NameTable); xmlnsManager.AddNamespace("def", "http://www.sec.gov/edgar/thirteenffiler"); XmlNode nTotalValue = doc.SelectSingleNode("//def:edgarSubmission//def:formData//def:summaryPage//def:tableValueTotal", xmlnsManager); XmlNode nEntityTotal = doc.SelectSingleNode("//def:edgarSubmission//def:formData//def:summaryPage//def:tableEntryTotal", xmlnsManager); string idTotalValue = GenerateMultivalueFactId(); string idEntityTotal = GenerateMultivalueFactId(); Statement statementSection = new Statement("Totals"); secResult.Statements.Add(statementSection); statementSection.Records.Add(new StatementRecord( "TableValueTotal", Decimal.Parse(nTotalValue.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, idTotalValue )); statementSection.Records.Add(new StatementRecord( "TableEntryTotal", Decimal.Parse(nEntityTotal.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, idEntityTotal )); }
void ExtractDerivaties(XmlDocument doc, SECParserResult secResult) { string xpath = "//derivativeTable//derivativeTransaction"; XmlNodeList nsNonDerivs = doc.SelectNodes(xpath); if (nsNonDerivs != null && nsNonDerivs.Count > 0) { Statement section = new Statement("DerivativeTransactions"); secResult.Statements.Add(section); foreach (XmlNode n in nsNonDerivs) { string factId = GenerateMultivalueFactId(); XmlNode nSecurityTitle = n.SelectSingleNode("securityTitle//value"); XmlNode nConvExPrice = n.SelectSingleNode("conversionOrExercisePrice//value"); XmlNode nTransactionDate = n.SelectSingleNode("transactionDate//value"); XmlNode nTransactionFormType = n.SelectSingleNode("transactionCoding//transactionFormType"); XmlNode nTransactionFormTransCode = n.SelectSingleNode("transactionCoding//transactionCode"); XmlNode nTransactionFormEquitySwapInvolved = n.SelectSingleNode("transactionCoding//equitySwapInvolved"); XmlNode nTransactionAmountShares = n.SelectSingleNode("transactionAmounts//transactionShares//value"); XmlNode nTransactionAmountPrice = n.SelectSingleNode("transactionAmounts//transactionPricePerShare//value"); XmlNode nTransactionAmountADCode = n.SelectSingleNode("transactionAmounts//transactionAcquiredDisposedCode//value"); XmlNode nExDate = n.SelectSingleNode("exerciseDate//value"); XmlNode nExpDate = n.SelectSingleNode("expirationDate//value"); XmlNode nUnderSecurityTitle = n.SelectSingleNode("underlyingSecurity//underlyingSecurityTitle//value"); XmlNode nUnderSecurityShares = n.SelectSingleNode("underlyingSecurity//underlyingSecurityShares//value"); XmlNode nPostShares = n.SelectSingleNode("postTransactionAmounts//sharesOwnedFollowingTransaction//value"); XmlNode nPostOwnership = n.SelectSingleNode("ownershipNature//directOrIndirectOwnership//value"); DateTime dtDate = DateTime.Parse(nTransactionDate.InnerText); StatementRecord rIsDerivTrans = new StatementRecord( "IsDerivTrans", (decimal)1.0, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rIsDerivTrans); if (nSecurityTitle != null) { StatementRecord rSecurityTitle = new StatementRecord( "SecurityTitle", nSecurityTitle.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rSecurityTitle); } if (nConvExPrice != null) { StatementRecord rConvExPrice = new StatementRecord( "ConversionOrExercisePrice", Decimal.Parse(nConvExPrice.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rConvExPrice); } if (nTransactionFormType != null) { StatementRecord rFormType = new StatementRecord( "FormType", nTransactionFormType.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rFormType); } if (nTransactionFormTransCode != null) { StatementRecord rFormTransCode = new StatementRecord( "TransactionCode", nTransactionFormTransCode.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rFormTransCode); } if (nTransactionFormEquitySwapInvolved != null) { StatementRecord rFormEquitySwapInv = new StatementRecord( "EquitySwapInvolved", Decimal.Parse(nTransactionFormEquitySwapInvolved.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rFormEquitySwapInv); } if (nTransactionAmountShares != null) { StatementRecord rTransShares = new StatementRecord( "TransactionShares", (nTransactionAmountADCode != null && nTransactionAmountADCode.InnerText.ToUpper().Equals("D") ? -1 : 1) * Decimal.Parse(nTransactionAmountShares.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rTransShares); } if (nTransactionAmountPrice != null) { StatementRecord rTransPrice = new StatementRecord( "TransactionPrice", Decimal.Parse(nTransactionAmountPrice.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rTransPrice); } if (nExDate != null) { StatementRecord rExDate = new StatementRecord( "ExerciseDate", DateTime.Parse(nExDate.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rExDate); } if (nExpDate != null) { StatementRecord rExpDate = new StatementRecord( "ExpirationDate", DateTime.Parse(nExpDate.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rExpDate); } if (nUnderSecurityTitle != null) { StatementRecord rUnderSecurityTitle = new StatementRecord( "UnderlyingSecurityTitle", nUnderSecurityTitle.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rUnderSecurityTitle); } if (nUnderSecurityShares != null) { StatementRecord rUnderSecurityShares = new StatementRecord( "UnderlyingSecurityShares", Decimal.Parse(nUnderSecurityShares.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rUnderSecurityShares); } if (nPostShares != null) { StatementRecord rPostShares = new StatementRecord( "PostTransactionSharesOwnership", Decimal.Parse(nPostShares.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rPostShares); } if (nPostOwnership != null) { StatementRecord rPostOwnership = new StatementRecord( "PostTransactionDirectOrIndirectOwnership", nPostOwnership.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rPostOwnership); } } } }
void ExtractNonDerivaties(XmlDocument doc, SECParserResult secResult, DateTime dtReportDate) { string[] xpaths = { "//nonDerivativeTable//nonDerivativeTransaction", "//nonDerivativeTable//nonDerivativeHolding" }; foreach (var xpath in xpaths) { XmlNodeList nsNonDerivs = doc.SelectNodes(xpath); if (nsNonDerivs != null && nsNonDerivs.Count > 0) { Statement section = new Statement("NonDerivativeTransactions"); secResult.Statements.Add(section); foreach (XmlNode n in nsNonDerivs) { string factId = GenerateMultivalueFactId(); XmlNode nSecurityTitle = n.SelectSingleNode("securityTitle//value"); XmlNode nTransactionDate = n.SelectSingleNode("transactionDate//value"); XmlNode nTransactionFormType = n.SelectSingleNode("transactionCoding//transactionFormType"); XmlNode nTransactionFormTransCode = n.SelectSingleNode("transactionCoding//transactionCode"); XmlNode nTransactionFormEquitySwapInvolved = n.SelectSingleNode("transactionCoding//equitySwapInvolved"); XmlNode nTransactionAmountShares = n.SelectSingleNode("transactionAmounts//transactionShares//value"); XmlNode nTransactionAmountPrice = n.SelectSingleNode("transactionAmounts//transactionPricePerShare//value"); XmlNode nTransactionAmountADCode = n.SelectSingleNode("transactionAmounts//transactionAcquiredDisposedCode//value"); XmlNode nPostShares = n.SelectSingleNode("postTransactionAmounts//sharesOwnedFollowingTransaction//value"); XmlNode nPostOwnership = n.SelectSingleNode("ownershipNature//directOrIndirectOwnership//value"); XmlNode nOwnershipNature = n.SelectSingleNode("ownershipNature//natureOfOwnership//value"); DateTime dtDate = dtReportDate; if (nTransactionDate != null) { dtDate = DateTime.Parse(nTransactionDate.InnerText); } StatementRecord rIsDerivTrans = new StatementRecord( "IsDerivTrans", (decimal)0.0, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rIsDerivTrans); if (nSecurityTitle != null) { StatementRecord rSecurityTitle = new StatementRecord( "SecurityTitle", nSecurityTitle.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rSecurityTitle); } if (nTransactionFormType != null) { StatementRecord rFormType = new StatementRecord( "FormType", nTransactionFormType.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rFormType); } if (nTransactionFormTransCode != null) { StatementRecord rFormTransCode = new StatementRecord( "TransactionCode", nTransactionFormTransCode.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rFormTransCode); } if (nTransactionFormEquitySwapInvolved != null) { decimal dEquitySwapInvolved = 0; if (!Decimal.TryParse(nTransactionFormEquitySwapInvolved.InnerText, out dEquitySwapInvolved)) { bool bEquitySwapInvolved = false; bool.TryParse(nTransactionFormEquitySwapInvolved.InnerText, out bEquitySwapInvolved); dEquitySwapInvolved = bEquitySwapInvolved ? 1 : 0; } StatementRecord rFormEquitySwapInv = new StatementRecord( "EquitySwapInvolved", dEquitySwapInvolved, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rFormEquitySwapInv); } if (nTransactionAmountShares != null) { StatementRecord rTransShares = new StatementRecord( "TransactionShares", (nTransactionAmountADCode != null && nTransactionAmountADCode.InnerText.ToUpper().Equals("D") ? -1 : 1) * Decimal.Parse(nTransactionAmountShares.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rTransShares); } if (nTransactionAmountPrice != null) { StatementRecord rTransPrice = new StatementRecord( "TransactionPrice", Decimal.Parse(nTransactionAmountPrice.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rTransPrice); } if (nPostShares != null) { StatementRecord rPostShares = new StatementRecord( "PostTransactionSharesOwnership", Decimal.Parse(nPostShares.InnerText), null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rPostShares); } if (nPostOwnership != null) { StatementRecord rPostOwnership = new StatementRecord( "PostTransactionDirectOrIndirectOwnership", nPostOwnership.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rPostOwnership); } if (nOwnershipNature != null) { StatementRecord rOwnershipNature = new StatementRecord( "PostTransactionOwnershipNature", nOwnershipNature.InnerText, null, dtDate, dtDate, dtDate, null, factId); section.Records.Add(rOwnershipNature); } } } } }
void ExtractHoldingsData(XmlDocument doc, SECParserResult secResult) { XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(doc.NameTable); xmlnsManager.AddNamespace("def", "http://www.sec.gov/edgar/document/thirteenf/informationtable"); string xpath = "//def:informationTable//def:infoTable"; XmlNodeList nsNonDerivs = doc.SelectNodes(xpath, xmlnsManager); if (nsNonDerivs != null && nsNonDerivs.Count > 0) { Statement section = new Statement("Holdings"); secResult.Statements.Add(section); foreach (XmlNode n in nsNonDerivs) { string factId = GenerateMultivalueFactId(); XmlNode nNameOfIssuer = null; XmlNode nTitleOfClass = null; XmlNode nCusip = null; XmlNode nValue = null; XmlNode nAmount = null; XmlNode nType = null; XmlNode nInvestmentDiscretion = null; XmlNode nPutCall = null; XmlNode nOtherManager = null; XmlNode nVoteSole = null; XmlNode nVoteShared = null; XmlNode nVoteNone = null; foreach (XmlNode c in n.ChildNodes) { switch (c.Name) { case "nameOfIssuer": nNameOfIssuer = c; break; case "titleOfClass": nTitleOfClass = c; break; case "cusip": nCusip = c; break; case "value": nValue = c; break; case "shrsOrPrnAmt": nAmount = c.SelectSingleNode("def:sshPrnamt", xmlnsManager); nType = c.SelectSingleNode("def:sshPrnamtType", xmlnsManager); break; case "investmentDiscretion": nInvestmentDiscretion = c; break; case "putCall": nPutCall = c; break; case "otherManager": nOtherManager = c; break; case "votingAuthority": nVoteSole = c.SelectSingleNode("def:Sole", xmlnsManager); nVoteShared = c.SelectSingleNode("def:Shared", xmlnsManager); nVoteNone = c.SelectSingleNode("def:None", xmlnsManager); break; } } if (nNameOfIssuer != null) { section.Records.Add(new StatementRecord( "NameOfIssuer", nNameOfIssuer.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nTitleOfClass != null) { section.Records.Add(new StatementRecord( "TitleOfClass", nTitleOfClass.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nCusip != null) { section.Records.Add(new StatementRecord( "CUSIP", nCusip.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nValue != null) { section.Records.Add(new StatementRecord( "Value", Decimal.Parse(nValue.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nAmount != null) { section.Records.Add(new StatementRecord( "Amount", Decimal.Parse(nAmount.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nType != null) { section.Records.Add(new StatementRecord( "Type", nType.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nInvestmentDiscretion != null) { section.Records.Add(new StatementRecord( "InvestmentDiscretion", nInvestmentDiscretion.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nPutCall != null) { section.Records.Add(new StatementRecord( "PutCall", nPutCall.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nOtherManager != null) { section.Records.Add(new StatementRecord( "OtherManager", nOtherManager.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nVoteSole != null) { section.Records.Add(new StatementRecord( "VoteSole", Decimal.Parse(nVoteSole.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nVoteShared != null) { section.Records.Add(new StatementRecord( "VoteShared", Decimal.Parse(nVoteShared.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nVoteNone != null) { section.Records.Add(new StatementRecord( "VoteNone", Decimal.Parse(nVoteNone.InnerText.Trim()), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } #if DEBUG //if (section.Records.Count > 100000) break; #endif } } }
void ExtractManagersData(XmlDocument doc, SECParserResult secResult) { XmlNamespaceManager xmlnsManager = new XmlNamespaceManager(doc.NameTable); xmlnsManager.AddNamespace("def", "http://www.sec.gov/edgar/thirteenffiler"); string xpath = "//def:edgarSubmission//def:summaryPage//def:otherManagers2Info//def:otherManager2"; XmlNodeList nsNonDerivs = doc.SelectNodes(xpath, xmlnsManager); if (nsNonDerivs != null && nsNonDerivs.Count > 0) { Statement section = new Statement("Managers"); secResult.Statements.Add(section); foreach (XmlNode n in nsNonDerivs) { string factId = GenerateMultivalueFactId(); XmlNode nSeqNumber = n.SelectSingleNode("def:sequenceNumber", xmlnsManager); XmlNode nManagerF13FileNum = n.SelectSingleNode("def:otherManager//def:form13FFileNumber", xmlnsManager); XmlNode nManagerName = n.SelectSingleNode("def:otherManager//def:name", xmlnsManager); if (nSeqNumber != null) { section.Records.Add(new StatementRecord( "SequenceNumber", nSeqNumber.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nManagerF13FileNum != null) { section.Records.Add(new StatementRecord( "ManagerForm13FFileNumber", nManagerF13FileNum.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } if (nManagerName != null) { section.Records.Add(new StatementRecord( "ManagerName", nManagerName.InnerText.Trim(), null, secResult.PeriodStart, secResult.PeriodEnd, secResult.PeriodEnd, null, factId)); } } } }