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