public virtual double value(double t) { Matrix m = param_.diffusion(t, new Vector()); double u = 0; m.row(i_).ForEach((ii, vv) => u += vv * m.row(j_)[ii]); return(u); }
public override Vector evolve(double t0, Vector x0, double dt, Vector dw) { /* 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. */ int m = nextIndexReset(t0); double sdt = Math.Sqrt(dt); Vector f = new Vector(x0); Matrix diff = lfmParam_.diffusion(t0, x0); Matrix covariance = lfmParam_.covariance(t0, x0); for (int k = m; k < size_; ++k) { double y = accrualPeriod_[k] * x0[k]; m1[k] = y / (1 + y); double d = 0; m1.GetRange(m, k + 1 - m).ForEach( (ii, vv) => d += vv * covariance.column(k).GetRange(m, covariance.rows() - m)[ii]); d = (d - 0.5 * covariance[k, k]) * dt; double r = 0; diff.row(k).ForEach((kk, vv) => r += vv * dw[kk]); r *= sdt; double x = y * Math.Exp(d + r); m2[k] = x / (1 + x); double inner_product = 0; m2.GetRange(m, k + 1 - m).ForEach( (ii, vv) => inner_product += vv * covariance.column(k).GetRange(m, covariance.rows() - m)[ii]); f[k] = x0[k] * Math.Exp(0.5 * (d + (inner_product - 0.5 * covariance[k, k]) * dt) + r); } return(f); }
public override Vector evolve(double t0, Vector x0, double dt, Vector dw) { // predictor-corrector step to reduce discretization errors. int m = nextIndexReset(t0); double sdt = Math.Sqrt(dt); Vector f = new Vector(x0); Matrix diff = lfmParam_.diffusion(t0, x0); Matrix covariance = lfmParam_.covariance(t0, x0); for (int k = m; k < size_; ++k) { double y = accrualPeriod_[k] * x0[k]; m1[k] = y / (1 + y); double d = 0; m1.GetRange(m, k + 1 - m).ForEach( (ii, vv) => d += vv * covariance.column(k).GetRange(m, covariance.rows() - m)[ii]); d = (d - 0.5 * covariance[k, k]) * dt; double r = 0; diff.row(k).ForEach((kk, vv) => r += vv * dw[kk]); r *= sdt; double x = y * Math.Exp(d + r); m2[k] = x / (1 + x); double inner_product = 0; m2.GetRange(m, k + 1 - m).ForEach( (ii, vv) => inner_product += vv * covariance.column(k).GetRange(m, covariance.rows() - m)[ii]); f[k] = x0[k] * Math.Exp(0.5 * (d + (inner_product - 0.5 * covariance[k, k]) * dt) + r); } return(f); }
public LfmHullWhiteParameterization( LiborForwardModelProcess process, OptionletVolatilityStructure capletVol, Matrix correlation, int factors) : base(process.size(), factors) { diffusion_ = new Matrix(size_ - 1, factors_); fixingTimes_ = process.fixingTimes(); Matrix sqrtCorr = new Matrix(size_ - 1, factors_, 1.0); if (correlation.empty()) { if (!(factors_ == 1)) { throw new ApplicationException("correlation matrix must be given for " + "multi factor models"); } } else { if (!(correlation.rows() == size_ - 1 && correlation.rows() == correlation.columns())) { throw new ApplicationException("wrong dimesion of the correlation matrix"); } if (!(factors_ <= size_ - 1)) { throw new ApplicationException("too many factors for given LFM process"); } Matrix tmpSqrtCorr = MatrixUtilitites.pseudoSqrt(correlation, MatrixUtilitites.SalvagingAlgorithm.Spectral); // reduce to n factor model // "Reconstructing a valid correlation matrix from invalid data" // (<http://www.quarchome.org/correlationmatrix.pdf>) for (int i = 0; i < size_ - 1; ++i) { double d = 0; tmpSqrtCorr.row(i).GetRange(0, factors_).ForEach((ii, vv) => d += vv * tmpSqrtCorr.row(i)[ii]); //sqrtCorr.row(i).GetRange(0, factors_).ForEach((ii, vv) => sqrtCorr.row(i)[ii] = tmpSqrtCorr.row(i).GetRange(0, factors_)[ii] / Math.Sqrt(d)); for (int k = 0; k < factors_; ++k) { sqrtCorr[i, k] = tmpSqrtCorr.row(i).GetRange(0, factors_)[k] / Math.Sqrt(d); } } } List <double> lambda = new List <double>(); DayCounter dayCounter = process.index().dayCounter(); List <double> fixingTimes = process.fixingTimes(); List <Date> fixingDates = process.fixingDates(); for (int i = 1; i < size_; ++i) { double cumVar = 0.0; for (int j = 1; j < i; ++j) { cumVar += lambda[i - j - 1] * lambda[i - j - 1] * (fixingTimes[j + 1] - fixingTimes[j]); } double vol = capletVol.volatility(fixingDates[i], 0.0, false); double var = vol * vol * capletVol.dayCounter().yearFraction(fixingDates[0], fixingDates[i]); lambda.Add(Math.Sqrt((var - cumVar) / (fixingTimes[1] - fixingTimes[0]))); for (int q = 0; q < factors_; ++q) { diffusion_[i - 1, q] = sqrtCorr[i - 1, q] * lambda.Last(); } } covariance_ = diffusion_ * Matrix.transpose(diffusion_); }