// helper object methods public double payoffKIKO(double spot, double variance, DoubleBarrier.Type barrierType, int maxIteration = 1000, double requiredConvergence = 1e-8) { Utils.QL_REQUIRE(spot > 0.0, () => "positive spot value required"); Utils.QL_REQUIRE(variance >= 0.0, () => "negative variance not allowed"); double residualTime = process_.time(arguments_.exercise.lastDate()); Utils.QL_REQUIRE(residualTime > 0.0, () => "expiration time must be > 0"); double cash = payoff_.cashPayoff(); double barrier_lo = arguments_.barrier_lo.Value; double barrier_hi = arguments_.barrier_hi.Value; if (barrierType == DoubleBarrier.Type.KOKI) { Utils.swap(ref barrier_lo, ref barrier_hi); } double sigmaq = variance / residualTime; double r = process_.riskFreeRate().currentLink().zeroRate(residualTime, Compounding.Continuous, Frequency.NoFrequency).rate(); double q = process_.dividendYield().currentLink().zeroRate(residualTime, Compounding.Continuous, Frequency.NoFrequency).rate(); double b = r - q; double alpha = -0.5 * (2 * b / sigmaq - 1); double beta = -0.25 * Math.Pow((2 * b / sigmaq - 1), 2) - 2 * r / sigmaq; double Z = Math.Log(barrier_hi / barrier_lo); double log_S_L = Math.Log(spot / barrier_lo); double tot = 0, term = 0; for (int i = 1; i < maxIteration; ++i) { double factor = Math.Pow(i * Const.M_PI / Z, 2) - beta; double term1 = (beta - Math.Pow(i * Const.M_PI / Z, 2) * Math.Exp(-0.5 * factor * variance)) / factor; double term2 = Math.Sin(i * Const.M_PI / Z * log_S_L); term = (2.0 / (i * Const.M_PI)) * term1 * term2; tot += term; } tot += 1 - log_S_L / Z; tot *= cash * Math.Pow(spot / barrier_lo, alpha); // Check if convergence is sufficiently fast Utils.QL_REQUIRE(Math.Abs(term) < requiredConvergence, () => "serie did not converge sufficiently fast"); return(Math.Max(tot, 0.0)); }
public void swap(TripleBandLinearOp m) { Utils.swap(ref mesher_, ref m.mesher_); Utils.swap(ref direction_, ref m.direction_); Utils.swap(ref i0_, ref m.i0_); Utils.swap(ref i2_, ref m.i2_); Utils.swap(ref reverseIndex_, ref m.reverseIndex_); Utils.swap(ref lower_, ref m.lower_); Utils.swap(ref diag_, ref m.diag_); Utils.swap(ref upper_, ref m.upper_); }
protected void createInterpolation() { SviInterpolation tmp = new SviInterpolation(actualStrikes_.Where(x => actualStrikes_.First().IsEqual(x)).ToList(), actualStrikes_.Count, vols_.Where(x => vols_.First().IsEqual(x)).ToList(), exerciseTime(), forwardValue_, a_, b_, sigma_, rho_, m_, isAFixed_, isBFixed_, isSigmaFixed_, isRhoFixed_, isMFixed_, vegaWeighted_, endCriteria_, method_); Utils.swap <SviInterpolation>(ref tmp, ref sviInterpolation_); }
protected void createInterpolation() { SABRInterpolation tmp = new SABRInterpolation(actualStrikes_.Where(x => actualStrikes_.First().IsEqual(x)).ToList(), actualStrikes_.Count, vols_.Where(x => vols_.First().IsEqual(x)).ToList(), exerciseTime(), forwardValue_, alpha_, beta_, nu_, rho_, isAlphaFixed_, isBetaFixed_, isNuFixed_, isRhoFixed_, vegaWeighted_, endCriteria_, method_, 0.0020, false, 50, shift()); Utils.swap <SABRInterpolation>(ref tmp, ref sabrInterpolation_); }
public void swap(NinePointLinearOp m) { Utils.swap(ref d0_, ref m.d0_); Utils.swap(ref d1_, ref m.d1_); Utils.swap(ref i00_, ref m.i00_); Utils.swap(ref i10_, ref m.i10_); Utils.swap(ref i20_, ref m.i20_); Utils.swap(ref i01_, ref m.i01_); Utils.swap(ref i21_, ref m.i21_); Utils.swap(ref i02_, ref m.i02_); Utils.swap(ref i12_, ref m.i12_); Utils.swap(ref i22_, ref m.i22_); Utils.swap(ref a00_, ref m.a00_); Utils.swap(ref a10_, ref m.a10_); Utils.swap(ref a20_, ref m.a20_); Utils.swap(ref a01_, ref m.a01_); Utils.swap(ref a21_, ref m.a21_); Utils.swap(ref a02_, ref m.a02_); Utils.swap(ref a12_, ref m.a12_); Utils.swap(ref a22_, ref m.a22_); Utils.swap(ref a11_, ref m.a11_); Utils.swap(ref mesher_, ref m.mesher_); }
public void swap(FdmLinearOpIterator iter) { Utils.swap(ref iter.index_, ref index_); Utils.swap(ref iter.dim_, ref dim_); Utils.swap(ref iter.coordinates_, ref coordinates_); }
public override void calculate() { if (!(arguments_.exercise.type() == Exercise.Type.American)) { throw new ApplicationException("not an American Option"); } AmericanExercise ex = arguments_.exercise as AmericanExercise; if (ex == null) { throw new ApplicationException("non-American exercise given"); } if (ex.payoffAtExpiry()) { throw new ApplicationException("payoff at expiry not handled"); } PlainVanillaPayoff payoff = arguments_.payoff as PlainVanillaPayoff; if (payoff == null) { throw new ApplicationException("non-plain payoff given"); } double variance = process_.blackVolatility().link.blackVariance(ex.lastDate(), payoff.strike()); double dividendDiscount = process_.dividendYield().link.discount(ex.lastDate()); double riskFreeDiscount = process_.riskFreeRate().link.discount(ex.lastDate()); double spot = process_.stateVariable().link.value(); if (!(spot > 0.0)) { throw new ApplicationException("negative or null underlying given"); } double strike = payoff.strike(); if (payoff.optionType() == Option.Type.Put) { // use put-call simmetry Utils.swap <double>(ref spot, ref strike); Utils.swap <double>(ref riskFreeDiscount, ref dividendDiscount); payoff = new PlainVanillaPayoff(Option.Type.Call, strike); } if (dividendDiscount >= 1.0) { // early exercise is never optimal - use Black formula double forwardPrice = spot * dividendDiscount / riskFreeDiscount; BlackCalculator black = new BlackCalculator(payoff, forwardPrice, Math.Sqrt(variance), riskFreeDiscount); results_.value = black.value(); results_.delta = black.delta(spot); results_.deltaForward = black.deltaForward(); results_.elasticity = black.elasticity(spot); results_.gamma = black.gamma(spot); DayCounter rfdc = process_.riskFreeRate().link.dayCounter(); DayCounter divdc = process_.dividendYield().link.dayCounter(); DayCounter voldc = process_.blackVolatility().link.dayCounter(); double t = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(), arguments_.exercise.lastDate()); results_.rho = black.rho(t); t = divdc.yearFraction(process_.dividendYield().link.referenceDate(), arguments_.exercise.lastDate()); results_.dividendRho = black.dividendRho(t); t = voldc.yearFraction(process_.blackVolatility().link.referenceDate(), arguments_.exercise.lastDate()); results_.vega = black.vega(t); results_.theta = black.theta(spot, t); results_.thetaPerDay = black.thetaPerDay(spot, t); results_.strikeSensitivity = black.strikeSensitivity(); results_.itmCashProbability = black.itmCashProbability(); } else { // early exercise can be optimal - use approximation results_.value = americanCallApproximation(spot, strike, riskFreeDiscount, dividendDiscount, variance); } }