/*
Copyright (C) 2009 Praneet Tiwari
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.model.shortrate.onefactormodels;
import static org.jquantlib.pricingengines.BlackFormula.blackFormula;
import org.jquantlib.instruments.Option;
import org.jquantlib.math.Constants;
import org.jquantlib.math.optimization.NoConstraint;
import org.jquantlib.math.optimization.PositiveConstraint;
import org.jquantlib.model.ConstantParameter;
import org.jquantlib.model.Parameter;
import org.jquantlib.processes.OrnsteinUhlenbeckProcess;
/**
* Vasicek model class
*
* This class implements the Vasicek model defined by \f[ dr_t = a(b - r_t)dt + \sigma dW_t , \f] where \f$ a \f$, \f$ b \f$ and
* \f$ \sigma \f$ are constants; a risk premium \f$ \lambda \f$ can also be specified.
*
* @category shortrate
*
* @author Praneet Tiwari
*/
// TODO: code review :: license, class comments, comments for access modifiers, comments for @Override
public class Vasicek extends OneFactorAffineModel {
//
// protected fields
//
protected double r0_;
protected Parameter a_;
protected Parameter b_;
protected Parameter sigma_;
protected Parameter lambda_;
//
// public methods
//
public Vasicek(/* @Rate */ final double r0, final double a, final double b, final double sigma, final double lambda) {
super(4);
if (System.getProperty("EXPERIMENTAL") == null)
throw new UnsupportedOperationException("Work in progress");
this.r0_ = r0;
// TODO: code review :: please verify against QL/C++ code :: Seems to be non-sense!
this.a_ = arguments_.get(0);
this.b_ = arguments_.get(1);
this.sigma_ = arguments_.get(2);
this.lambda_ = arguments_.get(3);
// TODO: code review :: please verify against QL/C++ code :: Seems to be non-sense!
this.a_ = new ConstantParameter(a, new PositiveConstraint());
this.b_ = new ConstantParameter(b, new NoConstraint());
this.sigma_ = new ConstantParameter(sigma, new PositiveConstraint());
this.lambda_ = new ConstantParameter(lambda, new NoConstraint());
}
//
// protected methods
//
protected double a() /* @ReadOnly */ {
return a_.get(0.0);
}
protected double b() /* @ReadOnly */ {
return b_.get(0.0);
}
protected double lambda() /* @ReadOnly */ {
return lambda_.get(0.0);
}
protected double sigma() /* @ReadOnly */ {
return sigma_.get(0.0);
}
//
// implements AffineModel
//
@Override
public double discountBondOption(
final Option.Type type,
final double strike,
/* @Time */ final double maturity,
/* @Time */ final double bondMaturity) /* @ReadOnly */ {
double v;
final double _a = a();
if (Math.abs(maturity) < Constants.QL_EPSILON)
v = 0.0;
else if (_a < Math.sqrt(Constants.QL_EPSILON))
v = sigma() * B(maturity, bondMaturity) * Math.sqrt(maturity);
else
v = sigma() * B(maturity, bondMaturity) * Math.sqrt(0.5 * (1.0 - Math.exp(-2.0 * _a * maturity)) / _a);
final double /* @Real */f = discountBond(0.0, bondMaturity, r0_);
final double /* @Real */k = discountBond(0.0, maturity, r0_) * strike;
return blackFormula(type, k, f, v);
}
//
// implements OneFactorAffineModel
//
@Override
public ShortRateDynamics dynamics() /* @ReadOnly */ {
return new Dynamics(a(), b(), sigma(), r0_);
}
@Override
protected double A(/* @Time */ final double t, /* @Time */ final double T) /* @ReadOnly */ {
final double /* @Real */_a = a();
if (_a < Math.sqrt(Constants.QL_EPSILON))
return 0.0;
else {
final double /* @Real */sigma2 = sigma() * sigma();
final double /* @Real */bt = B(t, T);
return Math.exp((b() + lambda() * sigma() / _a - 0.5 * sigma2 / (_a * _a)) * (bt - (T - t)) - 0.25 * sigma2 * bt * bt
/ _a);
}
}
@Override
protected double B(/* @Time */ final double t, /* @Time */ final double T) /* @ReadOnly */ {
final double /* @Real */_a = a();
if (_a < Math.sqrt(Constants.QL_EPSILON))
return (T - t);
else
return (1.0 - Math.exp(-_a * (T - t))) / _a;
}
//
// private inner classes
//
/**
* Short-rate dynamics in the %Vasicek model
*
* The short-rate follows an Ornstein-Uhlenbeck process with mean \f$ b \f$.
*/
private final class Dynamics extends ShortRateDynamics {
//
// private fields
//
private final double a_;
private final double b_;
private final double r0_;
//
// public methods
//
public Dynamics(final double a, final double b, final double sigma, final double r0) {
super(new OrnsteinUhlenbeckProcess(a, sigma, r0 - b, 0.0));
this.a_ = a;
this.b_ = b;
this.r0_ = r0;
}
@Override
public double variable(/* @Time */ final double t, /* @Rate */ final double r) /* @ReadOnly */ {
return r - b_;
}
@Override
public double shortRate(/* @Time */ final double t, final double x) /* @ReadOnly */ {
return x + b_;
}
}
}
Ads help maintain this website.