// 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));
        }
Example #2
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_);
 }
Example #3
0
        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_);
        }
Example #4
0
        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_);
        }
Example #5
0
        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_);
        }
Example #6
0
 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_);
 }
Example #7
0
        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);
            }
        }