public QuoteData GetSymbolData(string symbol, Action <string> onWebError = null)
        {
            // try getting from cache
            QuoteData quoteCache;

            if (_prices.TryGetValue(symbol, out quoteCache))
            {
                return(quoteCache);
            }
            QuoteData quoteData = new QuoteData();

            // not in cache, get now
            var t         = DateTime.Today;
            var startDate = new DateTime(t.Year - 10, 1, 1);
            var fmt       = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={0}&apikey=IF6RVQ6S90CZZ7VJ&datatype=csv&outputsize=full";
            var url       = string.Format(fmt, symbol);


            // get content
            var sb      = new StringBuilder();
            var request = System.Net.WebRequest.Create(url);


            var task = request.GetResponseAsync(); //where it's exiting

            try
            {
                using (var sr = new StreamReader(task.Result.GetResponseStream()))
                {
                    // skip headers
                    sr.ReadLine();

                    // read each line
                    for (var line = sr.ReadLine(); line != null; line = sr.ReadLine())
                    {
                        // append date (field 0) and adjusted close price (field 6)
                        var items = line.Split(',');
                        {
                            Quote q = new Quote(quoteData.ReferenceValue)
                            {
                                date   = DateTime.Parse(items[0]),
                                open   = Convert.ToDouble(items[1]),
                                high   = Convert.ToDouble(items[2]),
                                low    = Convert.ToDouble(items[3]),
                                close  = Convert.ToDouble(items[4]),
                                volume = Convert.ToDouble(items[5]),
                            };
                            if (q.date < startDate)
                            {
                                break;
                            }
                            quoteData.Add(q);
                        }
                    }
                }
            }
            catch (AggregateException ex)
            {
                if (onWebError != null)
                {
                    onWebError(ex.Message);
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }
            catch (System.Net.WebException ex)
            {
                if (onWebError != null)
                {
                    onWebError(ex.Message);
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }

            FillEvents(symbol, quoteData);

            quoteData.Reverse();
            _prices[symbol] = quoteData;

            return(quoteData);
        }
        public QuoteData GetSymbolData(string symbol, Action <string> onWebError = null)
        {
            // try getting from cache
            QuoteData quoteCache;

            if (_prices.TryGetValue(symbol, out quoteCache))
            {
                return(quoteCache);
            }
            QuoteData quoteData = new QuoteData();

            DateTime     t               = DateTime.Today;
            DateTime     startDate       = new DateTime(t.Year - 10, 01, 01);
            Stream       dataStream      = null;
            StreamWriter dataCacheStream = null;

            // check the file cache as well
            FileInfo fileInfo = new FileInfo(symbol + ".dataCache");

            if (fileInfo.Exists && fileInfo.LastWriteTime.Date == t)
            {
                try { dataStream = fileInfo.OpenRead(); }
                catch { dataStream = null; }
            }

            // not in cache, get now
            if (dataStream == null)
            {
                var fmt = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={0}&apikey=IF6RVQ6S90CZZ7VJ&datatype=csv&outputsize=full";
                var url = string.Format(fmt, symbol);
                try
                {
                    var wc = new System.Net.WebClient();
                    dataStream      = wc.OpenRead(url);
                    dataCacheStream = fileInfo.CreateText();
                }
                catch { dataStream = null; }
            }

            if (dataStream == null)
            {
                string msg = "Data for \"" + symbol + "\" not available.";
                if (fileInfo.Exists)
                {
                    try
                    {
                        dataStream = fileInfo.OpenRead();
                        msg        = "New Data for \"" + symbol + "\" not available.\r\n" +
                                     "Using cached data from " +
                                     fileInfo.LastWriteTime.Date.ToShortDateString();
                    }
                    catch
                    {
                        dataStream = null;
                    }
                }
                if (onWebError != null)
                {
                    onWebError(msg);
                }
                else if (dataStream == null)
                {
                    throw new Exception(msg);
                }
                if (dataStream == null)
                {
                    return(quoteData);
                }
            }

            try
            {
                using (var sr = new StreamReader(dataStream))
                {
                    // skip headers
                    if (dataCacheStream != null)
                    {
                        dataCacheStream.WriteLine(sr.ReadLine());
                        dataCacheStream.WriteLine(sr.ReadLine());
                    }
                    else
                    {
                        sr.ReadLine();
                        sr.ReadLine();
                    }

                    // read each line
                    for (var line = sr.ReadLine(); line != null; line = sr.ReadLine())
                    {
                        if (dataCacheStream != null)
                        {
                            dataCacheStream.WriteLine(line);
                        }

                        // append date (field 0) and adjusted close price (field 6)
                        var items = line.Split(',');

                        {
                            Quote q = new Quote(quoteData.ReferenceValue)
                            {
                                date   = DateTime.Parse(items[0], CultureInfo.InvariantCulture),
                                open   = Convert.ToDouble(items[1], CultureInfo.InvariantCulture),
                                high   = Convert.ToDouble(items[2], CultureInfo.InvariantCulture),
                                low    = Convert.ToDouble(items[3], CultureInfo.InvariantCulture),
                                close  = Convert.ToDouble(items[4], CultureInfo.InvariantCulture),
                                volume = Convert.ToDouble(items[5], CultureInfo.InvariantCulture),
                            };
                            if (q.date < startDate)
                            {
                                break;
                            }
                            quoteData.Add(q);
                        }
                    }
                }
            }
            catch (System.Net.WebException ex)
            {
                if (onWebError != null)
                {
                    onWebError(ex.Message);
                }
                else
                {
                    throw ex;
                }
            }
            finally
            {
                if (dataCacheStream != null)
                {
                    dataCacheStream.Close();
                }
            }

            if (symbol != "SP")
            {
                FillEvents(symbol, quoteData);
            }

            quoteData.Reverse();
            _prices[symbol] = quoteData;

            return(quoteData);
        }