1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2006, 2007 Banca Profilo S.p.A.
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/processes/hullwhiteprocess.hpp>
21
22namespace QuantLib {
23
24 HullWhiteProcess::HullWhiteProcess(const Handle<YieldTermStructure>& h,
25 Real a,
26 Real sigma)
27 : process_(new OrnsteinUhlenbeckProcess(
28 a, sigma, h->forwardRate(t1: 0.0,t2: 0.0,comp: Continuous,freq: NoFrequency))),
29 h_(h), a_(a), sigma_(sigma) {
30 QL_REQUIRE(a_ >= 0.0, "negative a given");
31 QL_REQUIRE(sigma_ >= 0.0, "negative sigma given");
32 }
33
34 Real HullWhiteProcess::x0() const {
35 return process_->x0();
36 }
37
38 Real HullWhiteProcess::drift(Time t, Real x) const {
39 Real alpha_drift = sigma_*sigma_/(2*a_)*(1-std::exp(x: -2*a_*t));
40 Real shift = 0.0001;
41 Real f = h_->forwardRate(t1: t, t2: t, comp: Continuous, freq: NoFrequency);
42 Real fup = h_->forwardRate(t1: t+shift, t2: t+shift, comp: Continuous, freq: NoFrequency);
43 Real f_prime = (fup-f)/shift;
44 alpha_drift += a_*f+f_prime;
45 return process_->drift(t, x) + alpha_drift;
46 }
47
48 Real HullWhiteProcess::diffusion(Time t, Real x) const{
49 return process_->diffusion(t, x);
50 }
51
52 Real HullWhiteProcess::expectation(Time t0, Real x0, Time dt) const {
53 return process_->expectation(t0, x0, dt)
54 + alpha(t: t0 + dt) - alpha(t: t0)*std::exp(x: -a_*dt);
55 }
56
57 Real HullWhiteProcess::stdDeviation(Time t0, Real x0, Time dt) const{
58 return process_->stdDeviation(t: t0, x0, dt);
59 }
60
61 Real HullWhiteProcess::variance(Time t0, Real x0, Time dt) const{
62 return process_->variance(t0, x0, dt);
63 }
64
65 Real HullWhiteProcess::alpha(Time t) const {
66 Real alfa = a_ > QL_EPSILON ?
67 Real((sigma_/a_)*(1 - std::exp(x: -a_*t))) :
68 sigma_*t;
69 alfa *= 0.5*alfa;
70 alfa += h_->forwardRate(t1: t, t2: t, comp: Continuous, freq: NoFrequency);
71 return alfa;
72 }
73
74 Real HullWhiteProcess::a() const {
75 return a_;
76 }
77
78 Real HullWhiteProcess::sigma() const {
79 return sigma_;
80 }
81
82 HullWhiteForwardProcess::HullWhiteForwardProcess(
83 const Handle<YieldTermStructure>& h,
84 Real a,
85 Real sigma)
86 : process_(new OrnsteinUhlenbeckProcess(
87 a, sigma, h->forwardRate(t1: 0.0,t2: 0.0,comp: Continuous,freq: NoFrequency))),
88 h_(h), a_(a), sigma_(sigma) {}
89
90 Real HullWhiteForwardProcess::x0() const {
91 return process_->x0();
92 }
93
94 Real HullWhiteForwardProcess::drift(Time t, Real x) const {
95 Real alpha_drift = sigma_*sigma_/(2*a_)*(1-std::exp(x: -2*a_*t));
96 Real shift = 0.0001;
97 Real f = h_->forwardRate(t1: t, t2: t, comp: Continuous, freq: NoFrequency);
98 Real fup = h_->forwardRate(t1: t+shift, t2: t+shift, comp: Continuous, freq: NoFrequency);
99 Real f_prime = (fup-f)/shift;
100 alpha_drift += a_*f+f_prime;
101 return process_->drift(t, x) + alpha_drift - B(t, T: T_)*sigma_*sigma_;
102 }
103
104 Real HullWhiteForwardProcess::diffusion(Time t, Real x) const{
105 return process_->diffusion(t, x);
106 }
107
108 Real HullWhiteForwardProcess::expectation(Time t0, Real x0,
109 Time dt) const {
110 return process_->expectation(t0, x0, dt)
111 + alpha(t: t0 + dt) - alpha(t: t0)*std::exp(x: -a_*dt)
112 - M_T(s: t0, t: t0+dt, T: T_);
113 }
114
115 Real HullWhiteForwardProcess::stdDeviation(Time t0, Real x0,
116 Time dt) const {
117 return process_->stdDeviation(t: t0, x0, dt);
118 }
119
120 Real HullWhiteForwardProcess::variance(Time t0, Real x0, Time dt) const{
121 return process_->variance(t0, x0, dt);
122 }
123
124 Real HullWhiteForwardProcess::alpha(Time t) const {
125 Real alfa = a_ > QL_EPSILON ?
126 Real((sigma_/a_)*(1 - std::exp(x: -a_*t))) :
127 sigma_*t;
128 alfa *= 0.5*alfa;
129 alfa += h_->forwardRate(t1: t, t2: t, comp: Continuous, freq: NoFrequency);
130
131 return alfa;
132 }
133
134 Real HullWhiteForwardProcess::M_T(Real s, Real t, Real T) const {
135 if (a_ > QL_EPSILON) {
136 Real coeff = (sigma_*sigma_)/(a_*a_);
137 Real exp1 = std::exp(x: -a_*(t-s));
138 Real exp2 = std::exp(x: -a_*(T-t));
139 Real exp3 = std::exp(x: -a_*(T+t-2.0*s));
140 return coeff*(1-exp1)-0.5*coeff*(exp2-exp3);
141 } else {
142 // low-a algebraic limit
143 Real coeff = (sigma_*sigma_)/2.0;
144 return coeff*(t-s)*(2.0*T-t-s);
145 }
146 }
147
148 Real HullWhiteForwardProcess::B(Time t, Time T) const {
149 return a_ > QL_EPSILON ?
150 Real(1/a_ * (1-std::exp(x: -a_*(T-t)))) :
151 T-t;
152 }
153
154 Real HullWhiteForwardProcess::a() const {
155 return a_;
156 }
157
158 Real HullWhiteForwardProcess::sigma() const {
159 return sigma_;
160 }
161}
162
163

source code of quantlib/ql/processes/hullwhiteprocess.cpp