private void OnHistoryAvailable(object sender, StockQuoteHistory history)
 {
     if (HistoryAvailable != null)
     {
         HistoryAvailable(this, history);
     }
 }
        void OnHistoryAvailable(StockQuoteHistory history)
        {
            _downloadLog.AddHistory(history);

            if (HistoryAvailable != null)
            {
                HistoryAvailable(this, history);
            }
        }
Exemple #3
0
        public async Task <bool> UpdateHistory(StockQuoteHistory history)
        {
            if (!_downloadError)
            {
                _downloadError = true;
                OnComplete(true, "Download history is not supported by IEXCloud service");
            }
            await Task.Delay(0);

            return(false);
        }
Exemple #4
0
 internal void Merge(StockQuoteHistory newHistory)
 {
     foreach (var item in newHistory.History)
     {
         this.AddQuote(item);
     }
     // promote any stock quote names to the root (to save space)
     foreach (var item in this.History)
     {
         if (!string.IsNullOrEmpty(item.Name))
         {
             this.Name = item.Name;
             item.Name = null;
         }
     }
 }
        public void AddHistory(StockQuoteHistory history)
        {
            this.database[history.Symbol] = history;
            DownloadInfo info = GetInfo(history.Symbol);

            if (info == null)
            {
                info = new DownloadInfo()
                {
                    Downloaded = DateTime.Today, Symbol = history.Symbol
                };
                this.Downloaded.Add(info);
                this._downloaded[info.Symbol] = info;
            }
            else
            {
                info.Downloaded = DateTime.Today;
            }
            DelayedSave();
        }
Exemple #6
0
        private StockQuoteHistory ParseTimeSeries(JObject o)
        {
            StockQuoteHistory history = new StockQuoteHistory();

            history.History  = new List <StockQuote>();
            history.Complete = true; // this is a complete history.

            Newtonsoft.Json.Linq.JToken value;

            if (o.TryGetValue("Note", StringComparison.Ordinal, out value))
            {
                string message = (string)value;
                throw new Exception(message);
            }

            if (o.TryGetValue("Error Message", StringComparison.Ordinal, out value))
            {
                string message = (string)value;
                throw new Exception(message);
            }

            if (o.TryGetValue("Meta Data", StringComparison.Ordinal, out value))
            {
                if (value.Type == JTokenType.Object)
                {
                    JObject child = (JObject)value;
                    if (child.TryGetValue("2. Symbol", StringComparison.Ordinal, out value))
                    {
                        history.Symbol = (string)value;
                    }
                }
            }
            else
            {
                throw new Exception("Time series data schema has changed");
            }

            if (o.TryGetValue("Time Series (Daily)", StringComparison.Ordinal, out value))
            {
                if (value.Type == JTokenType.Object)
                {
                    JObject series = (JObject)value;
                    foreach (var p in series.Properties().Reverse())
                    {
                        DateTime date;
                        if (DateTime.TryParse(p.Name, out date))
                        {
                            value = series.GetValue(p.Name);
                            if (value.Type == JTokenType.Object)
                            {
                                StockQuote quote = new StockQuote()
                                {
                                    Date = date, Downloaded = DateTime.Now
                                };
                                JObject child = (JObject)value;

                                if (child.TryGetValue("1. open", StringComparison.Ordinal, out value))
                                {
                                    quote.Open = (decimal)value;
                                }
                                if (child.TryGetValue("4. close", StringComparison.Ordinal, out value))
                                {
                                    quote.Close = (decimal)value;
                                }
                                if (child.TryGetValue("2. high", StringComparison.Ordinal, out value))
                                {
                                    quote.High = (decimal)value;
                                }
                                if (child.TryGetValue("3. low", StringComparison.Ordinal, out value))
                                {
                                    quote.Low = (decimal)value;
                                }
                                if (child.TryGetValue("5. volume", StringComparison.Ordinal, out value))
                                {
                                    quote.Volume = (decimal)value;
                                }
                                history.History.Add(quote);
                            }
                        }
                    }
                }
            }
            else
            {
                throw new Exception("Time series data schema has changed");
            }
            return(history);
        }
Exemple #7
0
        public async Task <bool> UpdateHistory(StockQuoteHistory history)
        {
            string outputsize;

            if (!history.Complete)
            {
                outputsize = "full";
            }
            else
            {
                outputsize = "compact";
            }
            bool         updated           = false;
            const string timeSeriesAddress = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol={0}&outputsize={1}&apikey={2}";
            string       symbol            = history.Symbol;
            string       uri = string.Format(timeSeriesAddress, symbol, outputsize, this._settings.ApiKey);
            await Task.Run(new Action(() =>
            {
                try
                {
                    // first check if history needs updating!
                    bool historyComplete = history.IsComplete();
                    if (historyComplete)
                    {
                        OnError(string.Format("History for symbol {0} is already up to date", symbol));
                    }
                    else
                    {
                        // this service doesn't want too many calls per second.
                        int ms = _throttle.GetSleep();
                        while (ms > 0)
                        {
                            string message = null;
                            string suffix = (ms > 1000) ? "seconds" : "ms";
                            int amount = (ms > 1000) ? ms / 1000 : ms;
                            message = string.Format("AlphaVantage history service needs to sleep for {0} {1}", suffix, amount);

                            OnComplete(PendingCount == 0, message);
                            while (!_cancelled && ms > 0)
                            {
                                Thread.Sleep(1000);
                                ms -= 1000;
                            }
                            ms = _throttle.GetSleep();
                        }
                        if (!_cancelled)
                        {
                            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
                            req.UserAgent = "USER_AGENT=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;)";
                            req.Method = "GET";
                            req.Timeout = 10000;
                            req.UseDefaultCredentials = false;
                            _current = req;

                            OnError("AlphaVantage fetching history for " + symbol);

                            WebResponse resp = req.GetResponse();
                            _throttle.RecordCall();

                            using (Stream stm = resp.GetResponseStream())
                            {
                                using (StreamReader sr = new StreamReader(stm, Encoding.UTF8))
                                {
                                    string json = sr.ReadToEnd();
                                    JObject o = JObject.Parse(json);
                                    var newHistory = ParseTimeSeries(o);

                                    if (string.Compare(newHistory.Symbol, symbol, StringComparison.OrdinalIgnoreCase) != 0)
                                    {
                                        OnError(string.Format("History for symbol {0} return different symbol {1}", symbol, newHistory.Symbol));
                                    }
                                    else
                                    {
                                        updated = true;
                                        history.Merge(newHistory);
                                        history.Complete = true;
                                        history.Save(this._logPath);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string message = ex.Message;
                    OnError(message);
                    if (message.Contains("Please visit https://www.alphavantage.co/premium/"))
                    {
                        _throttle.CallsThisMinute += this._settings.ApiRequestsPerMinuteLimit;
                    }
                }
                OnComplete(PendingCount == 0, null);
            }));

            return(updated);
        }
        public async void BeginFetchHistory(List <string> batch)
        {
            string singleton = null;
            bool   busy      = false;

            lock (_downloadSync)
            {
                busy = _downloadingHistory;
                if (busy)
                {
                    if (batch.Count == 1)
                    {
                        // then we need this individual stock ASAP
                        var item = batch[0];
                        if (_downloadBatch.Contains(item))
                        {
                            _downloadBatch.Remove(item);
                        }
                        _downloadBatch.Insert(0, item);
                        singleton = item;
                    }
                    else
                    {
                        // then merge the new batch with existing batch that we are downloading.
                        foreach (var item in batch)
                        {
                            if (!_downloadBatch.Contains(item))
                            {
                                _downloadBatch.Add(item);
                            }
                        }
                    }
                }
                else
                {
                    // starting a new download batch.
                    _downloadBatch = new List <string>(batch);
                }
            }
            if (busy)
            {
                if (!string.IsNullOrEmpty(singleton))
                {
                    // in this case we want to load any cached history and make that available to unblock the UI thread ASAP
                    // otherwise UI might be blocks on slow HTTP downloads.
                    var history = await this._downloadLog.GetHistory(singleton);

                    if (history != null && history.History != null && history.History.Count != 0)
                    {
                        // unblock the UI thread with the cached history for now.
                        OnHistoryAvailable(history);
                    }
                }
                // only allow one thread do all the downloading.
                return;
            }

            tokenSource         = new CancellationTokenSource();
            _downloadingHistory = true;

            while (_downloadingHistory)
            {
                string symbol = null;
                lock (_downloadSync)
                {
                    if (_downloadBatch != null && _downloadBatch.Count > 0)
                    {
                        symbol = _downloadBatch.First();
                        _downloadBatch.Remove(symbol);
                    }
                }
                if (symbol == null)
                {
                    break;
                }
                else
                {
#if PerformanceBlocks
                    using (PerformanceBlock.Create(ComponentId.Money, CategoryId.View, MeasurementId.DownloadStockQuoteHistory))
                    {
#endif
                    StockQuoteHistory history = null;
                    var info = this._downloadLog.GetInfo(symbol);
                    history = await this._downloadLog.GetHistory(symbol);

                    if (history == null)
                    {
                        history = new StockQuoteHistory()
                        {
                            Symbol = symbol
                        };
                    }
                    if (info != null && info.Downloaded.Date == DateTime.Today && history != null && history.Complete)
                    {
                        // already up to date
                    }
                    else
                    {
                        try
                        {
                            await _service.UpdateHistory(history);
                        }
                        catch (Exception ex)
                        {
                            OnError("Download history error: " + ex.Message);
                        }
                    }
                    if (history != null && history.History != null && history.History.Count != 0)
                    {
                        OnHistoryAvailable(history);
                    }
#if PerformanceBlocks
                }
#endif
                }
            }
            _downloadingHistory = false;

            while (_downloadingHistory && _downloadBatch.Count > 0)
            {
                Thread.Sleep(1000); // wait for download to finish.
            }
            _downloadingHistory = false;
        }
        public async Task <StockQuoteHistory> GetHistory(string symbol)
        {
            if (database.ContainsKey(symbol))
            {
                return(database[symbol]);
            }

            StockQuoteHistory history = null;
            DownloadInfo      info;
            var changed        = false;
            var changedHistory = false;

            if (_downloaded.TryGetValue(symbol, out info))
            {
                // read from disk on background thread so we don't block the UI thread loading
                // all these stock quote histories.
                await Task.Run(() =>
                {
                    try
                    {
                        history = StockQuoteHistory.Load(this._logFolder, symbol);
                        if (symbol == "GE")
                        {
                            Debug.WriteLine("debug me");
                        }
                        if (history.RemoveDuplicates())
                        {
                            changedHistory = true;
                        }
                    }
                    catch (Exception)
                    {
                        // file is bad, so ignore it
                    }
                });

                if (history == null)
                {
                    this.Downloaded.Remove(info);
                    this._downloaded.Remove(info.Symbol);
                    changed = true;
                }
                else
                {
                    database[symbol] = history;
                }
                lock (_downloadedQuotes)
                {
                    if (_downloadedQuotes.ContainsKey(info.Symbol))
                    {
                        if (history.AddQuote(_downloadedQuotes[info.Symbol]))
                        {
                            changedHistory = true;
                        }
                    }
                }
            }
            if (changed)
            {
                DelayedSave();
            }
            if (changedHistory)
            {
                history.Save(_logFolder);
            }
            return(history);
        }