/// <summary> /// Gets a series of Historical Market Data from the starting date /// to the end date. /// </summary> /// <param name="mdq"> /// A <see cref="MarketDataQuery"/> with the data request. /// </param> /// <param name="end"> /// A <see cref="DateTime"/> with the ending date of the period to fetch data from. /// </param> /// <param name="dates"> /// In case of success, a list of the dates data was fetched from in the requested period. /// </param> /// <param name="marketData"> /// In case of success, a list of the fetched market data day /// by day corresponding to <see cref="dates"/>. /// </param> /// <returns> /// A <see cref="RefreshStatus"/> indicating if the query was successful. /// </returns> public RefreshStatus GetTimeSeries(MarketDataQuery mdq, DateTime end, out DateTime[] dates, out IMarketData[] marketData) { RefreshStatus status = new RefreshStatus(); // Check if close value was requested. switch (mdq.Field) { case "close": { break; } default: { // In case the request is not close return an error. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data not available (only " + "close values are available, " + mdq.Field + " was requested)."; return(status); } } // For now only Scalar requests are handled. if (mdq.MarketDataType == typeof(Scalar).ToString()) { List <MEFFHistoricalQuote> quotes = null; try { // Request the data to the Market Data Provider. quotes = MEFFAPI.GetHistoricalQuotes(TickerUtility.PreparseSymbol(mdq.Ticker), mdq.Date, end); } catch (Exception e) { // There can be conversion, server availability // and other exceptions during this request. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data not available due " + "to problems with MEFF service: " + e.Message; return(status); } // Check if there is at least one result. if (quotes.Count >= 1) { // Allocate the structures for the output. marketData = new Scalar[quotes.Count]; dates = new DateTime[quotes.Count]; // Scan the list of quotes to prepare the data for Fairmat. for (int i = 0; i < quotes.Count; i++) { // Fill the dates array from the date field of each quote. dates[i] = quotes[i].SessionDate; // Prepare the single scalar data. Scalar val = new Scalar(); val.TimeStamp = quotes[i].SessionDate; val.Value = quotes[i].SettlPrice; // Put it in the output structure. marketData[i] = val; } return(status); } else { // If there isn't at least one result return an error. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data not available: " + "empty data set for the request."; return(status); } } else { // If control falls through here it means the request type was not supported. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data request type (" + mdq.MarketDataType + ") not supported by the Market Data Provider."; return(status); } }
/// <summary> /// Gets a series of Historical Market Data from the starting date /// to the end date. /// </summary> /// <param name="mdq"> /// A <see cref="MarketDataQuery"/> with the data request. /// </param> /// <param name="end"> /// A <see cref="DateTime"/> with the ending date of the period to fetch data from. /// </param> /// <param name="dates"> /// In case of success, a list of the dates data was fetched from in the requested period. /// </param> /// <param name="marketData"> /// In case of success, a list of the fetched market data day /// by day corresponding to <see cref="dates"/>. /// </param> /// <returns> /// A <see cref="RefreshStatus"/> indicating if the query was successful. /// </returns> public RefreshStatus GetTimeSeries(MarketDataQuery mdq, DateTime end, out DateTime[] dates, out IMarketData[] marketData) { RefreshStatus status = new RefreshStatus(); // Holds whathever we should take market close or market open values. bool closeRequest; // Holds the currency conversion target in case a market different than // US is choosen. This handles conversion from USD values provided by yahoo. string targetMarket = null; string ticker = TickerUtility.PreparseSymbol(mdq.Ticker); bool divisionTransformation = false; bool inverseTransformation = false; // Check if open or close value was requested. switch (mdq.Field) { case "open": { closeRequest = false; break; } case "close": { closeRequest = true; break; } default: { // In case the request is neither open or close return an error. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data not available (only " + "open and close values are available, " + mdq.Field + " was requested)."; return(status); } } // Gather in which currency to get the data, this will require // an additional data fetching for the target currency for the same time period. if (mdq.Market.Length > 0 && mdq.Market != "US") { // Try to convert the entries in the Fairmat drop down box, // for the rest rely on the user. switch (mdq.Market) { case "EU": { targetMarket = "EUR"; break; } case "GB": { targetMarket = "GBP"; break; } case "JP": { targetMarket = "JPY"; break; } case "CH": { targetMarket = "CHF"; break; } case "HK": { targetMarket = "HKD"; break; } default: { // In the fallback scenario just use directly the provided string. targetMarket = mdq.Market; break; } } } // Check for currencies and handle them in a special way. // Check the single currency only (eg: EUR for USDEUR). if (GetCurrencyList().Contains(ticker)) { ticker += "=X"; // Disable the feature for this for now. targetMarket = null; } else { // Attempt a more throughout parsing. Check for <currency><currency> formats. foreach (string currency in GetCurrencyList()) { if (ticker.StartsWith(currency)) { if (currency == "USD") { // If usd is in the ticker name it's a special case due to the way // Yahoo! Finance keeps currencies. ticker = ticker.Remove(0, 3) + "=X"; targetMarket = null; } else if (ticker.Remove(0, 3) == "USD") { // This is the inverse of the previous case. // From other currency to USD. Similarly to above it's a special case. ticker = currency + "=X"; targetMarket = null; inverseTransformation = true; } else { // Normal not USD to not USD currency conversions. targetMarket = currency; ticker = ticker.Remove(0, 3) + "=X"; divisionTransformation = true; } break; } } } // For now only Scalar requests are handled. if (mdq.MarketDataType == typeof(Scalar).ToString()) { List <YahooHistoricalQuote> quotes = null; Dictionary <DateTime, YahooHistoricalQuote> currencyQuotes = new Dictionary <DateTime, YahooHistoricalQuote>(); try { // Request the data to the Market Data Provider. quotes = YahooFinanceAPI.GetHistoricalQuotes(ticker, mdq.Date, end); if (targetMarket != null) { // If we need currency quotes in order to handle currency conversions // fetch them now. List <YahooHistoricalQuote> fetchedCurrencyQuotes = YahooFinanceAPI.GetHistoricalQuotes(targetMarket + "=X", mdq.Date, end); // Put all items in a dictionary for easy fetching. fetchedCurrencyQuotes.ForEach(x => currencyQuotes.Add(x.Date, x)); } } catch (Exception e) { // There can be conversion, server availability // and other exceptions during this request. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data not available due " + "to problems with Yahoo! Finance: " + e.Message; return(status); } // Check if there is at least one result. if (quotes.Count >= 1) { // Allocate the structures for the output. List <Scalar> readyMarketData = new List <Scalar>(); List <DateTime> readyDates = new List <DateTime>(); // Scan the list of quotes to prepare the data for Fairmat. for (int i = 0; i < quotes.Count; i++) { // Prepare the single scalar data. Scalar val = new Scalar(); val.TimeStamp = quotes[i].Date; val.Value = (closeRequest == true) ? quotes[i].Close : quotes[i].Open; // Handle currency conversions if needed. if (currencyQuotes != null) { // Check if the entry in a date exists also for the // currency conversion, if not discard the data. if (!currencyQuotes.ContainsKey(quotes[i].Date)) { // We skip this entry. continue; } YahooHistoricalQuote currencyQuote = currencyQuotes[quotes[i].Date]; //if (divisionTransformation) //{ // val.Value /= (closeRequest == true) ? currencyQuote.Close : currencyQuote.Open; //} //else //{ // val.Value *= (closeRequest == true) ? currencyQuote.Close : currencyQuote.Open; //} } // Apply an inverse transformation, used for currency values when going // from a not USD currency to USD. //if (inverseTransformation) //{ // val.Value = 1 / val.Value; //} // Put it in the output structure. readyMarketData.Add(val); // Fill the dates array from the date field of each quote. readyDates.Add(quotes[i].Date); } // Put in the output data. marketData = readyMarketData.ToArray(); dates = readyDates.ToArray(); return(status); } else { // If there isn't at least one result return an error. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data not available: " + "empty data set for the request."; return(status); } } else { // If control falls through here it means the request type was not supported. marketData = null; dates = null; status.HasErrors = true; status.ErrorMessage += "GetTimeSeries: Market data request type (" + mdq.MarketDataType + ") not supported by the Market Data Provider."; return(status); } }