/// <summary> /// Parse stock information into pseDocument object /// </summary> /// <param name="pseDocument"></param> private void ParseReportBody(PSEDocument pseDocument) { SectorItem sector = null; Nullable <ulong> uLongValue = null; Nullable <double> doubleValue = null; foreach (string s in this.reportBody) { //retrieve the sector object then move on to the next line if (sectorNameMap.ContainsValue(s)) { sector = pseDocument.GetSector(sectorNameMap.GetKey(s)); bool parseCondition = (s == sectorNameMap[PSEDocument.PREFERRED]) || (s == sectorNameMap[PSEDocument.SME]) || (s == sectorNameMap[PSEDocument.WARRANT]); if (DateTime.Compare(_tradeDate, _reportChangeDate1) >= 0) { parseCondition = parseCondition || s == sectorNameMap[PSEDocument.DEPOSITORY_RECEIPTS]; } if (DateTime.Compare(_tradeDate, _reportChangeDate2) >= 0) { parseCondition = parseCondition || s == sectorNameMap[PSEDocument.ETF]; } if (DateTime.Compare(_tradeDate, _reportChangeDate3) >= 0) { parseCondition = parseCondition || s == sectorNameMap[PSEDocument.DOLLAR_DONOMINATED_SECURITIES]; } if (parseCondition) { var subSector = new SubSectorItem(); subSector.Name = s; sector.SubSectors.Add(subSector); } continue; } string[] row = s.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (row[0] == "****") { // retrieve the subsector then create the subsector object // continue to the next line after var subSector = new SubSectorItem(); string subSectorName = s.Replace("****", null); subSector.Name = subSectorName.Trim(); sector.SubSectors.Add(subSector); continue; } // skip volume summary if (s.Contains("TOTAL VOLUME")) { continue; } if (sector.SubSectors.Count == 0) { sector.SubSectors.Add(new SubSectorItem() { Name = "UNKNOWN" }); } // now load stock information into the subsector object row = row.Reverse <string>().ToArray <string>(); SubSectorItem currentSubSector = sector.SubSectors[sector.SubSectors.Count - 1]; // always points to the last added subsector //Name Symbol Bid Ask Open High Low Close Volume Value NB/S //in reverse order StockItem stock = new StockItem(pseDocument, sector); doubleValue = row[0].ParseDouble(); stock.NetForeignBuy = doubleValue.HasValue ? (double)doubleValue : 0; doubleValue = row[1].ParseDouble(); stock.Value = doubleValue.HasValue ? (double)doubleValue : 0; uLongValue = row[2].ParseUlong(); stock.Volume = uLongValue.HasValue ? (ulong)uLongValue : 0; doubleValue = row[3].ParseDouble(); stock.Close = doubleValue.HasValue ? (double)doubleValue : 0; doubleValue = row[4].ParseDouble(); stock.Low = doubleValue.HasValue ? (double)doubleValue : 0; doubleValue = row[5].ParseDouble(); stock.High = doubleValue.HasValue ? (double)doubleValue : 0; doubleValue = row[6].ParseDouble(); stock.Open = doubleValue.HasValue ? (double)doubleValue : 0; doubleValue = row[7].ParseDouble(); stock.Ask = doubleValue.HasValue ? (double)doubleValue : 0; doubleValue = row[8].ParseDouble(); stock.Bid = doubleValue.HasValue ? (double)doubleValue : 0; stock.Symbol = row[9]; int index = 9; StringBuilder sb = new StringBuilder(); for (int i = row.Length - 1; i > index; i--) { sb.Append(row[i] + " "); } stock.Description = sb.ToString().TrimEnd(); currentSubSector.Stocks.Add(stock); } }
private void ParseReportBody() { string[] lines = _reportString.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); SectorItem sector = null; SubSectorItem subSector = null; foreach (var line in lines) { // end of the line var pattern = @"(TOTAL MAIN BOARD.+\s+)(.+)"; if (Regex.Match(line, pattern).Success) { break; } // create the sector object pattern = @"\b([A-Z&\.,]\s+)+([A-Z])\b"; Match sectorTextMatch = Regex.Match(line, pattern); if (sectorTextMatch.Success) { var sectorKey = sectorNameMap.GetKey(sectorTextMatch.Value); Debug.Assert(sectorKey != null, "Unable to locate sector key" + sectorTextMatch.Value); sector = _pseDocument.GetSector(sectorKey); // not all sectors have sub-sectors. // we have to null this to make sure stocks don't get mixed up in other sectors subSector = null; continue; } // sub sector // proceed to next line if matched pattern = @"(\*+\s+)(.+\s)(.\*+)"; Match match = Regex.Match(line, pattern); if (match.Success) { Debug.Assert(sector != null, "Unable to initialize the sector object."); subSector = new SubSectorItem(); subSector.Name = match.Groups[2].Value.Trim(); sector.SubSectors.Add(subSector); continue; } // will only match stocks that has trading activity pattern = @"\b([\w]+\s)+\b([0-9\.\s,\(\)\-]+)"; // malformed report line looks like this // 506,200 8,042,620 4,009,350 // LT GROUP LTG 15.9 15.98 15.78 15.98 15.78 15.9 var stockLine = line; if (_errorLine != string.Empty) { // fix the malformed line stockLine = line + " " + _errorLine; _errorLine = string.Empty; // reset } if (Regex.Match(stockLine, pattern).Success) { // found the stock line Debug.Assert(sector != null, "Unable to initialize the sector object."); if (subSector == null) { // not all sectors have sub-sectors so we create a default subSector = new SubSectorItem(); subSector.Name = "DEFAULT"; sector.SubSectors.Add(subSector); } StockItem stock = ParseStockLine(stockLine, sector); if (stock != null) { subSector.Stocks.Add(stock); } } } //calculate sector netforeign buying/selling foreach (SectorItem sectorItem in _pseDocument.Sectors) { if (sectorItem.Symbol == "^PSEi") { continue; } sectorItem.NetForeignBuy = 0; foreach (SubSectorItem subSectorItem in sectorItem.SubSectors) { foreach (StockItem stockItem in subSectorItem.Stocks) { sectorItem.NetForeignBuy += stockItem.NetForeignBuy; } } } }