Ejemplo n.º 1
0
        // Golden Section search form Heston
        public double GoldenSearchMS(double a, double b, double tol, int MaxIter, double K, HParam param, double theta, double r, double q, double T, int NumTerms)
        {
            MSExpansionHeston MS = new MSExpansionHeston();
            double            x1, x2, x3, x4, f1, f2, f3, f4;
            double            GR = (Math.Sqrt(5.0) - 1.0) / 2.0;
            int k = 0;

            while (Math.Abs(b - a) > tol)
            {
                k  = k + 1;
                x1 = a;
                x2 = a + (1.0 - GR) * (b - a);
                x3 = a + GR * (b - a);
                x4 = b;
                f1 = -MS.MSPutHeston(x1, theta, K, param, r, q, T, NumTerms);
                f2 = -MS.MSPutHeston(x2, theta, K, param, r, q, T, NumTerms);
                f3 = -MS.MSPutHeston(x3, theta, K, param, r, q, T, NumTerms);
                f4 = -MS.MSPutHeston(x4, theta, K, param, r, q, T, NumTerms);
                if ((f1 > f2) & (f2 < f3))
                {
                    b = x3;
                }
                else if ((f2 > f3) & (f3 < f4))
                {
                    a = x2;
                }
                if (k > MaxIter)
                {
                    break;
                }
            }
            return((a + b) / 2.0);
        }
        public double[] MSPriceHeston(HParam param, OpSet opset, MSSet msset)
        {
            // param  = Heston parameters
            // opset  = option settings
            // msset  = Medvedev-Scaillet expansion settings

            // Extract quantities from the option settings
            double K  = opset.K;
            double S  = opset.S;
            double v0 = param.v0;
            double T  = opset.T;
            double r  = opset.r;
            double q  = opset.q;

            // Extract quantities from the MS structure
            int    N        = msset.N;
            double a        = msset.a;
            double b        = msset.b;
            double A        = msset.A;
            double B        = msset.B;
            double dt       = msset.dt;
            double tol      = msset.tol;
            int    MaxIter  = msset.MaxIter;
            int    NumTerms = msset.NumTerms;
            double yinf     = msset.yinf;
            int    method   = msset.method;

            // Closed-form European put
            NewtonCotes NC            = new NewtonCotes();
            double      EuroPutClosed = NC.HestonPriceNewtonCotes(param, opset, method, A, B, N);

            // Moneyness
            double theta = Math.Log(K / S) / Math.Sqrt(v0) / Math.Sqrt(T);

            // Find the barrier level
            // Bisection method to find y
            // a = Math.Max(1.25,0.95*theta);
            // b = 3.0;
            // double y = BisectionMS(a,b,theta,K,param,r,q,T,NumTerms,tol,MaxIter,dt);

            // Golden section search method to find y
            GoldenSearch GS = new GoldenSearch();

            a = 1.5;
            b = 2.5;
            double y = GS.GoldenSearchMS(a, b, tol, MaxIter, K, param, theta, r, q, T, NumTerms);

            if (y < theta)
            {
                y = theta;
            }

            // Find the early exercise premium
            MSExpansionHeston MS        = new MSExpansionHeston();
            double            AmerPutMS = MS.MSPutHeston(y, theta, K, param, r, q, T, NumTerms);
            double            EuroPutMS = MS.MSPutHeston(yinf, theta, K, param, r, q, T, NumTerms);
            double            EEP       = AmerPutMS - EuroPutMS;

            // Control variate American put
            double AmerPut = EuroPutClosed + EEP;

            // Output the results
            double[] output = new double[6];
            output[0] = EuroPutClosed;
            output[1] = AmerPutMS;
            output[2] = AmerPut;      // Medvedev and Scaillet recommend this one.
            output[3] = EEP;
            output[4] = theta;
            output[5] = y;
            return(output);
        }
        public double MSGreeksFD(HParam param, OpSet opset, int method, double A, double B, int N, double hi, double tol, int MaxIter, int NumTerms, double yinf, string Greek)
        {
            MSExpansionHeston MS = new MSExpansionHeston();

            double[] output = new double[6];
            double   AmerPut, AmerPutp, AmerPutm;
            double   AmerPutpp, AmerPutpm, AmerPutmp, AmerPutmm;

            double S  = opset.S;
            double v0 = param.v0;
            double T  = opset.T;

            // Define the finite difference increments
            double ds = opset.S * 0.005;
            double dt = opset.T * 0.005;
            double dv = param.v0 * 0.005;

            if (Greek == "price")
            {
                output  = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPut = output[2];
                return(AmerPut);
            }
            else if ((Greek == "delta") || (Greek == "gamma"))
            {
                opset.S  = S + ds;
                output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutp = output[2];
                opset.S  = S - ds;
                output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutm = output[2];
                if (Greek == "gamma")
                {
                    opset.S = S;
                    output  = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                    AmerPut = output[2];
                    return((AmerPutp - 2.0 * AmerPut + AmerPutm) / ds / ds);
                }
                else
                {
                    return((AmerPutp - AmerPutm) / 2.0 / ds);
                }
            }
            else if (Greek == "theta")
            {
                opset.T  = T + dt;
                output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutp = output[2];
                opset.T  = T - dt;
                output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutm = output[2];
                return(-(AmerPutp - AmerPutm) / 2.0 / dt);
            }
            else if ((Greek == "vega1") || (Greek == "volga"))
            {
                param.v0 = v0 + dv;
                output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutp = output[2];
                param.v0 = v0 - dv;
                output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutm = output[2];
                double Vega1 = (AmerPutp - AmerPutm) / 2.0 / dv * 2.0 * Math.Sqrt(v0);
                if (Greek == "volga")
                {
                    param.v0 = v0;
                    output   = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                    AmerPut  = output[2];
                    double dC2 = (AmerPutp - 2.0 * AmerPut + AmerPutm) / dv / dv;
                    return(4.0 * Math.Sqrt(v0) * (dC2 * Math.Sqrt(v0) + Vega1 / 4.0 / v0));
                }
                else
                {
                    return(Vega1);
                }
            }
            else if (Greek == "vanna")
            {
                opset.S   = S + ds;
                param.v0  = v0 + dv;
                output    = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutpp = output[2];
                param.v0  = v0 - dv;
                output    = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutpm = output[2];
                opset.S   = S - ds;
                param.v0  = v0 + dv;
                output    = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutmp = output[2];
                param.v0  = v0 - dv;
                output    = MS.MSPrice(param, opset, method, A, B, N, hi, tol, MaxIter, NumTerms, yinf);
                AmerPutmm = output[2];
                return((AmerPutpp - AmerPutpm - AmerPutmp + AmerPutmm) / 4.0 / dv / ds * 2.0 * Math.Sqrt(v0));
            }
            else
            {
                return(0.0);
            }
        }
        // Derivative of the MS approximation
        public double MSPutHestonDiff(double y, double theta, double Strike, HParam param, double r, double q, double T, int NumTerms, double dy)
        {
            MSExpansionHeston MS = new MSExpansionHeston();

            return((MS.MSPutHeston(y + dy, theta, Strike, param, r, q, T, NumTerms) - MS.MSPutHeston(y - dy, theta, Strike, param, r, q, T, NumTerms)) / 2.0 / dy);
        }