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
            private Complex Phi(HestonProcess process, Complex a, double nu_0, double nu_t, double dt)
            {
                double theta = process.theta();
                double kappa = process.kappa();
                double sigma = process.sigma();

                double  sigma2 = sigma * sigma;
                Complex ga     = Complex.Sqrt(kappa * kappa - 2 * sigma2 * a * new Complex(0.0, 1.0));
                double  d      = 4 * theta * kappa / sigma2;

                double  nu    = 0.5 * d - 1;
                Complex z     = ga * Complex.Exp(-0.5 * ga * dt) / (1.0 - Complex.Exp(-ga * dt));
                Complex log_z = -0.5 * ga * dt + Complex.Log(ga / (1.0 - Complex.Exp(-ga * dt)));

                Complex alpha = 4.0 * ga * Complex.Exp(-0.5 * ga * dt) / (sigma2 * (1.0 - Complex.Exp(-ga * dt)));
                Complex beta  = 4.0 * kappa * Complex.Exp(-0.5 * kappa * dt) / (sigma2 * (1.0 - Complex.Exp(-kappa * dt)));

                return(ga * Complex.Exp(-0.5 * (ga - kappa) * dt) * (1 - Complex.Exp(-kappa * dt))
                       / (kappa * (1.0 - Complex.Exp(-ga * dt)))
                       * Complex.Exp((nu_0 + nu_t) / sigma2 * (
                                         kappa * (1.0 + Complex.Exp(-kappa * dt)) / (1.0 - Complex.Exp(-kappa * dt))
                                         - ga * (1.0 + Complex.Exp(-ga * dt)) / (1.0 - Complex.Exp(-ga * dt))))
                       * Complex.Exp(nu * log_z) / Complex.Pow(z, nu)
                       * ((nu_t > 1e-8)
                      ? Utils.modifiedBesselFunction_i(nu, Complex.Sqrt(nu_0 * nu_t) * alpha)
                          / Utils.modifiedBesselFunction_i(nu, Complex.Sqrt(nu_0 * nu_t) * beta)
                      : Complex.Pow(alpha / beta, nu)
                          ));
            }
示例#3
0
            private double cornishFisherEps(HestonProcess process, double nu_0, double nu_t, double dt, double eps)
            {
                // use moment generating function to get the
                // first,second, third and fourth moment of the distribution
                double d   = 1e-2;
                double p2  = Phi(process, new Complex(0, -2 * d), nu_0, nu_t, dt).Real;
                double p1  = Phi(process, new Complex(0, -d), nu_0, nu_t, dt).Real;
                double p0  = Phi(process, new Complex(0, 0), nu_0, nu_t, dt).Real;
                double pm1 = Phi(process, new Complex(0, d), nu_0, nu_t, dt).Real;
                double pm2 = Phi(process, new Complex(0, 2 * d), nu_0, nu_t, dt).Real;

                double avg    = (pm2 - 8 * pm1 + 8 * p1 - p2) / (12 * d);
                double m2     = (-pm2 + 16 * pm1 - 30 * p0 + 16 * p1 - p2) / (12 * d * d);
                double var    = m2 - avg * avg;
                double stdDev = Math.Sqrt(var);

                double m3   = (-0.5 * pm2 + pm1 - p1 + 0.5 * p2) / (d * d * d);
                double skew = (m3 - 3 * var * avg - avg * avg * avg) / (var * stdDev);

                double m4   = (pm2 - 4 * pm1 + 6 * p0 - 4 * p1 + p2) / (d * d * d * d);
                double kurt = (m4 - 4 * m3 * avg + 6 * m2 * avg * avg - 3 * avg * avg * avg * avg) / (var * var);

                // Cornish-Fisher relation to come up with an improved
                // estimate of 1-F(u_\eps) < \eps
                double q = new InverseCumulativeNormal().value(1 - eps);
                double w = q + (q * q - 1) / 6 * skew + (q * q * q - 3 * q) / 24 * (kurt - 3)
                           - (2 * q * q * q - 5 * q) / 36 * skew * skew;

                return(avg + w * stdDev);
            }
示例#4
0
 public ch(HestonProcess _process, double _x, double _nu_0, double _nu_t, double _dt)
 {
     process = _process;
     x       = _x;
     nu_0    = _nu_0;
     nu_t    = _nu_t;
     dt      = _dt;
 }
示例#5
0
 protected override void generateArguments()
 {
     process_ = new HestonProcess(process_.riskFreeRate(),
                                  process_.dividendYield(),
                                  process_.s0(),
                                  v0(), kappa(), theta(),
                                  sigma(), rho());
 }
示例#6
0
 public cdf_nu_ds(HestonProcess _process, double _nu_0, double _nu_t, double _dt,
                  Discretization _discretization)
 {
     process        = _process;
     nu_0           = _nu_0;
     nu_t           = _nu_t;
     dt             = _dt;
     discretization = _discretization;
 }
 public MakeMGenericHestonInstrument(HestonProcess process)
 {
     process_        = process;
     antithetic_     = true;
     steps_          = null;
     stepsPerYear_   = null;
     samples_        = null;
     maxSamples_     = null;
     tolerance_      = null;
     brownianBridge_ = false;
     seed_           = 0;
 }
 public MCGenericHestonInstrument(HestonProcess process,
                                  bool antithetic,
                                  int?steps,
                                  int?stepsPerYear,
                                  int?samples,
                                  int?maxSamples,
                                  double?tolerance,
                                  bool brownianBridge,
                                  ulong seed)
     : base(process, antithetic, steps, stepsPerYear, samples, maxSamples, tolerance, brownianBridge, seed)
 {
 }
示例#9
0
        protected override double blackVolImpl(double t, double strike)
        {
            HestonProcess process = hestonModel_.link.process();

            double df        = process.riskFreeRate().link.discount(t, true);
            double div       = process.dividendYield().link.discount(t, true);
            double spotPrice = process.s0().link.value();

            double fwd = spotPrice
                         * process.dividendYield().link.discount(t, true)
                         / process.riskFreeRate().link.discount(t, true);

            var payoff = new PlainVanillaPayoff(fwd > strike ? Option.Type.Put : Option.Type.Call, strike);

            double kappa = hestonModel_.link.kappa();
            double theta = hestonModel_.link.theta();
            double rho   = hestonModel_.link.rho();
            double sigma = hestonModel_.link.sigma();
            double v0    = hestonModel_.link.v0();

            AnalyticHestonEngine.ComplexLogFormula cpxLogFormula = AnalyticHestonEngine.ComplexLogFormula.Gatheral;

            AnalyticHestonEngine hestonEnginePtr = null;

            double?npv         = null;
            int    evaluations = 0;

            AnalyticHestonEngine.doCalculation(
                df, div, spotPrice, strike, t,
                kappa, theta, sigma, v0, rho,
                payoff, integration_, cpxLogFormula,
                hestonEnginePtr, ref npv, ref evaluations);

            if (npv <= 0.0)
            {
                return(Math.Sqrt(theta));
            }

            Brent solver = new Brent();

            solver.setMaxEvaluations(10000);
            double guess    = Math.Sqrt(theta);
            double accuracy = Const.QL_EPSILON;

            var f = new ImpliedVolHelper(payoff.optionType(), strike, fwd, t, df, npv.Value);

            return(solver.solve(f, accuracy, guess, 0.01));
        }
示例#10
0
        public HestonModel(HestonProcess process)
            : base(5)
        {
            process_ = process;

            arguments_[0] = new ConstantParameter(process.theta(), new PositiveConstraint());
            arguments_[1] = new ConstantParameter(process.kappa(), new PositiveConstraint());
            arguments_[2] = new ConstantParameter(process.sigma(), new PositiveConstraint());
            arguments_[3] = new ConstantParameter(process.rho(), new BoundaryConstraint(-1.0, 1.0));
            arguments_[4] = new ConstantParameter(process.v0(), new PositiveConstraint());
            generateArguments();

            process_.riskFreeRate().registerWith(update);
            process_.dividendYield().registerWith(update);
            process_.s0().registerWith(update);
        }
示例#11
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));
        }
示例#12
0
        protected override PathPricer <IPath> controlPathPricer()
        {
            HybridHestonHullWhiteProcess process = process_ as HybridHestonHullWhiteProcess;

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

            HestonProcess hestonProcess = process.hestonProcess();

            Utils.QL_REQUIRE(hestonProcess != null, () =>
                             "first constituent of the joint stochastic process need to be of type HestonProcess");

            Exercise exercise = this.arguments_.exercise;

            Utils.QL_REQUIRE(exercise.type() == Exercise.Type.European, () => "only european exercise is supported");

            double exerciseTime = process.time(exercise.lastDate());

            return(new HestonHullWhitePathPricer(exerciseTime, this.arguments_.payoff, process));
        }
示例#13
0
        public override void calculate()
        {
            // this is a european option pricer
            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () => "not an European option");

            // plain vanilla
            PlainVanillaPayoff payoff = arguments_.payoff as PlainVanillaPayoff;

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

            HestonProcess process = model_.link.process();

            double riskFreeDiscount = process.riskFreeRate().link.discount(arguments_.exercise.lastDate());
            double dividendDiscount = process.dividendYield().link.discount(arguments_.exercise.lastDate());

            double spotPrice = process.s0().link.value();

            Utils.QL_REQUIRE(spotPrice > 0.0, () => "negative or null underlying given");

            double strikePrice = payoff.strike();
            double term        = process.time(arguments_.exercise.lastDate());

            double?resultsValue = null;

            doCalculation(riskFreeDiscount,
                          dividendDiscount,
                          spotPrice,
                          strikePrice,
                          term,
                          model_.link.kappa(),
                          model_.link.theta(),
                          model_.link.sigma(),
                          model_.link.v0(),
                          model_.link.rho(),
                          payoff,
                          integration_,
                          cpxLog_,
                          this,
                          ref resultsValue,
                          ref evaluations_);
            results_.value = resultsValue;
        }
示例#14
0
 public cdf_nu_ds_minus_x(double _x0, HestonProcess _process, double _nu_0, double _nu_t, double _dt,
                          Discretization _discretization)
 {
     cdf_nu = new cdf_nu_ds(_process, _nu_0, _nu_t, _dt, _discretization);
     x0     = _x0;
 }