Пример #1
0
 public YoYInflationIndex clone(Handle <YoYInflationTermStructure> h)
 {
     return(new YoYInflationIndex(familyName_, region_, revised_,
                                  interpolated_, ratio_, frequency_,
                                  availabilityLag_, currency_, h));
 }
Пример #2
0
        public override double swapletRate()
        {
            OvernightIndex index = coupon_.index() as OvernightIndex;

            List <Date>   fixingDates = coupon_.fixingDates();
            List <double> dt          = coupon_.dt();

            int n = dt.Count();
            int i = 0;

            double compoundFactor = 1.0;

            // already fixed part
            Date today = Settings.evaluationDate();

            while (fixingDates[i] < today && i < n)
            {
                // rate must have been fixed
                double pastFixing = IndexManager.instance().getHistory(
                    index.name()).value()[fixingDates[i]];

                if (pastFixing == default(double))
                {
                    throw new ApplicationException("Missing " + index.name() + " fixing for "
                                                   + fixingDates[i].ToString());
                }

                compoundFactor *= (1.0 + pastFixing * dt[i]);
                ++i;
            }

            // today is a border case
            if (fixingDates[i] == today && i < n)
            {
                // might have been fixed
                try
                {
                    double pastFixing = IndexManager.instance().getHistory(
                        index.name()).value()[fixingDates[i]];

                    if (pastFixing != default(double))
                    {
                        compoundFactor *= (1.0 + pastFixing * dt[i]);
                        ++i;
                    }
                    else
                    {
                        ; // fall through and forecast
                    }
                }
                catch (Exception)
                {
                    ;  // fall through and forecast
                }
            }

            // forward part using telescopic property in order
            // to avoid the evaluation of multiple forward fixings
            if (i < n)
            {
                Handle <YieldTermStructure> curve = index.forwardingTermStructure();
                if (curve.empty())
                {
                    throw new ArgumentException("null term structure set to this instance of" +
                                                index.name());
                }

                List <Date> dates         = coupon_.valueDates();
                double      startDiscount = curve.link.discount(dates[i]);
                double      endDiscount   = curve.link.discount(dates[n]);

                compoundFactor *= startDiscount / endDiscount;
            }

            double rate = (compoundFactor - 1.0) / coupon_.accrualPeriod();

            return(coupon_.gearing() * rate + coupon_.spread());
        }
Пример #3
0
 public BlackProcess(Handle <Quote> x0,
                     Handle <YieldTermStructure> riskFreeTS,
                     Handle <BlackVolTermStructure> blackVolTS)
     : this(x0, riskFreeTS, blackVolTS, new EulerDiscretization())
 {
 }
Пример #4
0
 public static GFunction newGFunctionWithShifts(CmsCoupon coupon, Handle <Quote> meanReversion)
 {
     return(new GFunctionWithShifts(coupon, meanReversion) as GFunction);
 }
 //! returns a copy of itself linked to a different forwarding curve
 public new IborIndex clone(Handle <YieldTermStructure> h)
 {
     return(new OvernightIndex(familyName(), fixingDays(), currency(), fixingCalendar(),
                               dayCounter(), h));
 }
Пример #6
0
 public G2(Handle <YieldTermStructure> termStructure)
     : this(termStructure, 0.1, 0.01, 0.1, 0.01, -0.75)
 {
 }
Пример #7
0
        protected HaganPricer(Handle <SwaptionVolatilityStructure> swaptionVol, GFunctionFactory.YieldCurveModel modelOfYieldCurve, Handle <Quote> meanReversion)
            : base(swaptionVol)
        {
            modelOfYieldCurve_ = modelOfYieldCurve;
            cutoffForCaplet_   = 2;
            cutoffForFloorlet_ = 0;
            meanReversion_     = meanReversion;

            if (meanReversion_.link != null)
            {
                meanReversion_.registerWith(update);
            }
        }
Пример #8
0
 //! NPV of income/dividends/storage-costs etc. of underlying instrument
 public abstract double spotIncome(Handle <YieldTermStructure> incomeDiscountCurve);
 // constructors. special case when convexityAdjustment is really delivered as Quote
 public FuturesRateHelper(Handle <Quote> price, Date immDate, int lengthInMonths, Calendar calendar,
                          BusinessDayConvention convention, bool endOfMonth, DayCounter dayCounter)
     : this(price, immDate, lengthInMonths, calendar, convention, endOfMonth, dayCounter, new Handle <Quote>())
 {
 }
Пример #10
0
 public NZDLibor(Period tenor, Handle <YieldTermStructure> h)
     : base("NZDLibor", tenor, 2, new NZDCurrency(), new NewZealand(), new Actual360(), h)
 {
 }
Пример #11
0
 public BondHelper(Handle <Quote> cleanPrice, Bond bond)
     : base(cleanPrice, bond)
 {
 }
Пример #12
0
        public override void calculate()
        {
            DayCounter rfdc   = process_.riskFreeRate().link.dayCounter();
            DayCounter divdc  = process_.dividendYield().link.dayCounter();
            DayCounter voldc  = process_.blackVolatility().link.dayCounter();
            Calendar   volcal = process_.blackVolatility().link.calendar();

            double s0 = process_.stateVariable().link.value();

            Utils.QL_REQUIRE(s0 > 0.0, () => "negative or null underlying given");
            double v             = process_.blackVolatility().link.blackVol(arguments_.exercise.lastDate(), s0);
            Date   maturityDate  = arguments_.exercise.lastDate();
            double r             = process_.riskFreeRate().link.zeroRate(maturityDate, rfdc, Compounding.Continuous, Frequency.NoFrequency).value();
            double q             = process_.dividendYield().link.zeroRate(maturityDate, divdc, Compounding.Continuous, Frequency.NoFrequency).value();
            Date   referenceDate = process_.riskFreeRate().link.referenceDate();

            // binomial trees with constant coefficient
            Handle <YieldTermStructure>    flatRiskFree  = new Handle <YieldTermStructure>(new FlatForward(referenceDate, r, rfdc));
            Handle <YieldTermStructure>    flatDividends = new Handle <YieldTermStructure>(new FlatForward(referenceDate, q, divdc));
            Handle <BlackVolTermStructure> flatVol       = new Handle <BlackVolTermStructure>(new BlackConstantVol(referenceDate, volcal, v, voldc));

            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-striked payoff given");

            double maturity = rfdc.yearFraction(referenceDate, maturityDate);

            StochasticProcess1D bs = new GeneralizedBlackScholesProcess(process_.stateVariable(),
                                                                        flatDividends, flatRiskFree, flatVol);

            // correct timesteps to ensure a (local) minimum, using Boyle and Lau
            // approach. See Journal of Derivatives, 1/1994,
            // "Bumping up against the barrier with the binomial method"
            // Note: this approach works only for CoxRossRubinstein lattices, so
            // is disabled if T is not a CoxRossRubinstein or derived from it.
            int optimum_steps = timeSteps_;

            if (maxTimeSteps_ > timeSteps_ && s0 > 0 && arguments_.barrier > 0) // boost::is_base_of<CoxRossRubinstein, T>::value &&
            {
                double divisor;
                if (s0 > arguments_.barrier)
                {
                    divisor = Math.Pow(Math.Log(s0 / arguments_.barrier.Value), 2);
                }
                else
                {
                    divisor = Math.Pow(Math.Log(arguments_.barrier.Value / s0), 2);
                }
                if (!Utils.close(divisor, 0))
                {
                    for (int i = 1; i < timeSteps_; ++i)
                    {
                        int optimum = (int)((i * i * v * v * maturity) / divisor);
                        if (timeSteps_ < optimum)
                        {
                            optimum_steps = optimum;
                            break; // found first minimum with iterations>=timesteps
                        }
                    }
                }

                if (optimum_steps > maxTimeSteps_)
                {
                    optimum_steps = maxTimeSteps_; // too high, limit
                }
            }

            TimeGrid grid = new TimeGrid(maturity, optimum_steps);

            ITree tree = getTree_(bs, maturity, optimum_steps, payoff.strike());

            BlackScholesLattice <ITree> lattice = new BlackScholesLattice <ITree>(tree, r, maturity, optimum_steps);

            DiscretizedAsset option = getAsset_(arguments_, process_, grid);

            option.initialize(lattice, maturity);

            // Partial derivatives calculated from various points in the
            // binomial tree
            // (see J.C.Hull, "Options, Futures and other derivatives", 6th edition, pp 397/398)

            // Rollback to third-last step, and get underlying prices (s2) &
            // option values (p2) at this point
            option.rollback(grid[2]);
            Vector va2 = new Vector(option.values());

            Utils.QL_REQUIRE(va2.size() == 3, () => "Expect 3 nodes in grid at second step");
            double p2u = va2[2];                   // up
            double p2m = va2[1];                   // mid
            double p2d = va2[0];                   // down (low)
            double s2u = lattice.underlying(2, 2); // up price
            double s2m = lattice.underlying(2, 1); // middle price
            double s2d = lattice.underlying(2, 0); // down (low) price

            // calculate gamma by taking the first derivate of the two deltas
            double delta2u = (p2u - p2m) / (s2u - s2m);
            double delta2d = (p2m - p2d) / (s2m - s2d);
            double gamma   = (delta2u - delta2d) / ((s2u - s2d) / 2);

            // Rollback to second-last step, and get option values (p1) at
            // this point
            option.rollback(grid[1]);
            Vector va = new Vector(option.values());

            Utils.QL_REQUIRE(va.size() == 2, () => "Expect 2 nodes in grid at first step");
            double p1u = va[1];
            double p1d = va[0];
            double s1u = lattice.underlying(1, 1); // up (high) price
            double s1d = lattice.underlying(1, 0); // down (low) price

            double delta = (p1u - p1d) / (s1u - s1d);

            // Finally, rollback to t=0
            option.rollback(0.0);
            double p0 = option.presentValue();

            // Store results
            results_.value = p0;
            results_.delta = delta;
            results_.gamma = gamma;
            // theta can be approximated by calculating the numerical derivative
            // between mid value at third-last step and at t0. The underlying price
            // is the same, only time varies.
            results_.theta = (p2m - p0) / grid[2];
        }
Пример #13
0
        public GeneralizedBlackScholesProcess(Handle <Quote> x0, Handle <YieldTermStructure> dividendTS,
                                              Handle <YieldTermStructure> riskFreeTS, Handle <BlackVolTermStructure> blackVolTS, IDiscretization1D disc = null)
            : base(disc ?? new EulerDiscretization())
        {
            x0_              = x0;
            riskFreeRate_    = riskFreeTS;
            dividendYield_   = dividendTS;
            blackVolatility_ = blackVolTS;
            updated_         = false;

            x0_.registerWith(update);
            riskFreeRate_.registerWith(update);
            dividendYield_.registerWith(update);
            blackVolatility_.registerWith(update);
        }
Пример #14
0
 public GarmanKohlagenProcess(Handle <Quote> x0, Handle <YieldTermStructure> foreignRiskFreeTS,
                              Handle <YieldTermStructure> domesticRiskFreeTS,
                              Handle <BlackVolTermStructure> blackVolTS, IDiscretization1D d)
     : base(x0, foreignRiskFreeTS, domesticRiskFreeTS, blackVolTS, d)
 {
 }
Пример #15
0
 public ImpliedVolTermStructure(Handle <BlackVolTermStructure> originalTS, Date referenceDate)
     : base(referenceDate)
 {
     originalTS_ = originalTS;
     originalTS_.registerWith(update);
 }
Пример #16
0
 protected CmsCouponPricer(Handle <SwaptionVolatilityStructure> v = null)
 {
     swaptionVol_ = v ?? new Handle <SwaptionVolatilityStructure>();
     swaptionVol_.registerWith(update);
 }
Пример #17
0
 public G2(Handle <YieldTermStructure> termStructure,
           double a,
           double sigma)
     : this(termStructure, a, sigma, 0.1, 0.01, -0.75)
 {
 }
Пример #18
0
 public virtual void setCapletVolatility(Handle <CPIVolatilitySurface> capletVol)
 {
     Utils.QL_REQUIRE(!capletVol.empty(), () => "empty capletVol handle");
     capletVol_ = capletVol;
     capletVol_.registerWith(update);
 }
Пример #19
0
 public AnalyticHaganPricer(Handle <SwaptionVolatilityStructure> swaptionVol, GFunctionFactory.YieldCurveModel modelOfYieldCurve, Handle <Quote> meanReversion)
     : base(swaptionVol, modelOfYieldCurve, meanReversion)
 {
 }
Пример #20
0
 public FittingParameter(Handle<YieldTermStructure> termStructure,
                         double a, double sigma)
    : base(new FittingParameter.Impl(termStructure, a, sigma))
 { }
Пример #21
0
        public override void initialize(FloatingRateCoupon coupon)
        {
            coupon_ = coupon as CmsCoupon;
            Utils.QL_REQUIRE(coupon_ != null, () => "CMS coupon needed");
            gearing_ = coupon_.gearing();
            spread_  = coupon_.spread();

            fixingDate_  = coupon_.fixingDate();
            paymentDate_ = coupon_.date();
            SwapIndex swapIndex = coupon_.swapIndex();

            rateCurve_ = swapIndex.forwardingTermStructure().link;

            Date today = Settings.evaluationDate();

            if (paymentDate_ > today)
            {
                discount_ = rateCurve_.discount(paymentDate_);
            }
            else
            {
                discount_ = 1.0;
            }

            spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_;

            if (fixingDate_ > today)
            {
                swapTenor_ = swapIndex.tenor();
                VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_);

                swapRateValue_ = swap.fairRate();

                annuity_ = Math.Abs(swap.fixedLegBPS() / Const.BASIS_POINT);

                int        q                    = (int)swapIndex.fixedLegTenor().frequency();
                Schedule   schedule             = swap.fixedSchedule();
                DayCounter dc                   = swapIndex.dayCounter();
                double     startTime            = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate());
                double     swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1));
                double     paymentTime          = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_);
                double     delta                = (paymentTime - startTime) / (swapFirstPaymentTime - startTime);

                switch (modelOfYieldCurve_)
                {
                case GFunctionFactory.YieldCurveModel.Standard:
                    gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length());
                    break;

                case GFunctionFactory.YieldCurveModel.ExactYield:
                    gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_);
                    break;

                case GFunctionFactory.YieldCurveModel.ParallelShifts:
                {
                    Handle <Quote> nullMeanReversionQuote = new Handle <Quote>(new SimpleQuote(0.0));
                    gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote);
                }
                break;

                case GFunctionFactory.YieldCurveModel.NonParallelShifts:
                    gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_);
                    break;

                default:
                    Utils.QL_FAIL("unknown/illegal gFunction type");
                    break;
                }
                vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link);
            }
        }
Пример #22
0
 public HullWhite(Handle<YieldTermStructure> termStructure,
                  double a)
    : this(termStructure, a, 0.01)
 { }
 //! returns a copy of itself linked to a different forwarding curve
 public IborIndex clone(Handle <YieldTermStructure> forwarding)
 {
     return(new IborIndex(familyName(), tenor(), fixingDays(), currency(), fixingCalendar(),
                          businessDayConvention(), endOfMonth(), dayCounter(), forwarding));
 }
Пример #24
0
 public HullWhite(Handle<YieldTermStructure> termStructure)
    : this(termStructure, 0.1, 0.01)
 { }
Пример #25
0
        public override void calculate()
        {
            double sigmaShift_vega  = 0.001;
            double sigmaShift_volga = 0.0001;
            double spotShift_delta  = 0.0001 * spotFX_.link.value();
            double sigmaShift_vanna = 0.0001;

            Utils.QL_REQUIRE(arguments_.barrierType == DoubleBarrier.Type.KnockIn ||
                             arguments_.barrierType == DoubleBarrier.Type.KnockOut, () =>
                             "Only same type barrier supported");

            Handle <Quote> x0Quote     = new Handle <Quote>(new SimpleQuote(spotFX_.link.value()));
            Handle <Quote> atmVolQuote = new Handle <Quote>(new SimpleQuote(atmVol_.link.value()));

            BlackVolTermStructure blackVolTS = new BlackConstantVol(Settings.evaluationDate(),
                                                                    new NullCalendar(), atmVolQuote, new Actual365Fixed());

            BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(x0Quote, foreignTS_, domesticTS_,
                                                                                   new Handle <BlackVolTermStructure>(blackVolTS));

            IPricingEngine engineBS = getOriginalEngine_(stochProcess, series_);

            BlackDeltaCalculator blackDeltaCalculatorAtm = new BlackDeltaCalculator(
                Option.Type.Call, atmVol_.link.deltaType(), x0Quote.link.value(),
                domesticTS_.link.discount(T_), foreignTS_.link.discount(T_),
                atmVol_.link.value() * Math.Sqrt(T_));

            double atmStrike = blackDeltaCalculatorAtm.atmStrike(atmVol_.link.atmType());

            double call25Vol = vol25Call_.link.value();
            double put25Vol  = vol25Put_.link.value();
            BlackDeltaCalculator blackDeltaCalculatorPut25 = new BlackDeltaCalculator(
                Option.Type.Put, vol25Put_.link.deltaType(), x0Quote.link.value(),
                domesticTS_.link.discount(T_), foreignTS_.link.discount(T_),
                put25Vol * Math.Sqrt(T_));
            double put25Strike = blackDeltaCalculatorPut25.strikeFromDelta(-0.25);
            BlackDeltaCalculator blackDeltaCalculatorCall25 = new BlackDeltaCalculator(
                Option.Type.Call, vol25Call_.link.deltaType(), x0Quote.link.value(),
                domesticTS_.link.discount(T_), foreignTS_.link.discount(T_),
                call25Vol * Math.Sqrt(T_));
            double call25Strike = blackDeltaCalculatorCall25.strikeFromDelta(0.25);

            //here use vanna volga interpolated smile to price vanilla
            List <double> strikes = new List <double>();
            List <double> vols    = new List <double>();

            strikes.Add(put25Strike);
            vols.Add(put25Vol);
            strikes.Add(atmStrike);
            vols.Add(atmVol_.link.value());
            strikes.Add(call25Strike);
            vols.Add(call25Vol);
            VannaVolga vannaVolga = new VannaVolga(x0Quote.link.value(), foreignTS_.link.discount(T_),
                                                   foreignTS_.link.discount(T_), T_);
            Interpolation interpolation = vannaVolga.interpolate(strikes, strikes.Count, vols);

            interpolation.enableExtrapolation();
            StrikedTypePayoff payoff = arguments_.payoff as StrikedTypePayoff;

            Utils.QL_REQUIRE(payoff != null, () => "invalid payoff");
            double strikeVol = interpolation.value(payoff.strike());
            //vannila option price
            double vanillaOption = Utils.blackFormula(payoff.optionType(), payoff.strike(),
                                                      x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                      strikeVol * Math.Sqrt(T_),
                                                      domesticTS_.link.discount(T_));

            //already out
            if ((x0Quote.link.value() > arguments_.barrier_hi || x0Quote.link.value() < arguments_.barrier_lo) &&
                arguments_.barrierType == DoubleBarrier.Type.KnockOut)
            {
                results_.value = 0.0;
                results_.additionalResults["VanillaPrice"]    = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption;
                results_.additionalResults["BarrierInPrice"]  = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption;
                results_.additionalResults["BarrierOutPrice"] = 0.0;
            }
            //already in
            else if ((x0Quote.link.value() > arguments_.barrier_hi || x0Quote.link.value() < arguments_.barrier_lo) &&
                     arguments_.barrierType == DoubleBarrier.Type.KnockIn)
            {
                results_.value = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption;
                results_.additionalResults["VanillaPrice"]    = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption;
                results_.additionalResults["BarrierInPrice"]  = adaptVanDelta_? bsPriceWithSmile_ : vanillaOption;
                results_.additionalResults["BarrierOutPrice"] = 0.0;
            }
            else
            {
                //set up BS barrier option pricing
                //only calculate out barrier option price
                // in barrier price = vanilla - out barrier
                DoubleBarrierOption doubleBarrierOption = new DoubleBarrierOption(
                    arguments_.barrierType,
                    arguments_.barrier_lo.GetValueOrDefault(),
                    arguments_.barrier_hi.GetValueOrDefault(),
                    arguments_.rebate.GetValueOrDefault(),
                    payoff,
                    arguments_.exercise);

                doubleBarrierOption.setPricingEngine(engineBS);

                //BS price
                double priceBS = doubleBarrierOption.NPV();

                double priceAtmCallBS = Utils.blackFormula(Option.Type.Call, atmStrike,
                                                           x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                           atmVol_.link.value() * Math.Sqrt(T_),
                                                           domesticTS_.link.discount(T_));
                double price25CallBS = Utils.blackFormula(Option.Type.Call, call25Strike,
                                                          x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                          atmVol_.link.value() * Math.Sqrt(T_),
                                                          domesticTS_.link.discount(T_));
                double price25PutBS = Utils.blackFormula(Option.Type.Put, put25Strike,
                                                         x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                         atmVol_.link.value() * Math.Sqrt(T_),
                                                         domesticTS_.link.discount(T_));

                //market price
                double priceAtmCallMkt = Utils.blackFormula(Option.Type.Call, atmStrike,
                                                            x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                            atmVol_.link.value() * Math.Sqrt(T_),
                                                            domesticTS_.link.discount(T_));
                double price25CallMkt = Utils.blackFormula(Option.Type.Call, call25Strike,
                                                           x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                           call25Vol * Math.Sqrt(T_),
                                                           domesticTS_.link.discount(T_));
                double price25PutMkt = Utils.blackFormula(Option.Type.Put, put25Strike,
                                                          x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_),
                                                          put25Vol * Math.Sqrt(T_),
                                                          domesticTS_.link.discount(T_));

                //Analytical Black Scholes formula
                NormalDistribution norm  = new NormalDistribution();
                double             d1atm = (Math.Log(x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_) / atmStrike)
                                            + 0.5 * Math.Pow(atmVolQuote.link.value(), 2.0) * T_) / (atmVolQuote.link.value() * Math.Sqrt(T_));
                double vegaAtm_Analytical  = x0Quote.link.value() * norm.value(d1atm) * Math.Sqrt(T_) * foreignTS_.link.discount(T_);
                double vannaAtm_Analytical = vegaAtm_Analytical / x0Quote.link.value() * (1.0 - d1atm / (atmVolQuote.link.value() * Math.Sqrt(T_)));
                double volgaAtm_Analytical = vegaAtm_Analytical * d1atm * (d1atm - atmVolQuote.link.value() * Math.Sqrt(T_)) / atmVolQuote.link.value();

                double d125call = (Math.Log(x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_) / call25Strike)
                                   + 0.5 * Math.Pow(atmVolQuote.link.value(), 2.0) * T_) / (atmVolQuote.link.value() * Math.Sqrt(T_));
                double vega25Call_Analytical  = x0Quote.link.value() * norm.value(d125call) * Math.Sqrt(T_) * foreignTS_.link.discount(T_);
                double vanna25Call_Analytical = vega25Call_Analytical / x0Quote.link.value() * (1.0 - d125call / (atmVolQuote.link.value() * Math.Sqrt(T_)));
                double volga25Call_Analytical = vega25Call_Analytical * d125call * (d125call - atmVolQuote.link.value() * Math.Sqrt(T_)) / atmVolQuote.link.value();

                double d125Put = (Math.Log(x0Quote.link.value() * foreignTS_.link.discount(T_) / domesticTS_.link.discount(T_) / put25Strike)
                                  + 0.5 * Math.Pow(atmVolQuote.link.value(), 2.0) * T_) / (atmVolQuote.link.value() * Math.Sqrt(T_));
                double vega25Put_Analytical  = x0Quote.link.value() * norm.value(d125Put) * Math.Sqrt(T_) * foreignTS_.link.discount(T_);
                double vanna25Put_Analytical = vega25Put_Analytical / x0Quote.link.value() * (1.0 - d125Put / (atmVolQuote.link.value() * Math.Sqrt(T_)));
                double volga25Put_Analytical = vega25Put_Analytical * d125Put * (d125Put - atmVolQuote.link.value() * Math.Sqrt(T_)) / atmVolQuote.link.value();


                //BS vega
                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value() + sigmaShift_vega);
                doubleBarrierOption.recalculate();
                double vegaBarBS = (doubleBarrierOption.NPV() - priceBS) / sigmaShift_vega;
                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value() - sigmaShift_vega);//setback

                //BS volga

                //vegaBar2
                //base NPV
                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value() + sigmaShift_volga);
                doubleBarrierOption.recalculate();
                double priceBS2 = doubleBarrierOption.NPV();

                //shifted npv
                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value() + sigmaShift_vega);
                doubleBarrierOption.recalculate();
                double vegaBarBS2 = (doubleBarrierOption.NPV() - priceBS2) / sigmaShift_vega;
                double volgaBarBS = (vegaBarBS2 - vegaBarBS) / sigmaShift_volga;
                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value()
                                                                  - sigmaShift_volga
                                                                  - sigmaShift_vega);                        //setback

                //BS Delta
                //base delta
                ((SimpleQuote)x0Quote.currentLink()).setValue(x0Quote.link.value() + spotShift_delta);//shift forth
                doubleBarrierOption.recalculate();
                double priceBS_delta1 = doubleBarrierOption.NPV();

                ((SimpleQuote)x0Quote.currentLink()).setValue(x0Quote.link.value() - 2 * spotShift_delta);//shift back
                doubleBarrierOption.recalculate();
                double priceBS_delta2 = doubleBarrierOption.NPV();

                ((SimpleQuote)x0Quote.currentLink()).setValue(x0Quote.link.value() + spotShift_delta);//set back
                double deltaBar1 = (priceBS_delta1 - priceBS_delta2) / (2.0 * spotShift_delta);

                //shifted vanna
                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value() + sigmaShift_vanna); //shift sigma
                //shifted delta
                ((SimpleQuote)x0Quote.currentLink()).setValue(x0Quote.link.value() + spotShift_delta);          //shift forth
                doubleBarrierOption.recalculate();
                priceBS_delta1 = doubleBarrierOption.NPV();

                ((SimpleQuote)x0Quote.currentLink()).setValue(x0Quote.link.value() - 2 * spotShift_delta);//shift back
                doubleBarrierOption.recalculate();
                priceBS_delta2 = doubleBarrierOption.NPV();

                ((SimpleQuote)x0Quote.currentLink()).setValue(x0Quote.link.value() + spotShift_delta);//set back
                double deltaBar2 = (priceBS_delta1 - priceBS_delta2) / (2.0 * spotShift_delta);

                double vannaBarBS = (deltaBar2 - deltaBar1) / sigmaShift_vanna;

                ((SimpleQuote)atmVolQuote.currentLink()).setValue(atmVolQuote.link.value() - sigmaShift_vanna);//set back

                //Matrix
                Matrix A = new Matrix(3, 3, 0.0);

                //analytical
                A[0, 0] = vegaAtm_Analytical;
                A[0, 1] = vega25Call_Analytical;
                A[0, 2] = vega25Put_Analytical;
                A[1, 0] = vannaAtm_Analytical;
                A[1, 1] = vanna25Call_Analytical;
                A[1, 2] = vanna25Put_Analytical;
                A[2, 0] = volgaAtm_Analytical;
                A[2, 1] = volga25Call_Analytical;
                A[2, 2] = volga25Put_Analytical;

                Vector b = new Vector(3, 0.0);
                b[0] = vegaBarBS;
                b[1] = vannaBarBS;
                b[2] = volgaBarBS;
                Vector q = Matrix.inverse(A) * b;

                double H = arguments_.barrier_hi.GetValueOrDefault();
                double L = arguments_.barrier_lo.GetValueOrDefault();
                double theta_tilt_minus = ((domesticTS_.link.zeroRate(T_, Compounding.Continuous).value() -
                                            foreignTS_.link.zeroRate(T_, Compounding.Continuous).value()) /
                                           atmVol_.link.value() - atmVol_.link.value() / 2.0) * Math.Sqrt(T_);
                double h = 1.0 / atmVol_.link.value() * Math.Log(H / x0Quote.link.value()) / Math.Sqrt(T_);
                double l = 1.0 / atmVol_.link.value() * Math.Log(L / x0Quote.link.value()) / Math.Sqrt(T_);
                CumulativeNormalDistribution cnd = new CumulativeNormalDistribution();

                double doubleNoTouch = 0.0;
                for (int j = -series_; j < series_; j++)
                {
                    double e_minus = 2 * j * (h - l) - theta_tilt_minus;
                    doubleNoTouch += Math.Exp(-2.0 * j * theta_tilt_minus * (h - l)) * (cnd.value(h + e_minus) - cnd.value(l + e_minus))
                                     - Math.Exp(-2.0 * j * theta_tilt_minus * (h - l) + 2.0 * theta_tilt_minus * h) *
                                     (cnd.value(h - 2.0 * h + e_minus) - cnd.value(l - 2.0 * h + e_minus));
                }

                double p_survival = doubleNoTouch;

                double lambda = p_survival;
                double adjust = q[0] * (priceAtmCallMkt - priceAtmCallBS)
                                + q[1] * (price25CallMkt - price25CallBS)
                                + q[2] * (price25PutMkt - price25PutBS);
                double outPrice = priceBS + lambda * adjust;//
                double inPrice;

                //adapt Vanilla delta
                if (adaptVanDelta_ == true)
                {
                    outPrice += lambda * (bsPriceWithSmile_ - vanillaOption);
                    //capfloored by (0, vanilla)
                    outPrice = Math.Max(0.0, Math.Min(bsPriceWithSmile_, outPrice));
                    inPrice  = bsPriceWithSmile_ - outPrice;
                }
                else
                {
                    //capfloored by (0, vanilla)
                    outPrice = Math.Max(0.0, Math.Min(vanillaOption, outPrice));
                    inPrice  = vanillaOption - outPrice;
                }

                if (arguments_.barrierType == DoubleBarrier.Type.KnockOut)
                {
                    results_.value = outPrice;
                }
                else
                {
                    results_.value = inPrice;
                }

                results_.additionalResults["VanillaPrice"]    = vanillaOption;
                results_.additionalResults["BarrierInPrice"]  = inPrice;
                results_.additionalResults["BarrierOutPrice"] = outPrice;
                results_.additionalResults["lambda"]          = lambda;
            }
        }
Пример #26
0
 public ImpliedTermStructure(Handle <YieldTermStructure> h, Date referenceDate)
     : base(referenceDate)
 {
     originalCurve_ = h;
     originalCurve_.registerWith(update);
 }
Пример #27
0
 public LocalVolCurve(Handle <BlackVarianceCurve> curve)
     : base(curve.link.businessDayConvention(), curve.link.dayCounter())
 {
     blackVarianceCurve_ = curve;
     blackVarianceCurve_.registerWith(update);
 }
Пример #28
0
 public NumericHaganPricer(Handle <SwaptionVolatilityStructure> swaptionVol, GFunctionFactory.YieldCurveModel modelOfYieldCurve, Handle <Quote> meanReversion, double lowerLimit, double upperLimit, double precision)
     : base(swaptionVol, modelOfYieldCurve, meanReversion)
 {
     upperLimit_                   = upperLimit;
     lowerLimit_                   = lowerLimit;
     requiredStdDeviations_        = 8;
     precision_                    = precision;
     refiningIntegrationTolerance_ = 0.0001;
 }