Esempio n. 1
0
        /// <summary>
        /// Replaces the no exercise cashflows for the product at position <paramref name="key"/> with the cashflows based on
        /// an estimated optimal exercise policy.
        /// </summary>
        /// <param name="key">The position in <see cref="_allTrades"/> of the product to be updated.</param>
        private void ApplyEarlyExercise(int key)
        {
            // Get path-wise regressed values of post exercise products.
            var option  = _allTrades[key] as IProductWithEarlyExercise;
            var exDates = option.GetExerciseDates();
            var postExRegressedValues = new double[_numberOfPaths, exDates.Count];

            for (var i = 0; i < exDates.Count; i++)
            {
                // perform regression on each exercise date
                var postExerciseProductInd = _postExerciseTrades[key][option.GetPostExProductAtDate(exDates[i])];
                var fitted = PerformRegression(exDates[i], _simulatedCFs, _simulatedRegs,
                                               new List <int> {
                    postExerciseProductInd
                });
                postExRegressedValues.SetColumn(i, fitted);
            }

            // Iterate backwards
            // initially the stopping time on all paths is infinity (actually the year 3000)
            var optimalStop = new Date[_numberOfPaths];
            var finalDate   = new Date(3000, 1, 1);

            for (var i = 0; i < _numberOfPaths; i++)
            {
                optimalStop[i] = finalDate;
            }

            for (var exDateCount = exDates.Count - 1; exDateCount >= 0; exDateCount--)
            {
                var exDate = exDates[exDateCount];

                // Optimal flows are underlying product up to the stopping time, then the post exercise product flows afterwards
                var pvOptimalCFs = Vector.Zeros(_numberOfPaths);
                for (var pathCount = 0; pathCount < _numberOfPaths; pathCount++)
                {
                    if (optimalStop[pathCount] < finalDate)
                    {
                        var exProductInd =
                            _postExerciseTrades[key][option.GetPostExProductAtDate(optimalStop[pathCount])];
                        foreach (var cf in _simulatedCFs.GetCFs(exProductInd, pathCount))
                        {
                            if (cf.Date > optimalStop[pathCount])
                            {
                                pvOptimalCFs[pathCount] += cf.Amount;
                            }
                        }
                    }

                    foreach (var cf in _simulatedCFs.GetCFs(key, pathCount))
                    {
                        if (cf.Date > _valueDate && cf.Date <= optimalStop[pathCount])
                        {
                            pvOptimalCFs[pathCount] += cf.Amount;
                        }
                    }
                }

                // update optimal stopping times
                var optimalCV = _simulatedRegs.FitCFs(exDate, pvOptimalCFs);

                for (var pathCount = 0; pathCount < _numberOfPaths; pathCount++)
                {
                    if (option.IsLongOptionality(exDate) &&
                        optimalCV[pathCount] < postExRegressedValues[pathCount, exDateCount])
                    {
                        optimalStop[pathCount] = exDate;
                    }
                    else if (!option.IsLongOptionality(exDate) &&
                             optimalCV[pathCount] > postExRegressedValues[pathCount, exDateCount])
                    {
                        optimalStop[pathCount] = exDate;
                    }
                }
            }

            // All stopping times have been found so now we can update the cashflows.
            // The cashflows are continuation flows up to the exercise date then cashflows from the
            // exercise product after that.
            var newCFs = new List <Cashflow> [_numberOfPaths];

            for (var pathCount = 0; pathCount < _numberOfPaths; pathCount++)
            {
                newCFs[pathCount] = new List <Cashflow>();
                var exProductInd = _postExerciseTrades[key][option.GetPostExProductAtDate(optimalStop[pathCount])];
                foreach (var cf in _simulatedCFs.GetCFs(exProductInd, pathCount))
                {
                    if (cf.Date > optimalStop[pathCount])
                    {
                        newCFs[pathCount].Add(cf);
                    }
                }
                foreach (var cf in _simulatedCFs.GetCFs(key, pathCount))
                {
                    if (cf.Date > _valueDate && cf.Date <= optimalStop[pathCount])
                    {
                        newCFs[pathCount].Add(cf);
                    }
                }
            }

            _simulatedCFs.Update(key, newCFs);
        }
Esempio n. 2
0
        /// <summary>
        /// Replaces the no exercise cashflows for the product at position <paramref name="key"/> with the cashflows based on
        /// an estimated optimal exercise policy.
        /// </summary>
        /// <param name="key">The postion in <see cref="allTrades"/> of the product to be updated.</param>
        private void ApplyEarlyExercise(int key)
        {
            // Get pathwise regressed values of post exercise products.
            ProductWithEarlyExercise option = allTrades[key] as ProductWithEarlyExercise;
            List <Date> exDates             = option.GetExerciseDates();

            double[,] postExRegressedValues = new double[N, exDates.Count];
            for (int i = 0; i < exDates.Count; i++)
            {
                // perform regression on each exercise date
                int      postExerciseProductInd = postExerciseTrades[key][option.GetPostExProductAtDate(exDates[i])];
                double[] fitted = PerformRegression(exDates[i], simulatedCFs, simulatedRegs, new List <int> {
                    postExerciseProductInd
                });
                postExRegressedValues.SetColumn(i, fitted);
            }

            // Iterate backwards
            // initially the stoppping time on all paths is infinity (actually the year 3000)
            Date[] optimalStop = new Date[N];
            Date   finalDate   = new Date(3000, 1, 1);

            for (int i = 0; i < N; i++)
            {
                optimalStop[i] = finalDate;
            }

            for (int exDateCount = exDates.Count - 1; exDateCount >= 0; exDateCount--)
            {
                Date exDate = exDates[exDateCount];

                // Optimal flows are underlying product up to the stopping time, then the post exercise product flows afterwards
                double[] pvOptimalCFs = Vector.Zeros(N);
                for (int pathCount = 0; pathCount < N; pathCount++)
                {
                    if (optimalStop[pathCount] < finalDate)
                    {
                        int exProductInd = postExerciseTrades[key][option.GetPostExProductAtDate(optimalStop[pathCount])];
                        foreach (Cashflow cf in simulatedCFs.GetCFs(exProductInd, pathCount))
                        {
                            if (cf.date > optimalStop[pathCount])
                            {
                                pvOptimalCFs[pathCount] += cf.amount;
                            }
                        }
                    }
                    foreach (Cashflow cf in simulatedCFs.GetCFs(key, pathCount))
                    {
                        if (cf.date > valueDate && cf.date <= optimalStop[pathCount])
                        {
                            pvOptimalCFs[pathCount] += cf.amount;
                        }
                    }
                }

                // update optimal stopping times
                double[] optimalCV = simulatedRegs.FitCFs(exDate, pvOptimalCFs);

                for (int pathCount = 0; pathCount < N; pathCount++)
                {
                    if (option.IsLongOptionality(exDate) && optimalCV[pathCount] < postExRegressedValues[pathCount, exDateCount])
                    {
                        optimalStop[pathCount] = exDate;
                    }
                    else if (!option.IsLongOptionality(exDate) && optimalCV[pathCount] > postExRegressedValues[pathCount, exDateCount])
                    {
                        optimalStop[pathCount] = exDate;
                    }
                }
            }
            // All stopping times have been found so now we can update the cashflows.
            // The cashflows are continuation flows up to the exercise date then cashflows from the
            // exercise product after that.
            List <Cashflow>[] newCFs = new List <Cashflow> [N];
            for (int pathCount = 0; pathCount < N; pathCount++)
            {
                newCFs[pathCount] = new List <Cashflow>();
                int exProductInd = postExerciseTrades[key][option.GetPostExProductAtDate(optimalStop[pathCount])];
                foreach (Cashflow cf in simulatedCFs.GetCFs(exProductInd, pathCount))
                {
                    if (cf.date > optimalStop[pathCount])
                    {
                        newCFs[pathCount].Add(cf);
                    }
                }
                foreach (Cashflow cf in simulatedCFs.GetCFs(key, pathCount))
                {
                    if (cf.date > valueDate && cf.date <= optimalStop[pathCount])
                    {
                        newCFs[pathCount].Add(cf);
                    }
                }
            }
            simulatedCFs.Update(key, newCFs);
        }