// Heston Price by Gauss-Laguerre Integration =================================================================
        static float HestonPriceGaussLaguerre(HParam param, float S, float K, float r, float q, float T, int trap, string PutCall, float[] x, float[] w)
        {
            float[] int1 = new float[32];
            float[] int2 = new float[32];

            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                int1[j] = w[j] * HestonProb(x[j], param, S, K, r, q, T, 1, trap);
                int2[j] = w[j] * HestonProb(x[j], param, S, K, r, q, T, 2, trap);
            }

            // Define P1 and P2
            float pi = Convert.ToSingle(Math.PI);
            float P1 = 0.5f + 1.0f / pi * int1.Sum();
            float P2 = 0.5f + 1.0f / pi * int2.Sum();

            // The call price
            float HestonC = Convert.ToSingle(S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2);

            // The put price by put-call parity
            float HestonP = Convert.ToSingle(HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T));

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
        public double CZEuroCall(double S0, double tau, HParam param, double K, double rf, double q, double[] Xs, double[] Ws)
        {
            Complex i   = new Complex(0.0, 1.0);
            double  xi  = 0;
            Complex psi = 0;
            int     Nx  = Xs.Length;

            double[] Int1 = new double[Nx];
            double[] Int2 = new double[Nx];
            Complex  I1, I2;

            // Compute the integrands
            CharFun CF = new CharFun();

            for (int k = 0; k <= Nx - 1; k++)
            {
                Complex phi = Xs[k];
                I1      = Complex.Exp(-i * phi * Math.Log(K)) * CF.CZCharFun(S0, tau, xi, param, K, rf, q, phi, psi, 1) / (i * phi);
                Int1[k] = Ws[k] * I1.Real;
                I2      = Complex.Exp(-i * phi * Math.Log(K)) * CF.CZCharFun(S0, tau, xi, param, K, rf, q, phi, psi, 2) / (i * phi);
                Int2[k] = Ws[k] * I2.Real;
            }

            // Define the probabilities
            double pi = Math.PI;
            double P1 = 0.5 + (1.0 / pi) * Int1.Sum();
            double P2 = 0.5 + (1.0 / pi) * Int2.Sum();

            // Return the call price
            return(S0 * Math.Exp(-q * tau) * P1 - K * Math.Exp(-rf * tau) * P2);
        }
Пример #3
0
        // Heston Price by Gauss-Laguerre Integration
        public double HestonPriceConsol(HParam param, OpSet settings, double[] x, double[] w)
        {
            double[] int1 = new Double[32];
            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                int1[j] = w[j] * HestonProbConsol(x[j], param, settings);
            }

            // Define P1 and P2
            double pi = Math.PI;
            double I  = int1.Sum();

            // The call price
            double S       = settings.S;
            double K       = settings.K;
            double r       = settings.r;
            double q       = settings.q;
            double T       = settings.T;
            string PutCall = settings.PutCall;
            double HestonC = 0.5 * S * Math.Exp(-q * T) - 0.5 * K * Math.Exp(-r * T) + I / pi;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
Пример #4
0
        // Mikhailov and Nogel (2003) Time dependent C function
        public Complex Ct(double phi, HParam param, double r, double q, double T, OpSet settings, int Pnum, Complex C0, Complex D0)
        {
            Complex i = new Complex(0.0, 1.0);                   // Imaginary unit
            double  kappa = param.kappa;
            double  theta = param.theta;
            double  sigma = param.sigma;
            double  v0 = param.v0;
            double  rho = param.rho;
            double  a = kappa * theta;
            int     Trap = settings.trap;
            Complex b, u, d, g, G, C = new Complex();

            // Parameters "u" and "b" are different for P1 and P2
            if (Pnum == 1)
            {
                u = 0.5;
                b = kappa - rho * sigma;
            }
            else
            {
                u = -0.5;
                b = kappa;
            }
            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2) - sigma * sigma * (2.0 * u * i * phi - phi * phi));
            g = (b - rho * sigma * i * phi + d - D0 * sigma * sigma) / (b - rho * sigma * i * phi - d - D0 * sigma * sigma);
            G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
            C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi + d) * T - 2.0 * Complex.Log(G)) + C0;

            return(C);
        }
Пример #5
0
        // Time dependent D function
        public Complex Dt(double phi, HParam param, double S, double K, double r, double q, double T, int Pnum, int Trap, Complex C0, Complex D0)
        {
            Complex i = new Complex(0.0, 1.0);                   // Imaginary unit
            double  kappa = param.kappa;
            double  theta = param.theta;
            double  sigma = param.sigma;
            double  v0 = param.v0;
            double  rho = param.rho;
            Complex b, u, d, g, G, D = new Complex();

            // Parameters "u" and "b" are different for P1 and P2
            if (Pnum == 1)
            {
                u = 0.5;
                b = kappa - rho * sigma;
            }
            else
            {
                u = -0.5;
                b = kappa;
            }
            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2) - sigma * sigma * (2.0 * u * i * phi - phi * phi));
            g = (b - rho * sigma * i * phi + d - D0 * sigma * sigma) / (b - rho * sigma * i * phi - d - D0 * sigma * sigma);
            G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
            D = ((b - rho * sigma * i * phi) * (1 - g * Complex.Exp(d * T)) + d * (1 + g * Complex.Exp(d * T))) / (sigma * sigma * (1 - g * Complex.Exp(d * T)));

            return(D);
        }
        static void Main(string[] args)
        {
            // 32-point Gauss-Laguerre Abscissas and weights
            double[] x = new Double[32];
            double[] w = new Double[32];
            using (TextReader reader = File.OpenText("../../GaussLaguerre32.txt"))
                for (int k = 0; k <= 31; k++)
                {
                    string   text = reader.ReadLine();
                    string[] bits = text.Split(' ');
                    x[k] = double.Parse(bits[0]);
                    w[k] = double.Parse(bits[1]);
                }
            HParam param = new HParam();

            param.kappa  = 6.2;
            param.theta  = 0.06;
            param.sigma  = 0.5;
            param.v0     = 0.03;
            param.rho    = -0.7;
            param.lambda = 0.0;

            OpSet settings = new OpSet();

            settings.S       = 100.0;
            settings.K       = 100.0;
            settings.T       = 0.25;
            settings.r       = 0.03;
            settings.q       = 0.02;
            settings.PutCall = "C";
            settings.trap    = 1;

            // Simulation settings
            double gamma1 = 0.5;
            double gamma2 = 0.5;
            double phic   = 1.5;
            int    MC     = 1;
            int    NT     = 100;
            int    NS     = 1500;

            // Calculate the IJK price
            QESimulation QE           = new QESimulation();
            double       QuadExpPrice = QE.QEPrice(param, settings, gamma1, gamma2, NT, NS, MC, phic, settings.PutCall);

            // Calculate the closed-form European option price
            HestonPrice HP          = new HestonPrice();
            double      ClosedPrice = HP.HestonPriceGaussLaguerre(param, settings, x, w);

            // Calculate the errors;
            double QError = Math.Abs((QuadExpPrice - ClosedPrice) / ClosedPrice * 100);

            // Output the results
            Console.WriteLine("European Heston price by simulation --------------------");
            Console.WriteLine("Uses  {0:0} stock price paths and {1:0} time increments", NS, NT);
            Console.WriteLine("--------------------------------------------------------");
            Console.WriteLine("Closed form price        {0:F5}", ClosedPrice);
            Console.WriteLine("Quadratic exp price      {0:F5}      Error {1,5:F5}", QuadExpPrice, QError);
            Console.WriteLine("--------------------------------------------------------");
            Console.WriteLine(" ");
        }
Пример #7
0
        // Heston Price by Gauss-Laguerre Integration =================================================================
        public double HestonPriceGaussLaguerre(HParam param, double S, double K, double r, double q, double T, int trap, string PutCall, double[] x, double[] w)
        {
            double[] int1 = new Double[32];
            double[] int2 = new Double[32];

            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                int1[j] = w[j] * HestonProb(x[j], param, S, K, r, q, T, 1, trap);
                int2[j] = w[j] * HestonProb(x[j], param, S, K, r, q, T, 2, trap);
            }

            // Define P1 and P2
            double pi = Math.PI;
            double P1 = 0.5 + 1.0 / pi * int1.Sum();
            double P2 = 0.5 + 1.0 / pi * int2.Sum();

            // The call price
            double HestonC = S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
        static void Main(string[] args)
        {
            // 32-point Gauss-Laguerre Abscissas and weights
            double[] x = new Double[32];
            double[] w = new Double[32];
            using (TextReader reader = File.OpenText("../../GaussLaguerre32.txt"))
                for (int k = 0; k <= 31; k++)
                {
                    string   text = reader.ReadLine();
                    string[] bits = text.Split(' ');
                    x[k] = double.Parse(bits[0]);
                    w[k] = double.Parse(bits[1]);
                }
            HParam param = new HParam();

            param.kappa  = 6.2;
            param.theta  = 0.06;
            param.sigma  = 0.5;
            param.v0     = 0.03;
            param.rho    = -0.7;
            param.lambda = 0.0;

            OpSet settings = new OpSet();

            settings.S       = 100.0;
            settings.K       = 90.0;
            settings.T       = 3.0 / 12.0;
            settings.r       = 0.03;
            settings.q       = 0.02;
            settings.PutCall = "C";
            settings.trap    = 1;

            // Simulation settings
            int NT = 100;
            int NS = 2000;

            // Calculate the Euler price and the transformed volatility price
            TVSimulation TV         = new TVSimulation();
            double       TVolPrice  = TV.TransVolPrice("TV", param, settings, NT, NS);
            double       EulerPrice = TV.TransVolPrice("Euler", param, settings, NT, NS);

            // Calculate the closed-form European option price
            double ClosedPrice = HestonPriceGaussLaguerre(param, settings, x, w);

            // Calculate the errors;
            double TVolError  = Math.Abs((TVolPrice - ClosedPrice) / ClosedPrice * 100);
            double EulerError = Math.Abs((EulerPrice - ClosedPrice) / ClosedPrice * 100);

            // Output the results
            Console.WriteLine("Uses  {0:0} stock price paths and {1:0} time increments", NS, NT);
            Console.WriteLine("--------------------------------------------------------");
            Console.WriteLine("Method                       Price     PercentError");
            Console.WriteLine("--------------------------------------------------------");
            Console.WriteLine("Exact with Gauss Laguerre  {0,10:F5}", ClosedPrice);
            Console.WriteLine("Euler discretization       {0,10:F5}  {1,10:F5}", EulerPrice, EulerError);
            Console.WriteLine("Transformed volatility     {0,10:F5}  {1,10:F5}", TVolPrice, TVolError);
            Console.WriteLine("--------------------------------------------------------");
            Console.WriteLine(" ");
        }
Пример #9
0
        // Double integral using trapezoidal rule
        public double DoubleTrapezoidal(HParam param, double S0, double K, double tau, double rf, double q,
                                        double b0, double b1, double[] X, double[] T, int funNum)
        {
            Complex i = new Complex(0.0, 1.0);
            double  a, b, c, d, qr = 0.0;
            Complex fun1, fun2, fun3, fun4;
            double  g1, g2, g3, g4, term1, term2, term3;
            int     Nt = T.Length;
            int     Nx = X.Length;

            // Select rate or dividend
            if (funNum == 1)
            {
                qr = q;
            }
            else if (funNum == 2)
            {
                qr = rf;
            }
            double[,] Int = new double[Nt, Nx];
            double sumInt = 0.0;

            // Double trapezoidal rule
            CharFun CF = new CharFun();

            for (int t = 1; t <= Nt - 1; t++)
            {
                a = T[t - 1];
                b = T[t];
                for (int x = 1; x <= Nx - 1; x++)
                {
                    c         = X[x - 1];
                    d         = X[x];
                    fun1      = Complex.Exp(-b0 * i * c) * CF.CZCharFun(S0, tau, a, param, K, rf, q, c, -b1 * c, funNum) / (i * c);
                    fun2      = Complex.Exp(-b0 * i * d) * CF.CZCharFun(S0, tau, a, param, K, rf, q, d, -b1 * d, funNum) / (i * d);
                    fun3      = Complex.Exp(-b0 * i * c) * CF.CZCharFun(S0, tau, b, param, K, rf, q, c, -b1 * c, funNum) / (i * c);
                    fun4      = Complex.Exp(-b0 * i * d) * CF.CZCharFun(S0, tau, b, param, K, rf, q, d, -b1 * d, funNum) / (i * d);
                    g1        = Math.Exp(qr * a) * fun1.Real;
                    g2        = Math.Exp(qr * a) * fun2.Real;
                    g3        = Math.Exp(qr * b) * fun3.Real;
                    g4        = Math.Exp(qr * b) * fun4.Real;
                    term1     = g1 + g2 + g3 + g4;
                    fun1      = Complex.Exp(-b0 * i * c) * CF.CZCharFun(S0, tau, (a + b) / 2.0, param, K, rf, q, c, -b1 * c, funNum) / (i * c);
                    fun2      = Complex.Exp(-b0 * i * d) * CF.CZCharFun(S0, tau, (a + b) / 2.0, param, K, rf, q, d, -b1 * d, funNum) / (i * d);
                    fun3      = Complex.Exp(-b0 * i * (c + d) / 2.0) * CF.CZCharFun(S0, tau, a, param, K, rf, q, (c + d) / 2.0, -b1 * (c + d) / 2.0, funNum) / (i * (c + d) / 2.0);
                    fun4      = Complex.Exp(-b0 * i * (c + d) / 2.0) * CF.CZCharFun(S0, tau, b, param, K, rf, q, (c + d) / 2.0, -b1 * (c + d) / 2.0, funNum) / (i * (c + d) / 2.0);
                    g1        = Math.Exp(qr * (a + b) / 2.0) * fun1.Real;
                    g2        = Math.Exp(qr * (a + b) / 2.0) * fun2.Real;
                    g3        = Math.Exp(qr * a) * fun3.Real;
                    g4        = Math.Exp(qr * b) * fun4.Real;
                    term2     = g1 + g2 + g3 + g4;
                    fun1      = Complex.Exp(-b0 * i * (c + d) / 2.0) * CF.CZCharFun(S0, tau, (a + b) / 2.0, param, K, rf, q, (c + d) / 2.0, -b1 * (c + d) / 2.0, funNum) / (i * (c + d) / 2.0);
                    term3     = Math.Exp(qr * (a + b) / 2.0) * fun1.Real;
                    Int[t, x] = (b - a) * (d - c) / 16.0 * (term1 + 2 * term2 + 4 * term3);
                    sumInt   += Int[t, x];
                }
            }
            return(sumInt);
        }
Пример #10
0
        // Heston Integrand
        public double HestonProb(double phi, HParam param, OpSet settings, int Pnum)
        {
            Complex i = new Complex(0.0, 1.0);                   // Imaginary unit
            double  S = settings.S;
            double  K = settings.K;
            double  T = settings.T;
            double  r = settings.r;
            double  q = settings.q;
            double  kappa = param.kappa;
            double  theta = param.theta;
            double  sigma = param.sigma;
            double  v0 = param.v0;
            double  rho = param.rho;
            double  lambda = param.lambda;
            double  x = Math.Log(S);
            double  a = kappa * theta;
            int     Trap = settings.trap;
            Complex b, u, d, g, c, D, G, C, f, integrand = new Complex();

            // Parameters "u" and "b" are different for P1 and P2
            if (Pnum == 1)
            {
                u = 0.5;
                b = kappa + lambda - rho * sigma;
            }
            else
            {
                u = -0.5;
                b = kappa + lambda;
            }
            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2) - sigma * sigma * (2.0 * u * i * phi - phi * phi));
            g = (b - rho * sigma * i * phi + d) / (b - rho * sigma * i * phi - d);
            if (Trap == 1)
            {
                // "Little Heston Trap" formulation
                c = 1.0 / g;
                D = (b - rho * sigma * i * phi - d) / sigma / sigma * ((1.0 - Complex.Exp(-d * T)) / (1.0 - c * Complex.Exp(-d * T)));
                G = (1.0 - c * Complex.Exp(-d * T)) / (1 - c);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi - d) * T - 2.0 * Complex.Log(G));
            }
            else
            {
                // Original Heston formulation.
                G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi + d) * T - 2.0 * Complex.Log(G));
                D = (b - rho * sigma * i * phi + d) / sigma / sigma * ((1.0 - Complex.Exp(d * T)) / (1.0 - g * Complex.Exp(d * T)));
            }

            // The characteristic function.
            f = Complex.Exp(C + D * v0 + i * phi * x);

            // The integrand.
            integrand = Complex.Exp(-i * phi * Complex.Log(K)) * f / i / phi;

            // Return the real part of the integrand.
            return(integrand.Real);
        }
        public Complex CZCharFun(double S0, double tau, double t, HParam param, double K, double rf, double q, Complex phi, Complex psi, int FunNum)
        {
            Complex i      = new Complex(0.0, 1.0);
            double  kappa  = param.kappa;
            double  theta  = param.theta;
            double  sigma  = param.sigma;
            double  v0     = param.v0;
            double  rho    = param.rho;
            double  lambda = param.lambda;

            double x = Math.Log(S0);

            // Parameters "a" and "b"
            double a = kappa * theta;
            double b = kappa + lambda;

            // "d" and "g" functions
            Complex d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2.0) + sigma * sigma * phi * (phi + i));
            Complex g = (b - rho * sigma * i * phi - sigma * sigma * i * psi + d)
                        / (b - rho * sigma * i * phi - sigma * sigma * i * psi - d);

            // The components of the affine characteristic function.
            Complex G = (1.0 - g * Complex.Exp(d * (tau - t))) / (1.0 - g);
            Complex C = (rf - q) * i * phi * (tau - t) + a / sigma / sigma * ((b - rho * sigma * i * phi + d) * (tau - t) - 2.0 * Complex.Log(G));
            Complex F = (1.0 - Complex.Exp(d * (tau - t))) / (1.0 - g * Complex.Exp(d * (tau - t)));
            Complex D = i * psi + (b - rho * sigma * i * phi - sigma * sigma * i * psi + d) / sigma / sigma * F;

            // The characteristic function.
            Complex f2 = Complex.Exp(C + D * v0 + i * phi * x);

            if (FunNum == 2)
            {
                return(f2);
            }
            else if (FunNum == 1)
            {
                d = Complex.Sqrt(Complex.Pow(rho * sigma * i * (phi - i) - b, 2.0) + sigma * sigma * (phi - i) * phi);
                g = (b - rho * sigma * i * (phi - i) - sigma * sigma * i * psi + d)
                    / (b - rho * sigma * i * (phi - i) - sigma * sigma * i * psi - d);

                // The components of the affine characteristic function.
                G = (1.0 - g * Complex.Exp(d * (tau - t))) / (1.0 - g);
                C = (rf - q) * i * (phi - i) * (tau - t) + a / sigma / sigma * ((b - rho * sigma * i * (phi - i) + d) * (tau - t) - 2.0 * Complex.Log(G));
                F = (1.0 - Complex.Exp(d * (tau - t))) / (1.0 - g * Complex.Exp(d * (tau - t)));
                D = i * psi + (b - rho * sigma * i * (phi - i) - sigma * sigma * i * psi + d) / sigma / sigma * F;

                Complex F2 = Complex.Exp(C + D * v0 + i * (phi - i) * x);
                return(1.0 / S0 * Complex.Exp(-(rf - q) * (tau - t)) * F2);
            }
            else
            {
                return(0.0);
            }
        }
        public double[] CZAmerCall(double S0, double tau, HParam param, double K, double rf, double q, double[] xs, double[] ws, double[] xt, double[] wt,
                                   int Nt, double b0, double b1, double a, double b, double c, double d, string DoubleType)
        {
            EarlyExercise EE      = new EarlyExercise();
            double        Euro    = CZEuroCall(S0, tau, param, K, rf, q, xs, ws);
            double        Premium = EE.CZEarlyExercise(S0, tau, param, K, rf, q, xt, wt, xt, wt, Nt, b0, b1, a, b, c, d, DoubleType);
            double        Amer    = Euro + Premium;

            double[] output = new double[2];
            output[0] = Amer;
            output[1] = Euro;
            return(output);
        }
        // Heston Integrand
        static float HestonProb(float phi, HParam param, float S, float K, float r, float q, float T, int Pnum, int Trap)
        {
            Complex i = new Complex(0.0, 1.0);                   // Imaginary unit
            float   kappa = param.kappa;
            float   theta = param.theta;
            float   sigma = param.sigma;
            float   v0 = param.v0;
            float   rho = param.rho;
            float   lambda = 0.0f;
            float   x = Convert.ToSingle(Math.Log(S));
            float   a = kappa * theta;
            Complex b, u, d, g, c, D, G, C, f, integrand = new Complex();

            // Parameters "u" and "b" are different for P1 and P2
            if (Pnum == 1)
            {
                u = 0.5;
                b = kappa + lambda - rho * sigma;
            }
            else
            {
                u = -0.5;
                b = kappa + lambda;
            }
            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2) - sigma * sigma * (2.0 * u * i * phi - phi * phi));
            g = (b - rho * sigma * i * phi + d) / (b - rho * sigma * i * phi - d);
            if (Trap == 1)
            {
                // "Little Heston Trap" formulation
                c = 1.0 / g;
                D = (b - rho * sigma * i * phi - d) / sigma / sigma * ((1.0 - Complex.Exp(-d * T)) / (1.0 - c * Complex.Exp(-d * T)));
                G = (1.0 - c * Complex.Exp(-d * T)) / (1 - c);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi - d) * T - 2.0 * Complex.Log(G));
            }
            else
            {
                // Original Heston formulation.
                G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi + d) * T - 2.0 * Complex.Log(G));
                D = (b - rho * sigma * i * phi + d) / sigma / sigma * ((1.0 - Complex.Exp(d * T)) / (1.0 - g * Complex.Exp(d * T)));
            }

            // The characteristic function.
            f = Complex.Exp(C + D * v0 + i * phi * x);

            // The integrand.
            integrand = Complex.Exp(-i * phi * Complex.Log(K)) * f / i / phi;

            // Return the real part of the integrand.
            return(Convert.ToSingle(integrand.Real));
        }
        static void Main(string[] args)
        {
            // 32-point Gauss-Laguerre Abscissas and weights
            double[] x = new Double[32];
            double[] w = new Double[32];
            using (TextReader reader = File.OpenText("../../GaussLaguerre32.txt"))
            {
                for (int k = 0; k <= 31; k++)
                {
                    string   text = reader.ReadLine();
                    string[] bits = text.Split(' ');
                    x[k] = double.Parse(bits[0]);
                    w[k] = double.Parse(bits[1]);
                }
            }
            // Heston parameters
            HParam param = new HParam();

            param.kappa  = 1.5;
            param.theta  = 0.04;
            param.sigma  = 0.3;
            param.v0     = 0.05412;
            param.rho    = -0.9;
            param.lambda = 0.0;

            // Option settings
            OpSet settings = new OpSet();

            settings.S       = 101.52;
            settings.K       = 100.0;
            settings.T       = 0.15;
            settings.r       = 0.02;
            settings.q       = 0.0;
            settings.PutCall = "C";
            settings.trap    = 1;

            // The Heston price
            HestonPrice HP    = new HestonPrice();
            double      Price = HP.HestonPriceGaussLaguerre(param, settings, x, w);

            Console.WriteLine("Heston price using 32-point Gauss Laguerre");
            Console.WriteLine("------------------------------------------ ");
            Console.WriteLine("Option Flavor =  {0,0:F5}", settings.PutCall);
            Console.WriteLine("Strike Price  =  {0,0:0}", settings.K);
            Console.WriteLine("Maturity      =  {0,0:F2}", settings.T);
            Console.WriteLine("Price         =  {0,0:F4}", Price);
            Console.WriteLine("------------------------------------------ ");
            Console.WriteLine(" ");
        }
Пример #15
0
        public Complex HestonBivariateCF(Complex phi1, Complex phi2, HParam param, OpSet settings)
        {
            Complex i = new Complex(0.0, 1.0);                  // Imaginary unit
            Complex S = new Complex(settings.S, 0.0);           // Spot Price
            Complex K = new Complex(settings.K, 0.0);           // Strike Price
            Complex T = new Complex(settings.T, 0.0);           // Maturity in years
            Complex r = new Complex(settings.r, 0.0);           // Interest rate
            Complex q = new Complex(settings.q, 0.0);           // Dividend yield
            Complex rho = new Complex(param.rho, 0.0);          // Heston parameter: correlation
            Complex kappa = new Complex(param.kappa, 0.0);      // Heston parameter: mean reversion speed
            Complex theta = new Complex(param.theta, 0.0);      // Heston parameter: mean reversion speed
            Complex lambda = new Complex(param.lambda, 0.0);    // Heston parameter: price of volatility risk
            Complex sigma = new Complex(param.sigma, 0.0);      // Heston parameter: volatility of variance
            Complex v0 = new Complex(param.v0, 0.0);            // Heston parameter: initial variance
            Complex x = Complex.Log(S);
            Complex a = kappa * theta;
            int     trap = settings.trap;
            Complex b, u, d, g, c, A = 0.0, C = 0.0, B, G = new Complex();

            // Log stock price
            Complex x0 = Complex.Log(S);

            u = -0.5;
            b = kappa + lambda;

            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi1 - b, 2) - sigma * sigma * (2.0 * u * i * phi1 - phi1 * phi1));
            g = (b - rho * sigma * i * phi1 + d - sigma * sigma * i * phi2)
                / (b - rho * sigma * i * phi1 - d - sigma * sigma * i * phi2);
            c = 1 / g;
            B = i * phi1;

            if (trap == 1)
            {
                // Little Trap formulation in Kahl (2008)
                G = (c * Complex.Exp(-d * T) - 1.0) / (c - 1.0);
                A = (r - q) * i * phi1 * T + a / sigma / sigma * ((b - rho * sigma * i * phi1 - d) * T - 2.0 * Complex.Log(G));
                C = ((b - rho * sigma * i * phi1 - d) - (b - rho * sigma * i * phi1 + d) * c * Complex.Exp(-d * T)) / (sigma * sigma) / (1 - c * Complex.Exp(-d * T));
            }
            else if (trap == 0)
            {
                // Original Heston formulation.
                G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
                A = (r - q) * i * phi1 * T + a / sigma / sigma * ((b - rho * sigma * i * phi1 + d) * T - 2.0 * Complex.Log(G));
                C = ((b - rho * sigma * i * phi1 + d) - (b - rho * sigma * i * phi1 - d) * g * Complex.Exp(d * T)) / (sigma * sigma) / (1.0 - g * Complex.Exp(d * T));
            }

            // The characteristic function.
            return(Complex.Exp(A + B * x0 + C * v0));
        }
        // Heston Price by Gauss-Laguerre Integration
        public double HestonPriceGaussLaguerre(HParam param, OpSet settings, double[] x, double[] w)
        {
            Complex i = new Complex(0.0, 1.0);

            Complex[] f1   = new Complex[32];
            Complex[] f2   = new Complex[32];
            double[]  int1 = new double[32];
            double[]  int2 = new double[32];

            double S = settings.S;
            double K = settings.K;
            double T = settings.T;
            double r = settings.r;
            double q = settings.q;

            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                double phi = x[j];
                f1[j] = HestonCF(phi - i, param, settings) / (S * Math.Exp((r - q) * T));
                f2[j] = HestonCF(phi, param, settings);
                Complex FF1 = Complex.Exp(-i * phi * Complex.Log(K)) * f1[j] / i / phi;
                Complex FF2 = Complex.Exp(-i * phi * Complex.Log(K)) * f2[j] / i / phi;
                int1[j] = w[j] * FF1.Real;
                int2[j] = w[j] * FF2.Real;
            }

            // Define P1 and P2
            double pi = Math.PI;
            double P1 = 0.5 + 1.0 / pi * int1.Sum();
            double P2 = 0.5 + 1.0 / pi * int2.Sum();

            // The call price
            string PutCall = settings.PutCall;
            double HestonC = S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
Пример #17
0
        // Simulation of stock price paths and variance paths using Euler or Milstein schemes
        public double[,] MMSim(HParam param, OpSet settings, int NT, int NS, double[,] Zv, double[,] Zs)
        {
            // Heston parameters
            double kappa  = param.kappa;
            double theta  = param.theta;
            double sigma  = param.sigma;
            double v0     = param.v0;
            double rho    = param.rho;
            double lambda = param.lambda;

            // option settings
            double r = settings.r;
            double q = settings.q;

            // Time increment
            double dt = settings.T / Convert.ToDouble(NT);

            // Initialize the variance and stock processes
            double[,] V = new double[NT, NS];
            double[,] S = new double[NT, NS];

            // Flags for negative variances
            int F = 0;

            // Starting values for the variance and stock processes
            for (int s = 0; s <= NS - 1; s++)
            {
                S[0, s] = settings.S; // Spot price
                V[0, s] = v0;         // Heston v0 initial variance
            }

            // Generate the stock and volatility paths
            for (int s = 0; s <= NS - 1; s++)
            {
                for (int t = 1; t <= NT - 1; t++)
                {
                    // Matched moment lognormal approximation
                    double dW  = Math.Sqrt(dt) * Zv[t, s];
                    double num = 0.5 * sigma * sigma * V[t - 1, s] * (1.0 - Math.Exp(-2.0 * kappa * dt)) / kappa;
                    double den = Math.Pow(Math.Exp(-kappa * dt) * V[t - 1, s] + (1.0 - Math.Exp(-kappa * dt)) * theta, 2);
                    double Gam = Math.Log(1 + num / den);
                    V[t, s] = (Math.Exp(-kappa * dt) * V[t - 1, s] + (1.0 - Math.Exp(-kappa * dt)) * theta) * Math.Exp(-0.5 * Gam * Gam + Gam * Zv[t, s]);

                    // Euler/Milstein discretization scheme for the log stock prices
                    S[t, s] = S[t - 1, s] * Math.Exp((r - q - V[t - 1, s] / 2) * dt + Math.Sqrt(V[t - 1, s] * dt) * Zs[t, s]);
                }
            }
            return(S);
        }
Пример #18
0
        static void Main(string[] args)
        {
            // 32-point Gauss-Laguerre Abscissas and weights
            double[] x = new Double[32];
            double[] w = new Double[32];
            using (TextReader reader = File.OpenText("../../GaussLaguerre32.txt"))
            {
                for (int k = 0; k <= 31; k++)
                {
                    string   text = reader.ReadLine();
                    string[] bits = text.Split(' ');
                    x[k] = double.Parse(bits[0]);
                    w[k] = double.Parse(bits[1]);
                }
            }
            HParam param = new HParam();

            param.rho    = -0.9;                            // Heston Parameter: Correlation
            param.kappa  = 2;                               // Heston Parameter: Mean reversion speed
            param.theta  = 0.05;                            // Heston Parameter: Mean reversion level
            param.lambda = 0.0;                             // Heston Parameter: Risk parameter
            param.sigma  = 0.3;                             // Heston Parameter: Volatility of Variance
            param.v0     = 0.035;                           // Heston Parameter: Current Variance

            OpSet settings = new OpSet();

            settings.S       = 100.0;           // Spot Price
            settings.K       = 100.0;           // Strike Price
            settings.T       = 0.25;            // Maturity in Years
            settings.r       = 0.05;            // Interest Rate
            settings.q       = 0.02;            // Dividend yield
            settings.PutCall = "P";             // "P"ut or "C"all
            settings.trap    = 1;               // 1="Little Trap" characteristic function

            // The Heston price
            HestonPriceConsolidated HPC = new HestonPriceConsolidated();
            double Price = HPC.HestonPriceConsol(param, settings, x, w);

            Console.WriteLine("Heston price using consolidated integral");
            Console.WriteLine("------------------------------------------------ ");
            Console.WriteLine("Option Flavor =  {0,0:F5}", settings.PutCall);
            Console.WriteLine("Strike Price  =  {0,0:0}", settings.S);
            Console.WriteLine("Maturity      =  {0,0:F2}", settings.T);
            Console.WriteLine("Price         =  {0,0:F4}", Price);
            Console.WriteLine("------------------------------------------------ ");
            Console.WriteLine(" ");
        }
Пример #19
0
        // Price by simulation
        public double EulerMilsteinPrice(string scheme, string negvar, HParam param, OpSet settings, double alpha, int NT, int NS, string PutCall)
        {
            RandomNumbers RA = new RandomNumbers();

            double[] STe   = EulerMilsteinSim(scheme, negvar, param, settings, alpha, NT, NS);
            double[] Price = new double[NS];
            for (int s = 0; s <= NS - 1; s++)
            {
                if (settings.PutCall == "C")
                {
                    Price[s] = Math.Max(STe[s] - settings.K, 0.0);
                }
                else if (settings.PutCall == "P")
                {
                    Price[s] = Math.Max(settings.K - STe[s], 0.0);
                }
            }
            return(Math.Exp(-settings.r * settings.T) * RA.Mean(Price));
        }
Пример #20
0
        // Price by simulation
        public double QEPrice(HParam param, OpSet settings, double gamma1, double gamma2, int NT, int NS, int MC, double phic, string PutCall)
        {
            RandomNumbers RN = new RandomNumbers();

            double[] STe   = QESim(param, settings, gamma1, gamma2, NT, NS, MC, phic);
            double[] Price = new double[NS];
            for (int s = 0; s <= NS - 1; s++)
            {
                if (settings.PutCall == "C")
                {
                    Price[s] = Math.Max(STe[s] - settings.K, 0.0);
                }
                else if (settings.PutCall == "P")
                {
                    Price[s] = Math.Max(settings.K - STe[s], 0.0);
                }
            }
            return(Math.Exp(-settings.r * settings.T) * RN.Mean(Price));
        }
Пример #21
0
        // Price by simulation
        public double MMPrice(HParam param, OpSet settings, int NT, int NS)
        {
            RandomNumbers RN = new RandomNumbers();

            double[] STe   = MMSim(param, settings, NT, NS);
            double[] Price = new double[NS];
            for (int s = 0; s <= NS - 1; s++)
            {
                if (settings.PutCall == "C")
                {
                    Price[s] = Math.Max(STe[s] - settings.K, 0.0);
                }
                else if (settings.PutCall == "P")
                {
                    Price[s] = Math.Max(settings.K - STe[s], 0.0);
                }
            }
            return(Math.Exp(-settings.r * settings.T) * RN.Mean(Price));
        }
Пример #22
0
        // Heston Price by Gauss-Laguerre Integration =============================================================================================================
        public double HestonPriceGaussLaguerre(HParam param, double S, double K, double r, double q, double T, int trap, string PutCall, double[] X, double[] W)
        {
            Complex i = new Complex(0.0, 1.0);

            Complex[] f1   = new Complex[32];
            Complex[] f2   = new Complex[32];
            double[]  int1 = new double[32];
            double[]  int2 = new double[32];

            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                double phi = X[j];
                f1[j] = HestonCF(phi - i, param, S, r, q, T, trap) / (S * Math.Exp((r - q) * T));
                f2[j] = HestonCF(phi, param, S, r, q, T, trap);
                Complex FF1 = Complex.Exp(-i * phi * Complex.Log(K)) * f1[j] / i / phi;
                Complex FF2 = Complex.Exp(-i * phi * Complex.Log(K)) * f2[j] / i / phi;
                int1[j] = W[j] * FF1.Real;
                int2[j] = W[j] * FF2.Real;
            }

            // Define P1 and P2
            double pi = Math.PI;
            double P1 = 0.5 + 1.0 / pi * int1.Sum();
            double P2 = 0.5 + 1.0 / pi * int2.Sum();

            // The call price
            double HestonC = S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
        // Heston characteristic function (f2)
        public Complex HestonCF(Complex phi, HParam param, OpSet settings)
        {
            Complex i = new Complex(0.0, 1.0);                   // Imaginary unit
            double  S = settings.S;
            double  K = settings.K;
            double  T = settings.T;
            double  r = settings.r;
            double  q = settings.q;
            double  kappa = param.kappa;
            double  theta = param.theta;
            double  sigma = param.sigma;
            double  v0 = param.v0;
            double  rho = param.rho;
            double  lambda = param.lambda;
            double  x = Math.Log(S);
            double  a = kappa * theta;
            int     Trap = settings.trap;
            Complex b, u, d, g, c, D, G, C = new Complex();

            u = -0.5;
            b = kappa + lambda;
            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2) - sigma * sigma * (2.0 * u * i * phi - phi * phi));
            g = (b - rho * sigma * i * phi + d) / (b - rho * sigma * i * phi - d);
            if (Trap == 1)
            {
                // "Little Heston Trap" formulation
                c = 1.0 / g;
                D = (b - rho * sigma * i * phi - d) / sigma / sigma * ((1.0 - Complex.Exp(-d * T)) / (1.0 - c * Complex.Exp(-d * T)));
                G = (1.0 - c * Complex.Exp(-d * T)) / (1 - c);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi - d) * T - 2.0 * Complex.Log(G));
            }
            else
            {
                // Original Heston formulation.
                G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi + d) * T - 2.0 * Complex.Log(G));
                D = (b - rho * sigma * i * phi + d) / sigma / sigma * ((1.0 - Complex.Exp(d * T)) / (1.0 - g * Complex.Exp(d * T)));
            }

            // The characteristic function.
            return(Complex.Exp(C + D * v0 + i * phi * x));
        }
Пример #24
0
        // Heston Univariate characteristic function (f2)
        public Complex HestonCF(Complex phi, HParam param, OpSet settings)
        {
            Complex i = new Complex(0.0, 1.0);                 // Imaginary unit
            Complex S = new Complex(settings.S, 0.0);          // Spot Price
            Complex K = new Complex(settings.K, 0.0);          // Strike Price
            Complex T = new Complex(settings.T, 0.0);          // Maturity in years
            Complex r = new Complex(settings.r, 0.0);          // Interest rate
            Complex q = new Complex(settings.q, 0.0);          // Dividend yield
            Complex rho = new Complex(param.rho, 0.0);         // Heston parameter: correlation
            Complex kappa = new Complex(param.kappa, 0.0);     // Heston parameter: mean reversion speed
            Complex theta = new Complex(param.theta, 0.0);     // Heston parameter: mean reversion speed
            Complex lambda = new Complex(param.lambda, 0.0);   // Heston parameter: price of volatility risk
            Complex sigma = new Complex(param.sigma, 0.0);     // Heston parameter: volatility of variance
            Complex v0 = new Complex(param.v0, 0.0);           // Heston parameter: initial variance
            Complex x = Complex.Log(S);
            Complex a = kappa * theta;
            int     Trap = settings.trap;
            Complex b, u, d, g, c, D, G, C = new Complex();

            u = -0.5;
            b = kappa + lambda;
            d = Complex.Sqrt(Complex.Pow(rho * sigma * i * phi - b, 2) - sigma * sigma * (2.0 * u * i * phi - phi * phi));
            g = (b - rho * sigma * i * phi + d) / (b - rho * sigma * i * phi - d);
            if (Trap == 1)
            {
                // "Little Heston Trap" formulation
                c = 1.0 / g;
                D = (b - rho * sigma * i * phi - d) / sigma / sigma * ((1.0 - Complex.Exp(-d * T)) / (1.0 - c * Complex.Exp(-d * T)));
                G = (1.0 - c * Complex.Exp(-d * T)) / (1 - c);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi - d) * T - 2.0 * Complex.Log(G));
            }
            else
            {
                // Original Heston formulation.
                G = (1.0 - g * Complex.Exp(d * T)) / (1.0 - g);
                C = (r - q) * i * phi * T + a / sigma / sigma * ((b - rho * sigma * i * phi + d) * T - 2.0 * Complex.Log(G));
                D = (b - rho * sigma * i * phi + d) / sigma / sigma * ((1.0 - Complex.Exp(d * T)) / (1.0 - g * Complex.Exp(d * T)));
            }

            // The characteristic function.
            return(Complex.Exp(C + D * v0 + i * phi * x));
        }
Пример #25
0
        // Double integral using Gauss-Legendre
        public double DoubleGaussLegendre(double S0, double tau, HParam param, double K, double rf, double q, double b0, double b1,
                                          double[] xt, double[] wt, double[] xs, double[] ws, double a, double b, double c, double d, int funNum)
        {
            Complex i = new Complex(0.0, 1.0);
            int     Nt = xt.Length;
            int     Ns = xs.Length;
            double  h1 = (b - a) / 2.0;
            double  h2 = (b + a) / 2.0;
            double  k1 = (d - c) / 2.0;
            double  k2 = (d + c) / 2.0;
            double  time, phi, realfun, qr = 0.0;
            Complex fun;

            // Select rate or dividend
            if (funNum == 1)
            {
                qr = q;
            }
            else if (funNum == 2)
            {
                qr = rf;
            }
            double Int = 0.0;

            // Double integral
            CharFun CF = new CharFun();

            for (int t = 0; t <= Nt - 1; t++)
            {
                time = h1 * xt[t] + h2;
                for (int x = 0; x <= Ns - 1; x++)
                {
                    phi     = k1 * xs[x] + k2;
                    fun     = Complex.Exp(-b0 * i * phi) * CF.CZCharFun(S0, tau, time, param, K, rf, q, phi, -b1 * phi, funNum) / (i * phi);
                    realfun = Math.Exp(qr * time) * fun.Real;
                    Int    += h1 * k1 * wt[t] * ws[x] * realfun;
                }
            }
            return(Int);
        }
Пример #26
0
        // Heston Price by Gauss-Legendre Integration
        public double HestonPriceGaussLegendre(HParam param, OpSet settings, double[] x, double[] w, double a, double b)
        {
            double[] int1 = new Double[32];
            double[] int2 = new Double[32];
            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                double X = (a + b) / 2.0 + (b - a) / 2.0 * x[j];
                int1[j] = w[j] * HestonProb(X, param, settings, 1);
                int2[j] = w[j] * HestonProb(X, param, settings, 2);
            }

            // Define P1 and P2
            double pi = Math.PI;
            double P1 = 0.5 + 1.0 / pi * int1.Sum() * (b - a) / 2.0;
            double P2 = 0.5 + 1.0 / pi * int2.Sum() * (b - a) / 2.0;

            // The call price
            double S       = settings.S;
            double K       = settings.K;
            double T       = settings.T;
            double r       = settings.r;
            double q       = settings.q;
            string PutCall = settings.PutCall;
            double HestonC = S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
        // Heston Price by Gauss-Laguerre Integration
        public double HestonPriceGaussLaguerre(HParam param, OPSet settings, string PutCall, double T, int trap, double[] x, double[] w)
        {
            int Nx = x.Length;

            double[] int1 = new Double[Nx];
            double[] int2 = new Double[Nx];

            // Numerical integration
            for (int j = 0; j <= Nx - 1; j++)
            {
                int1[j] = w[j] * HestonProb(x[j], param, settings, T, trap, 1);
                int2[j] = w[j] * HestonProb(x[j], param, settings, T, trap, 2);
            }

            // Define P1 and P2
            double pi = Math.PI;
            double P1 = 0.5 + 1.0 / pi * int1.Sum();
            double P2 = 0.5 + 1.0 / pi * int2.Sum();

            // The call price
            double S       = settings.S;
            double K       = settings.K;
            double r       = settings.r;
            double q       = settings.q;
            double HestonC = S * Math.Exp(-q * T) * P1 - K * Math.Exp(-r * T) * P2;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * T) + K * Math.Exp(-r * T);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
Пример #28
0
        // The early exercise price using the composite trapezoidal rule

        public double CZEarlyExercise(double S0, double tau, HParam param, double K, double rf, double q,
                                      double[] xs, double[] ws, double[] xt, double[] wt, int Nt, double b0, double b1,
                                      double a, double b, double c, double d, string DoubleType)
        {
            DoubleIntegral DI = new DoubleIntegral();
            double         Int1 = 0.0, Int2 = 0.0;

            if (DoubleType == "GLe")
            {
                Int1 = DI.DoubleGaussLegendre(S0, tau, param, K, rf, q, b0, b1, xt, wt, xt, wt, a, b, c, d, 1);
                Int2 = DI.DoubleGaussLegendre(S0, tau, param, K, rf, q, b0, b1, xt, wt, xt, wt, a, b, c, d, 2);
            }
            else if (DoubleType == "Trapz")
            {
                double   ht = (b - a) / Nt;
                double   hs = (d - c) / Nt;
                double[] T  = new double[Nt + 1];
                double[] X  = new double[Nt + 1];
                for (int j = 0; j <= Nt; j++)
                {
                    T[j] = a + j * ht;
                    X[j] = c + j * hs;
                }

                Int1 = DI.DoubleTrapezoidal(param, S0, K, tau, rf, q, b0, b1, X, T, 1);
                Int2 = DI.DoubleTrapezoidal(param, S0, K, tau, rf, q, b0, b1, X, T, 2);
            }
            else
            {
                return(0.0);
            }

            // The early exercise premium
            double pi = Math.PI;
            double V1 = S0 * (1 - Math.Exp(-q * tau)) / 2 + (1 / pi) * S0 * q * Math.Exp(-q * tau) * Int1;
            double V2 = K * (1 - Math.Exp(-rf * tau)) / 2 + (1 / pi) * K * rf * Math.Exp(-rf * tau) * Int2;

            return(V1 - V2);
        }
Пример #29
0
        // Mikhailov-Nogel Price by Gauss-Laguerre Integration
        public double MNPriceGaussLaguerre(HParam param, double[,] param0, double tau, double[] tau0, OpSet settings, double[] x, double[] w)
        {
            double[] int1 = new Double[32];
            double[] int2 = new Double[32];

            // Numerical integration
            for (int j = 0; j <= 31; j++)
            {
                int1[j] = w[j] * HestonProbTD(x[j], param, param0, tau, tau0, settings, 1);
                int2[j] = w[j] * HestonProbTD(x[j], param, param0, tau, tau0, settings, 2);
            }

            // Define P1 and P2
            double pi = Math.PI;
            double P1 = 0.5 + 1.0 / pi * int1.Sum();
            double P2 = 0.5 + 1.0 / pi * int2.Sum();

            // The call price
            double S       = settings.S;
            double K       = settings.K;
            double r       = settings.r;
            double q       = settings.q;
            string PutCall = settings.PutCall;
            double HestonC = S * Math.Exp(-q * tau) * P1 - K * Math.Exp(-r * tau) * P2;

            // The put price by put-call parity
            double HestonP = HestonC - S * Math.Exp(-q * tau) + K * Math.Exp(-r * tau);

            // Output the option price
            if (PutCall == "C")
            {
                return(HestonC);
            }
            else
            {
                return(HestonP);
            }
        }
Пример #30
0
        // CIR moments
        public double[] CIRmoments(HParam param, double Vs, double dt)
        {
            double kappa = param.kappa;
            double theta = param.theta;
            double sigma = param.sigma;
            double v0    = param.v0;
            double rho   = param.rho;

            // E[vt | vs];
            double e = theta + (Vs - theta) * Math.Exp(-kappa * dt);

            // Var[vt | vs]
            double v = Vs * sigma * sigma * Math.Exp(-kappa * dt) / kappa * (1.0 - Math.Exp(-kappa * dt))
                       + theta * sigma * sigma / 2.0 / kappa * Math.Pow((1.0 - Math.Exp(-kappa * dt)), 2.0);

            // E[vt^2 | vs]
            double e2 = v + e * e;

            double[] output = new double[2];
            output[0] = e;
            output[1] = e2;
            return(output);
        }