private Tuple <double, double> GetReturns(string TrancheID, double Price, DateTime AsOfDate, DateTime CallDate)
        {
            // Set up
            string DealID       = TrancheID.Split('.')[0];
            string trancheLabel = TrancheID.Split('.')[1];

            string[] RateName  = new string[] { "Libor 1M", "Libor 2M", "Libor 3M", "Libor 6M", "Libor 1Y", "Swap 2Y", "Swap 3Y", "Swap 4Y", "Swap 5Y", "Swap 6Y" };
            double[] YearFracs = new double[] { 1 / 12.0, 2 / 12.0, 3 / 12.0, 6 / 12.0, 1, 2, 3, 4, 5, 6 };
            double[] Rates     = new double[RateName.Length];
            double   FixRate   = 0;

            ITranche targetTranche = null;


            // Load Econ
            ObjCDONet.Application.Economy().Load(CDONetDealLib_Settings.StandardEcon);
            ObjCDONet.Application.Economy().CallDateOverrideOption = "Input";
            ObjCDONet.Application.Economy().CallDateOverrideValue  = CallDate;
            ObjCDONet.Application.Economy().LoadRatesFromLibrary(AsOfDate);
            ObjCDONet.Application.Economy().Model.PrincipalLossSeverity = 60;
            ObjCDONet.Application.Deal().DefaultRate = 2;

            for (int i = 0; i < RateName.Length; i++)
            {
                Rates[i] = ObjCDONet.Economy.Rates().IndexRates[RateName[i]];
            }
            FixRate = ToolKit.lagrange((CallDate - AsOfDate).Days / 365.25, YearFracs, Rates) / 100;

            // Run Cashflows
            ObjCDONet.Application.Deal().Run();


            // Calculate Numbers
            foreach (ITranche itranche in ObjCDONet.Application.Deal().CMO().Tranches)
            {
                if (itranche.Label == trancheLabel)
                {
                    targetTranche = itranche;
                    break;
                }
            }

            bool            ToStop      = false;
            List <double>   Cashflows   = new List <double>();
            List <DateTime> AllDates    = new List <DateTime>();
            double          CurrentSize = targetTranche.UpdateFace;
            double          IRR         = 0;

            for (int m = 0; m < 100; m++)
            {
                if (!ToStop)
                {
                    DateTime iPayDate  = targetTranche.PayDate[(short)m];
                    double   iCashflow = targetTranche.Interest[(short)m] + targetTranche.Principal[(short)m];

                    if (iPayDate > AsOfDate && iCashflow != 0)
                    {
                        Cashflows.Add(iCashflow);
                        AllDates.Add(iPayDate);
                    }

                    ToStop = (targetTranche.Balance[(short)m] == 0);
                }
            }
            Cashflows.Insert(0, -CurrentSize * Price / 100);
            AllDates.Insert(0, AsOfDate);

            IRR = XIRR.GetIRR(Cashflows.ToArray(), AllDates.ToArray());
            return(new Tuple <double, double>(IRR, IRR - FixRate));
        }
        private Tuple <double, double> GetCleanDirty(string TrancheID, DateTime AsOfDate, double ReqDM, DateTime CallDate)
        {
            // Set up
            string DealID       = TrancheID.Split('.')[0];
            string trancheLabel = TrancheID.Split('.')[1];

            string[] RateName = new string[] { "Libor 1M", "Libor 2M", "Libor 3M", "Libor 6M", "Libor 1Y", "Swap 2Y", "Swap 3Y", "Swap 4Y", "Swap 5Y", "Swap 6Y" };
            double[] YearFracs = new double[] { 1 / 12.0, 2 / 12.0, 3 / 12.0, 6 / 12.0, 1, 2, 3, 4, 5, 6 };
            double[] Rates = new double[RateName.Length];
            double   FixRate = 0;
            double   CleanPrice, DirtyPrice = 0;
            DateTime StartAccrualDate = new DateTime(1, 1, 1);
            ITranche targetTranche    = null;


            // Load Econ
            ObjCDONet.Application.Economy().Load(CDONetDealLib_Settings.StandardEcon);
            ObjCDONet.Application.Economy().CallDateOverrideOption = "Input";
            ObjCDONet.Application.Economy().CallDateOverrideValue  = CallDate;
            ObjCDONet.Application.Economy().LoadRatesFromLibrary(AsOfDate);
            ObjCDONet.Application.Economy().Model.PrincipalLossSeverity = 60;
            ObjCDONet.Application.Deal().DefaultRate = 2;

            for (int i = 0; i < RateName.Length; i++)
            {
                Rates[i] = ObjCDONet.Economy.Rates().IndexRates[RateName[i]];
            }
            FixRate = ToolKit.lagrange((CallDate - AsOfDate).Days / 365.25, YearFracs, Rates) / 100;

            // Run Cashflows
            ObjCDONet.Application.Deal().Run();


            // Get Target Tranche
            foreach (ITranche itranche in ObjCDONet.Application.Deal().CMO().Tranches)
            {
                if (itranche.Label == trancheLabel)
                {
                    targetTranche = itranche;
                    break;
                }
            }

            // Get Start Accrual Date
            for (int i = 0; i < 50; i++)
            {
                if (ObjCDONet.Application.Deal().CMO().LiabilityFlow.PayDate[(short)i] < AsOfDate)
                {
                    StartAccrualDate = ObjCDONet.Application.Deal().CMO().LiabilityFlow.PayDate[(short)i];
                }
                else
                {
                    break;
                }
            }
            if (StartAccrualDate.Year == 1)
            {
                StartAccrualDate = ObjCDONet.Application.Deal().CMO().CutoffDatedDate;
            }

            // Calculate Numbers
            bool            ToStop         = false;
            List <double>   CleanCashflows = new List <double>();
            List <double>   DirtyCashflows = new List <double>();
            List <DateTime> AllDates       = new List <DateTime>();
            double          CurrentSize    = targetTranche.UpdateFace;
            double          IRR            = 0;

            for (int m = 0; m < 100; m++)
            {
                if (!ToStop)
                {
                    DateTime iPayDate  = targetTranche.PayDate[(short)m];
                    double   iCashflow = targetTranche.Interest[(short)m] + targetTranche.Principal[(short)m];

                    if (iPayDate > AsOfDate && iCashflow != 0)
                    {
                        CleanCashflows.Add(iCashflow);
                        AllDates.Add(iPayDate);
                    }

                    ToStop = (targetTranche.Balance[(short)m] == 0);
                }
            }
            DirtyCashflows     = new List <double>(CleanCashflows);
            DirtyCashflows[0] *= (1 + ((AsOfDate - StartAccrualDate).TotalDays - 1) / ((AllDates[0] - StartAccrualDate).TotalDays - 1));

            CleanPrice = ToolKit.XNPV(ReqDM + FixRate, CleanCashflows.ToArray(), AllDates.ToArray(), AsOfDate) / targetTranche.UpdateFace;
            DirtyPrice = ToolKit.XNPV(ReqDM + FixRate, DirtyCashflows.ToArray(), AllDates.ToArray(), AsOfDate) / targetTranche.UpdateFace;

            return(new Tuple <double, double>(CleanPrice, DirtyPrice));
        }