private void ThreadPoolCallback(Object obj) { ThreadPoolT arg = (ThreadPoolT)obj; // execute option update UpdateOptionDetails(arg.option, false); // signal done event arg.done_event.Set(); // update progress bar if (ThreadPoolT.bw != null) { lock (ThreadPoolT.bw) { try { ThreadPoolT.count++; ThreadPoolT.current = ThreadPoolT.count * 100 / ThreadPoolT.total; if (ThreadPoolT.current != ThreadPoolT.last) { ThreadPoolT.bw.ReportProgress(ThreadPoolT.current); ThreadPoolT.last = ThreadPoolT.current; } } catch { } } } }
public ArrayList GetOptionsChain(string ticker) { // get corrected ticker ticker = CorrectSymbol(ticker); string url = null; UnderlyingType type = UnderlyingType.Unknown; // get url url = GetOptionChainUrl(ticker, out type); if (url == null || type == UnderlyingType.Unknown) { return(null); } XmlDocument xml = cap.DownloadXmlPartialWebPage(url, "<tbody", "</tbody>", 1, 1); if (xml == null) { return(null); } ArrayList options_list = new ArrayList(); options_list.Clear(); double s_factor, o_factor; switch (type) { case UnderlyingType.Currency: s_factor = 0.001; o_factor = 0.0001; break; default: s_factor = 1; o_factor = 0.01; break; } for (int i = 1; ; i++) { XmlNode nd, row_nd = prs.GetXmlNodeByPath(xml.FirstChild, @"tbody\tr(" + i.ToString() + @")"); if (row_nd == null) { break; } Option option = new Option(); option.stock = ticker; option.stocks_per_contract = 100; option.update_timestamp = DateTime.Now; // type, strike, and symbol try { // get symbol nd = prs.GetXmlNodeByPath(row_nd, @"td(2)"); if (nd == null || nd.InnerText == null) { continue; } option.symbol = System.Web.HttpUtility.HtmlDecode(nd.InnerText).Trim().Trim(); if (debug_en) { debug_log += "option.symbol = '" + option.symbol.ToString() + "'\r\n"; } // get type and strike nd = prs.GetXmlNodeByPath(row_nd, @"td(11)"); if (nd == null || nd.InnerText == null) { continue; } string[] split = System.Web.HttpUtility.HtmlDecode(nd.InnerText).Trim().Trim().Split(new char[] { ' ' }); int j, n; for (n = 0, j = -1; j == -1 && n < split.Length; n++) { if (split[n] == "C" || split[n] == "P") { j = n; } } if (j == -1) { continue; } option.type = (split[j] == "C") ? "Call" : "Put"; if (debug_en) { debug_log += "option.type = '" + option.type.ToString() + "'\r\n"; } option.strike = double.Parse(split[j + 1]) * s_factor; if (debug_en) { debug_log += "option.strike = '" + option.strike.ToString() + "'\r\n"; } // get expiration date DateTime date = DateTime.Parse("1-" + split[j + 2] + "-" + DateTime.Now.Year.ToString()).AddMonths(1).AddDays(-2); if (date < DateTime.Now) { date = date.AddYears(1); } while (date.DayOfWeek != DayOfWeek.Thursday) { date = date.AddDays(-1); } option.expiration = date.AddDays(1); if (debug_en) { debug_log += "option.expiration = '" + option.expiration.ToString() + "'\r\n"; } } catch { continue; } try { // open int nd = prs.GetXmlNodeByPath(row_nd, @"td(5)"); option.open_int = 0; if (nd != null && nd.InnerText != null) { int.TryParse(System.Web.HttpUtility.HtmlDecode(nd.InnerText).Trim().Trim(), NumberStyles.Number, ci, out option.open_int); } if (debug_en) { debug_log += "option.open_int = '" + option.open_int.ToString() + "'\r\n"; } // ask / bid prices option.price.ask = double.NaN; option.price.bid = double.NaN; // last price nd = prs.GetXmlNodeByPath(row_nd, @"td(10)"); option.price.last = double.NaN; if (nd != null && nd.InnerText != null) { double.TryParse(System.Web.HttpUtility.HtmlDecode(nd.InnerText).Trim().Trim(), NumberStyles.Number, ci, out option.price.last); } if (debug_en) { debug_log += "option.price.last = '" + option.price.last.ToString() + "'\r\n"; } // price change nd = prs.GetXmlNodeByPath(row_nd, @"td(9)"); option.price.change = 0; if (nd != null && nd.InnerText != null) { double d = 0; double.TryParse(System.Web.HttpUtility.HtmlDecode(nd.InnerText).Trim().Trim(), NumberStyles.Number, ci, out d); option.price.change = option.price.last * d / (1.0 + d); } if (debug_en) { debug_log += "option.price.change = '" + option.price.change.ToString() + "'\r\n"; } // volume nd = prs.GetXmlNodeByPath(xml.FirstChild, @"td(6)"); option.volume.total = 0; if (nd != null && nd.InnerText != null) { double.TryParse(System.Web.HttpUtility.HtmlDecode(nd.InnerText).Trim().Trim(), NumberStyles.Number, ci, out option.volume.total); } if (debug_en) { debug_log += "option.volume.total = '" + option.volume.total.ToString() + "'\r\n"; } } catch { } options_list.Add(option); } if (mode == ModeT.MODE_WITH_ASK_BID_PRICES) { if (host != null) { ThreadPoolT.bw = host.BackgroundWorker; ThreadPoolT.current = 0; ThreadPoolT.last = 0; ThreadPoolT.count = 0; ThreadPoolT.total = options_list.Count; } List <ManualResetEvent> event_list = new List <ManualResetEvent>(); ThreadPool.SetMaxThreads(16, 16); for (int i = 0; i < options_list.Count; i++) { // update option Option option = (Option)options_list[i]; // create operation argument ThreadPoolT arg = new ThreadPoolT(option, new ManualResetEvent(false)); event_list.Add(arg.done_event); // queue work ThreadPool.QueueUserWorkItem(ThreadPoolCallback, arg); // we wait every 64 since the WaitAll is limited by 64 decsriptors if (event_list.Count == 64) { // wait for work to complete WaitHandle.WaitAll(event_list.ToArray()); event_list.Clear(); } } // wait for work to complete if (event_list.Count > 0) { WaitHandle.WaitAll(event_list.ToArray()); } // reset progress bar if (ThreadPoolT.bw != null) { ThreadPoolT.bw.ReportProgress(0); } } // update for (int i = 0; i < options_list.Count; i++) { Option option = (Option)options_list[i]; option.price.last *= o_factor; option.price.change *= o_factor; option.price.ask *= o_factor; option.price.bid *= o_factor; } return(options_list); }