Package org.jquantlib.processes

Source Code of org.jquantlib.processes.LiborForwardModelProcess

/*
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
<jquant-devel@lists.sourceforge.net>. The license is also available online at
<http://www.jquantlib.org/index.php/LICENSE.TXT>.

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.processes;

import java.util.ArrayList;
import java.util.List;

import org.jquantlib.QL;
import org.jquantlib.cashflow.CashFlow;
import org.jquantlib.cashflow.IborCoupon;
import org.jquantlib.daycounters.DayCounter;
import org.jquantlib.indexes.IborIndex;
import org.jquantlib.math.matrixutilities.Array;
import org.jquantlib.math.matrixutilities.Matrix;
import org.jquantlib.time.Date;

/**
* Libor-forward-model process
* <p>
* Stochastic process of a libor forward model using the rolling forward measure including predictor-corrector step
* <p>
* References:
* <li>Glasserman, Paul, 2004, Monte Carlo Methods in Financial Engineering, Springer, Section 3.7</li>
* <li>Antoon Pelsser, 2000, Efficient Methods for Valuing Interest Rate Derivatives, Springer, 8</li>
* <li>Hull, John, White, Alan, 1999, Forward Rate Volatilities, Swap Rate Volatilities and the Implementation of the Libor Market
* Model<li>
*
* @see <a href="http://www.rotman.utoronto.ca/~amackay/fin/libormktmodel2.pdf">FORWARD RATE VOLATILITIES, SWAP RATE VOLATILITIES,
*      AND THE IMPLEMENTATION OF THE LIBOR MARKET MODEL</a>
*
* @category processes
*
* @author Ueli Hofstetter
*/
// TODO: license, class comments, access modifiers organization, good formatting
public class LiborForwardModelProcess extends StochasticProcess {

    //Exception messages
    private static final String wrong_number_of_cashflows = "wrong number of cashflows";
    private static final String irregular_coupon_types = "irregular coupon types are not suppported";

    private final int size_;
    private final IborIndex index_;
    private LfmCovarianceParameterization lfmParam_;
    private final Array initialValues_;
    private final List</*@Time*/Double> fixingTimes_;
    private final List</*@Time*/Date> fixingDates_;
    private final List</*@Time*/Double> accrualStartTimes_;
    private final List</*@Time*/Double> accrualEndTimes_;
    private final List</*@Time*/Double> accrualPeriod_;

    private final  Array m1, m2;

    public LiborForwardModelProcess(final int size, final IborIndex  index) {
        super(new EulerDiscretization());

        if (System.getProperty("EXPERIMENTAL") == null)
            throw new UnsupportedOperationException("Work in progress");

        this.size_ = size;
        this.index_ = index;
        this.initialValues_ = new Array(size_);
        this.fixingDates_ = new ArrayList<Date>(size_);
        this.fixingTimes_ = new ArrayList<Double>(size_);
        this.accrualStartTimes_ = new ArrayList<Double>(size_);
        this.accrualEndTimes_ = new ArrayList<Double>(size_);
        this.accrualPeriod_ = new ArrayList<Double>(size_);
        this.m1 = new Array(size_);
        this.m2 = new Array(size_);

        final DayCounter dayCounter = index_.dayCounter();
        final List<CashFlow> flows = null /* cashFlows() */; // FIXME: translate cashFlows();

        QL.require(this.size_ == flows.size() , wrong_number_of_cashflows); // QA:[RG]::verified // TODO: message

        final Date settlement = index_.termStructure().currentLink().referenceDate();
        final Date startDate = ((IborCoupon) flows.get(0)).fixingDate();
        for (int i = 0; i < size_; ++i) {
            final IborCoupon coupon = (IborCoupon) flows.get(i);
            QL.require(coupon.date().eq(coupon.accrualEndDate()) , irregular_coupon_types); // QA:[RG]::verified // TODO: message

            initialValues_.set(i, coupon.rate());
            accrualPeriod_.set(i, coupon.accrualPeriod());

            fixingDates_.set(i, coupon.fixingDate());
            fixingTimes_.set(i, dayCounter.yearFraction(startDate, coupon.fixingDate()));
            accrualStartTimes_.set(i, dayCounter.yearFraction(settlement, coupon.accrualStartDate()));
            accrualEndTimes_.set(i, dayCounter.yearFraction(settlement, coupon.accrualEndDate()));
        }
    }


    //
    // public methods
    //

    public void setCovarParam(final LfmCovarianceParameterization  param) {
        lfmParam_ = param;
    }

    public LfmCovarianceParameterization covarParam()  {
        return lfmParam_;
    }

    public IborIndex index() {
        return index_;
    }


    //
    // Overrides StochasticProcess
    //

    @Override
    public Array initialValues()  {
        return initialValues_.clone();
    }

    @Override
    public int size() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Array drift(/* @Time */final double t, final Array x) {
        final Array f = new Array(size_);
        final Matrix covariance = lfmParam_.covariance(t, x);
        final int m = 0;//NextA
        for (int k = m; k < size_; ++k) {
            m1.set(k, accrualPeriod_.get(k) * x.get(k) / (1 + accrualPeriod_.get(k) * x.get(k)));
            final double value = m1.innerProduct(covariance.constRangeCol(k), m, k+1-m) - 0.5 * covariance.get(k, k);
            f.set(k, value);
        }
        return f;
    }

    @Override
    public Matrix diffusion(/*@Time*/ final double t, final Array x){
        return lfmParam_.diffusion(t, x);
    }

    @Override
    public Matrix covariance(/*@Time*/final double t, final Array x, /*@Time*/ final double dt){
        return lfmParam_.covariance(dt, x).mul(lfmParam_.covariance(dt, x).mulAssign(dt));
    }

    @Override
    public Array apply(final Array x0, final Array dx){
        final Array tmp = new Array(size_);
        for(int k = 0; k<size_; ++k) {
            tmp.set(k, x0.get(k)*Math.exp(dx.get(k)));
        }
        return tmp;
    }

    @Override
    public Array evolve(/*@Time*/ final double t0, final Array x0, /*@Time*/ final double dt, final Array dw)  {

        //FIXME:: code review against QuantLib/C++

        /* predictor-corrector step to reduce discretization errors.

           Short - but slow - solution would be

           Array rnd_0     = stdDeviation(t0, x0, dt)*dw;
           Array drift_0   = discretization_->drift(*this, t0, x0, dt);

           return apply(x0, ( drift_0 + discretization_
                ->drift(*this,t0,apply(x0, drift_0 + rnd_0),dt) )*0.5 + rnd_0);

           The following implementation does the same but is faster.
        */

        if (true)
            throw new UnsupportedOperationException("work in progress");
        final int m   = 0;//nextIndexReset(t0);
        final double sdt = Math.sqrt(dt);

        final Array f = x0.clone();
        final Matrix diff       = lfmParam_.diffusion(t0, x0);
        final Matrix covariance = lfmParam_.covariance(t0, x0);

        // TODO: review iterators
        for (int k=m; k<size_; ++k) {
            final double y = accrualPeriod_.get(k)*x0.get(k);
            m1.set(k,y/(1+y));

            final double d = (m1.innerProduct(covariance.constRangeCol(k), m, k+1-m)-0.5*covariance.get(k, k)) * dt;
            final double r = diff.rangeRow(k).innerProduct(dw)*sdt;
            final double x = y*Math.exp(d + r);
            m2.set(k, x/(1+x));

            final double ip = m2.innerProduct(covariance.constRangeCol(k), m, k+1-m);
            final double value = x0.get(k) * Math.exp(0.5*(d+ip-0.5*covariance.get(k,k))*dt) + r;
            f.set(k, value);
        }

        return f;
    }
//    /*
//    private /*Size*/ int nextIndexReset(/*Time*/ final double t)  {
//        return Std.getInstance().
//                 - fixingTimes_.begin();
//    }


}





/*
    public List<CashFlow> cashFlows{

        final Date refDate = index_.getTermStructure().getLink().referenceDate();

        List<CashFlow> floatingLeg = Leg.FloatingLe, schedule, index, paymentDayCounter, paymentAdj, fixingDays, gearings, spreads, caps, floors, isInArrears)(
                   std::vector<Real>(1, amount),
                   Schedule(refDate,
                            refDate + Period(index_->tenor().length()*size_,
                                             index_->tenor().units()),
                            index_->tenor(), index_->fixingCalendar(),
                            index_->businessDayConvention(),
                            index_->businessDayConvention(), false, false),
                   index_,
                   index_->dayCounter(),
                   index_->businessDayConvention(),
                   index_->fixingDays());
        boost::shared_ptr<IborCouponPricer>
                        fictitiousPricer(new BlackIborCouponPricer(Handle<CapletVolatilityStructure>()));
        setCouponPricer(floatingLeg,fictitiousPricer);
        return floatingLeg;

    }

    Size LiborForwardModelProcess::size() const {
        return size_;
    }

    Size LiborForwardModelProcess::factors() const {
        return lfmParam_->factors();
    }

    const std::vector<Time> & LiborForwardModelProcess::fixingTimes() const {
        return fixingTimes_;
    }

    const std::vector<Date> & LiborForwardModelProcess::fixingDates() const {
        return fixingDates_;
    }

    const std::vector<Time> &
    LiborForwardModelProcess::accrualStartTimes() const {
        return accrualStartTimes_;
    }

    const std::vector<Time> &
    LiborForwardModelProcess::accrualEndTimes() const {
        return accrualEndTimes_;
    }

    Size LiborForwardModelProcess::nextIndexReset(Time t) const {
        return std::upper_bound(fixingTimes_.begin(), fixingTimes_.end(), t)
                 - fixingTimes_.begin();
    }

    std::vector<DiscountFactor> LiborForwardModelProcess::discountBond(
        const std::vector<Rate> & rates) const {

        std::vector<DiscountFactor> discountFactors(size_);
        discountFactors[0] = 1.0/(1.0 + rates[0]*accrualPeriod_[0]);

        for (Size i = 1; i < size_; ++i) {
            discountFactors[i] =
                discountFactors[i-1]/(1.0 + rates[i]*accrualPeriod_[i]);
        }

        return discountFactors;
    }*/

 
TOP

Related Classes of org.jquantlib.processes.LiborForwardModelProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.