/// <summary> /// Gets the web data for a ticker /// </summary> /// <param name="ticker"></param> /// <returns></returns> private static HttpWebResponse GetWebData(TickerData ticker) { try { string yRange; // if quotes needs to be updated if (ticker.QuoteDataStatus >= QuoteDataStatus.Failed & ticker.Quotes != null) { switch (ticker.Quotes.Periodicity) { case Periodicity.OneMinute: yRange = "1d"; break; case Periodicity.FiveMinutes: yRange = "5d"; break; case Periodicity.EndOfDay: yRange = "3y"; break; default: throw new ArgumentException(); } } // if only RT window update is needed else { yRange = "1d"; } HttpWebResponse response = null; string url = "http://chartapi.finance.yahoo.com/instrument/1.0/" + ticker.Ticker + "/chartdata;type=quote;range=" + yRange + "/csv/"; WebRequest request = WebRequest.Create(url); request.Credentials = CredentialCache.DefaultCredentials; response = (HttpWebResponse)request.GetResponse(); if (response.StatusCode == HttpStatusCode.OK) { return(response); } return(null); } catch (Exception ex) { LogAndMessage.LogAndAdd(MessageType.Error, "Web request failed: " + ex); return(null); } }
public void Disconnect() { // stop timer timer.Change(Timeout.Infinite, Timeout.Infinite); // indicate disconnection connected = false; // clean up tickers from refreshQueue refreshQueue.Clear(); LogAndMessage.LogAndAdd(MessageType.Info, "Stopped updating data."); }
public void Connect() { LogAndMessage.LogAndAdd(MessageType.Info, "Start updating data at every " + config.RefreshPeriod.ToString() + " seconds."); // start timer timer.Change(1000, 300); // make it start an immediate refresh lastRun = -1; // indicate "successfull" connection connected = true; }
/// <summary> /// Ticker event handler /// 1. It checks if the delay is over. Then it puts all tickers in the refreshQueue /// 2. It checks if there is anything in the refreshQueue and less then 3 requests are currently executing, then it starts up a threadpool thread to execute the refresh. /// </summary> /// <param name="sender"></param> private void timer_tick(object sender) { if (inTimer || !connected) { return; } inTimer = true; try { // if refresh is needed... long currentRun = (int)(DateTime.Now.TimeOfDay.TotalSeconds / config.RefreshPeriod); if (currentRun != lastRun) { lastRun = currentRun; // enqueue all tickers string[] symbols = tickers.GetAllTickers(); foreach (string symbol in symbols) { EnqueueTickerForRefresh(symbol); } } // it there are tickers enqueued and there are less then 3 downloads already running if (refreshQueue.Count > 0 && Interlocked.Read(ref concurrentDownloads) < 3) { // increment no of downloads Interlocked.Increment(ref concurrentDownloads); // dequeue the ticker and get the tickerdata for it string ticker = refreshQueue.Dequeue(); TickerData tickerData = tickers.GetTickerData(ticker); // make an idle threadpool thread execute the download in the background ThreadPool.QueueUserWorkItem(RefreshTicker, tickerData); } } catch (Exception ex) { LogAndMessage.LogAndAdd(MessageType.Error, "Failed to process all tickers: " + ex); } finally { DataSourceBase.NotifyQuotesUpdate(); inTimer = false; } }
public void GetQuotesEx(string ticker, ref QuotationArray quotes) { // save database periodicity at the very first call if (!firstGetQuotesExCall) { periodicity = quotes.Periodicity; firstGetQuotesExCall = true; } try { TickerData tickerData = tickers.GetTickerData(ticker); // if ticker is not yet known (first time to use in charts and no RT window use) if (tickerData == null) { tickerData = tickers.RegisterTicker(ticker); } if (tickerData.QuoteDataStatus == QuoteDataStatus.Offline) { // mark it for periodic Quotation data update tickerData.MarkTickerForGetQuotes(periodicity); // we do not want to run data refresh on AB's thread... // we also want async processing of historical data download... if (connected) { EnqueueTickerForRefresh(ticker); } } lock (tickerData) { // merge downloaded data to AB's quotation array quotes.Merge(tickerData.Quotes); // save last download time tickerData.LastDownloaded = tickerData.LastProcessed; } } catch (Exception ex) { LogAndMessage.LogAndAdd(MessageType.Error, "Failed to subscribe to quote update: " + ex); } }
public void UpdateRecentInfo(string ticker) { try { TickerData tickerData = tickers.GetTickerData(ticker); // if ticker is not yet known (first time to use in RT window and no use in charts) if (tickerData == null) { tickerData = tickers.RegisterTicker(ticker); } tickerData.MarkTickerForRecentInfo(); } catch (Exception ex) { LogAndMessage.LogAndAdd(MessageType.Error, "Failed to subscribe to real time window update: " + ex); } }
internal AmiVar GetExtraData(string ticker, string name, Periodicity periodicity, int arraySize) { if (!connected) { return(new AmiVar(ATFloat.Null)); // to prevent AFL engine to report AFL method call failure } try { TickerData tickerData = tickers.GetTickerData(ticker); // if it is a new ticker or data is not available yet if (string.IsNullOrEmpty(name) | tickerData == null) { return(new AmiVar(ATFloat.Null)); // to prevent AFL engine to report AFL method call failure } lock (tickerData) { string[] parts = name.Split('.'); object obj = tickerData; Type type; // walk the object hierarchy using reflection for (int i = 0; i < parts.GetLength(0); i++) { type = obj.GetType(); obj = type.InvokeMember(parts[i], BindingFlags.Default | BindingFlags.GetField | BindingFlags.GetProperty, null, obj, null); if (obj == null && i < parts.GetLength(0) - 1) { LogAndMessage.LogAndAdd(MessageType.Warning, "Extra data field does not exist: " + name, tickerData); return(new AmiVar(ATFloat.Null)); // to prevent AFL engine to report AFL method call failure } } // convert object value to AmiVar and return it to AB if (obj == null) // it was a string or an object { return(new AmiVar("")); } Type valType = obj.GetType(); if (valType == typeof(bool)) { return(new AmiVar((bool)obj ? 1.0f : 0.0f)); } if (valType.BaseType == typeof(System.Enum)) { return(new AmiVar((int)obj)); } if (valType == typeof(short)) { return(new AmiVar((short)obj)); } if (valType == typeof(int)) { return(new AmiVar((int)obj)); } if (valType == typeof(long)) { return(new AmiVar((long)obj)); } if (valType == typeof(float)) { return(new AmiVar((float)obj)); } if (valType == typeof(double)) { return(new AmiVar((float)(double)obj)); } if (valType == typeof(string)) { return(new AmiVar((string)obj)); } if (valType == typeof(DateTime)) { return(new AmiVar(ATFloat.DateTimeToABDateNum((DateTime)obj))); } if (valType == typeof(TimeSpan)) { return(new AmiVar(ATFloat.TimeSpanToABTimeNum((TimeSpan)obj))); } return(new AmiVar(ATFloat.Null)); // to prevent AFL engine to report AFL method call failure } } catch (MissingMethodException) { LogAndMessage.LogAndAdd(MessageType.Warning, "Extra data field does not exist: " + name); return(new AmiVar(ATFloat.Null)); // to prevent AFL engine to report AFL method call failure } catch (Exception ex) { LogAndMessage.LogAndAdd(MessageType.Error, "Failed to get extra data: " + ex); return(new AmiVar(ATFloat.Null)); // to prevent AFL engine to report AFL method call failure } }