Example #1
0
        /// <summary>
        /// Lookup the exchange rate between two currencies at a given
        /// date.  If the given type is Direct, only direct exchange
        /// rates will be returned if available; if Derived, direct
        /// rates are still preferred but derived rates are allowed.
        /// </summary>
        /// <remarks>
        /// if two or more exchange-rate chains are possible
        /// which allow to specify a requested rate, it is
        /// unspecified which one is returned.
        /// </remarks>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <param name="date"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public ExchangeRate lookup(Currency source, Currency target, Date date, ExchangeRate.Type type)
        {
            if (source == target)
            {
                return(new ExchangeRate(source, target, 1.0));
            }

            if (date == new Date())
            {
                date = Settings.evaluationDate();
            }

            if (type == ExchangeRate.Type.Direct)
            {
                return(DirectLookup(source, target, date));
            }

            if (!source.triangulationCurrency.IsEmpty)
            {
                Currency link = source.triangulationCurrency;
                return(link == target?DirectLookup(source, link, date) : ExchangeRate.chain(DirectLookup(source, link, date), lookup(link, target, date)));
            }

            if (!target.triangulationCurrency.IsEmpty)
            {
                Currency link = target.triangulationCurrency;
                return(source == link?DirectLookup(link, target, date) : ExchangeRate.chain(lookup(source, link, date), DirectLookup(link, target, date)));
            }

            return(SmartLookup(source, target, date));
        }
Example #2
0
        private ExchangeRate SmartLookup(Currency source, Currency target, Date date, List <int> forbidden)
        {
            // direct exchange rates are preferred.
            ExchangeRate direct = Fetch(source, target, date);

            if (direct.HasValue)
            {
                return(direct);
            }

            // if none is found, turn to smart lookup. The source currency
            // is forbidden to subsequent lookups in order to avoid cycles.
            forbidden.Add(source.numericCode);

            foreach (KeyValuePair <int, List <ExchangeRateManagerEntry> > i in _data)
            {
                // we look for exchange-rate data which involve our source
                // currency...
                if (Hashes(i.Key, source) && (i.Value.Count != 0))
                {
                    // ...whose other currency is not forbidden...
                    ExchangeRateManagerEntry e = i.Value[0];                    // front();
                    Currency other             = source == e.Item1.source ? e.Item1.target : e.Item1.source;
                    if (!forbidden.Contains(other.numericCode))
                    {
                        // ...and which carries information for the requested date.
                        ExchangeRate head = Fetch(source, other, date);
                        if (((double?)head.rate).HasValue)
                        {
                            // if we can get to the target from here...
                            try
                            {
                                ExchangeRate tail = SmartLookup(other, target, date, forbidden);
                                // ..we're done.
                                return(ExchangeRate.chain(head, tail));
                            }
                            catch (Exception)
                            {
                            }
                        }
                    }
                }
            }

            // if the loop completed, we have no way to return the requested rate.
            throw new Exception("no conversion available from " + source.code + " to " + target.code + " for " + date);
        }