Skip to content

Commit

Permalink
Merge pull request #178 from tournierjc/FdmBermudanSwaptionHW
Browse files Browse the repository at this point in the history
Fdm bermudan swaption hw
  • Loading branch information
amaggiulli authored Oct 30, 2017
2 parents 35fdae7 + 33c7ab3 commit 4cb47c8
Show file tree
Hide file tree
Showing 11 changed files with 616 additions and 25 deletions.
18 changes: 18 additions & 0 deletions src/QLNet.Old/QLNet.Old.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,9 @@
<Compile Include="..\QLNet\Methods\Finitedifferences\Meshers\Fdm1dMesher.cs">
<Link>Methods\Finitedifferences\Meshers\Fdm1dMesher.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Meshers\FdmSimpleProcess1dMesher.cs">
<Link>Methods\Finitedifferences\Meshers\FdmSimpleProcess1dMesher.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Meshers\FdmBlackScholesMesher.cs">
<Link>Methods\Finitedifferences\Meshers\FdmBlackScholesMesher.cs</Link>
</Compile>
Expand All @@ -1023,6 +1026,9 @@
<Compile Include="..\QLNet\Methods\Finitedifferences\Operators\FdmBlackScholesOp.cs">
<Link>Methods\Finitedifferences\Operators\FdmBlackScholesOp.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Operators\FdmHullWhiteOp.cs">
<Link>Methods\Finitedifferences\Operators\FdmHullWhiteOp.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Operators\FdmLinearOp.cs">
<Link>Methods\Finitedifferences\Operators\FdmLinearOp.cs</Link>
</Compile>
Expand Down Expand Up @@ -1080,6 +1086,9 @@
<Compile Include="..\QLNet\Methods\Finitedifferences\Solvers\FdmBlackScholesSolver.cs">
<Link>Methods\Finitedifferences\Solvers\FdmBlackScholesSolver.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Solvers\FdmHullWhiteSolver.cs">
<Link>Methods\Finitedifferences\Solvers\FdmHullWhiteSolver.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Solvers\FdmSolverDesc.cs">
<Link>Methods\Finitedifferences\Solvers\FdmSolverDesc.cs</Link>
</Compile>
Expand Down Expand Up @@ -1110,6 +1119,12 @@
<Compile Include="..\QLNet\Methods\Finitedifferences\Utilities\FdmInnerValueCalculator.cs">
<Link>Methods\Finitedifferences\Utilities\FdmInnerValueCalculator.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Utilities\FdmAffineModelSwapInnerValue.cs">
<Link>Methods\Finitedifferences\Utilities\FdmAffineModelSwapInnerValue.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Utilities\FdmAffineModelTermStructure.cs">
<Link>Methods\Finitedifferences\Utilities\FdmAffineModelTermStructure.cs</Link>
</Compile>
<Compile Include="..\QLNet\Methods\Finitedifferences\Utilities\FdmMesherIntegral.cs">
<Link>Methods\Finitedifferences\Utilities\FdmMesherIntegral.cs</Link>
</Compile>
Expand Down Expand Up @@ -1487,6 +1502,9 @@
<Compile Include="..\QLNet\Pricingengines\vanilla\FdBlackScholesVanillaEngine.cs">
<Link>Pricingengines\vanilla\FdBlackScholesVanillaEngine.cs</Link>
</Compile>
<Compile Include="..\QLNet\Pricingengines\vanilla\FdHullWhiteSwaptionEngine.cs">
<Link>Pricingengines\vanilla\FdHullWhiteSwaptionEngine.cs</Link>
</Compile>
<Compile Include="..\QLNet\Pricingengines\vanilla\FDAmericanEngine.cs">
<Link>Pricingengines\vanilla\FDAmericanEngine.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
Copyright (C) 2017 Jean-Camille Tournier (jean-camille.tournier@avivainvestors.com)
This file is part of QLNet Project https://github.com/amaggiulli/qlnet
QLNet is free software: you can redistribute it and/or modify it
under the terms of the QLNet license. You should have received a
copy of the license along with this program; if not, license is
available online at <http://qlnet.sourceforge.net/License.html>.
QLNet is a based on QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
The QuantLib license is available online at http://quantlib.org/license.shtml.
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.
*/
using System;
using System.Collections.Generic;
using System.Linq;

namespace QLNet
{
/// <summary>
/// One-dimensional grid mesher
/// </summary>
public class FdmSimpleProcess1DMesher : Fdm1dMesher
{
public FdmSimpleProcess1DMesher(int size,
StochasticProcess1D process,
double maturity, int tAvgSteps = 10,
double epsilon = 0.0001,
double? mandatoryPoint = null)
: base(size)
{
locations_ = new InitializedList<double>(locations_.Count, 0.0);
for (int l=1; l<=tAvgSteps; ++l)
{
double t = (maturity*l)/tAvgSteps;

double mp = (mandatoryPoint != null) ? mandatoryPoint.Value
: process.x0();

double qMin = Math.Min(Math.Min(mp, process.x0()),
process.evolve(0, process.x0(), t,
new InverseCumulativeNormal().value(epsilon)));
double qMax = Math.Max(Math.Max(mp, process.x0()),
process.evolve(0, process.x0(), t,
new InverseCumulativeNormal().value(1 - epsilon)));

double dp = (1 - 2 * epsilon) / (size - 1);
double p = epsilon;
locations_[0] += qMin;

for (int i=1; i < size-1; ++i)
{
p += dp;
locations_[i] += process.evolve(0, process.x0(), t,
new InverseCumulativeNormal().value(p));
}
locations_[locations_.Count - 1] += qMax;
}
locations_ = locations_.Select(x => x / tAvgSteps).ToList();
for (int i=0; i < size-1; ++i)
{
dminus_[i+1] = dplus_[i] = locations_[i+1] - locations_[i];
}

dplus_[dplus_.Count - 1] = null;
dminus_[0] = null;
}
}
}
105 changes: 105 additions & 0 deletions src/QLNet/Methods/Finitedifferences/Operators/FdmHullWhiteOp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
Copyright (C) 2017 Jean-Camille Tournier (jean-camille.tournier@avivainvestors.com)
This file is part of QLNet Project https://github.com/amaggiulli/qlnet
QLNet is free software: you can redistribute it and/or modify it
under the terms of the QLNet license. You should have received a
copy of the license along with this program; if not, license is
available online at <http://qlnet.sourceforge.net/License.html>.
QLNet is a based on QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
The QuantLib license is available online at http://quantlib.org/license.shtml.
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.
*/
using System;
using System.Collections.Generic;

namespace QLNet
{
public class FdmHullWhiteOp : FdmLinearOpComposite
{
public FdmHullWhiteOp(FdmMesher mesher,
HullWhite model,
int direction)
{
x_ = mesher.locations(direction);
dzMap_ = new TripleBandLinearOp(new FirstDerivativeOp(direction, mesher).mult(-1.0 * x_ * model.a()).add(
new SecondDerivativeOp(direction, mesher).mult(0.5 * model.sigma() * model.sigma()
* new Vector(mesher.layout().size(), 1.0))));
mapT_ = new TripleBandLinearOp(direction, mesher);
direction_ = direction;
model_ = model;
}
public override int size() { return 1; }

//! Time \f$t1 <= t2\f$ is required
public override void setTime(double t1, double t2)
{
OneFactorModel.ShortRateDynamics dynamics = model_.dynamics();

double phi = 0.5* ( dynamics.shortRate(t1, 0.0)
+ dynamics.shortRate(t2, 0.0));

mapT_.axpyb(new Vector(), dzMap_, dzMap_, -1.0 * (x_ + phi));
}

public override Vector apply(Vector r)
{
return mapT_.apply(r);
}

public override Vector apply_mixed(Vector r) {
Vector retVal = new Vector(r.size(), 0.0);
return retVal;
}

public override Vector apply_direction(int direction, Vector r) {
if (direction == direction_)
return mapT_.apply(r);
else {
Vector retVal = new Vector(r.size(), 0.0);
return retVal;
}
}
public override Vector solve_splitting(int direction, Vector r, double s) {
if (direction == direction_)
return mapT_.solve_splitting(r, s, 1.0);
else {
Vector retVal = new Vector(r.size(), 0.0);
return retVal;
}
}
public override Vector preconditioner(Vector r, double s) { return solve_splitting(direction_, r, s); }

public override List<SparseMatrix> toMatrixDecomp()
{
List<SparseMatrix> retVal = new InitializedList<SparseMatrix>(1, mapT_.toMatrix());
return retVal;
}

#region IOperator interface
public override IOperator identity(int size) { return null; }
public override Vector applyTo(Vector v) { return new Vector(); }
public override Vector solveFor(Vector rhs) { return new Vector(); }

public override IOperator multiply(double a, IOperator D) { return null; }
public override IOperator add(IOperator A, IOperator B) { return null; }
public override IOperator subtract(IOperator A, IOperator B) { return null; }

public override bool isTimeDependent() { return false; }
public override void setTime(double t) { }
public override object Clone() { return this.MemberwiseClone(); }
#endregion

protected HullWhite model_;
protected Vector x_;
protected TripleBandLinearOp dzMap_;
protected TripleBandLinearOp mapT_;
protected int direction_;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ public TripleBandLinearOp(int direction, FdmMesher mesher)
public TripleBandLinearOp(TripleBandLinearOp m)
{
direction_ = m.direction_;
i0_ = new List<int>(m.mesher_.layout().size());
i2_ = new List<int>(m.mesher_.layout().size());
reverseIndex_ = new List<int>(m.mesher_.layout().size());
lower_ = new List<double>(m.mesher_.layout().size());
diag_ = new List<double>(m.mesher_.layout().size());
upper_ = new List<double>(m.mesher_.layout().size());
i0_ = new InitializedList<int>(m.mesher_.layout().size());
i2_ = new InitializedList<int>(m.mesher_.layout().size());
reverseIndex_ = new InitializedList<int>(m.mesher_.layout().size());
lower_ = new InitializedList<double>(m.mesher_.layout().size());
diag_ = new InitializedList<double>(m.mesher_.layout().size());
upper_ = new InitializedList<double>(m.mesher_.layout().size());
mesher_ = m.mesher_;

int len = m.mesher_.layout().size();
Expand Down
65 changes: 65 additions & 0 deletions src/QLNet/Methods/Finitedifferences/Solvers/FdmHullWhiteSolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright (C) 2017 Jean-Camille Tournier (jean-camille.tournier@avivainvestors.com)
This file is part of QLNet Project https://github.com/amaggiulli/qlnet
QLNet is free software: you can redistribute it and/or modify it
under the terms of the QLNet license. You should have received a
copy of the license along with this program; if not, license is
available online at <http://qlnet.sourceforge.net/License.html>.
QLNet is a based on QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
The QuantLib license is available online at http://quantlib.org/license.shtml.
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.
*/

using System;

namespace QLNet
{
public class FdmHullWhiteSolver : LazyObject
{
public FdmHullWhiteSolver(
Handle<HullWhite> model,
FdmSolverDesc solverDesc,
FdmSchemeDesc schemeDesc = null)
{
solverDesc_ = solverDesc;
schemeDesc_ = schemeDesc ?? new FdmSchemeDesc().Hundsdorfer();
model_ = model;
model_.registerWith(update);
}

public double valueAt(double s)
{
calculate();
return solver_.interpolateAt(s);
}
public double deltaAt(double s) {
return 0.0;
}
public double gammaAt(double s) {
return 0.0;
}
public double thetaAt(double s) {
return 0.0;
}

protected override void performCalculations()
{
FdmHullWhiteOp op = new FdmHullWhiteOp(
solverDesc_.mesher, model_.currentLink(), 0);

solver_ = new Fdm1DimSolver(solverDesc_, schemeDesc_, op);
}

protected Handle<HullWhite> model_;
protected FdmSolverDesc solverDesc_;
protected FdmSchemeDesc schemeDesc_;
protected Fdm1DimSolver solver_;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public FdmBermudanStepCondition(List<Date> exerciseDates,
public void applyTo(object o, double t)
{
Vector a = (Vector) o;
if (exerciseTimes_.BinarySearch(t) != exerciseTimes_.Count)
if (exerciseTimes_.BinarySearch(t) >= 0)
{
FdmLinearOpLayout layout = mesher_.layout();
FdmLinearOpIterator endIter = layout.end();
Expand Down
Loading

0 comments on commit 4cb47c8

Please sign in to comment.