Handles the calculation of the call prices on a given Heston model instance.
Inheritance: IIntegrable
コード例 #1
0
        /// <summary>
        /// Test method, displays a sensitivity on heston call and put prices.
        /// </summary>
        private void PutCallTest()
        {
            Console.WriteLine("Black-Sholes Calls Market Prices");
            Console.WriteLine(this.callMarketPrice);
            Console.WriteLine("Strikes");
            Console.WriteLine(this.strike);
            Console.WriteLine("Maturities");
            Console.WriteLine(this.maturity);

            var x = new Vector()
            {
                3.18344026504981,
                0.0427882999286046,
                0.644527074840708,
                -0.659960749691282,
                0.0150455464938991,
                0.0211747510984717
            };

            HestonCall hc = new HestonCall(this, x, this.s0);

            hc.T    = .1;
            hc.rate = this.rate[0];
            Console.WriteLine("Strike\tCall\tPut");
            for (int z = 200; z < 6500; z += 1000)
            {
                hc.K = z;

                var call    = hc.HestonCallPrice();
                var put     = hc.HestonPutPrice();
                var callPut = hc.HestonCallPutPrice();
                Console.WriteLine(z + "\t" + callPut[0] + "\t" + callPut[1]);
            }
        }
コード例 #2
0
        public void Test()
        {
            double k = 0.9;
            double tau = 2.0;

            double rate = 0.1;
            double dy = 0.07;
            double kappa = 2.5;
            double theta = 0.4;
            double sigma = 0.2;
            double s0 = 1.0;
            double v0 = 0.3;
            double rho = -0.8;

            // Calculates the theoretical value of the call.
            Vector param = new Vector(5);
            param[0] = kappa;
            param[1] = theta;
            param[2] = sigma;
            param[3] = rho;
            param[4] = v0;
            HestonCall hestonCall = new HestonCall();
            double fairmatPrice = hestonCall.HestonCallPrice(param, s0, tau, k, rate, dy);
            double tol = 1e-9;
            double benchmarkPrice = 0.339537359104676;

            Console.WriteLine("Theoretical Benchmark  Price = " + benchmarkPrice.ToString());
            Console.WriteLine("Theoretical Fairmat    Price = " + fairmatPrice);

            Assert.Less(Math.Abs(fairmatPrice - benchmarkPrice), tol);
        }
コード例 #3
0
        /// <summary>
        /// Calculates a single row of the objective function. Basically
        /// options with the same maturity and different strikes.
        /// </summary>
        /// <param name='context'>
        /// An object of type <see cref="HestonCall"/> containing the context.
        /// </param>
        private void CalculateSingleRow(object context)
        {
            CalculateSingleRowWithInterpolation(context);
            return;

            HestonCall hc = context as HestonCall;

            int r = hc.row;

            for (int c = 0; c < this.callMarketPrice.C; c++)
            {
                bool callCondition = this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0;
                bool putCondition  = this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0;
                if (callCondition)//||putCondition)
                {
                    hc.K = this.strike[c];
                    var callPut = hc.HestonCallPutPrice();
                    hc.hestonCallPrice[r, c] = callPut[0];
                    hc.hestonPutPrice[r, c]  = callPut[1];

                    if (callCondition)
                    {
                        if (HestonCallOptimizationProblem.optimizeRelativeError)
                        {
                            double mkt   = pricingMin + this.callMarketPrice[r, c];
                            double model = pricingMin + hc.hestonCallPrice[r, c];
                            hc.sum += callWeight[r, c] * Math.Pow((model - mkt) / mkt, 2);
                        }
                        else
                        {
                            hc.sum += callWeight[r, c] * Math.Pow(hc.hestonCallPrice[r, c] - this.callMarketPrice[r, c], 2);
                        }
                    }

                    /*
                     * if (putCondition)
                     * {
                     *  if (HestonCallOptimizationProblem.optimizeRelativeError)
                     *  {
                     *      double mkt = pricingMin + this.cpmd.PutPrice[r, c];
                     *      double model = pricingMin + hc.hestonPutPrice[r, c];
                     *      hc.sum += putWeight[r,c] * Math.Pow((model - mkt) / mkt, 2);
                     *  }
                     *  else
                     *  {
                     *      hc.sum += putWeight[r,c]* Math.Pow(hc.hestonPutPrice[r, c] - this.cpmd.PutPrice[r, c], 2);
                     *  }
                     * }
                     */
                }
            }
            return;
        }
コード例 #4
0
ファイル: TestHeston.cs プロジェクト: fairmat/EquityModels
        public void Test()
        {
            Engine.MultiThread = true;
            Document doc = new Document();
            ProjectROV rov = new ProjectROV(doc);
            doc.Part.Add(rov);
            doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;

            int n_sim = 50000;
            int n_steps = 512;
            double strike = 100.0;
            double tau = 5.0;
            double rate = 0.1;
            double dy = 0.07;

            ModelParameter pStrike = new ModelParameter(strike, "strike");
            pStrike.VarName = "strike";
            rov.Symbols.Add(pStrike);

            ModelParameter pRate = new ModelParameter(rate, "rfrate");
            pRate.VarName = "rfrate";
            rov.Symbols.Add(pRate);

            AFunction payoff = new AFunction(rov);
            payoff.VarName = "payoff";
            payoff.m_IndependentVariables = 1;
            payoff.m_Value = (RightValue)("max(x1 - strike ; 0)");
            rov.Symbols.Add(payoff);

            HestonProcess process = new HestonProcess();
            process.r = (ModelParameter)rate;
            process.q = (ModelParameter)dy;
            process.k = (ModelParameter)2.5;
            process.theta = (ModelParameter)0.4;
            process.sigma = (ModelParameter)0.2;
            process.S0 = (ModelParameter)100.0;
            process.V0 = (ModelParameter)0.3;

            StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);
            rov.Processes.AddProcess(s);

            // Set the discounting.
            RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;
            rfi.ActualizationType = EActualizationType.RiskFree;
            rfi.m_deterministicRF = rate;

            OptionTree op = new OptionTree(rov);
            op.PayoffInfo.PayoffExpression = "payoff(v1a)";
            op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)tau;
            op.PayoffInfo.European = true;
            rov.Map.Root = op;

            rov.NMethods.Technology = ETechType.T_SIMULATION;
            rov.NMethods.PathsNumber = n_sim;
            rov.NMethods.SimulationSteps = n_steps;

            ROVSolver solver = new ROVSolver();
            solver.BindToProject(rov);
            solver.DoValuation(-1);

            if (rov.HasErrors)
            {
                Console.WriteLine(rov.m_RuntimeErrorList[0]);
            }

            Assert.IsFalse(rov.HasErrors);

            ResultItem price = rov.m_ResultList[0] as ResultItem;

            double samplePrice = price.value;
            double sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);

            // Calculates the theoretical value of the call.
            Vector param = new Vector(5);
            param[0] = process.k.V();
            param[1] = process.theta.V();
            param[2] = process.sigma.V();
            param[3] = 0.0;
            param[4] = process.V0.V();
            HestonCall hestonCall = new HestonCall();
            double thPrice = hestonCall.HestonCallPrice(param, process.S0.V(),
                                                        tau, strike, rate, dy);
            Console.WriteLine("Theoretical Price = " + thPrice.ToString());
            Console.WriteLine("Monte Carlo Price = " + samplePrice);
            Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
            double tol = 4.0 * sampleDevSt;

            Assert.Less(Math.Abs(thPrice - samplePrice), tol);
        }
コード例 #5
0
        /// <summary>
        /// Test method, displays a sensitivity on heston call and put prices.
        /// </summary>
        private void PutCallTest()
        {
            Console.WriteLine("Black-Sholes Calls Market Prices");
            Console.WriteLine(this.callMarketPrice);
            Console.WriteLine("Strikes");
            Console.WriteLine(this.strike);
            Console.WriteLine("Maturities");
            Console.WriteLine(this.maturity);

            var x = new Vector() {3.18344026504981,
                0.0427882999286046,
                0.644527074840708,
                -0.659960749691282,
                0.0150455464938991,
                0.0211747510984717};

            HestonCall hc = new HestonCall(this, x, this.s0);
            hc.T = .1;
            hc.rate = this.rate[0];
            Console.WriteLine("Strike\tCall\tPut");
            for (int z = 200; z < 6500; z += 1000)
            {
                hc.K = z;

                var call = hc.HestonCallPrice();
                var put = hc.HestonPutPrice();
                var callPut = hc.HestonCallPutPrice();
                Console.WriteLine(z + "\t" + callPut[0] + "\t" + callPut[1]);
            }
        }
コード例 #6
0
        /// <summary>
        /// Calibration objective function.
        /// </summary>
        /// <param name='x'>
        /// The vector of parameters.
        /// </param>
        /// <returns>
        /// Objective function value.
        /// </returns>
        public virtual double Obj(DVPLI.Vector x)
        {
            double sum = 0;
            if(Engine.MultiThread && !displayObjInfo)
            {
                // Instantiate parallel computation if enabled.
                List<Task> tl = new List<Task>();

                // Context contains both input parameters and outputs.
                List<HestonCall> context = new List<HestonCall>();
                for (int r = 0; r < this.callMarketPrice.R; r++)
                {
                    if (this.maturity[r] >= this.matBound[0])
                    {
                        HestonCall hc = new HestonCall(this, x, this.s0);
                        context.Add(hc);

                        hc.T = this.maturity[r];
                        hc.rate = this.rate[r];
                        if (HestonConstantDriftEstimator.impliedDividends)
                            hc.dividend = x[Range.End];
                        else
                            hc.dividend = this.dividendYield[r];
                        hc.row = r;
                        tl.Add(Task.Factory.StartNew(this.CalculateSingleRow, hc));
                    }
                }

                tsScheduler.WaitTaskList(tl);
                for (int r = 0; r < tl.Count; r++)
                        sum += context[r].sum;
            }
            else
            {
                // Sequential version of the code, used when parallel computation is disabled.
                HestonCall hc = new HestonCall(this, x, this.s0);
                for (int r = 0; r < this.callMarketPrice.R; r++)
                {
                    if (this.maturity[r] >= this.matBound[0])
                    {
                        hc.T = this.maturity[r];
                        hc.rate = this.rate[r];
                        if (HestonConstantDriftEstimator.impliedDividends)
                            hc.dividend = x[Range.End];
                        else
                            hc.dividend = this.dividendYield[r];
                        hc.row = r;
                        hc.sum = 0;
                        this.CalculateSingleRow(hc);
                        sum += hc.sum;
                    }
                }

                var pricingErrors = hc.hestonCallPrice - this.callMarketPrice;
                if (displayObjInfo)
                {
                    avgPricingError = 0;
                    for (int r = 0; r < this.callMarketPrice.R; r++)
                        if (this.maturity[r] >= this.matBound[0])
                        {
                            for (int c = 0; c < this.callMarketPrice.C; c++)
                            {
                                if (this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0)
                                    avgPricingError += Math.Abs(pricingErrors[r, c]);
                                //if (this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0)
                                //    avgPricingError += Math.Abs(pricingErrors[r, c]);
                            }
                        }
                        avgPricingError /= numCall;

                    int RR = Math.Min(12, this.callMarketPrice.R - 1);
                    int CC = Math.Min(12, this.callMarketPrice.C - 1);
                    Console.WriteLine("Mkt Price");
                    Console.WriteLine(this.callMarketPrice[Range.New(0,RR),Range.New(0,CC)]);
                    Console.WriteLine("Pricing Errors");
                    Console.WriteLine(pricingErrors[Range.New(0, RR), Range.New(0, CC)]);
                }
                objCount++;
            }

            //Calculate average distance...
            sum = Math.Sqrt( sum /this.totalVolume);
            if (this.useBoundPenalty)
                sum += this.BoundPenalty(x);

            if (this.useFellerPenalty)
                sum +=this.FellerPenalty(x);

            return sum;
        }
コード例 #7
0
        /// <summary>
        /// Calculates call put prices for several strikes using controlled interpolation.
        /// </summary>
        /// <param name="context"></param>
        private void CalculateSingleRowWithInterpolation(object context)
        {
            HestonCall hc = context as HestonCall;
            int        r  = hc.row;

            hc.sum = 0;

            // Finds upper extreme for call and put
            int max_c = 0;

            for (int c = this.callMarketPrice.C - 1; c > 0; c--)
            {
                bool callCondition = this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0;
                bool putCondition  = this.cpmd.PutPrice != null && this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0;
                if (callCondition || putCondition)
                {
                    max_c = c;
                    break;
                }
            }


            var strikes = new List <double>();
            var calls   = new List <double>();
            var puts    = new List <double>();

            //Evaluates in strategic points
            for (int c = 0; c < this.callMarketPrice.C; c++)
            {
                bool callCondition = this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0;
                bool putCondition  = this.cpmd.PutPrice != null && this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0;
                if (callCondition || putCondition)
                {
                    hc.K = this.strike[c];
                    var callPut = hc.HestonCallPutPrice();
                    strikes.Add(hc.K);
                    calls.Add(callPut[0]);
                    puts.Add(callPut[1]);
                    if (c == max_c)
                    {
                        break;
                    }

                    c += 1;//skip the subsequent strikes

                    if (c > max_c)
                    {
                        c = max_c;
                    }
                }
            }

            // Builds interpolated call and put values.

            var callFun = new PFunction((Vector)strikes.ToArray(), (Vector)calls.ToArray());

            callFun.m_Function.iType = DVPLUtils.EInterpolationType.SPLINE;

            var putFun = new PFunction((Vector)strikes.ToArray(), (Vector)puts.ToArray());

            putFun.m_Function.iType = DVPLUtils.EInterpolationType.SPLINE;

            // Evaluates at the requested strikes

            for (int c = 0; c < this.callMarketPrice.C; c++)
            {
                bool callCondition = this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0;
                bool putCondition  = this.cpmd.PutPrice != null && this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0;


                if (callCondition)
                {
                    hc.hestonCallPrice[r, c] = callFun.Evaluate(this.strike[c]);
                    if (HestonCallOptimizationProblem.optimizeRelativeError)
                    {
                        double mkt   = pricingMin + this.callMarketPrice[r, c];
                        double model = pricingMin + hc.hestonCallPrice[r, c];
                        hc.sum += callWeight[r, c] * Math.Pow((model - mkt) / mkt, 2);
                    }
                    else
                    {
                        hc.sum += callWeight[r, c] * Math.Pow(hc.hestonCallPrice[r, c] - this.callMarketPrice[r, c], 2);
                    }
                }

                if (putCondition)
                {
                    hc.hestonPutPrice[r, c] = putFun.Evaluate(this.strike[c]);
                    if (HestonCallOptimizationProblem.optimizeRelativeError)
                    {
                        double mkt   = pricingMin + this.cpmd.PutPrice[r, c];
                        double model = pricingMin + hc.hestonPutPrice[r, c];
                        hc.sum += putWeight[r, c] * Math.Pow((model - mkt) / mkt, 2);
                    }
                    else
                    {
                        hc.sum += putWeight[r, c] * Math.Pow(hc.hestonPutPrice[r, c] - this.cpmd.PutPrice[r, c], 2);
                    }
                }
            }

            return;
        }
コード例 #8
0
        /// <summary>
        /// Calibration objective function.
        /// </summary>
        /// <param name='x'>
        /// The vector of parameters.
        /// </param>
        /// <returns>
        /// Objective function value.
        /// </returns>
        public virtual double Obj(DVPLI.Vector x)
        {
            double sum = 0;

            if (Engine.MultiThread && !displayObjInfo)
            {
                // Instantiate parallel computation if enabled.
                List <Task> tl = new List <Task>();

                // Context contains both input parameters and outputs.
                List <HestonCall> context = new List <HestonCall>();
                for (int r = 0; r < this.callMarketPrice.R; r++)
                {
                    if (this.maturity[r] >= this.matBound[0])
                    {
                        HestonCall hc = new HestonCall(this, x, this.s0);
                        context.Add(hc);

                        hc.T    = this.maturity[r];
                        hc.rate = this.rate[r];
                        if (HestonConstantDriftEstimator.impliedDividends)
                        {
                            hc.dividend = x[Range.End];
                        }
                        else
                        {
                            hc.dividend = this.dividendYield[r];
                        }
                        hc.row = r;
                        tl.Add(Task.Factory.StartNew(this.CalculateSingleRow, hc));
                    }
                }

                tsScheduler.WaitTaskList(tl);
                for (int r = 0; r < tl.Count; r++)
                {
                    sum += context[r].sum;
                }
            }
            else
            {
                // Sequential version of the code, used when parallel computation is disabled.
                HestonCall hc = new HestonCall(this, x, this.s0);
                for (int r = 0; r < this.callMarketPrice.R; r++)
                {
                    if (this.maturity[r] >= this.matBound[0])
                    {
                        hc.T    = this.maturity[r];
                        hc.rate = this.rate[r];
                        if (HestonConstantDriftEstimator.impliedDividends)
                        {
                            hc.dividend = x[Range.End];
                        }
                        else
                        {
                            hc.dividend = this.dividendYield[r];
                        }
                        hc.row = r;
                        hc.sum = 0;
                        this.CalculateSingleRow(hc);
                        sum += hc.sum;
                    }
                }

                var pricingErrors = hc.hestonCallPrice - this.callMarketPrice;
                if (displayObjInfo)
                {
                    avgPricingError = 0;
                    for (int r = 0; r < this.callMarketPrice.R; r++)
                    {
                        if (this.maturity[r] >= this.matBound[0])
                        {
                            for (int c = 0; c < this.callMarketPrice.C; c++)
                            {
                                if (this.callMarketPrice[r, c] > s0 * optionThreshold && this.cpmd.CallVolume[r, c] > 0)
                                {
                                    avgPricingError += Math.Abs(pricingErrors[r, c]);
                                }
                                //if (this.cpmd.PutPrice[r, c] > s0 * optionThreshold && this.cpmd.PutVolume[r, c] > 0)
                                //    avgPricingError += Math.Abs(pricingErrors[r, c]);
                            }
                        }
                    }
                    avgPricingError /= numCall;

                    int RR = Math.Min(12, this.callMarketPrice.R - 1);
                    int CC = Math.Min(12, this.callMarketPrice.C - 1);
                    Console.WriteLine("Mkt Price");
                    Console.WriteLine(this.callMarketPrice[Range.New(0, RR), Range.New(0, CC)]);
                    Console.WriteLine("Pricing Errors");
                    Console.WriteLine(pricingErrors[Range.New(0, RR), Range.New(0, CC)]);
                }
                objCount++;
            }

            //Calculate average distance...
            sum = Math.Sqrt(sum / this.totalVolume);
            if (this.useBoundPenalty)
            {
                sum += this.BoundPenalty(x);
            }

            if (this.useFellerPenalty)
            {
                sum += this.FellerPenalty(x);
            }

            return(sum);
        }
コード例 #9
0
        public static void Main(string[] args)
        {
            int Caso = 1;

            if (Caso == 0)
            {
                InterestRateMarketData MData   = InterestRateMarketData.FromFile("../../../TestData/InterestRatesModels/05052009-EU.xml");
                CallPriceMarketData    test    = CallPriceMarketData.FromFile("../../../TestData/Heston/05052009-SX5E-HestonData.xml");
                EquityCalibrationData  CalData = new EquityCalibrationData(test, MData);

                Matrix CallMarketPrice = (Matrix)test.CallPrice;
                Vector Maturity        = (Vector)test.Maturity;
                Vector Strike          = (Vector)test.Strike;
                Vector DividendYield   = (Vector)test.DividendYield;
                Vector Drift           = CalData.Rate - CalData.DividendYield;
                Vector Rate            = CalData.Rate;

                double u, kappa, theta, sigma, rho, v0, s0, r, q, T, K, val;
                u     = 1.0;
                kappa = 19.4;
                theta = 0.235;
                sigma = 0.00500999;
                rho   = -0.96;
                v0    = 0.664;
                s0    = 3872.15;
                r     = -0.0867303549580581;
                q     = 0;
                T     = 0.50;
                K     = 6000;
                Vector MatBound    = new Vector(2);
                Vector StrikeBound = new Vector(2);
                MatBound[0]    = 0.0;
                MatBound[1]    = 2.0;
                StrikeBound[0] = 0.7;
                StrikeBound[1] = 1.3;
                Matrix Volatility = new Matrix(test.CallPrice.R, test.CallPrice.C);
                HestonCallOptimizationProblem HP = new HestonCallOptimizationProblem(CallMarketPrice, Maturity, Strike, Rate, DividendYield, test.S0, MatBound, StrikeBound, Volatility);
                Complex Cval, Cu;
                Cu = u - Complex.I;
                HestonCall hc = new HestonCall(HP);

                Cval = hc.phi(u, kappa, theta, sigma, rho, s0, v0, r, T);
                Console.WriteLine("phi1 = {0}", Cval);
                Cval = hc.phi(Cu, kappa, theta, sigma, rho, s0, v0, r, T);
                Console.WriteLine("phi2 = {0}", Cval);
                val = hc.IntegrandFunc(u, kappa, theta, sigma, rho, s0, v0, r, q, T, K);
                Console.WriteLine("IntFunc = {0}", val);

                Vector x = new Vector(5);
                x[0] = kappa;
                x[1] = theta;
                x[2] = sigma;
                x[3] = rho;
                x[4] = v0;

                DateTime T1, T2;
                TimeSpan ElapsedTime;
                double   Time, Time2, Time3;

                T1          = DateTime.Now;
                val         = hc.HestonCallPrice(x, s0, T, K, r, q);
                T2          = DateTime.Now;
                ElapsedTime = T2 - T1;
                Time        = (double)ElapsedTime.Milliseconds;
                Time2       = (double)ElapsedTime.Seconds;
                Console.WriteLine("Price = {0}", val);
                Console.WriteLine("Elapsed Time = {0}", Time2 + Time / 1000);

                int    NProve = 10;
                int    NPassi = 1000;
                double val2;
                Random CasNum = new Random();
                for (int i = 0; i < NProve; i++)
                {
                    for (int j = 0; j < 5; j++)
                    {
                        val2 = ((double)CasNum.Next(0, NPassi)) / ((double)NPassi);
                        x[j] = HP.Bounds.Lb[j] + (HP.Bounds.Ub[j] - HP.Bounds.Lb[j]) * val2;
                    }
                    Console.Write("Trial {0}  x = " + x.ToString(), i + 1);
                    T1          = DateTime.Now;
                    val         = HP.Obj(x);
                    T2          = DateTime.Now;
                    ElapsedTime = T2 - T1;
                    Time        = (double)ElapsedTime.Milliseconds;
                    Time2       = (double)ElapsedTime.Seconds;
                    Time3       = (double)ElapsedTime.Minutes;
                    Console.WriteLine("  Time = {0}' {1}'' Val = {2}", Time3, Time2 + Time / 1000, val);
                }
            }
            if (Caso == 1)
            {
                TestHestonCallEstimation NewTest = new TestHestonCallEstimation();
                bool Result = NewTest.Run();
            }
        }