using System; using System.Text; using System.Collections.Generic; using System.IO; using HtmlAgilityPack; using MarketData.Utils; using MarketData.MarketDataModel; using MarketDataLib.Utility; namespace MarketData.Helper { public class InsiderTransactionsParser { private static Dictionary transactionCodes=new Dictionary(); private static InsiderTransactionsParser instance=null; private InsiderTransactionsParser() { BuildTransactionCodes(); } public static InsiderTransactionsParser GetInstance() { lock(typeof(InsiderTransactionsParser)) { if(null==instance)instance=new InsiderTransactionsParser(); return instance; } } private String ApplyNameCase(String name) { StringBuilder sb=new StringBuilder(); name=name.ToLower(); String[] parts=name.Split(' '); for(int index=0;index1)sb.Append(item.Substring(0,1).ToUpper()+item.Substring(1)); else sb.Append(item.ToUpper()); if(index sections) { String item=GetFirstSection(sections); if(item.Equals("D"))return "Direct Ownership"; else if(item.Equals("I"))return "Indirect Ownership"; return ""; } private String GetFirstSection(List sections) { if(null==sections || 0==sections.Count)return ""; return sections[0]; } private String CombineSections(List sections) { StringBuilder sb=new StringBuilder(); if(null==sections || 0==sections.Count)return ""; foreach(String section in sections) { sb.Append(section); } return sb.ToString(); } public InsiderTransactions Parse(SECFilings secFilings) { lock(instance) { try { InsiderTransactions insiderTransactions=new InsiderTransactions(); if(null==secFilings || 0==secFilings.Count)return insiderTransactions; foreach(SECFiling secFiling in secFilings) { List> dictionaryList=new List>(); String insiderName=null; String relationshipOfReportingPerson=null; byte[] streamBytes = Encoding.ASCII.GetBytes(secFiling.FormText); MemoryStream memoryStream = new MemoryStream(streamBytes); HtmlDocument htmlDocument = new HtmlDocument(); htmlDocument.Load(memoryStream); HtmlNodeCollection tables=htmlDocument.DocumentNode.SelectNodes("//table"); if(null==tables || tables.Count<5)continue; HtmlNode nameAndAddressTable=FindTable(tables,"1. Name and Address of Reporting Person"); if(null==nameAndAddressTable)continue; HtmlNodeCollection nameAndAddressRows = nameAndAddressTable.SelectNodes(".//tr"); if(nameAndAddressRows.Count<2)continue; insiderName=ApplyNameCase(nameAndAddressRows[1].InnerText); //HtmlNodeCollection nameAndAddressRows = tables[4].SelectNodes(".//tr"); //if(nameAndAddressRows.Count<10)continue; //insiderName=ApplyNameCase(nameAndAddressRows[1].InnerText); //relationshipOfReportingPerson=Utility.RemoveHtml(nameAndAddressRows[9].InnerText); for(int index=0;index dictionary=new Dictionary(); dictionary.Add("Title of Security",dataCollection[0].InnerHtml); dictionary.Add("Transaction Date",dataCollection[1].InnerHtml); dictionary.Add("Transaction Code",dataCollection[3].InnerHtml); dictionary.Add("Securities Acquired or Disposed",dataCollection[5].InnerHtml); dictionary.Add("Acquired or Disposed",dataCollection[6].InnerHtml); dictionary.Add("Price",dataCollection[7].InnerHtml); dictionary.Add("Ownership Form",dataCollection[9].InnerHtml); dictionaryList.Add(dictionary); } } } foreach(Dictionary dictionary in dictionaryList) { String strItem=null; InsiderTransaction insiderTransaction = new InsiderTransaction(); insiderTransaction.Symbol=secFiling.Symbol; insiderTransaction.SECAccessionNumber=secFiling.SECAccessionNumber; insiderTransaction.FormRowNumber=(secFiling.Sequence+1).ToString(); insiderTransaction.Form=secFiling.Form; insiderTransaction.FilingDate=secFiling.FilingDate; insiderTransaction.InsiderName=insiderName; insiderTransaction.Securities=GetFirstSection(Sections.GetSections(dictionary["Title of Security"])); insiderTransaction.OwnershipType=GetOwnershipForm(Sections.GetSections(dictionary["Ownership Form"])); if(String.IsNullOrEmpty(insiderTransaction.OwnershipType))continue; strItem=GetFirstSection(Sections.GetSections(dictionary["Transaction Date"])); if(String.IsNullOrEmpty(strItem))continue; insiderTransaction.TransactionDate=Utility.ParseDate(strItem); insiderTransaction.NatureOfTransaction=transactionCodes.ContainsKey(GetFirstSection(Sections.GetSections(dictionary["Transaction Code"])))?transactionCodes[GetFirstSection(Sections.GetSections(dictionary["Transaction Code"]))]:Constants.CONST_QUESTION; insiderTransaction.NumberOrValueAcquiredDisposed=FeedParser.ParseValue(GetFirstSection(Sections.GetSections(dictionary["Securities Acquired or Disposed"]))); insiderTransaction.Price=FeedParser.ParseValue(CombineSections(Sections.GetSections(dictionary["Price"]))); insiderTransactions.Add(insiderTransaction); } } return insiderTransactions; } catch(Exception exception) { MDTrace.WriteLine(LogLevel.DEBUG,String.Format("Parse SECFiling got exception {0}",exception.ToString())); return new InsiderTransactions(); } } } private HtmlNode FindTable(HtmlNodeCollection tables,String startsWith) { if(null==tables)return null; for(int index=0;index