/*
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.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
*
* Stochastic process of a libor forward model using the rolling forward measure including predictor-corrector step
*
* References:
*
Glasserman, Paul, 2004, Monte Carlo Methods in Financial Engineering, Springer, Section 3.7
* Antoon Pelsser, 2000, Efficient Methods for Valuing Interest Rate Derivatives, Springer, 8
* Hull, John, White, Alan, 1999, Forward Rate Volatilities, Swap Rate Volatilities and the Implementation of the Libor Market
* Model
*
* @see FORWARD RATE VOLATILITIES, SWAP RATE VOLATILITIES,
* AND THE IMPLEMENTATION OF THE LIBOR MARKET MODEL
*
* @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(size_);
this.fixingTimes_ = new ArrayList(size_);
this.accrualStartTimes_ = new ArrayList(size_);
this.accrualEndTimes_ = new ArrayList(size_);
this.accrualPeriod_ = new ArrayList(size_);
this.m1 = new Array(size_);
this.m2 = new Array(size_);
final DayCounter dayCounter = index_.dayCounter();
final List flows = null /* cashFlows() */; // FIXME: translate cashFlows();
QL.require(this.size_ == flows.size() , wrong_number_of_cashflows); // 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); // 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; kdrift(*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 cashFlows{
final Date refDate = index_.getTermStructure().getLink().referenceDate();
List floatingLeg = Leg.FloatingLe, schedule, index, paymentDayCounter, paymentAdj, fixingDays, gearings, spreads, caps, floors, isInArrears)(
std::vector(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
fictitiousPricer(new BlackIborCouponPricer(Handle()));
setCouponPricer(floatingLeg,fictitiousPricer);
return floatingLeg;
}
Size LiborForwardModelProcess::size() const {
return size_;
}
Size LiborForwardModelProcess::factors() const {
return lfmParam_->factors();
}
const std::vector
Ads help maintain this website.