コード例 #1
0
 public InverseNonCentralCumulativeChiSquareDistribution(double df, double ncp,
                                                         int maxEvaluations = 10,
                                                         double accuracy    = 1e-8)
 {
     nonCentralDist_ = new NonCentralCumulativeChiSquareDistribution(df, ncp);
     guess_          = (df + ncp);
     maxEvaluations_ = maxEvaluations;
     accuracy_       = accuracy;
 }
コード例 #2
0
 public MinFinder(NonCentralCumulativeChiSquareDistribution nonCentralDist, double x)
 {
     nonCentralDist_ = nonCentralDist;
     x_ = x;
 }
コード例 #3
0
        public FdmHestonVarianceMesher(int size,
                                       HestonProcess process,
                                       double maturity,
                                       int tAvgSteps  = 10,
                                       double epsilon = 0.0001)
            : base(size)
        {
            List <double> vGrid = new InitializedList <double>(size, 0.0);
            List <double> pGrid = new InitializedList <double>(size, 0.0);

            double df = 4.0 * process.theta() * process.kappa() /
                        Math.Pow(process.sigma(), 2);

            try
            {
                List <pair_double> grid = new List <pair_double>();

                for (int l = 1; l <= tAvgSteps; ++l)
                {
                    double t   = (maturity * l) / tAvgSteps;
                    double ncp = 4 * process.kappa() * Math.Exp(-process.kappa() * t)
                                 / (Math.Pow(process.sigma(), 2)
                                    * (1 - Math.Exp(-process.kappa() * t))) * process.v0();
                    double k = Math.Pow(process.sigma(), 2)
                               * (1 - Math.Exp(-process.kappa() * t)) / (4 * process.kappa());

                    double qMin = 0.0; // v_min = 0.0;
                    double qMax = Math.Max(process.v0(),
                                           k * new InverseNonCentralCumulativeChiSquareDistribution(
                                               df, ncp, 100, 1e-8).value(1 - epsilon));

                    double minVStep = (qMax - qMin) / (50 * size);
                    double ps, p = 0.0;

                    double vTmp = qMin;
                    grid.Add(new pair_double(qMin, epsilon));

                    for (int i = 1; i < size; ++i)
                    {
                        ps = (1 - epsilon - p) / (size - i);
                        p += ps;
                        double tmp = k * new InverseNonCentralCumulativeChiSquareDistribution(
                            df, ncp, 100, 1e-8).value(p);

                        double vx = Math.Max(vTmp + minVStep, tmp);
                        p    = new NonCentralCumulativeChiSquareDistribution(df, ncp).value(vx / k);
                        vTmp = vx;
                        grid.Add(new pair_double(vx, p));
                    }
                }
                Utils.QL_REQUIRE(grid.Count == size * tAvgSteps,
                                 () => "something wrong with the grid size");

                grid.Sort();

                List <Pair <double, double> > tp = new List <Pair <double, double> >(grid);

                for (int i = 0; i < size; ++i)
                {
                    int b = (i * tp.Count) / size;
                    int e = ((i + 1) * tp.Count) / size;
                    for (int j = b; j < e; ++j)
                    {
                        vGrid[i] += tp[j].first / (e - b);
                        pGrid[i] += tp[j].second / (e - b);
                    }
                }
            }
            catch (Exception)
            {
                // use default mesh
                double vol = process.sigma() *
                             Math.Sqrt(process.theta() / (2 * process.kappa()));

                double mean       = process.theta();
                double upperBound = Math.Max(process.v0() + 4 * vol, mean + 4 * vol);
                double lowerBound
                    = Math.Max(0.0, Math.Min(process.v0() - 4 * vol, mean - 4 * vol));

                for (int i = 0; i < size; ++i)
                {
                    pGrid[i] = i / (size - 1.0);
                    vGrid[i] = lowerBound + i * (upperBound - lowerBound) / (size - 1.0);
                }
            }

            double skewHint = ((process.kappa() != 0.0)
                    ? Math.Max(1.0, process.sigma() / process.kappa()) : 1.0);

            pGrid.Sort();
            volaEstimate_ = new GaussLobattoIntegral(100000, 1e-4).value(
                new interpolated_volatility(pGrid, vGrid).value,
                pGrid.First(),
                pGrid.Last()) * Math.Pow(skewHint, 1.5);

            double v0 = process.v0();

            for (int i = 1; i < vGrid.Count; ++i)
            {
                if (vGrid[i - 1] <= v0 && vGrid[i] >= v0)
                {
                    if (Math.Abs(vGrid[i - 1] - v0) < Math.Abs(vGrid[i] - v0))
                    {
                        vGrid[i - 1] = v0;
                    }
                    else
                    {
                        vGrid[i] = v0;
                    }
                }
            }
            locations_ = vGrid.Select(x => x).ToList();
            for (int i = 0; i < size - 1; ++i)
            {
                dminus_[i + 1] = dplus_[i] = vGrid[i + 1] - vGrid[i];
            }
            dplus_[dplus_.Count - 1] = null;
            dminus_[0] = null;
        }