/// <summary>
        /// Checks if the Central European Bank service is reachable
        /// and answers to requests correctly.
        /// </summary>
        /// <remarks>
        /// This is done by requesting a well known quote and checking if data is returned,
        /// the sanity of the data is not checked.
        /// </remarks>
        /// <returns>
        /// A <see cref="Status"/> indicating if the
        /// European Central Bank exchange service is working.
        /// </returns>
        public Status TestConnectivity()
        {
            // Prepare the default result, in case everything will go well.
            Status state = new Status();

            state.HasErrors    = false;
            state.ErrorMessage = string.Empty;

            try
            {
                // Try simply requesting a single data series known to exist
                // and to produce 1 result (we use ZAR at 31 jan 2011).
                List <EuropeanCentralBankQuote> quotes = EuropeanCentralBankAPI.GetHistoricalQuotes("ZAR",
                                                                                                    new DateTime(2011, 1, 31),
                                                                                                    new DateTime(2011, 1, 31));

                if (quotes.Count != 1)
                {
                    // If there is a number of results different than 1,
                    // it means the service is not answering as expected,
                    // so fail the test.
                    state.HasErrors    = true;
                    state.ErrorMessage = "Data from the European Central Bank " +
                                         "not available or unreliable.";
                }
            }
            catch (Exception e)
            {
                // If an exception was thrown during data fetching it means
                // there is a problem with the service (either timeout,
                // connection failure, or the European Central Bank changed data format).
                state.HasErrors    = true;
                state.ErrorMessage = "Unable to connect to the European CentralBank service: " +
                                     e.Message;
            }

            return(state);
        }
        /// <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();

            string currency;
            bool   invertedRequest = false;

            // Check if it's a close request.
            if (mdq.Field != "close")
            {
                // 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);
            }

            string ticker = RemoveTrailers(mdq.Ticker);

            // Check that the requested value is available.
            if (ticker.StartsWith("EUCF"))
            {
                // Extract the target currency name as that's used to request the data.
                currency = ticker.Remove(0, 4);
            }
            else if (ticker.StartsWith("EUR"))
            {
                // Extract the target currency name as that's used to request the data.
                currency = ticker.Remove(0, 3);
            }
            else if (ticker.EndsWith("EUR"))
            {
                // As EUR is the target currency this request is inverted compared to ECB data.
                invertedRequest = true;
                currency        = ticker.Remove(ticker.LastIndexOf("EUR"), 3);
            }
            else
            {
                // Only EUR TO TARGET CURRENCY is supported using the format EUCF<TARGET CURRENCY>
                marketData           = null;
                dates                = null;
                status.HasErrors     = true;
                status.ErrorMessage += "GetTimeSeries: Market data not available (only " +
                                       "conversion rates from EUR to another currency are " +
                                       "available, " + mdq.Ticker + " was requested).";
                return(status);
            }

            // For now only Scalar requests are handled.
            if (mdq.MarketDataType == typeof(Scalar).ToString())
            {
                List <EuropeanCentralBankQuote> quotes = null;

                try
                {
                    // Request the data to the Market Data Provider.
                    quotes = EuropeanCentralBankAPI.GetHistoricalQuotes(currency, 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 the European Central Bank 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].Date;

                        // Prepare the single scalar data.
                        Scalar val = new Scalar();
                        val.TimeStamp = quotes[i].Date;

                        if (invertedRequest)
                        {
                            // Handle the conversion from other currencies to EUR.
                            val.Value = 1 / quotes[i].Value;
                        }
                        else
                        {
                            val.Value = quotes[i].Value;
                        }

                        // 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);
            }
        }