public static Code toYahooFormat(Code code, Country country) { if (code == null) { throw new ArgumentException("Method parameters cannot be null in toYahooFormat"); } Code result = code; if (country == Country.Malaysia) { String _code = code.toString(); // Index's code start with ^. We will not intrude index's code. if (_code.StartsWith("^") == false && _code.EndsWith(".KL") == false) { // This is not index's code, and it does not end with .KL. // Let's intrude it! result = Code.newInstance(_code + ".KL"); } } return(result); }
public List <Stock> getStocksBySymbols(List <Symbol> symbols) { List <Stock> stocks = new List <Stock>(); if (symbols.Count == 0) { return(stocks); } int time = symbols.Count / MAX_STOCK_PER_ITERATION; int remainder = symbols.Count % MAX_STOCK_PER_ITERATION; for (int i = 0; i < time; i++) { int start = i * MAX_STOCK_PER_ITERATION; int end = start + MAX_STOCK_PER_ITERATION; StringBuilder stringBuilder = new StringBuilder(getYahooCSVBasedURL()); StringBuilder symbolBuilder = new StringBuilder(); List <Symbol> expectedSymbols = new List <Symbol>(); int endLoop = end - 1; for (int j = start; j < endLoop; j++) { String symbolString1 = null; try { //symbolString = java.net.URLEncoder.encode(symbols.get(j).toString(), "UTF-8"); symbolString1 = symbols[j].toString(); } catch (Exception ex) { throw new StockNotFoundException(); } symbolBuilder.Append(symbolString1).Append("+"); expectedSymbols.Add(symbols[j]); } String symbolString = null; try { //symbolString = java.net.URLEncoder.encode(symbols.get(end - 1).toString(), "UTF-8"); symbolString = symbols[end - 1].toString(); } catch (Exception ex) { throw new StockNotFoundException(); } symbolBuilder.Append(symbolString); expectedSymbols.Add(symbols[end - 1]); String _symbol = symbolBuilder.ToString(); stringBuilder.Append(_symbol).Append(YAHOO_STOCK_FORMAT); String location = stringBuilder.ToString(); bool success = false; for (int retry = 0; retry < NUM_OF_RETRY; retry++) { String respond = Gui.Utils.getResponseBodyAsStringBasedOnProxyAuthOption(location); if (respond == null) { continue; } List <Stock> tmpStocks = YahooStockFormat.getInstance().parse(respond); if (tmpStocks.Count != MAX_STOCK_PER_ITERATION) { if (retry == (NUM_OF_RETRY - 1)) { int currSize = tmpStocks.Count; int expectedSize = expectedSymbols.Count; if (this.isToleranceAllowed(currSize, expectedSize)) { List <Symbol> currSymbols = new List <Symbol>(); List <Stock> emptyStocks = new List <Stock>(); foreach (Stock stock in tmpStocks) { currSymbols.Add(stock.getSymbol()); } foreach (Symbol symbol in expectedSymbols) { if (currSymbols.Contains(symbol) == false) { emptyStocks.Add(Gui.Utils.getEmptyStock(Code.newInstance(symbol.toString()), symbol)); } } tmpStocks.AddRange(emptyStocks); } else { throw new StockNotFoundException("Expect " + expectedSize + " stock(s), but only receive " + currSize + " stock(s) from " + location); } } // if (retry == (NUM_OF_RETRY-1)) continue; } // if (tmpStocks.Count != MAX_STOCK_PER_ITERATION) stocks.AddRange(tmpStocks); success = true; break; } if (success == false) { throw new StockNotFoundException("Stock size (" + stocks.Count + ") inconsistent with symbol size (" + symbols.Count + ")"); } } int start2 = symbols.Count - remainder; int end2 = start2 + remainder; StringBuilder stringBuilder2 = new StringBuilder(getYahooCSVBasedURL()); StringBuilder symbolBuilder2 = new StringBuilder(); List <Symbol> expectedSymbols2 = new List <Symbol>(); int endLoop2 = end2 - 1; for (int i = start2; i < endLoop2; i++) { String symbolString = symbols[i].toString(); symbolBuilder2.Append(symbolString).Append("+"); expectedSymbols2.Add(symbols[i]); } String symbolString2 = symbols[end2 - 1].toString(); symbolBuilder2.Append(symbolString2); expectedSymbols2.Add(symbols[end2 - 1]); String _symbol2 = symbolBuilder2.ToString(); stringBuilder2.Append(_symbol2).Append(YAHOO_STOCK_FORMAT); String location2 = stringBuilder2.ToString(); for (int retry = 0; retry < NUM_OF_RETRY; retry++) { String respond = Gui.Utils.getResponseBodyAsStringBasedOnProxyAuthOption(location2); if (respond == null) { continue; } List <Stock> tmpStocks = YahooStockFormat.getInstance().parse(respond); if (tmpStocks.Count != remainder) { if (retry == (NUM_OF_RETRY - 1)) { int currSize = tmpStocks.Count; int expectedSize = expectedSymbols2.Count; if (this.isToleranceAllowed(currSize, expectedSize)) { List <Symbol> currSymbols = new List <Symbol>(); List <Stock> emptyStocks = new List <Stock>(); foreach (Stock stock in tmpStocks) { currSymbols.Add(stock.getSymbol()); } foreach (Symbol symbol in expectedSymbols2) { if (currSymbols.Contains(symbol) == false) { emptyStocks.Add(Gui.Utils.getEmptyStock(Code.newInstance(symbol.toString()), symbol)); } } tmpStocks.AddRange(emptyStocks); } else { throw new StockNotFoundException("Expect " + expectedSize + " stock(s), but only receive " + currSize + " stock(s) from " + location2); } } // if (retry == (NUM_OF_RETRY-1)) continue; } // if (tmpStocks.Count != remainder) stocks.AddRange(tmpStocks); break; } if (stocks.Count != symbols.Count) { throw new StockNotFoundException("Stock size (" + stocks.Count + ") inconsistent with symbol size (" + symbols.Count + ")"); } return(stocks); }
private IndexHelper() { _EnumNames.Add(Index.KLSE, "KLSE"); _EnumNames.Add(Index.Second, "Second Board"); _EnumNames.Add(Index.Mesdaq, "Mesdaq"); _EnumNames.Add(Index.STI, "Straits Times Index"); _EnumNames.Add(Index.DJI, "Dow Jones Industrial Average"); _EnumNames.Add(Index.IXIC, "Nasdaq Composite"); _EnumNames.Add(Index.DAX, "DAX"); _EnumNames.Add(Index.OMXSPI, "Stockholm General"); _EnumNames.Add(Index.OMXC20CO, "OMX Copenhagen 20"); _EnumNames.Add(Index.OSEAX, "OSE All Share"); _EnumNames.Add(Index.SPMIB, "S&P/MIB"); _EnumNames.Add(Index.SMSI, "Madrid General"); _EnumNames.Add(Index.FTSE, "FTSE 100"); _EnumNames.Add(Index.FCHI, "CAC 40"); _EnumNames.Add(Index.BSESN, "BSE SENSEX"); _EnumNames.Add(Index.NSEI, "S&P CNX NIFTY"); _EnumNames.Add(Index.AORD, "All Ordinaries"); _EnumNames.Add(Index.ATX, "ATX"); _EnumNames.Add(Index.BFX, "BEL-20"); _EnumNames.Add(Index.GSPTSE, "S&P TSX Composite"); _EnumNames.Add(Index.HSI, "Hang Seng"); _EnumNames.Add(Index.JKSE, "Jakarta Composite"); _EnumNames.Add(Index.KS11, "Seoul Composite"); _EnumNames.Add(Index.AEX, "AEX"); _EnumNames.Add(Index.PSI20, "PSI 20"); _EnumNames.Add(Index.TWII, "TSEC weighted index"); _EnumNames.Add(Index.SSMI, "Swiss Market"); _EnumNames.Add(Index.BVSP, "Bovespa"); _EnumNames.Add(Index.SSEC, "China Shanghai Composite"); _EnumCodes.Add(Index.KLSE, Code.newInstance("^KLSE")); _EnumCodes.Add(Index.Second, Code.newInstance("Second")); _EnumCodes.Add(Index.Mesdaq, Code.newInstance("Mesdaq")); _EnumCodes.Add(Index.STI, Code.newInstance("^STI")); _EnumCodes.Add(Index.DJI, Code.newInstance("^DJI")); _EnumCodes.Add(Index.IXIC, Code.newInstance("^IXIC")); _EnumCodes.Add(Index.DAX, Code.newInstance("^GDAXI")); _EnumCodes.Add(Index.OMXSPI, Code.newInstance("^OMXSPI")); _EnumCodes.Add(Index.OMXC20CO, Code.newInstance("OMXC20.CO")); _EnumCodes.Add(Index.OSEAX, Code.newInstance("^OSEAX")); _EnumCodes.Add(Index.SPMIB, Code.newInstance("^SPMIB")); _EnumCodes.Add(Index.SMSI, Code.newInstance("^SMSI")); _EnumCodes.Add(Index.FTSE, Code.newInstance("^FTSE")); _EnumCodes.Add(Index.FCHI, Code.newInstance("^FCHI")); _EnumCodes.Add(Index.BSESN, Code.newInstance("^BSESN")); _EnumCodes.Add(Index.NSEI, Code.newInstance("^NSEI")); _EnumCodes.Add(Index.AORD, Code.newInstance("^AORD")); _EnumCodes.Add(Index.ATX, Code.newInstance("^ATX")); _EnumCodes.Add(Index.BFX, Code.newInstance("^BFX")); _EnumCodes.Add(Index.GSPTSE, Code.newInstance("^GSPTSE")); _EnumCodes.Add(Index.HSI, Code.newInstance("^HSI")); _EnumCodes.Add(Index.JKSE, Code.newInstance("^JKSE")); _EnumCodes.Add(Index.KS11, Code.newInstance("^KS11")); _EnumCodes.Add(Index.AEX, Code.newInstance("^AEX")); _EnumCodes.Add(Index.PSI20, Code.newInstance("^PSI20")); _EnumCodes.Add(Index.TWII, Code.newInstance("^TWII")); _EnumCodes.Add(Index.SSMI, Code.newInstance("^SSMI")); _EnumCodes.Add(Index.BVSP, Code.newInstance("^BVSP")); _EnumCodes.Add(Index.SSEC, Code.newInstance("000001.SS")); }
private List <Stock> getStocks(String respond) { List <Stock> stocks = new List <Stock>(); // In order to avoid duplicated stock's code. HashSet <Code> codes = new HashSet <Code>(); // A hacking way to prevent // <a href="http://uk.finance.yahoo.com/q?s=SCRIA.ST+NCCA.ST+SHBB.ST+ELUXA.ST+LATOA.ST+VOLVA.ST+SCVA.ST+SKFA.ST+SEBC.ST+DV-BTA-1.ST+MTGB.ST+63054.ST+37341.ST+HOLMA.ST+TEL2A.ST+62893.ST+RATOA.ST+585671.ST+">View Quotes for All Above Symbols</a> // going into our database. Although we had placed some restriction on the // symbol maximum length, it may be some exceptional case sometimes. // For example : <a href="http://uk.finance.yahoo.com/q?s=SCRIA.ST+NCCA.ST+">View Quotes for All Above Symbols</a> Regex nonSymbolPattern = new Regex("View Quotes for All Above Symbols", RegexOptions.IgnoreCase); var matcher = stockAndBoardPattern.Matches(respond); for (int i = 1; i <= matcher.Count; i += 3) { String c = matcher[i].Value; if (c == null) { continue; } String s = matcher[i + 1].Value; if (s == null) { continue; } String b = matcher[i + 2].Value; if (b == null) { continue; } c = c.Trim(); s = s.Trim(); // Change Parken Sport & Entertainment A/S to // Parken Sport & Entertainment A/S s = HttpUtility.HtmlDecode(s); if (nonSymbolPattern.IsMatch(s)) { continue; } // Enum name is not allowed to have space in between. b = b.Trim().Replace("\\s+", ""); Code code = Code.newInstance(c); Symbol symbol = Symbol.newInstance(s); Stock.Board board = Stock.Board.Unknown; if (codes.Add(code) == false) { // The stock with same code had been added previously. We // do not want any stock with duplicated code. continue; } // Since '-' character is not allowed in enum, we need some sort // of hacking. if (b == "Virt-X") { b = "Virt_X"; } try { board = (Stock.Board)Enum.Parse(typeof(Stock.Board), b); } catch (ArgumentException exp) { log.Error(null, exp); board = Stock.Board.Unknown; } Stock stock = new Stock( code, symbol, "", board, Stock.Industry.Unknown, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, 0.0, 0, Calendar.getInstance() ); stocks.Add(stock); } return(stocks); }
// Update on 19 March 2009 : We cannot assume certain parameters will always // be float. They may become integer too. For example, in the case of Korea // Stock Market, Previous Close is in integer. We shall apply string quote // protection method too on them. // // Here are the index since 19 March 2009 : // (0) Symbol // (1) Name // (2) Stock Exchange // (3) Symbol // (4) Previous Close // (5) Symbol // (6) Open // (7) Symbol // (8) Last Trade // (9) Symbol // (10) Day's high // (11) Symbol // (12) Day's low // (13) Symbol // (14) Volume // (15) Symbol // (16) Change // (17) Symbol // (18) Change Percent // (19) Symbol // (20) Last Trade Size // (21) Symbol // (22) Bid // (23) Symbol // (24) Bid Size // (25) Symbol // (26) Ask // (27) Symbol // (28) Ask Size // (29) Symbol // (30) Last Trade Date // (31) Last Trade Time. // // s = Symbol // n = Name // x = Stock Exchange // o = Open <-- Although we will keep this value in our stock data structure, we will not show // it to clients. As some stock servers unable to retrieve open price. // p = Previous Close // l1 = Last Trade (Price Only) // h = Day's high // g = Day's low // v = Volume <-- We need to take special care on this, it may give us 1,234. This will // make us difficult to parse csv file. The only workaround is to make integer // in between two string literal (which will always Contains "). By using regular // expression, we will manually remove the comma. // c1 = Change // p2 = Change Percent // k3 = Last Trade Size <-- We need to take special care on this, it may give us 1,234... // b = Bid // b6 = Bid Size <-- We need to take special care on this, it may give us 1,234... // a = Ask // a5 = Ask Size <-- We need to take special care on this, it may give us 1,234... // d1 = Last Trade Date // t1 = Last Trade Time // // c6k2c1p2c -> Change (Real-time), Change Percent (Real-time), Change, Change in Percent, Change & Percent Change // "+1400.00","N/A - +4.31%",+1400.00,"+4.31%","+1400.00 - +4.31%" // // "MAERSKB.CO","AP MOELLER-MAERS-","Copenhagen",32500.00,33700.00,34200.00,33400.00,660,"+1200.00","N/A - +3.69%",33,33500.00,54,33700.00,96,"11/10/2008","10:53am" public List <Stock> parse(String source) { List <Stock> stocks = new List <Stock>(); if (source == null) { return(stocks); } String[] strings = source.Split(new string[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); foreach (String str in strings) { /// String tmp = YahooStockFormat.digitPattern.matcher(string).replaceAll("$1"); var tmp = YahooStockFormat.digitPattern.Matches(str); string strtmp = YahooStockFormat.digitPattern.Match(str).Value; foreach (var item in tmp) { // ?? } // Some string contain comma, remove them as well. If not, we face problem during csv parsing. String stringDigitWithoutComma = stringCommaPattern.Match(strtmp).Value; String[] fields = stringDigitWithoutComma.Split(','); int length = fields.Count(); Code code = null; Symbol symbol = null; String name = null; Stock.Board board = Stock.Board.Unknown; Stock.Industry industry = Stock.Industry.Unknown; double prevPrice = 0.0; double openPrice = 0.0; double lastPrice = 0.0; double highPrice = 0.0; double lowPrice = 0.0; // TODO: CRITICAL LONG BUG REVISED NEEDED. long volume = 0; double changePrice = 0.0; double changePricePercentage = 0.0; int lastVolume = 0; double buyPrice = 0.0; int buyQuantity = 0; double sellPrice = 0.0; int sellQuantity = 0; double secondBuyPrice = 0.0; int secondBuyQuantity = 0; double secondSellPrice = 0.0; int secondSellQuantity = 0; double thirdBuyPrice = 0.0; int thirdBuyQuantity = 0; double thirdSellPrice = 0.0; int thirdSellQuantity = 0; SimpleDate calendar = new SimpleDate(); do { if (length < 1) { break; } code = Code.newInstance(quotePattern.Match(fields[0]).Value.Trim()); if (length < 2) { break; } name = quotePattern.Match(fields[1]).Value.Trim(); // We use name as symbol, to make it more readable. symbol = Symbol.newInstance(name); if (length < 3) { break; } try { board = (Stock.Board)Enum.Parse(typeof(Stock.Board), quotePattern.Match(fields[2]).Value.Trim()); } catch (Exception exp) { board = Stock.Board.Unknown; } industry = Stock.Industry.Unknown; if (length < 5) { break; } try { prevPrice = Double.Parse(fields[4]); } catch (FormatException exp) { } if (length < 7) { break; } try { openPrice = Double.Parse(fields[6]); } catch (FormatException exp) { } if (length < 9) { break; } try { lastPrice = Double.Parse(fields[8]); } catch (FormatException exp) { } if (length < 11) { break; } try { highPrice = Double.Parse(fields[10]); } catch (FormatException exp) { } if (length < 13) { break; } try { lowPrice = Double.Parse(fields[12]); } catch (FormatException exp) { } if (length < 15) { break; } // TODO: CRITICAL LONG BUG REVISED NEEDED. try { volume = long.Parse(fields[14]); } catch (FormatException exp) { } if (length < 17) { break; } try { changePrice = Double.Parse(quotePattern.Match(fields[16]).Value.Trim()); } catch (FormatException exp) { } if (length < 19) { break; } String _changePricePercentage = quotePattern.Match(fields[18]).Value; _changePricePercentage = percentagePattern.Match(_changePricePercentage).Value; try { changePricePercentage = Double.Parse(_changePricePercentage); } catch (FormatException exp) { } if (length < 21) { break; } try { lastVolume = int.Parse(fields[20]); } catch (FormatException exp) { } if (length < 23) { break; } try { buyPrice = Double.Parse(fields[22]); } catch (FormatException exp) { } if (length < 25) { break; } try { buyQuantity = int.Parse(fields[24]); } catch (FormatException exp) { } if (length < 27) { break; } try { sellPrice = Double.Parse(fields[26]); } catch (FormatException exp) { } if (length < 29) { break; } try { sellQuantity = int.Parse(fields[28]); } catch (FormatException exp) { } if (length < 32) { break; } String data_and_time = quotePattern.Match(fields[28]).Value.Trim() + " " + quotePattern.Match(fields[29]).Value.Trim(); DateTime serverDate; try { serverDate = DateTime.ParseExact(data_and_time, "MM/dd/yyyy hh:mmaa", CultureInfo.InvariantCulture); calendar = new SimpleDate(serverDate); } catch (FormatException exp) { // Most of the time, we just obtain "N/A" // log.error(fields[23] + ", " + fields[24] + ", " + data_and_time, exp); } break; } while (true); if (code == null || symbol == null || name == null) { continue; } if (calendar == null) { calendar = new SimpleDate(); } Stock stock = new Stock( code, symbol, name, board, industry, prevPrice, openPrice, lastPrice, highPrice, lowPrice, volume, changePrice, changePricePercentage, lastVolume, buyPrice, buyQuantity, sellPrice, sellQuantity, secondBuyPrice, secondBuyQuantity, secondSellPrice, secondSellQuantity, thirdBuyPrice, thirdBuyQuantity, thirdSellPrice, thirdSellQuantity, calendar ); stocks.Add(stock); } return(stocks); }