public HybridHestonHullWhiteProcess(HestonProcess hestonProcess,
                                            HullWhiteForwardProcess hullWhiteProcess,
                                            double corrEquityShortRate,
                                            Discretization discretization = Discretization.BSMHullWhite)
        {
            hestonProcess_    = hestonProcess;
            hullWhiteProcess_ = hullWhiteProcess;
            hullWhiteModel_   = new HullWhite(hestonProcess.riskFreeRate(),
                                              hullWhiteProcess.a(),
                                              hullWhiteProcess.sigma());
            corrEquityShortRate_ = corrEquityShortRate;
            disc_   = discretization;
            maxRho_ = Math.Sqrt(1 - hestonProcess.rho() * hestonProcess.rho())
                      - Math.Sqrt(Const.QL_EPSILON) /* reserve for rounding errors */;

            T_           = hullWhiteProcess.getForwardMeasureTime();
            endDiscount_ = hestonProcess.riskFreeRate().link.discount(T_);

            Utils.QL_REQUIRE(corrEquityShortRate * corrEquityShortRate
                             + hestonProcess.rho() * hestonProcess.rho() <= 1.0, () =>
                             "correlation matrix is not positive definite");

            Utils.QL_REQUIRE(hullWhiteProcess.sigma() > 0.0, () =>
                             "positive vol of Hull White process is required");
        }
예제 #2
0
 public AnalyticH1HWEngine(HestonModel model, HullWhite hullWhiteModel, double rhoSr, int integrationOrder = 144)
     : base(model, hullWhiteModel, integrationOrder)
 {
     rhoSr_ = rhoSr;
     Utils.QL_REQUIRE(rhoSr_ >= 0.0, () => "Fourier integration is not stable if " +
                      "the equity interest rate correlation is negative");
 }
예제 #3
0
        public AnalyticHestonHullWhiteEngine(HestonModel hestonModel,
                                             HullWhite hullWhiteModel,
                                             double relTolerance, int maxEvaluations)
            : base(hestonModel, relTolerance, maxEvaluations)
        {
            hullWhiteModel_ = hullWhiteModel;

            update();
            hullWhiteModel_.registerWith(update);
        }
예제 #4
0
        // see AnalticHestonEninge for usage of different constructors
        public AnalyticHestonHullWhiteEngine(HestonModel hestonModel,
                                             HullWhite hullWhiteModel,
                                             int integrationOrder = 144)
            : base(hestonModel, integrationOrder)
        {
            hullWhiteModel_ = hullWhiteModel;

            update();
            hullWhiteModel_.registerWith(update);
        }
예제 #5
0
 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;
 }
예제 #6
0
 public Fj_Helper(Handle <HestonModel> hestonModel, HullWhite hullWhiteModel, double rhoSr, double term,
                  double strike, int j)
 {
     j_      = j;
     lambda_ = hullWhiteModel.a();
     eta_    = hullWhiteModel.sigma();
     v0_     = hestonModel.link.v0();
     kappa_  = hestonModel.link.kappa();
     theta_  = hestonModel.link.theta();
     gamma_  = hestonModel.link.sigma();
     d_      = 4.0 * kappa_ * theta_ / (gamma_ * gamma_);
     rhoSr_  = rhoSr;
     term_   = term;
 }
예제 #7
0
        protected override IPricingEngine controlPricingEngine()
        {
            HybridHestonHullWhiteProcess process = process_ as HybridHestonHullWhiteProcess;

            Utils.QL_REQUIRE(process != null, () => "invalid process");

            HestonProcess hestonProcess = process.hestonProcess();

            HullWhiteForwardProcess hullWhiteProcess = process.hullWhiteProcess();

            HestonModel hestonModel = new HestonModel(hestonProcess);

            HullWhite hwModel = new HullWhite(hestonProcess.riskFreeRate(),
                                              hullWhiteProcess.a(),
                                              hullWhiteProcess.sigma());

            return(new AnalyticHestonHullWhiteEngine(hestonModel, hwModel, 144));
        }
예제 #8
0
 public AnalyticH1HWEngine(HestonModel model, HullWhite hullWhiteModel, double rhoSr, double relTolerance,
                           int maxEvaluations)
     : base(model, hullWhiteModel, relTolerance, maxEvaluations)
 {
     rhoSr_ = rhoSr;
 }
예제 #9
0
        public void testCachedValues()
        {
            //("Testing Bermudan swaption against cached values...");

            CommonVars vars = new CommonVars();

            vars.today = new Date(15, Month.February, 2002);

            Settings.setEvaluationDate(vars.today);

            vars.settlement = new Date(19, Month.February, 2002);
            // flat yield term structure impling 1x5 swap at 5%
            vars.termStructure.linkTo(Utilities.flatRate(vars.settlement,
                                                  0.04875825,
                                                  new Actual365Fixed()));

            double atmRate = vars.makeSwap(0.0).fairRate();

            VanillaSwap itmSwap = vars.makeSwap(0.8*atmRate);
            VanillaSwap atmSwap = vars.makeSwap(atmRate);
            VanillaSwap otmSwap = vars.makeSwap(1.2*atmRate);

            double a = 0.048696, sigma = 0.0058904;
            ShortRateModel model=new HullWhite(vars.termStructure,a, sigma);
            List<Date> exerciseDates= new List<Date>();
            List<CashFlow> leg = atmSwap.fixedLeg();

            for (int i=0; i<leg.Count; i++) {
                Coupon coupon = (Coupon)(leg[i]);
                exerciseDates.Add(coupon.accrualStartDate());
            }

            Exercise exercise = new BermudanExercise(exerciseDates);
            IPricingEngine engine = new TreeSwaptionEngine(model, 50);

            #if QL_USE_INDEXED_COUPON
            Real itmValue = 42.2413, atmValue = 12.8789, otmValue = 2.4759;
            #else
            double itmValue = 42.2470, atmValue = 12.8826, otmValue = 2.4769;
            #endif

            double tolerance = 1.0e-4;

            Swaption swaption = new Swaption(itmSwap, exercise);
            swaption.setPricingEngine(engine);
            if (Math.Abs(swaption.NPV()-itmValue) > tolerance)
                Assert.Fail("failed to reproduce cached in-the-money swaption value:\n"
                            + "calculated: " + swaption.NPV() + "\n"
                            + "expected:   " + itmValue);

            swaption = new Swaption(atmSwap, exercise);
            swaption.setPricingEngine(engine);
            if (Math.Abs(swaption.NPV()-atmValue) > tolerance)
                Assert.Fail("failed to reproduce cached at-the-money swaption value:\n"
                            + "calculated: " + swaption.NPV() + "\n"
                            + "expected:   " + atmValue);

            swaption = new Swaption(otmSwap, exercise);
            swaption.setPricingEngine(engine);
            if (Math.Abs(swaption.NPV()-otmValue) > tolerance)
                Assert.Fail("failed to reproduce cached out-of-the-money "
                            + "swaption value:\n"
                            + "calculated: " + swaption.NPV() + "\n"
                            + "expected:   " + otmValue);

            for (int j=0; j<exerciseDates.Count; j++)
                exerciseDates[j] = vars.calendar.adjust(exerciseDates[j]-10);
            exercise = new BermudanExercise(exerciseDates);

            #if QL_USE_INDEXED_COUPON
            itmValue = 42.1917; atmValue = 12.7788; otmValue = 2.4388;
            #else
            itmValue = 42.1974; atmValue = 12.7825; otmValue = 2.4399;
            #endif

            swaption = new Swaption(itmSwap, exercise);
            swaption.setPricingEngine(engine);
            if (Math.Abs(swaption.NPV()-itmValue) > tolerance)
                Assert.Fail("failed to reproduce cached in-the-money swaption value:\n"
                            + "calculated: " + swaption.NPV() + "\n"
                            + "expected:   " + itmValue);

            swaption = new Swaption(atmSwap, exercise);
            swaption.setPricingEngine(engine);
            if (Math.Abs(swaption.NPV()-atmValue) > tolerance)
                Assert.Fail("failed to reproduce cached at-the-money swaption value:\n"
                            + "calculated: " + swaption.NPV() + "\n"
                            + "expected:   " + atmValue);

            swaption = new Swaption(otmSwap, exercise);
            swaption.setPricingEngine(engine);
            if (Math.Abs(swaption.NPV()-otmValue) > tolerance)
                Assert.Fail("failed to reproduce cached out-of-the-money "
                            + "swaption value:\n"
                            + "calculated: " + swaption.NPV() + "\n"
                            + "expected:   " + otmValue);
        }
        static void Main(string[] args)
        {

            DateTime timer = DateTime.Now;

            Date todaysDate = new Date(15, 2, 2002);
            Calendar calendar = new TARGET();
            Date settlementDate = new Date(19, 2, 2002);
            Settings.setEvaluationDate(todaysDate);

            // flat yield term structure impling 1x5 swap at 5%
            Quote flatRate = new SimpleQuote(0.04875825);
            Handle<YieldTermStructure> rhTermStructure = new Handle<YieldTermStructure>(
                          new FlatForward(settlementDate, new Handle<Quote>(flatRate),
                                          new Actual365Fixed()));

            // Define the ATM/OTM/ITM swaps
            Frequency fixedLegFrequency = Frequency.Annual;
            BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted;
            BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing;
            DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
            Frequency floatingLegFrequency = Frequency.Semiannual;
            VanillaSwap.Type type = VanillaSwap.Type.Payer;
            double dummyFixedRate = 0.03;
            IborIndex indexSixMonths = new Euribor6M(rhTermStructure);

            Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years,
                                              floatingLegConvention);
            Date maturity = calendar.advance(startDate, 5, TimeUnit.Years,
                                             floatingLegConvention);
            Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(fixedLegFrequency),
                                                    calendar, fixedLegConvention, fixedLegConvention,
                                                    DateGeneration.Rule.Forward, false);
            Schedule floatSchedule = new Schedule(startDate, maturity, new Period(floatingLegFrequency),
                                                    calendar, floatingLegConvention, floatingLegConvention,
                                                    DateGeneration.Rule.Forward, false);

            VanillaSwap swap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, dummyFixedRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            swap.setPricingEngine(new DiscountingSwapEngine(rhTermStructure));
            double fixedAtmRate = swap.fairRate();
            double fixedOtmRate = fixedAtmRate * 1.2;
            double fixedItmRate = fixedAtmRate * 0.8;

            VanillaSwap atmSwap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, fixedAtmRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            VanillaSwap otmSwap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, fixedOtmRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());
            VanillaSwap itmSwap = new VanillaSwap(
                type, 1000.0,
                fixedSchedule, fixedItmRate, fixedLegDayCounter,
                floatSchedule, indexSixMonths, 0.0,
                indexSixMonths.dayCounter());

            // defining the swaptions to be used in model calibration
            List<Period> swaptionMaturities = new List<Period>(5);
            swaptionMaturities.Add(new Period(1, TimeUnit.Years));
            swaptionMaturities.Add(new Period(2, TimeUnit.Years));
            swaptionMaturities.Add(new Period(3, TimeUnit.Years));
            swaptionMaturities.Add(new Period(4, TimeUnit.Years));
            swaptionMaturities.Add(new Period(5, TimeUnit.Years));

            List<CalibrationHelper> swaptions = new List<CalibrationHelper>();

            // List of times that have to be included in the timegrid
            List<double> times = new List<double>();

            for (int i = 0; i < NumRows; i++)
            {
                int j = NumCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1
                int k = i * NumCols + j;
                Quote vol = new SimpleQuote(SwaptionVols[k]);
                swaptions.Add(new SwaptionHelper(swaptionMaturities[i],
                                   new Period(SwapLenghts[j], TimeUnit.Years),
                                   new Handle<Quote>(vol),
                                   indexSixMonths,
                                   indexSixMonths.tenor(),
                                   indexSixMonths.dayCounter(),
                                   indexSixMonths.dayCounter(),
                                   rhTermStructure, false));
                swaptions.Last().addTimesTo(times);
            }

            // Building time-grid
            TimeGrid grid = new TimeGrid(times, 30);


            // defining the models
            G2 modelG2 = new G2(rhTermStructure);
            HullWhite modelHw = new HullWhite(rhTermStructure);
            HullWhite modelHw2 = new HullWhite(rhTermStructure);
            BlackKarasinski modelBk = new BlackKarasinski(rhTermStructure);


            // model calibrations

            Console.WriteLine("G2 (analytic formulae) calibration");
            for (int i = 0; i < swaptions.Count; i++)
                swaptions[i].setPricingEngine(new G2SwaptionEngine(modelG2, 6.0, 16));
            CalibrateModel(modelG2, swaptions);
            Console.WriteLine("calibrated to:\n" +
                                "a     = {0:0.000000}, " +
                                "sigma = {1:0.0000000}\n" +
                                "b     = {2:0.000000}, " +
                                "eta   = {3:0.0000000}\n" +
                                "rho   = {4:0.00000}\n",
                                modelG2.parameters()[0],
                                modelG2.parameters()[1],
                                modelG2.parameters()[2],
                                modelG2.parameters()[3],
                                modelG2.parameters()[4]);

            Console.WriteLine("Hull-White (analytic formulae) calibration");
            for (int i = 0; i < swaptions.Count; i++)
                swaptions[i].setPricingEngine(new JamshidianSwaptionEngine(modelHw));
            CalibrateModel(modelHw, swaptions);
            Console.WriteLine("calibrated to:\n" +
                              "a = {0:0.000000}, " +
                              "sigma = {1:0.0000000}\n",
                              modelHw.parameters()[0],
                              modelHw.parameters()[1]);

            Console.WriteLine("Hull-White (numerical) calibration");
            for (int i = 0; i < swaptions.Count(); i++)
                swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelHw2, grid));
            CalibrateModel(modelHw2, swaptions);
            Console.WriteLine("calibrated to:\n" +
                              "a = {0:0.000000}, " +
                              "sigma = {1:0.0000000}\n",
                              modelHw2.parameters()[0],
                              modelHw2.parameters()[1]);

            Console.WriteLine("Black-Karasinski (numerical) calibration");
            for (int i = 0; i < swaptions.Count; i++)
                swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelBk, grid));
            CalibrateModel(modelBk, swaptions);
            Console.WriteLine("calibrated to:\n" +
                              "a = {0:0.000000}, " +
                              "sigma = {1:0.00000}\n",
                              modelBk.parameters()[0],
                              modelBk.parameters()[1]);


            // ATM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption "
                              + "struck at {0:0.00000 %} (ATM)",
                              fixedAtmRate);

            List<Date> bermudanDates = new List<Date>();
            List<CashFlow> leg = swap.fixedLeg();
            for (int i = 0; i < leg.Count; i++)
            {
                Coupon coupon = (Coupon)leg[i];
                bermudanDates.Add(coupon.accrualStartDate());
            }

            Exercise bermudanExercise = new BermudanExercise(bermudanDates);

            Swaption bermudanSwaption = new Swaption(atmSwap, bermudanExercise);

            // Do the pricing for each model

            // G2 price the European swaption here, it should switch to bermudan
            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50));
            Console.WriteLine("G2:       {0:0.00}", bermudanSwaption.NPV());

            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50));
            Console.WriteLine("HW:       {0:0.000}", bermudanSwaption.NPV());

            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50));
            Console.WriteLine("HW (num): {0:0.000}", bermudanSwaption.NPV());

            bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50));
            Console.WriteLine("BK:       {0:0.000}", bermudanSwaption.NPV());


            // OTM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption "
                              + "struck at {0:0.00000 %} (OTM)",
                              fixedOtmRate);

            Swaption otmBermudanSwaption = new Swaption(otmSwap, bermudanExercise);

            // Do the pricing for each model
            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50));
            Console.WriteLine("G2:       {0:0.0000}", otmBermudanSwaption.NPV());

            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50));
            Console.WriteLine("HW:       {0:0.0000}", otmBermudanSwaption.NPV());

            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50));
            Console.WriteLine("HW (num): {0:0.000}", otmBermudanSwaption.NPV());

            otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50));
            Console.WriteLine("BK:       {0:0.0000}", otmBermudanSwaption.NPV());

            // ITM Bermudan swaption pricing
            Console.WriteLine("Payer bermudan swaption "
                              + "struck at {0:0.00000 %} (ITM)",
                              fixedItmRate);

            Swaption itmBermudanSwaption = new Swaption(itmSwap, bermudanExercise);

            // Do the pricing for each model
            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50));
            Console.WriteLine("G2:       {0:0.000}", itmBermudanSwaption.NPV());

            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50));
            Console.WriteLine("HW:       {0:0.000}", itmBermudanSwaption.NPV());

            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50));
            Console.WriteLine("HW (num): {0:0.000}", itmBermudanSwaption.NPV());

            itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50));
            Console.WriteLine("BK:       {0:0.000}", itmBermudanSwaption.NPV());


            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
예제 #11
0
        public void testCachedHullWhite()
        {
            //("Testing Hull-White calibration against cached values...");

             Date today=new Date(15, Month.February, 2002);
             Date settlement=new Date(19, Month.February, 2002);
             Settings.setEvaluationDate(today);
             Handle<YieldTermStructure> termStructure=
             new Handle<YieldTermStructure>(Utilities.flatRate(settlement, 0.04875825, new Actual365Fixed()));
             //termStructure.link
             HullWhite model=new HullWhite(termStructure);

             CalibrationData[] data = { new CalibrationData( 1, 5, 0.1148 ),
                                    new CalibrationData( 2, 4, 0.1108 ),
                                    new CalibrationData( 3, 3, 0.1070 ),
                                    new CalibrationData( 4, 2, 0.1021 ),
                                    new CalibrationData( 5, 1, 0.1000 )};
             IborIndex index = new Euribor6M(termStructure);

             IPricingEngine engine = new JamshidianSwaptionEngine(model);

             List<CalibrationHelper> swaptions = new List<CalibrationHelper>();
             for (int i=0; i<data.Length; i++) {
               Quote vol = new SimpleQuote(data[i].volatility);
               CalibrationHelper helper =
                                    new SwaptionHelper(new Period(data[i].start,TimeUnit.Years),
                                                      new Period(data[i].length, TimeUnit.Years),
                                                      new Handle<Quote>(vol),
                                                      index,
                                                      new Period(1, TimeUnit.Years),
                                                      new Thirty360(),
                                                      new Actual360(),
                                                      termStructure);
               helper.setPricingEngine(engine);
               swaptions.Add(helper);
             }

             // Set up the optimization problem
             // Real simplexLambda = 0.1;
             // Simplex optimizationMethod(simplexLambda);
             LevenbergMarquardt optimizationMethod = new LevenbergMarquardt(1.0e-8,1.0e-8,1.0e-8);
             EndCriteria endCriteria = new EndCriteria(10000, 100, 1e-6, 1e-8, 1e-8);

             //Optimize
             model.calibrate(swaptions, optimizationMethod, endCriteria, new Constraint(),new List<double>());
             EndCriteria.Type ecType = model.endCriteria();

             // Check and print out results
             #if QL_USE_INDEXED_COUPON
             double cachedA = 0.0488199, cachedSigma = 0.00593579;
             #else
             double cachedA = 0.0488565, cachedSigma = 0.00593662;
             #endif
             double tolerance = 1.120e-5;
             //double tolerance = 1.0e-6;
             Vector xMinCalculated = model.parameters();
             double yMinCalculated = model.value(xMinCalculated, swaptions);
             Vector xMinExpected = new Vector(2);
             xMinExpected[0]= cachedA;
             xMinExpected[1]= cachedSigma;
             double yMinExpected = model.value(xMinExpected, swaptions);
             if (Math.Abs(xMinCalculated[0]-cachedA) > tolerance
               || Math.Abs(xMinCalculated[1]-cachedSigma) > tolerance) {
               Assert.Fail ("Failed to reproduce cached calibration results:\n"
                           + "calculated: a = " + xMinCalculated[0] + ", "
                           + "sigma = " + xMinCalculated[1] + ", "
                           + "f(a) = " + yMinCalculated + ",\n"
                           + "expected:   a = " + xMinExpected[0] + ", "
                           + "sigma = " + xMinExpected[1] + ", "
                           + "f(a) = " + yMinExpected + ",\n"
                           + "difference: a = " + (xMinCalculated[0]-xMinExpected[0]) + ", "
                           + "sigma = " + (xMinCalculated[1]-xMinExpected[1]) + ", "
                           + "f(a) = " + (yMinCalculated - yMinExpected) + ",\n"
                           + "end criteria = " + ecType );
             }
        }
예제 #12
0
        public void testSwaps()
        {
            //BOOST_MESSAGE("Testing Hull-White swap pricing against known values...");

            Date today;  //=Settings::instance().evaluationDate();;

            Calendar calendar = new TARGET();
            today = calendar.adjust(Date.Today);
            Settings.setEvaluationDate(today);

            Date settlement = calendar.advance(today, 2, TimeUnit.Days);

            Date[] dates = {
                settlement,
                calendar.advance(settlement,1,TimeUnit.Weeks),
                calendar.advance(settlement,1,TimeUnit.Months),
                calendar.advance(settlement,3,TimeUnit.Months),
                calendar.advance(settlement,6,TimeUnit.Months),
                calendar.advance(settlement,9,TimeUnit.Months),
                calendar.advance(settlement,1,TimeUnit.Years),
                calendar.advance(settlement,2,TimeUnit.Years),
                calendar.advance(settlement,3,TimeUnit.Years),
                calendar.advance(settlement,5,TimeUnit.Years),
                calendar.advance(settlement,10,TimeUnit.Years),
                calendar.advance(settlement,15,TimeUnit.Years)
            };
            double[] discounts = {
                1.0,
                0.999258,
                0.996704,
                0.990809,
                0.981798,
                0.972570,
                0.963430,
                0.929532,
                0.889267,
                0.803693,
                0.596903,
                0.433022
            };

            //for (int i = 0; i < dates.Length; i++)
            //    dates[i] + dates.Length;

            LogLinear Interpolator = new LogLinear();

            Handle<YieldTermStructure> termStructure =
               new Handle<YieldTermStructure>(
                   new InterpolatedDiscountCurve<LogLinear>(
                       dates.ToList<Date>(),
                       discounts.ToList<double>(),
                       new Actual365Fixed(),new Calendar(), null, null , Interpolator)
            );

            HullWhite model = new HullWhite(termStructure);

            int[] start = { -3, 0, 3 };
            int[] length = { 2, 5, 10 };
            double[] rates = { 0.02, 0.04, 0.06 };
            IborIndex euribor = new Euribor6M(termStructure);

            IPricingEngine engine = new TreeVanillaSwapEngine(model, 120, termStructure);

            #if QL_USE_INDEXED_COUPON
            double tolerance = 4.0e-3;
            #else
            double tolerance = 1.0e-8;
            #endif

            for (int i=0; i<start.Length; i++) {

                Date startDate = calendar.advance(settlement,start[i],TimeUnit.Months);
                if (startDate < today) {
                    Date fixingDate = calendar.advance(startDate,-2,TimeUnit.Days);
                    //TimeSeries<double> pastFixings;
                    ObservableValue<TimeSeries<double>> pastFixings = new ObservableValue<TimeSeries<double>>();
                    pastFixings.value()[fixingDate] = 0.03;
                    IndexManager.instance().setHistory(euribor.name(),
                                                        pastFixings);
                }

                for (int j=0; j<length.Length; j++) {

                    Date maturity = calendar.advance(startDate, length[i], TimeUnit.Years);
                    Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(Frequency.Annual),
                                           calendar, BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                           DateGeneration.Rule.Forward, false);
                    Schedule floatSchedule = new Schedule(startDate, maturity, new Period(Frequency.Semiannual),
                                           calendar, BusinessDayConvention.Following, BusinessDayConvention.Following,
                                           DateGeneration.Rule.Forward, false);
                    for (int k=0; k<rates.Length; k++) {

                        VanillaSwap swap = new VanillaSwap(VanillaSwap.Type.Payer, 1000000.0,
                                         fixedSchedule, rates[k], new Thirty360(),
                                         floatSchedule, euribor, 0.0, new Actual360());
                        swap.setPricingEngine(new DiscountingSwapEngine(termStructure));
                        double expected = swap.NPV();
                        swap.setPricingEngine(engine);
                        double calculated = swap.NPV();

                        double error = Math.Abs((expected-calculated)/expected);
                        if (error > tolerance) {
                            Assert.Fail("Failed to reproduce swap NPV:"
                                        //+ QL_FIXED << std::setprecision(9)
                                        + "\n    calculated: " + calculated
                                        + "\n    expected:   " + expected
                                        //+ QL_SCIENTIFIC
                                        + "\n    rel. error: " + error);
                        }
                    }
                }
            }
        }
예제 #13
0
        static void Main(string[] args)
        {
            // boost::timer timer;

             Date today = new Date(16,Month.October,2007);
             Settings.setEvaluationDate(today);

             Console.WriteLine();
             Console.WriteLine("Pricing a callable fixed rate bond using");
             Console.WriteLine("Hull White model w/ reversion parameter = 0.03");
             Console.WriteLine("BAC4.65 09/15/12  ISIN: US06060WBJ36");
             Console.WriteLine("roughly five year tenor, ");
             Console.WriteLine("quarterly coupon and call dates");
             Console.WriteLine("reference date is : " + today );

             /* Bloomberg OAS1: "N" model (Hull White)
               varying volatility parameter

               The curve entered into Bloomberg OAS1 is a flat curve,
               at constant yield = 5.5%, semiannual compounding.
               Assume here OAS1 curve uses an ACT/ACT day counter,
               as documented in PFC1 as a "default" in the latter case.
             */

             // set up a flat curve corresponding to Bloomberg flat curve

             double bbCurveRate = 0.055;
             DayCounter bbDayCounter = new ActualActual(ActualActual.Convention.Bond);
             InterestRate bbIR = new InterestRate(bbCurveRate,bbDayCounter,Compounding.Compounded ,Frequency.Semiannual);

             Handle<YieldTermStructure> termStructure = new Handle<YieldTermStructure>(flatRate( today,
                                                              bbIR.rate(),
                                                              bbIR.dayCounter(),
                                                              bbIR.compounding(),
                                                              bbIR.frequency()));
             // set up the call schedule

             CallabilitySchedule callSchedule = new CallabilitySchedule();
             double callPrice = 100.0;
             int numberOfCallDates = 24;
             Date callDate = new Date(15,Month.September,2006);

             for (int i=0; i< numberOfCallDates; i++)
             {
            Calendar nullCalendar = new NullCalendar();

            Callability.Price myPrice = new Callability.Price(callPrice, Callability.Price.Type.Clean);
            callSchedule.Add( new Callability(myPrice,Callability.Type.Call, callDate ));
            callDate = nullCalendar.advance(callDate, 3, TimeUnit.Months);
             }

             // set up the callable bond

             Date dated = new Date(16,Month.September,2004);
             Date issue = dated;
             Date maturity = new Date(15,Month.September,2012);
             int settlementDays = 3;  // Bloomberg OAS1 settle is Oct 19, 2007
             Calendar bondCalendar = new UnitedStates(UnitedStates.Market.GovernmentBond);
             double coupon = .0465;
             Frequency frequency = Frequency.Quarterly;
             double redemption = 100.0;
             double faceAmount = 100.0;

             /* The 30/360 day counter Bloomberg uses for this bond cannot
            reproduce the US Bond/ISMA (constant) cashflows used in PFC1.
            Therefore use ActAct(Bond)
             */
             DayCounter bondDayCounter = new ActualActual(ActualActual.Convention.Bond);

             // PFC1 shows no indication dates are being adjusted
             // for weekends/holidays for vanilla bonds
             BusinessDayConvention accrualConvention = BusinessDayConvention.Unadjusted;
             BusinessDayConvention paymentConvention = BusinessDayConvention.Unadjusted;

             Schedule sch = new Schedule( dated, maturity, new Period(frequency), bondCalendar,
                                      accrualConvention, accrualConvention,
                                      DateGeneration.Rule.Backward, false);

             int maxIterations = 1000;
             double accuracy = 1e-8;
             int gridIntervals = 40;
             double reversionParameter = .03;

             // output price/yield results for varying volatility parameter

             double sigma = Const.QL_Epsilon; // core dumps if zero on Cygwin

             ShortRateModel hw0 = new HullWhite(termStructure,reversionParameter,sigma);

             IPricingEngine engine0 = new TreeCallableFixedRateBondEngine(hw0, gridIntervals, termStructure);

             CallableFixedRateBond callableBond = new CallableFixedRateBond( settlementDays, faceAmount, sch,
                                                                         new InitializedList<double>(1, coupon),
                                                                         bondDayCounter, paymentConvention,
                                                                         redemption, issue, callSchedule);
             callableBond.setPricingEngine(engine0);

             Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma));

             Console.WriteLine("QuantLib price/yld (%)  ");
             Console.WriteLine(  "{0:0.00} / {1:0.00} ", callableBond.cleanPrice() ,
                                                     100.0 * callableBond.yield(bondDayCounter,
                                                                                Compounding.Compounded,
                                                                                frequency,
                                                                                accuracy,
                                                                                maxIterations));
             Console.WriteLine("Bloomberg price/yld (%) ");
             Console.WriteLine("96.50 / 5.47");

             //

             sigma = .01;

             Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma));

             ShortRateModel hw1 = new HullWhite(termStructure,reversionParameter,sigma);

             IPricingEngine engine1 = new TreeCallableFixedRateBondEngine(hw1,gridIntervals,termStructure);

             callableBond.setPricingEngine(engine1);

             Console.WriteLine("QuantLib price/yld (%)  ");
             Console.WriteLine(  "{0:0.00} / {1:0.00} ", callableBond.cleanPrice() ,
                                                     100.0 * callableBond.yield(bondDayCounter,
                                                                                Compounding.Compounded,
                                                                                frequency,
                                                                                accuracy,
                                                                                maxIterations));

             Console.WriteLine("Bloomberg price/yld (%) ");
             Console.WriteLine("95.68 / 5.66");

             //

             sigma = .03;

             Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma));

             ShortRateModel hw2 = new HullWhite(termStructure, reversionParameter, sigma);

             IPricingEngine engine2 = new TreeCallableFixedRateBondEngine(hw2, gridIntervals, termStructure);

             callableBond.setPricingEngine(engine2);

             Console.WriteLine("QuantLib price/yld (%)  ");
             Console.WriteLine("{0:0.00} / {1:0.00} ", callableBond.cleanPrice(),
                                                     100.0 * callableBond.yield(bondDayCounter,
                                                                                Compounding.Compounded,
                                                                                frequency,
                                                                                accuracy,
                                                                                maxIterations));

             Console.WriteLine("Bloomberg price/yld (%) ");
             Console.WriteLine("92.34 / 6.49");

             //

             sigma = .06;

             Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma));

             ShortRateModel hw3 = new HullWhite(termStructure, reversionParameter, sigma);

             IPricingEngine engine3 = new TreeCallableFixedRateBondEngine(hw3, gridIntervals, termStructure);

             callableBond.setPricingEngine(engine3);

             Console.WriteLine("QuantLib price/yld (%)  ");
             Console.WriteLine("{0:0.00} / {1:0.00} ", callableBond.cleanPrice(),
                                                     100.0 * callableBond.yield(bondDayCounter,
                                                                                Compounding.Compounded,
                                                                                frequency,
                                                                                accuracy,
                                                                                maxIterations));

             Console.WriteLine("Bloomberg price/yld (%) ");
             Console.WriteLine("87.16 / 7.83");

             //

             sigma = .12;

             Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma));

             ShortRateModel hw4 = new HullWhite(termStructure, reversionParameter, sigma);

             IPricingEngine engine4 = new TreeCallableFixedRateBondEngine(hw4, gridIntervals, termStructure);

             callableBond.setPricingEngine(engine4);

             Console.WriteLine("QuantLib price/yld (%)  ");
             Console.WriteLine("{0:0.00} / {1:0.00} ", callableBond.cleanPrice(),
                                                     100.0 * callableBond.yield(bondDayCounter,
                                                                                Compounding.Compounded,
                                                                                frequency,
                                                                                accuracy,
                                                                                maxIterations));

             Console.WriteLine("Bloomberg price/yld (%) ");
             Console.WriteLine("77.31 / 10.65");
        }