/// <summary> /// Add an exchange rate. /// </summary> /// <param name="rate"></param> /// <param name="startDate"></param> /// <param name="endDate"></param> /// <remarks> /// 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. /// </remarks> 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 ExchangeRateManagerEntry(rate, startDate, endDate)); } else { _data[k] = new List <ExchangeRateManagerEntry> { new ExchangeRateManagerEntry(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 <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); }
/// <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 { throw new Exception("exchange rates not chainable"); } return(result); }
public void Add(ExchangeRate rate, Date startDate) { Add(rate, startDate, Date.maxDate()); }
public void Add(ExchangeRate rate) { Add(rate, Date.minDate(), Date.maxDate()); }
/// <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 { throw new Exception("exchange rates not chainable"); } return result; }