/*
 Copyright (C) 2009 Ueli Hofstetter

 This source code is release under the BSD License.

 This file is part of JQuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://jquantlib.org/

 JQuantLib is free software: you can redistribute it and/or modify it
 under the terms of the JQuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */

package org.jquantlib.currencies;

import org.jquantlib.lang.exceptions.LibraryException;
import org.jquantlib.math.Constants;
import org.jquantlib.util.Pair;


public class ExchangeRate {

    public enum Type {
        Direct,  /** given directly by the user */
        Derived  /** derived from exchange rates between
                      other currencies */
    };
    /** The source currency of this ExchangeRate.*/
    private Currency source_;
    /** The target currency of this ExchangeRate.*/
    private Currency target_;
    /** The rate of this exchange rate.*/
    private     /*@Decimal*/double rate_;
    /** The type of this ExchangeRate.*/
    private     Type type_;
    /** The pair of chained ExchangeRates.*/
    public     Pair rateChain_;

    /**
     * Creates a new ExchangeRate instance.
     */
    public ExchangeRate(){
        this.rate_=Constants.NULL_REAL;
    }

   /**
    * Creates clone of an existing ExchangeRate instance.
    * @param toCopy the ExchangeRate to be cloned.
    */
    public ExchangeRate(final ExchangeRate toCopy){
        //shouldn't matter
        source_ = toCopy.source_;
        target_ = toCopy.target_;
        rate_ = toCopy.rate_;
        type_ = toCopy.type_;
    }

    /**
     * Creates a new ExchangeRate instance
     * @param source The source currency of this ExchangeRate Currency
     * @param target The target currency of this ExchangeRate Currency
     * @param rate The rate of this ExchangeRate
     */
    public  ExchangeRate(final Currency  source,
                                      final Currency  target,
                                      /*@Decimal*/final double rate){
        this.source_=(source);
        this.target_=(target);
        this.rate_=(rate);
        this.type_=(Type.Direct) ;
    }


    //accessors
    public Currency source() {
        return source_;
    }

    public Currency target()   {
        return target_;
    }

    public  Type  type()   {
        return type_;
    }

    public /*@Decimal*/ double rate()   {
        return rate_;
    }

    /**
     * Apply this ExchangeRate an amount of cash. A new money instance will be returned.
     * The input remains unchanged.
     * @param amount The money instance the exchange rate should be applied to. Money
     * @return A new money instance where this ExchangeRate has been applied to. Money
     */
    public Money exchange(final Money amount) {
        switch (type_) {
        case Direct:
            if (amount.currency().eq(source_)) {
                return new Money(amount.value() * rate_, target_);
            } else if (amount.currency().eq(target_)) {
                return new Money(amount.value() / rate_, source_);
            } else {
                throw new LibraryException("exchange rate not applicable"); // TODO: message
            }
        case Derived:
            if (amount.currency() == rateChain_.first().source() || amount.currency() == rateChain_.first().target()) {
                return rateChain_.second().exchange(rateChain_.first().exchange(amount));
            } else if (amount.currency() == rateChain_.second().source() || amount.currency() == rateChain_.second().target()) {
                return rateChain_.first().exchange(rateChain_.second().exchange(amount));
            } else {
                throw new LibraryException("exchange rate not applicable"); // TODO: message
            }
        default:
            throw new LibraryException("unknown exchange-rate type"); // TODO: message
        }
    }

    /**
     * Returns a new ExchangeRate with a initialized ratechain. The ratechain will
     * be initialized by copies of r1 and r1.
     * @param r1 The first ExchangeRate to be used in the ratechain ExchangeRate
     * @param r2 The second ExchangeRate to be used inthe ratechain ExchangeRate
     * @return A new ExchangeRate
     */
    public static ExchangeRate chain(final ExchangeRate  r1,
                                     final ExchangeRate  r2) {
        final ExchangeRate result = new ExchangeRate();
        result.type_ = ExchangeRate.Type.Derived;
        result.rateChain_ = new Pair( new ExchangeRate(r1), new ExchangeRate(r2));
        if (r1.source_.eq(r2.source_)) {
            result.source_ = r1.target_;
            result.target_ = r2.target_;
            result.rate_ = r2.rate_/r1.rate_;
        } else if (r1.source_.eq(r2.target_)) {
            result.source_ = r1.target_;
            result.target_ = r2.source_;
            result.rate_ = 1.0/(r1.rate_*r2.rate_);
        } else if (r1.target_.eq(r2.source_)) {
            result.source_ = r1.source_;
            result.target_ = r2.target_;
            result.rate_ = r1.rate_*r2.rate_;
        } else if (r1.target_.eq(r2.target_)) {
            result.source_ = r1.source_;
            result.target_ = r2.source_;
            result.rate_ = r1.rate_/r2.rate_;
        } else {
            throw new LibraryException("exchange rates not chainable"); // TODO: message
        }
        return result;
    }

}

 

Ads help maintain this website.