예제 #1
0
        // Call price by Fractional Fast Fourier Transform =====================================================================
        public double[,] HestonFRFT(int N, double uplimit, double alpha, string rule, double lambdainc, double eta, HParam param, OpSet settings)
        {
            double s0 = Math.Log(settings.S);
            double pi = Math.PI;

            // Initialize and specify the weights
            double[] w = new double[N];
            if (rule == "Trapezoidal")
            {
                w[0]     = 0.5;
                w[N - 1] = 0.5;
                for (int j = 1; j <= N - 2; j++)
                {
                    w[j] = 1;
                }
            }
            else if (rule == "Simpsons")
            {
                w[0]     = 1.0 / 3.0;
                w[N - 1] = 1.0 / 3.0;
                for (int j = 1; j <= N - 1; j++)
                {
                    w[j] = (1.0 / 3.0) * (3 + Math.Pow(-1, j + 1));
                }
            }

            // Specify the b parameter
            double b = Convert.ToDouble(N) * lambdainc / 2.0;

            // Create the grid for the integration
            double[] v = new double[N];
            for (int j = 0; j <= N - 1; j++)
            {
                v[j] = eta * j;
            }

            // Create the grid for the log-strikes and strikes
            double[] k = new double[N];
            double[] K = new double[N];
            for (int j = 0; j <= N - 1; j++)
            {
                k[j] = -b + lambdainc * Convert.ToDouble(j) + s0;
                K[j] = Math.Exp(k[j]);
            }

            // Beta parameter for the FRFT
            double beta = lambdainc * eta / 2.0 / pi;

            // Option price settings
            double tau = settings.T;
            double r   = settings.r;
            double q   = settings.q;

            // Implement the FFT
            Complex i = new Complex(0.0, 1.0);

            Complex[] psi      = new Complex[N];
            Complex[] phi      = new Complex[N];
            Complex[] x        = new Complex[N];
            Complex[] y        = new Complex[N];
            double[]  CallFRFT = new double[N];
            double[]  sume     = new double[N];

            // Build the input vectors for the FRFT
            HestonPrice HP = new HestonPrice();

            for (int j = 0; j <= N - 1; j++)
            {
                psi[j] = HP.HestonCF(v[j] - (alpha + 1.0) * i, param, settings);
                phi[j] = Complex.Exp(-r * tau) * psi[j] / (alpha * alpha + alpha - v[j] * v[j] + i * v[j] * (2.0 * alpha + 1.0));
                x[j]   = Complex.Exp(i * (b - s0) * v[j]) * phi[j] * w[j];
            }
            y = FRFT(x, beta);
            Complex Call = new Complex(0.0, 0.0);

            for (int u = 0; u <= N - 1; u++)
            {
                Call        = eta * Complex.Exp(-alpha * k[u]) * y[u] / pi;
                CallFRFT[u] = Call.Real;
            }

            // Return the FRFT call price and the strikes
            double[,] output = new double[N, 2];
            for (int j = 0; j <= N - 1; j++)
            {
                output[j, 0] = K[j];
                output[j, 1] = CallFRFT[j];
            }
            return(output);
        }
예제 #2
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]);
                }
            }
            // Heston parameters
            HParam param = new HParam();

            param.kappa  = 0.2;
            param.theta  = 0.05;
            param.sigma  = 0.3;
            param.v0     = 0.05;
            param.rho    = -0.7;
            param.lambda = 0.0;

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

            settings.S       = 50.0;
            settings.T       = 0.5;
            settings.r       = 0.03;
            settings.q       = 0.05;
            settings.PutCall = "C";
            settings.trap    = 1;

            // FFT settings
            double M       = Math.Pow(2, 10);
            int    N       = Convert.ToInt16(M);
            double alpha   = 1.5;
            double uplimit = 100.0;
            string rule;

            // Set the integration increment
            double eta = 1e-2;

            // Set the log-strike increment
            double lambdainc = 1e-2;

            // Alternative: Set the log-strike increment so that the strike range is Spot +/ 5
            //double lambdainc = 2.0/M*Math.Log(settings.S/(settings.S - 5.0));

            // Obtain the FFT strikes and calls using the Trapezoidal rule
            HFRFT FRFT = new HFRFT();

            double[,] PriceTrapz = new double[N, 2];
            rule       = "Trapezoidal";
            PriceTrapz = FRFT.HestonFRFT(N, uplimit, alpha, rule, lambdainc, eta, param, settings);

            // Obtain the FFT strikes and calls using Simpson's rule
            double[,] PriceSimps = new double[N, 2];
            rule       = "Simpsons";
            PriceSimps = FRFT.HestonFRFT(N, uplimit, alpha, rule, lambdainc, eta, param, settings);

            // Obtain the extact price and compare to FFT price
            HestonPrice HP = new HestonPrice();

            double[] PriceHeston = new double[N];
            double[] ErrorTrapz  = new double[N];
            double[] ErrorSimps  = new double[N];
            for (int j = 0; j <= N - 1; j++)
            {
                settings.K     = PriceTrapz[j, 0];
                PriceHeston[j] = HP.HestonPriceGaussLaguerre(param, settings, x, w);
                ErrorTrapz[j]  = (PriceTrapz[j, 1] - PriceHeston[j]) / PriceHeston[j] * 100.0;
                ErrorSimps[j]  = (PriceSimps[j, 1] - PriceHeston[j]) / PriceHeston[j] * 100.0;
            }

            // Output the results near the money
            int start = N / 2 - 3;
            int end   = N / 2 + 3;

            Console.WriteLine("FRFT strike range from {0:F2} to {1:F2}", PriceTrapz[0, 0], PriceTrapz[N - 1, 0]);
            Console.WriteLine();
            Console.WriteLine("Sample Strikes");
            Console.WriteLine("---------------------------------------------------------------------------");
            Console.WriteLine("Strike        Exact     FRFT Trapz  FRFT Simpson  %ErrorTrapz  %ErrorSimpson");
            Console.WriteLine("---------------------------------------------------------------------------");
            for (int j = start; j <= end; j++)
            {
                Console.WriteLine("{0:F4} {1,12:F4} {2,12:F4} {3,12:F4} {4,12:F4} {5,12:F4}", PriceTrapz[j, 0], PriceHeston[j], PriceTrapz[j, 1], PriceSimps[j, 1], ErrorTrapz[j], ErrorSimps[j]);
            }
            Console.WriteLine("---------------------------------------------------------------------------");
            Console.WriteLine("Integration increment {0:F10}", eta);
            Console.WriteLine("Log strike increment {0:F10}", lambdainc);
        }