Ejemplo n.º 1
0
        // Call price by Fractional Fast Fourier Transform =====================================================================
        public double[,] HestonFRFTGreek(int N, double uplimit, double alpha, string rule, double lambdainc, double eta, HParam param, OpSet settings, string Greek)
        {
            HestonGreeks HG = new HestonGreeks();

            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
            for (int j = 0; j <= N - 1; j++)
            {
                psi[j] = HG.HestonCFGreek(v[j] - (alpha + 1.0) * i, param, settings, Greek);
                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);
        }
Ejemplo n.º 2
0
        static void Main(string[] args)
        {
            FastFT        FaFT  = new FastFT();
            FractionalFFT FrFFT = new FractionalFFT();
            HestonGreeks  HG    = new HestonGreeks();

            // 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  = 2.0;
            param.theta  = 0.06;
            param.sigma  = 0.1;
            param.v0     = 0.06;
            param.rho    = -0.7;
            param.lambda = 0.0;

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

            settings.S       = 100.0;
            settings.T       = 0.5;
            settings.r       = 0.05;
            settings.q       = 0.0;
            settings.PutCall = "C";
            settings.trap    = 1;

            // FFT settings
            double N2      = 9.0;
            double M       = Math.Pow(2.0, N2);
            int    N       = Convert.ToInt16(M);
            double alpha   = 1.5;
            double uplimit = 100.0;
            string rule    = "Simpsons";

            // Greeks by the FFT or FRFT
            string method    = "FRFT";
            double eta       = 0.1;
            double lambdainc = 0.005;

            string[] Greek = { "Price", "Delta", "Gamma", "Theta", "Rho", "Vega1", "Vanna", "Volga" };
            double[,] GreeksFFT = new double[N, 8];
            double[,] FFT       = new double[N, 2];
            for (int j = 0; j <= 7; j++)
            {
                if (method == "FFT")
                {
                    FFT = FaFT.HestonFFTGreek(N, uplimit, alpha, rule, param, settings, Greek[j]);
                }
                else
                {
                    FFT = FrFFT.HestonFRFTGreek(N, uplimit, alpha, rule, lambdainc, eta, param, settings, Greek[j]);
                }
                for (int k = 0; k <= N - 1; k++)
                {
                    GreeksFFT[k, j] = FFT[k, 1];
                }
            }
            double[] K = new double[N];
            for (int k = 0; k <= N - 1; k++)
            {
                K[k] = FFT[k, 0];
            }

            // Select results near the money
            int start = N / 2 - 3;
            int end   = N / 2 + 3;
            int Nm    = end - start + 1;

            double[,] Greeks = new double[Nm, 8];
            double[] Strike = new double[Nm];
            for (int k = 0; k <= Nm - 1; k++)
            {
                Strike[k] = K[start + k];
                for (int j = 0; j <= 7; j++)
                {
                    Greeks[k, j] = GreeksFFT[start + k, j];
                }
            }

            // Adjust the FFT Greeks vega1 and vanna for v0
            for (int k = 0; k <= Nm - 1; k++)
            {
                Greeks[k, 5] *= 2.0 * Math.Sqrt(param.v0);
                Greeks[k, 6] *= 2.0 * Math.Sqrt(param.v0);
            }

            // Closed-form Greeks near the money and errors
            double[,] GreeksClosed = new double[Nm, 8];
            double[] SumAbsError = new double[8];
            for (int j = 0; j <= 7; j++)
            {
                for (int k = 0; k <= Nm - 1; k++)
                {
                    settings.K         = Strike[k];
                    GreeksClosed[k, j] = HG.CarrMadanGreeks(alpha, settings.T, param, settings, Greek[j], x, w);
                    SumAbsError[j]    += Math.Abs(GreeksClosed[k, j] - Greeks[k, j]);
                }
            }

            // Output the results near the money
            Console.WriteLine("-----------------------------------------------------------------------------");
            Console.WriteLine("              Call             Delta              Gamma            Theta");
            Console.WriteLine("Strike   FFT       CM      FFT       CM       FFT       CM     FFT       CM");
            Console.WriteLine("-----------------------------------------------------------------------------");
            for (int k = 0; k <= Nm - 1; k++)
            {
                Console.WriteLine("{0,6:F2} {1,8:F3} {2,8:F3} {3,8:F3} {4,8:F3} {5,8:F3} {6,8:F3} {7,8:F3} {8,8:F3}", Strike[k],
                                  Greeks[k, 0], GreeksClosed[k, 0],
                                  Greeks[k, 1], GreeksClosed[k, 1],
                                  Greeks[k, 2], GreeksClosed[k, 2],
                                  Greeks[k, 3], GreeksClosed[k, 3]);
            }
            Console.WriteLine("Error {0,15:E3} {1,17:E3} {2,17:E3} {3,17:E3}", SumAbsError[0], SumAbsError[1], SumAbsError[2], SumAbsError[3]);
            Console.WriteLine("-----------------------------------------------------------------------------");
            Console.WriteLine("              Rho              Vega1              Vanna            Volga");
            Console.WriteLine("Strike   FFT       CM      FFT       CM       FFT       CM     FFT       CM");
            Console.WriteLine("-----------------------------------------------------------------------------");
            for (int k = 0; k <= Nm - 1; k++)
            {
                Console.WriteLine("{0,6:F2} {1,8:F3} {2,8:F3} {3,8:F3} {4,8:F3} {5,8:F3} {6,8:F3} {7,8:F3} {8,8:F3}", Strike[k],
                                  Greeks[k, 4], GreeksClosed[k, 4],
                                  Greeks[k, 5], GreeksClosed[k, 5],
                                  Greeks[k, 6], GreeksClosed[k, 6],
                                  Greeks[k, 7], GreeksClosed[k, 7]);
            }
            Console.WriteLine("Error {0,15:E3} {1,17:E3} {2,17:E3} {3,17:E3}", SumAbsError[4], SumAbsError[5], SumAbsError[6], SumAbsError[7]);
            Console.WriteLine("-----------------------------------------------------------------------------");
        }