示例#1
0
 public MCPREuropeanHestonEngine(HestonProcess process, int timeSteps, int timeStepsPerYear) : this(NQuantLibcPINVOKE.new_MCPREuropeanHestonEngine__SWIG_5(HestonProcess.getCPtr(process), timeSteps, timeStepsPerYear), true)
 {
     if (NQuantLibcPINVOKE.SWIGPendingException.Pending)
     {
         throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
     }
 }
示例#2
0
 public MCPREuropeanHestonEngine(HestonProcess process) : this(NQuantLibcPINVOKE.new_MCPREuropeanHestonEngine__SWIG_7(HestonProcess.getCPtr(process)), true)
 {
     if (NQuantLibcPINVOKE.SWIGPendingException.Pending)
     {
         throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
     }
 }
示例#3
0
        public void testFdmHestonBlackScholes()
        {
            //Testing FDM Heston with Black Scholes model...
            using (SavedSettings backup = new SavedSettings())
            {
                Settings.Instance.setEvaluationDate(new Date(28, 3, 2004));
                Date exerciseDate = new Date(26, 6, 2004);

                Handle <YieldTermStructure>    rTS   = new Handle <YieldTermStructure>(Utilities.flatRate(0.10, new Actual360()));
                Handle <YieldTermStructure>    qTS   = new Handle <YieldTermStructure>(Utilities.flatRate(0.0, new Actual360()));
                Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(rTS.currentLink().referenceDate(), 0.25, rTS.currentLink().dayCounter()));

                Exercise          exercise = new EuropeanExercise(exerciseDate);
                StrikedTypePayoff payoff   = new PlainVanillaPayoff(Option.Type.Put, 10);
                VanillaOption     option   = new VanillaOption(payoff, exercise);

                double[] strikes = new double[] { 8, 9, 10, 11, 12 };
                double   tol     = 0.0001;

                for (int i = 0; i < strikes.Length; ++i)
                {
                    Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(strikes[i]));
                    GeneralizedBlackScholesProcess bsProcess = new GeneralizedBlackScholesProcess(s0, qTS, rTS, volTS);
                    option.setPricingEngine(new AnalyticEuropeanEngine(bsProcess));

                    double expected = option.NPV();

                    HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, 0.0625, 1, 0.0625, 0.0001, 0.0);

                    // Hundsdorfer scheme
                    option.setPricingEngine(new FdHestonVanillaEngine(new HestonModel(hestonProcess),
                                                                      100, 400, 3));

                    double calculated = option.NPV();
                    if (Math.Abs(calculated - expected) > tol)
                    {
                        QAssert.Fail("Failed to reproduce expected npv"
                                     + "\n    strike:     " + strikes[i]
                                     + "\n    calculated: " + calculated
                                     + "\n    expected:   " + expected
                                     + "\n    tolerance:  " + tol);
                    }

                    // Explicit scheme
                    option.setPricingEngine(new FdHestonVanillaEngine(new HestonModel(hestonProcess),
                                                                      4000, 400, 3, 0,
                                                                      new FdmSchemeDesc().ExplicitEuler()));

                    calculated = option.NPV();
                    if (Math.Abs(calculated - expected) > tol)
                    {
                        QAssert.Fail("Failed to reproduce expected npv"
                                     + "\n    strike:     " + strikes[i]
                                     + "\n    calculated: " + calculated
                                     + "\n    expected:   " + expected
                                     + "\n    tolerance:  " + tol);
                    }
                }
            }
        }
示例#4
0
 public MCPREuropeanHestonEngine(HestonProcess process, int timeSteps, int timeStepsPerYear, bool antitheticVariate, int requiredSamples) : this(NQuantLibcPINVOKE.new_MCPREuropeanHestonEngine__SWIG_3(HestonProcess.getCPtr(process), timeSteps, timeStepsPerYear, antitheticVariate, requiredSamples), true)
 {
     if (NQuantLibcPINVOKE.SWIGPendingException.Pending)
     {
         throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
     }
 }
示例#5
0
 public HestonModel(HestonProcess process) : this(NQuantLibcPINVOKE.new_HestonModel(HestonProcess.getCPtr(process)), true)
 {
     if (NQuantLibcPINVOKE.SWIGPendingException.Pending)
     {
         throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
     }
 }
        public HestonProcess hestonProcess()
        {
            global::System.IntPtr cPtr = NQuantLibcPINVOKE.HestonSLVFDMModel_hestonProcess(swigCPtr);
            HestonProcess         ret  = (cPtr == global::System.IntPtr.Zero) ? null : new HestonProcess(cPtr, true);

            if (NQuantLibcPINVOKE.SWIGPendingException.Pending)
            {
                throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
            }
            return(ret);
        }
示例#7
0
 public MakeMCEuropeanHestonEngine(HestonProcess process)
 {
     process_      = process;
     antithetic_   = false;
     steps_        = null;
     stepsPerYear_ = null;
     samples_      = null;
     maxSamples_   = null;
     tolerance_    = null;
     seed_         = 0;
 }
示例#8
0
 public MCEuropeanHestonEngine(HestonProcess process,
                               int?timeSteps,
                               int?timeStepsPerYear,
                               bool antitheticVariate,
                               int?requiredSamples,
                               double?requiredTolerance,
                               int?maxSamples,
                               ulong seed)
     : base(process, timeSteps, timeStepsPerYear, false, antitheticVariate, false, requiredSamples, requiredTolerance,
            maxSamples, seed)
 {
 }
示例#9
0
        public void testFdmHestonEuropeanWithDividends()
        {
            //Testing FDM with European option with dividends in Heston model...
            using (SavedSettings backup = new SavedSettings())
            {
                Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100.0));

                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.05, new Actual365Fixed()));
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.0, new Actual365Fixed()));

                HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, 0.04, 2.5, 0.04, 0.66, -0.8);

                Settings.Instance.setEvaluationDate(new Date(28, 3, 2004));
                Date              exerciseDate = new Date(28, 3, 2005);
                Exercise          exercise     = new AmericanExercise(exerciseDate);
                StrikedTypePayoff payoff       = new PlainVanillaPayoff(Option.Type.Put, 100);

                List <double> dividends     = new InitializedList <double>(1, 5);
                List <Date>   dividendDates = new InitializedList <Date>(1, new Date(28, 9, 2004));

                DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends);
                IPricingEngine        engine = new FdHestonVanillaEngine(new HestonModel(hestonProcess), 50, 100, 50);
                option.setPricingEngine(engine);

                double tol           = 0.01;
                double gammaTol      = 0.001;
                double npvExpected   = 7.365075;
                double deltaExpected = -0.396678;
                double gammaExpected = 0.027681;

                if (Math.Abs(option.NPV() - npvExpected) > tol)
                {
                    QAssert.Fail("Failed to reproduce expected npv"
                                 + "\n    calculated: " + option.NPV()
                                 + "\n    expected:   " + npvExpected
                                 + "\n    tolerance:  " + tol);
                }
                if (Math.Abs(option.delta() - deltaExpected) > tol)
                {
                    QAssert.Fail("Failed to reproduce expected delta"
                                 + "\n    calculated: " + option.delta()
                                 + "\n    expected:   " + deltaExpected
                                 + "\n    tolerance:  " + tol);
                }
                if (Math.Abs(option.gamma() - gammaExpected) > gammaTol)
                {
                    QAssert.Fail("Failed to reproduce expected gamma"
                                 + "\n    calculated: " + option.gamma()
                                 + "\n    expected:   " + gammaExpected
                                 + "\n    tolerance:  " + tol);
                }
            }
        }
示例#10
0
        protected override PathPricer <IPath> pathPricer()
        {
            PlainVanillaPayoff payoff = this.arguments_.payoff as PlainVanillaPayoff;

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

            HestonProcess process = this.process_ as HestonProcess;

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

            return(new EuropeanHestonPathPricer(payoff.optionType(),
                                                payoff.strike(),
                                                process.riskFreeRate().link.discount(this.timeGrid().Last())));
        }
示例#11
0
        public void testFdmHestonBarrier()
        {
            //Testing FDM with barrier option for Heston model vs Black-Scholes model...
            using (SavedSettings backup = new SavedSettings())
            {
                Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100.0));

                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.05, new Actual365Fixed()));
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.0, new Actual365Fixed()));

                HestonProcess hestonProcess =
                    new HestonProcess(rTS, qTS, s0, 0.04, 2.5, 0.04, 0.66, -0.8);

                Settings.Instance.setEvaluationDate(new Date(28, 3, 2004));
                Date exerciseDate = new Date(28, 3, 2005);

                Exercise          exercise = new EuropeanExercise(exerciseDate);
                StrikedTypePayoff payoff   = new PlainVanillaPayoff(Option.Type.Call, 100);

                BarrierOption barrierOption = new BarrierOption(Barrier.Type.UpOut, 135, 0.0, payoff, exercise);
                barrierOption.setPricingEngine(new FdHestonBarrierEngine(new HestonModel(hestonProcess), 50, 400, 100));

                double tol           = 0.01;
                double npvExpected   = 9.1530;
                double deltaExpected = 0.5218;
                double gammaExpected = -0.0354;

                if (Math.Abs(barrierOption.NPV() - npvExpected) > tol)
                {
                    QAssert.Fail("Failed to reproduce expected npv"
                                 + "\n    calculated: " + barrierOption.NPV()
                                 + "\n    expected:   " + npvExpected
                                 + "\n    tolerance:  " + tol);
                }
                if (Math.Abs(barrierOption.delta() - deltaExpected) > tol)
                {
                    QAssert.Fail("Failed to reproduce expected delta"
                                 + "\n    calculated: " + barrierOption.delta()
                                 + "\n    expected:   " + deltaExpected
                                 + "\n    tolerance:  " + tol);
                }
                if (Math.Abs(barrierOption.gamma() - gammaExpected) > tol)
                {
                    QAssert.Fail("Failed to reproduce expected gamma"
                                 + "\n    calculated: " + barrierOption.gamma()
                                 + "\n    expected:   " + gammaExpected
                                 + "\n    tolerance:  " + tol);
                }
            }
        }
示例#12
0
        public void testFdmHestonIkonenToivanen()
        {
            //Testing FDM Heston for Ikonen and Toivanen tests...

            /* check prices of american puts as given in:
             * From Efficient numerical methods for pricing American options under
             * stochastic volatility, Samuli Ikonen, Jari Toivanen,
             * http://users.jyu.fi/~tene/papers/reportB12-05.pdf
             */
            using (SavedSettings backup = new SavedSettings())
            {
                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.10, new Actual360()));
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.0, new Actual360()));

                Settings.Instance.setEvaluationDate(new Date(28, 3, 2004));
                Date              exerciseDate = new Date(26, 6, 2004);
                Exercise          exercise     = new AmericanExercise(exerciseDate);
                StrikedTypePayoff payoff       = new PlainVanillaPayoff(Option.Type.Put, 10);
                VanillaOption     option       = new VanillaOption(payoff, exercise);

                double[] strikes  = new double[] { 8, 9, 10, 11, 12 };
                double[] expected = new double[] { 2.00000, 1.10763, 0.520038, 0.213681, 0.082046 };
                double   tol      = 0.001;

                for (int i = 0; i < strikes.Length; ++i)
                {
                    Handle <Quote> s0            = new Handle <Quote>(new SimpleQuote(strikes[i]));
                    HestonProcess  hestonProcess = new HestonProcess(rTS, qTS, s0, 0.0625, 5, 0.16, 0.9, 0.1);
                    IPricingEngine engine        = new FdHestonVanillaEngine(new HestonModel(hestonProcess), 100, 400);
                    option.setPricingEngine(engine);

                    double calculated = option.NPV();
                    if (Math.Abs(calculated - expected[i]) > tol)
                    {
                        QAssert.Fail("Failed to reproduce expected npv"
                                     + "\n    strike:     " + strikes[i]
                                     + "\n    calculated: " + calculated
                                     + "\n    expected:   " + expected[i]
                                     + "\n    tolerance:  " + tol);
                    }
                }
            }
        }
        public void testH1HWPricingEngine()
        {
            /*
             * Example taken from Lech Aleksander Grzelak,
             * Equity and Foreign Exchange Hybrid Models for Pricing Long-Maturity
             * Financial Derivatives,
             * http://repository.tudelft.nl/assets/uuid:a8e1a007-bd89-481a-aee3-0e22f15ade6b/PhDThesis_main.pdf
             */
            Date today = new Date(15, Month.July, 2012);

            Settings.Instance.setEvaluationDate(today);
            Date       exerciseDate = new Date(13, Month.July, 2022);
            DayCounter dc           = new Actual365Fixed();

            Exercise exercise = new EuropeanExercise(exerciseDate);

            Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100.0));

            double r       = 0.02;
            double q       = 0.00;
            double v0      = 0.05;
            double theta   = 0.05;
            double kappa_v = 0.3;

            double[] sigma_v = { 0.3, 0.6 };
            double   rho_sv  = -0.30;
            double   rho_sr  = 0.6;
            double   kappa_r = 0.01;
            double   sigma_r = 0.01;

            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, r, dc));
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, q, dc));

            Handle <BlackVolTermStructure> flatVolTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(today, 0.20, dc));
            GeneralizedBlackScholesProcess bsProcess = new GeneralizedBlackScholesProcess(s0, qTS, rTS, flatVolTS);

            HullWhiteProcess hwProcess      = new HullWhiteProcess(rTS, kappa_r, sigma_r);
            HullWhite        hullWhiteModel = new HullWhite(new Handle <YieldTermStructure>(rTS), kappa_r, sigma_r);

            double tol = 0.0001;

            double[]   strikes  = { 40, 80, 100, 120, 180 };
            double[][] expected =
            {
                new double[]  { 0.267503, 0.235742, 0.228223, 0.223461, 0.217855 },
                new double[]  { 0.263626, 0.211625, 0.199907, 0.193502, 0.190025 }
            };

            for (int j = 0; j < sigma_v.Length; ++j)
            {
                HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, v0, kappa_v, theta, sigma_v[j], rho_sv);
                HestonModel   hestonModel   = new HestonModel(hestonProcess);

                for (int i = 0; i < strikes.Length; ++i)
                {
                    StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Call, strikes[i]);

                    VanillaOption option = new VanillaOption(payoff, exercise);

                    IPricingEngine analyticH1HWEngine = new AnalyticH1HWEngine(hestonModel, hullWhiteModel, rho_sr, 144);
                    option.setPricingEngine(analyticH1HWEngine);
                    double impliedH1HW = option.impliedVolatility(option.NPV(), bsProcess);

                    if (Math.Abs(expected[j][i] - impliedH1HW) > tol)
                    {
                        QAssert.Fail("Failed to reproduce H1HW implied volatility"
                                     + "\n   expected       : " + expected[j][i]
                                     + "\n   calculated     : " + impliedH1HW
                                     + "\n   tol            : " + tol
                                     + "\n   strike         : " + strikes[i]
                                     + "\n   sigma          : " + sigma_v[j]);
                    }
                }
            }
        }
        public void testDiscretizationError()
        {
            // Testing the discretization error of the Heston Hull-White process
            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            // construct a strange yield curve to check drifts and discounting
            // of the joint stochastic process

            List <Date>   dates = new List <Date>();
            List <double> times = new List <double>();
            List <double> rates = new List <double>(), divRates = new List <double>();

            for (int i = 0; i <= 31; ++i)
            {
                dates.Add(today + new Period(i, TimeUnit.Years));
                // FLOATING_POINT_EXCEPTION
                rates.Add(0.04 + 0.0001 * Math.Exp(Math.Sin(i)));
                divRates.Add(0.04 + 0.0001 * Math.Exp(Math.Sin(i)));
                times.Add(dc.yearFraction(today, dates.Last()));
            }

            Date   maturity = today + new Period(10, TimeUnit.Years);
            double v        = 0.25;

            Handle <Quote> s0  = new Handle <Quote>(new SimpleQuote(100));
            SimpleQuote    vol = new SimpleQuote(v);
            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(today, vol, dc));
            Handle <YieldTermStructure>    rTS   = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, rates, dc));
            Handle <YieldTermStructure>    qTS   = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, divRates, dc));

            BlackScholesMertonProcess bsmProcess = new BlackScholesMertonProcess(s0, qTS, rTS, volTS);

            HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, v * v, 1, v * v, 1e-6, -0.4);

            HullWhiteForwardProcess hwProcess = new HullWhiteForwardProcess(rTS, 0.01, 0.01);

            hwProcess.setForwardMeasureTime(20.1472222222222222);

            double tol = 0.05;

            double[] corr   = { -0.85, 0.5 };
            double[] strike = { 50, 100, 125 };

            for (int i = 0; i < corr.Length; ++i)
            {
                for (int j = 0; j < strike.Length; ++j)
                {
                    StrikedTypePayoff payoff   = new PlainVanillaPayoff(Option.Type.Put, strike[j]);
                    Exercise          exercise = new EuropeanExercise(maturity);

                    VanillaOption optionBsmHW = new VanillaOption(payoff, exercise);
                    HullWhite     hwModel     = new HullWhite(rTS, hwProcess.a(), hwProcess.sigma());
                    optionBsmHW.setPricingEngine(new AnalyticBSMHullWhiteEngine(corr[i], bsmProcess, hwModel));

                    double expected = optionBsmHW.NPV();

                    VanillaOption optionHestonHW = new VanillaOption(payoff, exercise);
                    HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess,
                                                                                                 hwProcess, corr[i]);
                    optionHestonHW.setPricingEngine(
                        new MakeMCHestonHullWhiteEngine <PseudoRandom, Statistics>(jointProcess)
                        .withSteps(1)
                        .withAntitheticVariate()
                        .withAbsoluteTolerance(tol)
                        .withSeed(42).getAsPricingEngine());

                    double calculated = optionHestonHW.NPV();
                    double error      = optionHestonHW.errorEstimate();

                    if ((Math.Abs(calculated - expected) > 3 * error &&
                         Math.Abs(calculated - expected) > 1e-5))
                    {
                        QAssert.Fail("Failed to reproduce discretization error"
                                     + "\n   corr:       " + corr[i]
                                     + "\n   strike:     " + strike[j]
                                     + "\n   calculated: " + calculated
                                     + "\n   error:      " + error
                                     + "\n   expected:   " + expected);
                    }
                }
            }
        }
        public void testCallableEquityPricing()
        {
            // Testing the pricing of a callable equity product

            /*
             * For the definition of the example product see
             * Alexander Giese, On the Pricing of Auto-Callable Equity
             * Structures in the Presence of Stochastic Volatility and
             * Stochastic Interest Rates .
             * http://workshop.mathfinance.de/2006/papers/giese/slides.pdf
             */

            int        maturity = 7;
            DayCounter dc       = new Actual365Fixed();
            Date       today    = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            Handle <Quote> spot             = new Handle <Quote>(new SimpleQuote(100.0));
            SimpleQuote    qRate            = new SimpleQuote(0.04);
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, qRate, dc));
            SimpleQuote rRate = new SimpleQuote(0.04);
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, rRate, dc));

            HestonProcess hestonProcess = new HestonProcess(rTS, qTS, spot, 0.0625, 1.0, 0.24 * 0.24, 1e-4, 0.0);
            // FLOATING_POINT_EXCEPTION
            HullWhiteForwardProcess hwProcess = new HullWhiteForwardProcess(rTS, 0.00883, 0.00526);

            hwProcess.setForwardMeasureTime(dc.yearFraction(today, today + new Period(maturity + 1, TimeUnit.Years)));

            HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess, hwProcess, -0.4);

            Schedule schedule = new Schedule(today, today + new Period(maturity, TimeUnit.Years), new Period(1, TimeUnit.Years),
                                             new TARGET(), BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false);

            List <double> times = new InitializedList <double>(maturity + 1);

            for (int i = 0; i <= maturity; ++i)
            {
                times[i] = i;
            }

            TimeGrid grid = new TimeGrid(times, times.Count);

            List <double> redemption = new InitializedList <double>(maturity);

            for (int i = 0; i < maturity; ++i)
            {
                redemption[i] = 1.07 + 0.03 * i;
            }

            ulong seed = 42;
            IRNG  rsg  = (InverseCumulativeRsg <RandomSequenceGenerator <MersenneTwisterUniformRng>
                                                , InverseCumulativeNormal>)
                         new PseudoRandom().make_sequence_generator(jointProcess.factors() * (grid.size() - 1), seed);

            MultiPathGenerator <IRNG> generator = new MultiPathGenerator <IRNG>(jointProcess, grid, rsg, false);
            GeneralStatistics         stat      = new GeneralStatistics();

            double antitheticPayoff = 0;
            int    nrTrails         = 40000;

            for (int i = 0; i < nrTrails; ++i)
            {
                bool antithetic = (i % 2) != 0;

                Sample <IPath> path  = antithetic ? generator.antithetic() : generator.next();
                MultiPath      value = path.value as MultiPath;
                Utils.QL_REQUIRE(value != null, () => "Invalid Path");

                double payoff = 0;
                for (int j = 1; j <= maturity; ++j)
                {
                    if (value[0][j] > spot.link.value())
                    {
                        Vector states = new Vector(3);
                        for (int k = 0; k < 3; ++k)
                        {
                            states[k] = value[k][j];
                        }
                        payoff = redemption[j - 1] / jointProcess.numeraire(grid[j], states);
                        break;
                    }
                    else if (j == maturity)
                    {
                        Vector states = new Vector(3);
                        for (int k = 0; k < 3; ++k)
                        {
                            states[k] = value[k][j];
                        }
                        payoff = 1.0 / jointProcess.numeraire(grid[j], states);
                    }
                }

                if (antithetic)
                {
                    stat.add(0.5 * (antitheticPayoff + payoff));
                }
                else
                {
                    antitheticPayoff = payoff;
                }
            }

            double expected   = 0.938;
            double calculated = stat.mean();
            double error      = stat.errorEstimate();

            if (Math.Abs(expected - calculated) > 3 * error)
            {
                QAssert.Fail("Failed to reproduce auto-callable equity structure price"
                             + "\n   calculated: " + calculated
                             + "\n   error:      " + error
                             + "\n   expected:   " + expected);
            }
        }
        public void testAnalyticHestonHullWhitePricing()
        {
            // Testing analytic Heston Hull-White option pricing
            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            // construct a strange yield curve to check drifts and discounting
            // of the joint stochastic process

            List <Date>   dates = new List <Date>();
            List <double> times = new List <double>();
            List <double> rates = new List <double>(), divRates = new List <double>();

            for (int i = 0; i <= 40; ++i)
            {
                dates.Add(today + new Period(i, TimeUnit.Years));
                // FLOATING_POINT_EXCEPTION
                rates.Add(0.03 + 0.0001 * Math.Exp(Math.Sin(i / 4.0)));
                divRates.Add(0.02 + 0.0002 * Math.Exp(Math.Sin(i / 3.0)));
                times.Add(dc.yearFraction(today, dates.Last()));
            }

            Date           maturity         = today + new Period(5, TimeUnit.Years);
            Handle <Quote> s0               = new Handle <Quote>(new SimpleQuote(100));
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, rates, dc));
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, divRates, dc));

            HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, 0.08, 1.5, 0.0625, 0.5, -0.8);
            HestonModel   hestonModel   = new HestonModel(hestonProcess);

            HullWhiteForwardProcess hwFwdProcess = new HullWhiteForwardProcess(rTS, 0.01, 0.01);

            hwFwdProcess.setForwardMeasureTime(dc.yearFraction(today, maturity));
            HullWhite hullWhiteModel = new HullWhite(rTS, hwFwdProcess.a(), hwFwdProcess.sigma());

            double tol = 0.002;

            double[]      strike = { 80, 120 };
            Option.Type[] types  = { Option.Type.Put, Option.Type.Call };

            for (int i = 0; i < types.Length; ++i)
            {
                for (int j = 0; j < strike.Length; ++j)
                {
                    HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess,
                                                                                                 hwFwdProcess, 0.0, HybridHestonHullWhiteProcess.Discretization.Euler);

                    StrikedTypePayoff payoff   = new PlainVanillaPayoff(types[i], strike[j]);
                    Exercise          exercise = new EuropeanExercise(maturity);

                    VanillaOption optionHestonHW = new VanillaOption(payoff, exercise);
                    optionHestonHW.setPricingEngine(new MakeMCHestonHullWhiteEngine <PseudoRandom, Statistics>(jointProcess)
                                                    .withSteps(1)
                                                    .withAntitheticVariate()
                                                    .withControlVariate()
                                                    .withAbsoluteTolerance(tol)
                                                    .withSeed(42).getAsPricingEngine());

                    VanillaOption optionPureHeston = new VanillaOption(payoff, exercise);
                    optionPureHeston.setPricingEngine(new AnalyticHestonHullWhiteEngine(hestonModel, hullWhiteModel, 128));

                    double calculated = optionHestonHW.NPV();
                    double error      = optionHestonHW.errorEstimate();
                    double expected   = optionPureHeston.NPV();

                    if (Math.Abs(calculated - expected) > 3 * error &&
                        Math.Abs(calculated - expected) > tol)
                    {
                        QAssert.Fail("Failed to reproduce hw heston vanilla prices"
                                     + "\n   strike:     " + strike[j]
                                     + "\n   calculated: " + calculated
                                     + "\n   error:      " + error
                                     + "\n   expected:   " + expected);
                    }
                }
            }
        }
        public void testZeroBondPricing()
        {
            // Testing Monte-Carlo zero bond pricing

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            // construct a strange yield curve to check drifts and discounting
            // of the joint stochastic process

            List <Date>   dates = new List <Date>();
            List <double> times = new List <double>();
            List <double> rates = new List <double>();

            dates.Add(today);
            rates.Add(0.02);
            times.Add(0.0);
            for (int i = 120; i < 240; ++i)
            {
                dates.Add(today + new Period(i, TimeUnit.Months));
                rates.Add(0.02 + 0.0002 * Math.Exp(Math.Sin(i / 8.0)));
                times.Add(dc.yearFraction(today, dates.Last()));
            }

            Date maturity = dates.Last() + new Period(10, TimeUnit.Years);

            dates.Add(maturity);
            rates.Add(0.04);
            //times.Add(dc.yearFraction(today, dates.Last()));

            Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100));

            Handle <YieldTermStructure> ts = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, rates, dc));
            Handle <YieldTermStructure> ds = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc));

            HestonProcess           hestonProcess = new HestonProcess(ts, ds, s0, 0.02, 1.0, 0.2, 0.5, -0.8);
            HullWhiteForwardProcess hwProcess     = new HullWhiteForwardProcess(ts, 0.05, 0.05);

            hwProcess.setForwardMeasureTime(dc.yearFraction(today, maturity));
            HullWhite hwModel = new HullWhite(ts, 0.05, 0.05);

            HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess, hwProcess, -0.4);

            TimeGrid grid = new TimeGrid(times);

            int factors = jointProcess.factors();
            int steps   = grid.size() - 1;
            SobolBrownianBridgeRsg rsg = new SobolBrownianBridgeRsg(factors, steps);
            MultiPathGenerator <SobolBrownianBridgeRsg> generator = new MultiPathGenerator <SobolBrownianBridgeRsg>(
                jointProcess, grid, rsg, false);

            int m = 90;
            List <GeneralStatistics> zeroStat   = new InitializedList <GeneralStatistics>(m);
            List <GeneralStatistics> optionStat = new InitializedList <GeneralStatistics>(m);

            int    nrTrails    = 8191;
            int    optionTenor = 24;
            double strike      = 0.5;

            for (int i = 0; i < nrTrails; ++i)
            {
                Sample <IPath> path  = generator.next();
                MultiPath      value = path.value as MultiPath;
                Utils.QL_REQUIRE(value != null, () => "Invalid Path");

                for (int j = 1; j < m; ++j)
                {
                    double t = grid[j];               // zero end and option maturity
                    double T = grid[j + optionTenor]; // maturity of zero bond
                    // of option

                    Vector states       = new Vector(3);
                    Vector optionStates = new Vector(3);
                    for (int k = 0; k < jointProcess.size(); ++k)
                    {
                        states[k]       = value[k][j];
                        optionStates[k] = value[k][j + optionTenor];
                    }

                    double zeroBond
                        = 1.0 / jointProcess.numeraire(t, states);
                    double zeroOption = zeroBond * Math.Max(0.0, hwModel.discountBond(t, T, states[2]) - strike);

                    zeroStat[j].add(zeroBond);
                    optionStat[j].add(zeroOption);
                }
            }

            for (int j = 1; j < m; ++j)
            {
                double t          = grid[j];
                double calculated = zeroStat[j].mean();
                double expected   = ts.link.discount(t);

                if (Math.Abs(calculated - expected) > 0.03)
                {
                    QAssert.Fail("Failed to reproduce expected zero bond prices"
                                 + "\n   t:          " + t
                                 + "\n   calculated: " + calculated
                                 + "\n   expected:   " + expected);
                }

                double T = grid[j + optionTenor];

                calculated = optionStat[j].mean();
                expected   = hwModel.discountBondOption(Option.Type.Call, strike, t, T);

                if (Math.Abs(calculated - expected) > 0.0035)
                {
                    QAssert.Fail("Failed to reproduce expected zero bond option prices"
                                 + "\n   t:          " + t
                                 + "\n   T:          " + T
                                 + "\n   calculated: " + calculated
                                 + "\n   expected:   " + expected);
                }
            }
        }
        public void testCompareBsmHWandHestonHW()
        {
            // Comparing European option pricing for a BSM process with one-factor Hull-White model
            DayCounter dc    = new Actual365Fixed();
            Date       today = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            Handle <Quote> spot = new Handle <Quote>(new SimpleQuote(100.0));
            List <Date>    dates = new List <Date>();
            List <double>  rates = new List <double>(), divRates = new List <double>();

            for (int i = 0; i <= 40; ++i)
            {
                dates.Add(today + new Period(i, TimeUnit.Years));
                // FLOATING_POINT_EXCEPTION
                rates.Add(0.01 + 0.0002 * Math.Exp(Math.Sin(i / 4.0)));
                divRates.Add(0.02 + 0.0001 * Math.Exp(Math.Sin(i / 5.0)));
            }

            Handle <Quote> s0               = new Handle <Quote>(new SimpleQuote(100));
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(
                new InterpolatedZeroCurve <Linear>(dates, rates, dc));
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(
                new InterpolatedZeroCurve <Linear>(dates, divRates, dc));

            SimpleQuote vol = new SimpleQuote(0.25);
            Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(today, vol, dc));

            BlackScholesMertonProcess bsmProcess = new BlackScholesMertonProcess(spot, qTS, rTS, volTS);

            HestonProcess hestonProcess = new HestonProcess(rTS, qTS, spot,
                                                            vol.value() * vol.value(), 1.0, vol.value() * vol.value(), 1e-4, 0.0);

            HestonModel hestonModel = new HestonModel(hestonProcess);

            HullWhite hullWhiteModel = new HullWhite(new Handle <YieldTermStructure>(rTS), 0.01, 0.01);

            IPricingEngine bsmhwEngine = new AnalyticBSMHullWhiteEngine(0.0, bsmProcess, hullWhiteModel);

            IPricingEngine hestonHwEngine = new AnalyticHestonHullWhiteEngine(hestonModel, hullWhiteModel, 128);

            double tol = 1e-5;

            double[]      strike   = { 0.25, 0.5, 0.75, 0.8, 0.9, 1.0, 1.1, 1.2, 1.5, 2.0, 4.0 };
            int[]         maturity = { 1, 2, 3, 5, 10, 15, 20, 25, 30 };
            Option.Type[] types    = { Option.Type.Put, Option.Type.Call };

            for (int i = 0; i < types.Length; ++i)
            {
                for (int j = 0; j < strike.Length; ++j)
                {
                    for (int l = 0; l < maturity.Length; ++l)
                    {
                        Date maturityDate = today + new Period(maturity[l], TimeUnit.Years);

                        Exercise exercise = new EuropeanExercise(maturityDate);

                        double fwd = strike[j] * spot.link.value()
                                     * qTS.link.discount(maturityDate) / rTS.link.discount(maturityDate);

                        StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], fwd);

                        EuropeanOption option = new EuropeanOption(payoff, exercise);

                        option.setPricingEngine(bsmhwEngine);
                        double calculated = option.NPV();

                        option.setPricingEngine(hestonHwEngine);
                        double expected = option.NPV();

                        if (Math.Abs(calculated - expected) > calculated * tol &&
                            Math.Abs(calculated - expected) > tol)
                        {
                            QAssert.Fail("Failed to reproduce npvs"
                                         + "\n    calculated: " + calculated
                                         + "\n    expected  : " + expected
                                         + "\n    strike    : " + strike[j]
                                         + "\n    maturity  : " + maturity[l]
                                         + "\n    type      : "
                                         + ((types[i] == QLCore.Option.Type.Put) ? "Put" : "Call"));
                        }
                    }
                }
            }
        }
示例#19
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(HestonProcess obj)
 {
     return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr);
 }
示例#20
0
 internal static global::System.Runtime.InteropServices.HandleRef getCPtr(HestonProcess obj) {
   return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
 }
示例#21
0
        public void testFdmHestonConvergence()
        {
            /* convergence tests based on
             * ADI finite difference schemes for option pricing in the
             * Heston model with correlation, K.J. in t'Hout and S. Foulon
             */

            //Testing FDM Heston convergence...

            using (SavedSettings backup = new SavedSettings())
            {
                HestonTestData[] values = new HestonTestData[] {
                    new HestonTestData(1.5, 0.04, 0.3, -0.9, 0.025, 0.0, 1.0, 100),
                    new HestonTestData(3.0, 0.12, 0.04, 0.6, 0.01, 0.04, 1.0, 100),
                    new HestonTestData(0.6067, 0.0707, 0.2928, -0.7571, 0.03, 0.0, 3.0, 100),
                    new HestonTestData(2.5, 0.06, 0.5, -0.1, 0.0507, 0.0469, 0.25, 100)
                };

                FdmSchemeDesc[] schemes = new FdmSchemeDesc[] {
                    new FdmSchemeDesc().Hundsdorfer(),
                    new FdmSchemeDesc().ModifiedCraigSneyd(),
                    new FdmSchemeDesc().ModifiedHundsdorfer(),
                    new FdmSchemeDesc().CraigSneyd(),
                    new FdmSchemeDesc().TrBDF2(),
                    new FdmSchemeDesc().CrankNicolson(),
                };

                int[]    tn = new int[] { 60 };
                double[] v0 = new double[] { 0.04 };

                Date todaysDate = new Date(28, 3, 2004);
                Settings.Instance.setEvaluationDate(todaysDate);

                Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(75.0));

                for (int l = 0; l < schemes.Length; ++l)
                {
                    for (int i = 0; i < values.Length; ++i)
                    {
                        for (int j = 0; j < tn.Length; ++j)
                        {
                            for (int k = 0; k < v0.Length; ++k)
                            {
                                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(
                                    Utilities.flatRate(values[i].r, new Actual365Fixed()));
                                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(
                                    Utilities.flatRate(values[i].q, new Actual365Fixed()));

                                HestonProcess hestonProcess =
                                    new HestonProcess(rTS, qTS, s0,
                                                      v0[k],
                                                      values[i].kappa,
                                                      values[i].theta,
                                                      values[i].sigma,
                                                      values[i].rho);

                                Date exerciseDate = todaysDate
                                                    + new Period(Convert.ToInt32(values[i].T * 365), TimeUnit.Days);

                                Exercise          exercise = new EuropeanExercise(exerciseDate);
                                StrikedTypePayoff payoff   = new PlainVanillaPayoff(Option.Type.Call, values[i].K);

                                VanillaOption  option = new VanillaOption(payoff, exercise);
                                IPricingEngine engine =
                                    new FdHestonVanillaEngine(
                                        new HestonModel(hestonProcess),
                                        tn[j], 101, 51, 0,
                                        schemes[l]);

                                option.setPricingEngine(engine);

                                double calculated = option.NPV();

                                IPricingEngine analyticEngine =
                                    new AnalyticHestonEngine(
                                        new HestonModel(hestonProcess), 144);

                                option.setPricingEngine(analyticEngine);
                                double expected = option.NPV();
                                if (Math.Abs(expected - calculated) / expected > 0.02 &&
                                    Math.Abs(expected - calculated) > 0.002)
                                {
                                    QAssert.Fail("Failed to reproduce expected npv"
                                                 + "\n    calculated: " + calculated
                                                 + "\n    expected:   " + expected
                                                 + "\n    tolerance:  " + 0.01);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#22
0
        public void testSpuriousOscillations()
        {
            //Testing for spurious oscillations when solving the Heston PDEs...
            using (SavedSettings backup = new SavedSettings())
            {
                DayCounter dc    = new Actual365Fixed();
                Date       today = new Date(7, 6, 2018);

                Settings.Instance.setEvaluationDate(today);

                Handle <Quote> spot             = new Handle <Quote>(new SimpleQuote(100.0));
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.1, dc));
                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc));

                double v0    = 0.005;
                double kappa = 1.0;
                double theta = 0.005;
                double sigma = 0.4;
                double rho   = -0.75;

                Date maturity = today + new Period(1, TimeUnit.Years);

                HestonProcess process =
                    new HestonProcess(
                        rTS, qTS, spot, v0, kappa, theta, sigma, rho);

                HestonModel model =
                    new HestonModel(process);

                FdHestonVanillaEngine hestonEngine =
                    new FdHestonVanillaEngine(
                        model, 6, 200, 13, 0, new FdmSchemeDesc().TrBDF2());

                VanillaOption option = new VanillaOption(new PlainVanillaPayoff(Option.Type.Call, spot.currentLink().value()),
                                                         new EuropeanExercise(maturity));

                option.setupArguments(hestonEngine.getArguments());

                List <Tuple <FdmSchemeDesc, string, bool> > descs = new List <Tuple <FdmSchemeDesc, string, bool> >();
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().CraigSneyd(), "Craig-Sneyd", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().Hundsdorfer(), "Hundsdorfer", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().ModifiedHundsdorfer(), "Mod. Hundsdorfer", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().Douglas(), "Douglas", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().CrankNicolson(), "Crank-Nicolson", true));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().ImplicitEuler(), "Implicit", false));
                descs.Add(new Tuple <FdmSchemeDesc, string, bool>(new FdmSchemeDesc().TrBDF2(), "TR-BDF2", false));

                for (int j = 0; j < descs.Count; ++j)
                {
                    FdmHestonSolver solver =
                        new FdmHestonSolver(new Handle <HestonProcess>(process),
                                            hestonEngine.getSolverDesc(1.0),
                                            descs[j].Item1);

                    List <double> gammas = new List <double>();
                    for (double x = 99; x < 101.001; x += 0.1)
                    {
                        gammas.Add(solver.gammaAt(x, v0));
                    }

                    double maximum = Double.MinValue;
                    for (int i = 1; i < gammas.Count; ++i)
                    {
                        double diff = Math.Abs(gammas[i] - gammas[i - 1]);
                        if (diff > maximum)
                        {
                            maximum = diff;
                        }
                    }

                    double tol = 0.01;
                    bool   hasSpuriousOscillations = maximum > tol;

                    if (hasSpuriousOscillations != descs[j].Item3)
                    {
                        QAssert.Fail("unable to reproduce spurious oscillation behaviour "
                                     + "\n   scheme name          : " + descs[j].Item2
                                     + "\n   oscillations observed: "
                                     + hasSpuriousOscillations
                                     + "\n   oscillations expected: " + descs[j].Item3
                                     );
                    }
                }
            }
        }
示例#23
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            ////////////////  DATES  //////////////////////////////////////////////

            Calendar calendar       = new TARGET();
            Date     todaysDate     = new Date(15, Month.January, 2017);
            Date     settlementDate = new Date(todaysDate);

            Settings.setEvaluationDate(todaysDate);
            DayCounter dayCounter = new Actual365Fixed();


            ////////////////  MARKET  //////////////////////////////////////////////

            // Spot
            double         underlying  = 4468.17;
            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // riskfree
            double riskFreeRate = 0.035;
            Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));

            // dividend
            double dividendYield = 0.0;
            double fixedDiv      = 5.0;

            Handle <YieldTermStructure> flatDividendTS        = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            Handle <YieldTermStructure> FixedDivTermStructure = new Handle <YieldTermStructure>(new FixedForward(settlementDate, fixedDiv, underlying, dayCounter));

            // vol surface

            Date StartDateVol = settlementDate + new Period(1, TimeUnit.Months);


            List <int> maturityInDays = new InitializedList <int>()
            {
                0, 13, 41, 90, 165, 256, 345, 524, 703
            };
            List <Date> datesVol = new InitializedList <Date>();

            for (int d = 1; d < maturityInDays.Count; d++)
            {
                datesVol.Add(calendar.advance(settlementDate, new Period(maturityInDays[d], TimeUnit.Days)));
            }

            List <double> strikes = new InitializedList <double>()
            {
                3400, 3600, 3800, 4000, 4200, 4400, 4500, 4600, 4800, 5000, 5200, 5400, 5600
            };

            Matrix blackVolMatrix = new Matrix(maturityInDays.Count - 1, strikes.Count, 0.2);
            var    vols           = new InitializedList <double>()
            {
                0.6625, 0.4875, 0.4204, 0.3667, 0.3431, 0.3267, 0.3121, 0.3121,
                0.6007, 0.4543, 0.3967, 0.3511, 0.3279, 0.3154, 0.2984, 0.2921,
                0.5084, 0.4221, 0.3718, 0.3327, 0.3155, 0.3027, 0.2919, 0.2889,
                0.4541, 0.3869, 0.3492, 0.3149, 0.2963, 0.2926, 0.2819, 0.2800,
                0.4060, 0.3607, 0.3330, 0.2999, 0.2887, 0.2811, 0.2751, 0.2775,
                0.3726, 0.3396, 0.3108, 0.2781, 0.2788, 0.2722, 0.2661, 0.2686,
                0.3550, 0.3277, 0.3012, 0.2781, 0.2781, 0.2661, 0.2661, 0.2681,
                0.3428, 0.3209, 0.2958, 0.2740, 0.2688, 0.2627, 0.2580, 0.2620,
                0.3302, 0.3062, 0.2799, 0.2631, 0.2573, 0.2533, 0.2504, 0.2544,
                0.3343, 0.2959, 0.2705, 0.2540, 0.2504, 0.2464, 0.2448, 0.2462,
                0.3460, 0.2845, 0.2624, 0.2463, 0.2425, 0.2385, 0.2373, 0.2422,
                0.3857, 0.2860, 0.2578, 0.2399, 0.2357, 0.2327, 0.2312, 0.2351,
                0.3976, 0.2860, 0.2607, 0.2356, 0.2297, 0.2268, 0.2241, 0.2320
            };


            for (int i = 0; i < vols.Count; i++)
            {
                int testraw = (int)(i % (datesVol.Count));
                int testcol = (int)(i / (datesVol.Count));

                blackVolMatrix[testraw, testcol] = vols[i];
            }



            BlackVarianceSurface mySurface = new BlackVarianceSurface(settlementDate, calendar, datesVol,
                                                                      strikes, Matrix.transpose(blackVolMatrix), dayCounter);

            Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(mySurface);


            ////////////////  CALIBRATION  //////////////////////////////////////////////

            Period helperPeriod = new Period();

            //helpers
            List <CalibrationHelper> calibrationHelpers = new List <CalibrationHelper>();

            for (int k = 0; k < strikes.Count; k++)
            {
                for (int d = 0; d < datesVol.Count; d++)
                {
                    helperPeriod = new Period(datesVol[d] - settlementDate, TimeUnit.Days);
                    calibrationHelpers.Add(new HestonModelHelper(helperPeriod,
                                                                 calendar,
                                                                 underlying,
                                                                 strikes[k],
                                                                 new Handle <Quote>(new SimpleQuote(blackVolMatrix[d, k])),
                                                                 flatTermStructure,
                                                                 flatDividendTS,
                                                                 CalibrationHelper.CalibrationErrorType.ImpliedVolError));
                }
            }


            // starting data
            double v0    = 0.1;
            double kappa = 1.0;
            double theta = 0.1;
            double sigma = 0.5;
            double rho   = -0.5;

            // model
            HestonProcess hestonProcess = new HestonProcess(flatTermStructure,
                                                            flatDividendTS,
                                                            underlyingH,
                                                            v0, kappa, theta, sigma, rho);

            HestonModel hestonmodel = new HestonModel(hestonProcess);

            AnalyticHestonEngine analyticHestonEngine = new AnalyticHestonEngine(hestonmodel);


            foreach (HestonModelHelper hmh in calibrationHelpers)
            {
                hmh.setPricingEngine(analyticHestonEngine);
            }


            // optimization
            double             tolerance          = 1.0e-8;
            LevenbergMarquardt optimizationmethod = new LevenbergMarquardt(tolerance, tolerance, tolerance);

            hestonmodel.calibrate(calibrationHelpers, optimizationmethod, new EndCriteria(400, 40, tolerance, tolerance, tolerance));

            double        error     = 0.0;
            List <double> errorList = new InitializedList <double>();


            ////////////////  CALIBRATION RESULTS  //////////////////////////////////////////////
            Console.WriteLine("Calbration :");
            Console.WriteLine("-----------");

            foreach (HestonModelHelper hmh in calibrationHelpers)
            {
                error += Math.Abs(hmh.calibrationError());
                errorList.Add(Math.Abs(hmh.calibrationError()));
            }

            Vector hestonParameters = hestonmodel.parameters();

            Console.WriteLine("v0    = {0:0.00%}", hestonParameters[4]);
            Console.WriteLine("kappa = {0:0.00%}", hestonParameters[1]);
            Console.WriteLine("theta = {0:0.00%}", hestonParameters[0]);
            Console.WriteLine("sigma = {0:0.00%}", hestonParameters[2]);
            Console.WriteLine("rho   = {0:0.00%}", hestonParameters[3]);
            Console.WriteLine();
            Console.WriteLine("Total error = {0:0.0000}", error);
            Console.WriteLine("Mean error  = {0:0.0000%}", error / (errorList.Count - 1));
            Console.WriteLine();

            int    StepsPerYear      = 52;
            double absoluteTolerance = 80.0;
            ulong  mcSeed            = 42;

            // MC Heston process
            HestonProcess calibratedHestonProcess = new HestonProcess(flatTermStructure,
                                                                      flatDividendTS,
                                                                      underlyingH,
                                                                      hestonParameters[4],
                                                                      hestonParameters[1],
                                                                      hestonParameters[0],
                                                                      hestonParameters[2],
                                                                      hestonParameters[3]);

            // BS process
            GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, FixedDivTermStructure, flatTermStructure, mySurfaceH);

            ////////////////  ENGINES  /////////////////////////////////////////////////


            IPricingEngine mcHestonEngine = new MakeMCEuropeanHestonEngine <PseudoRandom, Statistics>(calibratedHestonProcess)
                                            .withStepsPerYear(StepsPerYear)
                                            .withAbsoluteTolerance(absoluteTolerance)
                                            .withSeed(mcSeed)
                                            .getAsPricingEngine();

            double         absoluteTolerance2      = 1.0;
            IPricingEngine mcGenHestonEngineTestbs = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess)
                                                     .withStepsPerYear(StepsPerYear)
                                                     .withAbsoluteTolerance(absoluteTolerance2)
                                                     .withSeed(mcSeed)
                                                     .value();

            IPricingEngine mcGenHestonEngineTestbs2 = new MakeMCGenericScriptInstrument <PseudoRandom>(calibratedHestonProcess)
                                                      .withStepsPerYear(StepsPerYear)
                                                      .withAbsoluteTolerance(absoluteTolerance2)
                                                      .withSeed(mcSeed)
                                                      .value();


            ////////////////  PRICING  //////////////////////////////////////////////
            Console.WriteLine("Pricing Vanilla:");
            Console.WriteLine("---------------");


            Date     maturity         = new Date(17, Month.May, 2019);
            Exercise europeanExercise = new EuropeanExercise(maturity);

            Option.Type       type           = Option.Type.Call;
            double            strike         = underlying;
            StrikedTypePayoff payoff         = new PlainVanillaPayoff(type, strike);
            VanillaOption     europeanOption = new VanillaOption(payoff, europeanExercise);

            // heston
            europeanOption.setPricingEngine(analyticHestonEngine);
            Console.Write("Heston pricing = {0:0.0000}", europeanOption.NPV());
            Console.WriteLine("  ->   {0:0.0000%}", europeanOption.NPV() / underlying);

            // Mc heston
            europeanOption.setPricingEngine(mcHestonEngine);
            Console.Write("HestMC pricing = {0:0.0000}", europeanOption.NPV());
            Console.Write("  ->   {0:0.0000%}", europeanOption.NPV() / underlying);
            Console.WriteLine("  tolerance   {0:0.0} / {1:0.00%}", absoluteTolerance, absoluteTolerance / underlying);

            // analytic bs
            europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess));
            Console.Write("BS pricing     = {0:0.0000}", europeanOption.NPV());
            Console.WriteLine("  ->   {0:0.0000%}", europeanOption.NPV() / underlying);


            Console.WriteLine();
            ////////////////  AUTOCALL HESTON //////////////////////////////////////////////

            List <Date> fixingdates = new InitializedList <Date>();
            double      coupon      = 0.05;
            double      barrierlvl  = 0.6;

            for (int i = 1; i <= 4; i++)
            {
                fixingdates.Add(settlementDate + new Period(i, TimeUnit.Years));
            }

            ScriptGenericAutocall myGenericAutocallHTTEst = new ScriptGenericAutocall(fixingdates, coupon, barrierlvl, underlying);

            myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs);

            Console.WriteLine("Pricing Autocall BS :");
            Console.WriteLine("---------------------");
            Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples());
            Console.Write("\n");

            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1);
            }
            Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid"));
            Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.Write("\n");


            myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs2);

            Console.WriteLine("Pricing Autocall Heston:");
            Console.WriteLine("------------------------");
            Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV());
            Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples());
            Console.Write("\n");

            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1);
            }
            Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid"));
            Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown"));
            Console.Write("\n");


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

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
示例#24
0
        public void testFdmHestonVarianceMesher()
        {
            //Testing FDM Heston variance mesher...
            using (SavedSettings backup = new SavedSettings())
            {
                Date       today = new Date(22, 2, 2018);
                DayCounter dc    = new Actual365Fixed();
                Settings.Instance.setEvaluationDate(today);

                HestonProcess process = new HestonProcess(new Handle <YieldTermStructure>(Utilities.flatRate(0.02, dc)),
                                                          new Handle <YieldTermStructure>(Utilities.flatRate(0.02, dc)),
                                                          new Handle <Quote>(new SimpleQuote(100.0)),
                                                          0.09, 1.0, 0.09, 0.2, -0.5);

                FdmHestonVarianceMesher mesher    = new FdmHestonVarianceMesher(5, process, 1.0);
                List <double>           locations = mesher.locations();

                double[] expected = new double[] { 0.0, 6.652314e-02, 9.000000e-02, 1.095781e-01, 2.563610e-01 };

                double tol = 1e-6;
                double diff;
                for (int i = 0; i < locations.Count; ++i)
                {
                    diff = Math.Abs(expected[i] - locations[i]);

                    if (diff > tol)
                    {
                        QAssert.Fail("Failed to reproduce Heston variance mesh"
                                     + "\n    calculated: " + locations[i]
                                     + "\n    expected:   " + expected[i]
                                     + "\n    difference  " + diff
                                     + "\n    tolerance:  " + tol);
                    }
                }

                LocalVolTermStructure lVol = new LocalConstantVol(today, 2.5, dc);
                FdmHestonLocalVolatilityVarianceMesher constSlvMesher = new FdmHestonLocalVolatilityVarianceMesher(5, process, lVol, 1.0);

                double expectedVol   = 2.5 * mesher.volaEstimate();
                double calculatedVol = constSlvMesher.volaEstimate();

                diff = Math.Abs(calculatedVol - expectedVol);
                if (diff > tol)
                {
                    QAssert.Fail("Failed to reproduce Heston local volatility variance estimate"
                                 + "\n    calculated: " + calculatedVol
                                 + "\n    expected:   " + expectedVol
                                 + "\n    difference  " + diff
                                 + "\n    tolerance:  " + tol);
                }

                double alpha = 0.01;
                LocalVolTermStructure leverageFct = new ParableLocalVolatility(today, 100.0, alpha, dc);

                FdmHestonLocalVolatilityVarianceMesher slvMesher
                    = new FdmHestonLocalVolatilityVarianceMesher(5, process, leverageFct, 0.5, 1, 0.01);

                double initialVolEstimate = new FdmHestonVarianceMesher(5, process, 0.5, 1, 0.01).volaEstimate();

                // double vEst = leverageFct.currentLink().localVol(0, 100) * initialVolEstimate;
                // Mathematica solution
                //    N[Integrate[
                //      alpha*((100*Exp[vEst*x*Sqrt[0.5]] - 100)^2 + 25)*
                //       PDF[NormalDistribution[0, 1], x], {x ,
                //       InverseCDF[NormalDistribution[0, 1], 0.01],
                //       InverseCDF[NormalDistribution[0, 1], 0.99]}]]

                double leverageAvg = 0.455881 / (1 - 0.02);

                double volaEstExpected =
                    0.5 * (leverageAvg + leverageFct.localVol(0, 100)) * initialVolEstimate;

                double volaEstCalculated = slvMesher.volaEstimate();

                if (Math.Abs(volaEstExpected - volaEstCalculated) > 0.001)
                {
                    QAssert.Fail("Failed to reproduce Heston local volatility variance estimate"
                                 + "\n    calculated: " + calculatedVol
                                 + "\n    expected:   " + expectedVol
                                 + "\n    difference  " + Math.Abs(volaEstExpected - volaEstCalculated)
                                 + "\n    tolerance:  " + tol);
                }
            }
        }
示例#25
0
        public void testFdmHestonBarrierVsBlackScholes()
        {
            //Testing FDM with barrier option in Heston model...
            using (SavedSettings backup = new SavedSettings())
            {
                NewBarrierOptionData[] values = new NewBarrierOptionData[] {
                    /* The data below are from
                     * "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag. 72
                     */
                    //                          barrierType,        barrier, rebate,         type,  strike,     s,    q,    r,    t,    v
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.00, 0.08, 1.00, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.00, 0.08, 0.25, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.00, 0.08, 0.25, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.00, 0.08, 0.40, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.15),

                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.00, 0.08, 0.40, 0.35),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.15),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.00, 0.00, 1.00, 0.20),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.00, 0.08, 1.00, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30),

                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.00, 0.04, 1.00, 0.15),

                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownOut, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpOut, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),

                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.DownIn, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 1.00, 0.15),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30),
                    new NewBarrierOptionData(Barrier.Type.UpIn, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30)
                };

                DayCounter dc           = new Actual365Fixed();
                Date       todaysDate   = new Date(28, 3, 2004);
                Date       exerciseDate = new Date(28, 3, 2005);
                Settings.Instance.setEvaluationDate(todaysDate);

                Handle <Quote> spot             = new Handle <Quote>(new SimpleQuote(0.0));
                SimpleQuote    qRate            = new SimpleQuote(0.0);
                Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc));
                SimpleQuote rRate = new SimpleQuote(0.0);
                Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc));
                SimpleQuote vol = new SimpleQuote(0.0);
                Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc));

                BlackScholesMertonProcess bsProcess = new BlackScholesMertonProcess(spot, qTS, rTS, volTS);

                IPricingEngine analyticEngine = new AnalyticBarrierEngine(bsProcess);

                for (int i = 0; i < values.Length; i++)
                {
                    Date     exDate   = todaysDate + Convert.ToInt32(values[i].t * 365 + 0.5);
                    Exercise exercise = new EuropeanExercise(exDate);

                    (spot.currentLink() as SimpleQuote).setValue(values[i].s);
                    qRate.setValue(values[i].q);
                    rRate.setValue(values[i].r);
                    vol.setValue(values[i].v);

                    StrikedTypePayoff payoff = new PlainVanillaPayoff(values[i].type, values[i].strike);

                    BarrierOption barrierOption = new BarrierOption(values[i].barrierType, values[i].barrier,
                                                                    values[i].rebate, payoff, exercise);

                    double        v0            = vol.value() * vol.value();
                    HestonProcess hestonProcess =
                        new HestonProcess(rTS, qTS, spot, v0, 1.0, v0, 0.005, 0.0);

                    barrierOption.setPricingEngine(new FdHestonBarrierEngine(new HestonModel(hestonProcess), 200, 101, 3));

                    double calculatedHE = barrierOption.NPV();

                    barrierOption.setPricingEngine(analyticEngine);
                    double expected = barrierOption.NPV();

                    double tol = 0.0025;
                    if (Math.Abs(calculatedHE - expected) / expected > tol)
                    {
                        QAssert.Fail("Failed to reproduce expected Heston npv"
                                     + "\n    calculated: " + calculatedHE
                                     + "\n    expected:   " + expected
                                     + "\n    tolerance:  " + tol);
                    }
                }
            }
        }
 public HestonSLVProcess(HestonProcess hestonProcess, LocalVolTermStructure leverageFct) : this(NQuantLibcPINVOKE.new_HestonSLVProcess(HestonProcess.getCPtr(hestonProcess), LocalVolTermStructure.getCPtr(leverageFct)), true)
 {
     if (NQuantLibcPINVOKE.SWIGPendingException.Pending)
     {
         throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
     }
 }
示例#27
0
 public HestonModel(HestonProcess process) : this(NQuantLibcPINVOKE.new_HestonModel(HestonProcess.getCPtr(process)), true) {
   if (NQuantLibcPINVOKE.SWIGPendingException.Pending) throw NQuantLibcPINVOKE.SWIGPendingException.Retrieve();
 }