Exemplo n.º 1
0
        /// <summary>
        /// Prepares the portfolios by splitting products with early exercise into
        /// the products they become after exercise and the product that produces their
        /// cashflows until exercise.
        /// </summary>
        /// <param name="portfolioIn">The user supplied portfolio.</param>
        /// <param name="fwdValueDates">The extra forward value dates.</param>
        private void PreparePortfolios(Product[] portfolioIn, Date[] fwdValueDates)
        {
            allDates = fwdValueDates.Select(date => new Date(date)).ToList();
            allDates.Add(valueDate);
            allTrades          = new List <Product>();
            originalTrades     = new List <int>();
            postExerciseTrades = new Dictionary <int, List <int> >();

            // Add the orginal trades
            int counter = 0;

            foreach (Product product in portfolioIn)
            {
                allTrades.Add(product.Clone());
                originalTrades.Add(counter);
                ProductWithEarlyExercise option = product as ProductWithEarlyExercise;
                if (option != null)
                {
                    List <int> subList = new List <int>();
                    postExerciseTrades.Add(counter, subList);
                    counter++;
                    allDates.AddRange(option.GetExerciseDates());
                    List <Product> postExProducts = option.GetPostExProducts();
                    foreach (Product postExProduct in postExProducts)
                    {
                        allTrades.Add(postExProduct);
                        subList.Add(counter);
                        counter++;
                    }
                }
                else
                {
                    counter++;
                }
            }
            allDates = allDates.Distinct().ToList();
            allDates.Sort();
        }
Exemplo 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);
        }