/// <summary> /// Processes the web data to quotation list and rt window /// NOTE: AmiBroker' quotation array is not updated yet! It gets updated by this data in GetQuotesEx method call. /// </summary> /// <param name="tickerData"></param> /// <param name="data"></param> private static void ProcessWebData(TickerData tickerData, HttpWebResponse data) { if (tickerData == null | data == null) { return; } bool result = false; try { // opening response stream Stream stream = data.GetResponseStream(); StreamReader reader = new StreamReader(stream); // reading the lines until it finds ticker string line = reader.ReadLine(); while (!reader.EndOfStream && !line.StartsWith("ticker:")) { line = reader.ReadLine(); } // reading the next line line = reader.ReadLine(); // if line indicates error if (line.StartsWith("errorid")) { return; } string unit = string.Empty; if (!reader.EndOfStream && line.StartsWith("unit:")) { unit = line; } // reading the lines until it finds volume (after it start the quote section) while (!reader.EndOfStream && !line.StartsWith("volume:")) { line = reader.ReadLine(); } if (reader.EndOfStream) { return; } int ltzOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Seconds; CultureInfo ci = new CultureInfo("en-US"); // processing quotation data from HTML stream Quotation quote = new Quotation(); line = reader.ReadLine(); lock (tickerData) { if (tickerData.Quotes != null) { tickerData.Quotes.Clear(); } while (!reader.EndOfStream) { int startIndex = 0; int endIndex = line.IndexOf(','); int timestamp = int.Parse(line.Substring(startIndex, endIndex - startIndex)); if (timestamp >= tickerData.LastDownloaded) { DateTime date; if (unit == "unit:MIN") // timestamp: 1314192659 { date = new DateTime(1970, 1, 1); date = date.AddSeconds(timestamp + ltzOffset); } else // "unit:DAY", timestamp: 20100824 { date = new DateTime(timestamp / 10000, timestamp / 100 % 100, timestamp % 100); } quote = new Quotation(); quote.DateTime = (AmiDate)date; startIndex = endIndex + 1; endIndex = line.IndexOf(',', startIndex); quote.Price = float.Parse(line.Substring(startIndex, endIndex - startIndex), ci); startIndex = endIndex + 1; endIndex = line.IndexOf(',', startIndex); quote.High = float.Parse(line.Substring(startIndex, endIndex - startIndex), ci); startIndex = endIndex + 1; endIndex = line.IndexOf(',', startIndex); quote.Low = float.Parse(line.Substring(startIndex, endIndex - startIndex), ci); startIndex = endIndex + 1; endIndex = line.IndexOf(',', startIndex); quote.Open = float.Parse(line.Substring(startIndex, endIndex - startIndex), ci); startIndex = endIndex + 1; endIndex = line.Length; quote.Volume = float.Parse(line.Substring(startIndex, endIndex - startIndex), ci); if (tickerData.Quotes != null) { tickerData.Quotes.Merge(quote); tickerData.LastProcessed = timestamp; } } line = reader.ReadLine(); } } // updating real time quote window using the last quote if (tickerData.UpdateRecentInfo) { tickerData.RecentInfo.Last = quote.Price; DateTime now = DateTime.Now; int lastTickDate = now.Year * 10000 + now.Month * 100 + now.Day; int lastTickTime = now.Hour * 10000 + now.Minute * 100 + now.Second; tickerData.RecentInfo.DateChange = lastTickDate; tickerData.RecentInfo.TimeChange = lastTickTime; tickerData.RecentInfo.DateUpdate = lastTickDate; tickerData.RecentInfo.TimeUpdate = lastTickTime; DataSourceBase.NotifyRecentInfoUpdate(tickerData.Ticker, ref tickerData.RecentInfo); } tickerData.LastTickTime = quote.DateTime.Hour * 10000 + quote.DateTime.Minute * 100 + quote.DateTime.Second; tickerData.LastTickDate = quote.DateTime.Year * 10000 + quote.DateTime.Month * 100 + quote.DateTime.Day; result = true; } finally { // if ticker was used in a chart, scan, etc. we update it's quotation status if (tickerData.QuoteDataStatus != QuoteDataStatus.Offline) { tickerData.QuoteDataStatus = result ? QuoteDataStatus.Online : QuoteDataStatus.Failed; } // if ticker data was downloaded and processed with no error at least once... if (tickerData.QuoteDataStatus == QuoteDataStatus.Online) { tickerData.IsKnown = true; } } }
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 } }