// Add an exchange rate.
        // The given rate is valid between the given dates.
        // If two rates are given between the same currencies
        // and with overlapping date ranges, the latest one
        // added takes precedence during lookup.
        private void add
            (ExchangeRate rate, Date startDate, Date endDate)
        {
            int k = hash(rate.source, rate.target);

            if (data_.ContainsKey(k))
            {
                data_[k].Insert(0, new Entry(rate, startDate, endDate));
            }
            else
            {
                data_[k] = new List <Entry>();
                data_[k].Add(new Entry(rate, startDate, endDate));
            }
        }
        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 <Entry> > 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...
                    Entry    e     = i.Value[0];
                    Currency other = source == e.rate.source ? e.rate.target : e.rate.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)
                            {
                                // otherwise, we just discard this rate.
                            }
                        }
                    }
                }
            }
            // if the loop completed, we have no way to return the requested rate.
            Utils.QL_FAIL("no conversion available from " + source.code + " to " + target.code + " for " + date);
            return(null);
        }
        // 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.
        // if two or more exchange-rate chains are possible
        // which allow to specify a requested rate, it is
        // unspecified which one is returned.
        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.Instance.evaluationDate();
            }

            if (type == ExchangeRate.Type.Direct)
            {
                return(directLookup(source, target, date));
            }
            if (!source.triangulationCurrency.empty())
            {
                Currency link = source.triangulationCurrency;
                if (link == target)
                {
                    return(directLookup(source, link, date));
                }
                return(ExchangeRate.chain(directLookup(source, link, date), lookup(link, target, date)));
            }
            if (!target.triangulationCurrency.empty())
            {
                Currency link = target.triangulationCurrency;
                if (source == link)
                {
                    return(directLookup(link, target, date));
                }
                return(ExchangeRate.chain(lookup(source, link, date), directLookup(link, target, date)));
            }
            return(smartLookup(source, target, date));
        }
Esempio n. 4
0
        /// <summary>
        /// chain two exchange rates
        /// </summary>
        /// <param name="r1"></param>
        /// <param name="r2"></param>
        /// <returns></returns>
        public static ExchangeRate chain(ExchangeRate r1, ExchangeRate r2)
        {
            ExchangeRate result = new ExchangeRate();

            result.type_      = Type.Derived;
            result.rateChain_ = new KeyValuePair <ExchangeRate, ExchangeRate>(r1, r2);
            if (r1.source_ == r2.source_)
            {
                result.source_ = r1.target_;
                result.target_ = r2.target_;
                result.rate_   = r2.rate_ / r1.rate_;
            }
            else if (r1.source_ == r2.target_)
            {
                result.source_ = r1.target_;
                result.target_ = r2.source_;
                result.rate_   = 1.0 / (r1.rate_ * r2.rate_);
            }
            else if (r1.target_ == r2.source_)
            {
                result.source_ = r1.source_;
                result.target_ = r2.target_;
                result.rate_   = r1.rate_ * r2.rate_;
            }
            else if (r1.target_ == r2.target_)
            {
                result.source_ = r1.source_;
                result.target_ = r2.source_;
                result.rate_   = r1.rate_ / r2.rate_;
            }
            else
            {
                Utils.QL_FAIL("exchange rates not chainable");
            }
            return(result);
        }
 public void add
     (ExchangeRate rate)
 {
     add
         (rate, Date.minDate(), Date.maxDate());
 }
 public Entry(ExchangeRate r, Date s, Date e)
 {
     rate      = r;
     startDate = s;
     endDate   = e;
 }
 public void add
     (ExchangeRate rate, Date startDate)
 {
     add
         (rate, startDate, Date.maxDate());
 }