Ejemplo n.º 1
0
Archivo: Loan.cs Proyecto: ariesy/QLNet
 public Loan(int legs)
 {
     legs_ = new InitializedList<List<CashFlow>>(legs);
     payer_ = new InitializedList<double>(legs);
     notionals_ = new List<double>();
     legNPV_ = new InitializedList<double?>(legs);
 }
Ejemplo n.º 2
0
        private void initialize()
        {
            // firstSeed is chosen based on clock() and used for the first rng
            ulong firstSeed = (ulong)DateTime.Now.Ticks; // (std::time(0));
            MersenneTwisterUniformRng first = new MersenneTwisterUniformRng(firstSeed);

            // secondSeed is as random as it could be
            // feel free to suggest improvements
            ulong secondSeed = first.nextInt32();

            MersenneTwisterUniformRng second = new MersenneTwisterUniformRng(secondSeed);

            // use the second rng to initialize the final one
            ulong skip = second.nextInt32() % 1000;
            List<ulong> init = new InitializedList<ulong>(4);
            init[0]=second.nextInt32();
            init[1]=second.nextInt32();
            init[2]=second.nextInt32();
            init[3]=second.nextInt32();

            rng_ = new MersenneTwisterUniformRng(init);

            for (ulong i=0; i<skip ; i++)
                rng_.nextInt32();
        }
Ejemplo n.º 3
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria) {
            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x_ = P.currentValue();
            currentProblem_ = P;
            initCostValues_ = P.costFunction().values(x_);
            int m = initCostValues_.size();
            int n = x_.size();

            Vector xx = new Vector(x_);
            Vector fvec = new Vector(m), diag = new Vector(n);

            int mode = 1;
            double factor = 1;
            int nprint = 0;
            int info = 0;
            int nfev =0;

            Matrix fjac = new Matrix(m, n);

            int ldfjac = m;
            
            List<int> ipvt = new InitializedList<int>(n);
            Vector qtf = new Vector(n), wa1 = new Vector(n), wa2 = new Vector(n), wa3 = new Vector(n), wa4 = new Vector(m);

            // call lmdif to minimize the sum of the squares of m functions
            // in n variables by the Levenberg-Marquardt algorithm.
            MINPACK.lmdif(m, n, xx, ref fvec,
                                     endCriteria.functionEpsilon(),
                                     xtol_,
                                     gtol_,
                                     endCriteria.maxIterations(),
                                     epsfcn_,
                                     diag, mode, factor,
                                     nprint, ref info, ref nfev, ref fjac,
                                     ldfjac, ref ipvt, ref qtf,
                                     wa1, wa2, wa3, wa4,
                                     fcn);
            info_ = info;
            // check requirements & endCriteria evaluation
            if(info == 0) throw new ApplicationException("MINPACK: improper input parameters");
            //if(info == 6) throw new ApplicationException("MINPACK: ftol is too small. no further " +
            //                                             "reduction in the sum of squares is possible.");

            if (info != 6) ecType = EndCriteria.Type.StationaryFunctionValue;
            //QL_REQUIRE(info != 5, "MINPACK: number of calls to fcn has reached or exceeded maxfev.");
            endCriteria.checkMaxIterations(nfev, ref ecType);
            if(info == 7) throw new ApplicationException("MINPACK: xtol is too small. no further " +
                                           "improvement in the approximate " +
                                           "solution x is possible.");
            if(info == 8) throw new ApplicationException("MINPACK: gtol is too small. fvec is " +
                                           "orthogonal to the columns of the " +
                                           "jacobian to machine precision.");
            // set problem
            x_ = new Vector(xx.GetRange(0, n));
            P.setCurrentValue(x_);
            P.setFunctionValue(P.costFunction().value(x_));

            return ecType;
        }
Ejemplo n.º 4
0
 public AmericanExercise(Date latest, bool payoffAtExpiry)
     : base(Type.American, payoffAtExpiry)
 {
     dates_ = new InitializedList<Date>(2);
     dates_[0] = Date.minDate();
     dates_[1] = latest;
 }
      //public List<CashFlow> interestCashflows()
      //{
      //   List<CashFlow> icf = new List<CashFlow>();
      //   foreach (CashFlow cf in cashflows())
      //   {
      //      if (cf is QLNet.FixedRateCoupon)
      //         icf.Add(cf);
      //   }
      //   return icf;
      //}

      public List<CashFlow> expectedCashflows()
      {
         calcBondFactor();

         List<CashFlow> expectedcashflows = new List<CashFlow>();

         List<double> notionals = new InitializedList<double>(schedule_.Count);
         notionals[0] = notionals_[0];
         for (int i = 0; i < schedule_.Count - 1; ++i)
         {
            double currentNotional = notionals[i];
            double smm = SMM(schedule_[i]);
            double prepay = (notionals[i] * bondFactors_[i + 1]) / bondFactors_[i] * smm;
            double actualamort = currentNotional * (1 - bondFactors_[i + 1] / bondFactors_[i]);
            notionals[i + 1] = currentNotional - actualamort - prepay;

            // ADD
            CashFlow c1 = new VoluntaryPrepay(prepay, schedule_[i + 1]);
            CashFlow c2 = new AmortizingPayment(actualamort, schedule_[i + 1]);
            CashFlow c3 = new FixedRateCoupon(currentNotional, schedule_[i + 1], new InterestRate(PassThroughRate_, dCounter_, Compounding.Simple), schedule_[i], schedule_[i + 1]);
            expectedcashflows.Add(c1);
            expectedcashflows.Add(c2);
            expectedcashflows.Add(c3);
            
         }
         notionals[notionals.Count - 1] = 0.0;
         
         return expectedcashflows;
      }
Ejemplo n.º 6
0
        public static List<Func<Vector, double>> multiPathBasisSystem(int dim, int order, PolynomType polynomType)
        {
            List<Func<double, double>> b = pathBasisSystem(order, polynomType);

            List<Func<Vector, double>> ret = new List<Func<Vector,double>>();
            ret.Add((xx) => 1.0);

            for (int i=1; i<=order; ++i) {
                List<Func<Vector, double>> a = w(dim, i, polynomType, b);

                foreach (var iter in a) {
                    ret.Add(iter);
                }
            }

            // remove-o-zap: now remove redundant functions.
            // usually we do have a lot of them due to the construction schema.
            // We use a more "hands on" method here.
            List<bool> rm = new InitializedList<bool>(ret.Count, true);

            Vector x = new Vector(dim), v = new Vector(ret.Count);
            MersenneTwisterUniformRng rng = new MersenneTwisterUniformRng(1234UL);

            for (int i=0; i<10; ++i) {
                int k;

                // calculate random x vector
                for (k=0; k<dim; ++k) {
                    x[k] = rng.next().value;
                }

                // get return values for all basis functions
                for (k = 0; k < ret.Count; ++k) {
                    v[k] = ret[k](x);
                }

                // find duplicates
                for (k = 0; k < ret.Count; ++k) {
                    if (v.First(xx => (Math.Abs(v[k] - xx) <= 10*v[k]*Const.QL_Epsilon)) == v.First() + k) {
                        // don't remove this item, it's unique!
                        rm[k] = false;
                    }
                }
            }

            int iter2 = 0;
            for (int i = 0; i < rm.Count; ++i) {
                if (rm[i]) {
                    ret.RemoveAt(iter2);
                }
                else {
                    ++iter2;
                }
            }

            return ret;
        }
Ejemplo n.º 7
0
 public AmericanExercise(Date earliestDate, Date latestDate, bool payoffAtExpiry)
     : base(Type.American, payoffAtExpiry)
 {
     if (!(earliestDate <= latestDate))
         throw new ApplicationException("earliest > latest exercise date");
     dates_ = new InitializedList<Date>(2);
     dates_[0] = earliestDate;
     dates_[1] = latestDate;
 }
Ejemplo n.º 8
0
      public override double value(double x, double y) 
      {
         List<double> section = new InitializedList<double>( splines_.Count );
         for (int i=0; i<splines_.Count; i++)
            section[i]=splines_[i].value(x,true);

         CubicInterpolation spline = new CubicInterpolation(this.yBegin_, this.ySize_, section,
                                                            CubicInterpolation.DerivativeApprox.Spline, false,
                                                            CubicInterpolation.BoundaryCondition.SecondDerivative, 0.0,
                                                            CubicInterpolation.BoundaryCondition.SecondDerivative, 0.0);
         return spline.value(y,true);
      }
Ejemplo n.º 9
0
 //! generic times
 /*! \note the starting time of the path is assumed to be 0 and must not be included */
 public BrownianBridge(List<double> times) {
     size_ = times.Count;
     t_ = new InitializedList<double>(size_);
     sqrtdt_ = new InitializedList<double>(size_);
     bridgeIndex_ = new InitializedList<int>(size_);
     leftIndex_ = new InitializedList<int>(size_);
     rightIndex_ = new InitializedList<int>(size_);
     leftWeight_ = new InitializedList<double>(size_);
     rightWeight_ = new InitializedList<double>(size_);
     stdDev_ = new InitializedList<double>(size_);
     initialize();
 }
Ejemplo n.º 10
0
 public double secondDerivativeX(double x, double y) 
 {
    List<double> section = new InitializedList<double>( this.zData_.columns() );
    for (int i=0; i < section.Count; ++i) 
    {
       section[i] = value(this.xBegin_[i], y);
    }
           
    return new CubicInterpolation( this.xBegin_, this.xSize_, section,
                                   CubicInterpolation.DerivativeApprox.Spline, false,
                                   CubicInterpolation.BoundaryCondition.SecondDerivative, 0.0,
                                   CubicInterpolation.BoundaryCondition.SecondDerivative, 0.0).secondDerivative(x);
 }
Ejemplo n.º 11
0
 // Computes the size of the simplex
 public static double computeSimplexSize(InitializedList<Vector> vertices)
 {
     Vector center = new Vector(vertices[0].Count, 0);
     for (int i = 0; i < vertices.Count; ++i)
         center += vertices[i];
     center *= 1 / (double)(vertices.Count);
     double result = 0;
     for (int i = 0; i < vertices.Count; ++i)
     {
         Vector temp = vertices[i] - center;
         result += Math.Sqrt(Vector.DotProduct(temp, temp));
     }
     return result / (double)(vertices.Count);
 }
Ejemplo n.º 12
0
 //! unit-time path
 public BrownianBridge(int steps) {
     size_ = steps;
     t_ = new InitializedList<double>(size_);
     sqrtdt_ = new InitializedList<double>(size_);
     bridgeIndex_ = new InitializedList<int>(size_);
     leftIndex_ = new InitializedList<int>(size_);
     rightIndex_ = new InitializedList<int>(size_);
     leftWeight_ = new InitializedList<double>(size_);
     rightWeight_ = new InitializedList<double>(size_);
     stdDev_ = new InitializedList<double>(size_);
     for (int i=0; i<size_; ++i)
         t_[i] = i+1;
     initialize();
 }
Ejemplo n.º 13
0
        public DiscretizedSwaption(Swaption.Arguments args,
                                    Date referenceDate,
                                    DayCounter dayCounter)
            : base(new DiscretizedSwap(args, referenceDate, dayCounter), args.exercise.type(), new List<double>())
        {
            arguments_=args;
            exerciseTimes_ = new InitializedList<double>(arguments_.exercise.dates().Count);
            for (int i = 0; i < exerciseTimes_.Count; ++i)
                exerciseTimes_[i] =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.exercise.date(i));

            // Date adjustments can get time vectors out of synch.
            // Here, we try and collapse similar dates which could cause
            // a mispricing.
            for (int i=0; i<arguments_.exercise.dates().Count; i++) {
                Date exerciseDate = arguments_.exercise.date(i);
            for (int j = 0; j < arguments_.fixedPayDates.Count; j++) {
                if (withinNextWeek(exerciseDate,
                                   arguments_.fixedPayDates[j])
                    // coupons in the future are dealt with below
                    && arguments_.fixedResetDates[j] < referenceDate)
                    arguments_.fixedPayDates[j] = exerciseDate;
            }
            for (int j = 0; j < arguments_.fixedResetDates.Count; j++) {
                if (withinPreviousWeek(exerciseDate,
                                       arguments_.fixedResetDates[j]))
                    arguments_.fixedResetDates[j] = exerciseDate;
            }
            for (int j = 0; j < arguments_.floatingResetDates.Count; j++) {
                if (withinPreviousWeek(exerciseDate,
                                       arguments_.floatingResetDates[j]))
                    arguments_.floatingResetDates[j] = exerciseDate;
            }
        }

        double lastFixedPayment =
            dayCounter.yearFraction(referenceDate,
                                    arguments_.fixedPayDates.Last() );
        double lastFloatingPayment =
            dayCounter.yearFraction(referenceDate,
                                    arguments_.floatingPayDates.Last());
        lastPayment_ = Math.Max(lastFixedPayment,lastFloatingPayment);

        underlying_ =   new DiscretizedSwap(arguments_,
                                            referenceDate,
                                            dayCounter);

        }
Ejemplo n.º 14
0
        public void test1dLinearRegression()
        {
            //BOOST_MESSAGE("Testing 1d simple linear least-squares regression...");

            /* Example taken from the QuantLib-User list, see posting
             * Multiple linear regression/weighted regression, Boris Skorodumov */

            //SavedSettings backup;

            List<double> x = new InitializedList<double>(9),
                         y = new InitializedList<double>(9);
            x[0] = 2.4; x[1] = 1.8; x[2] = 2.5; x[3] = 3.0;
            x[4] = 2.1; x[5] = 1.2; x[6] = 2.0; x[7] = 2.7; x[8] = 3.6;

            y[0] = 7.8; y[1] = 5.5; y[2] = 8.0; y[3] = 9.0;
            y[4] = 6.5; y[5] = 4.0; y[6] = 6.3; y[7] = 8.4; y[8] = 10.2;

            List<Func<double, double>> v = new List<Func<double, double>>();
            v.Add(a => 1.0);
            v.Add(a => a);

            LinearRegression m = new LinearRegression(x, y);

            const double tol = 0.0002;
            double[] coeffExpected = new double[] { 0.9448, 2.6853 };
            double[] errorsExpected = new double[] { 0.3654, 0.1487 };

            for (int i = 0; i < 2; ++i) {
                if (Math.Abs(m.standardErrors()[i] - errorsExpected[i]) > tol) {
                    Assert.Fail("Failed to reproduce linear regression standard errors"
                                + "\n    calculated: " + m.standardErrors()[i]
                                + "\n    expected:   " + errorsExpected[i]
                                + "\n    tolerance:  " + tol);
                }

                if (Math.Abs(m.coefficients()[i] - coeffExpected[i]) > tol) {
                    Assert.Fail("Failed to reproduce linear regression coef."
                                + "\n    calculated: " + m.coefficients()[i]
                                + "\n    expected:   " + coeffExpected[i]
                                + "\n    tolerance:  " + tol);
                }
            }
        }
Ejemplo n.º 15
0
Archivo: Loan.cs Proyecto: ariesy/QLNet
        public override void fetchResults(IPricingEngineResults r)
        {
            base.fetchResults(r);

            LoanPricingEngineResults results = r as LoanPricingEngineResults;
            if (results == null) throw new ArgumentException("wrong result type");

            if (results.legNPV.Count != 0)
            {
                if (results.legNPV.Count != legNPV_.Count)
                {
                    throw new ArgumentException("wrong number of leg NPV returned");
                }

                legNPV_ = results.legNPV;
            }
            else
            {
                legNPV_ = new InitializedList<double?>(legNPV_.Count);
            }
        }
Ejemplo n.º 16
0
        public MersenneTwisterUniformRng(List<ulong> seeds) {
            mt = new InitializedList<ulong>(N);

            seedInitialization(19650218UL);
            int i = 1, j = 0, k = (N > seeds.Count ? N : seeds.Count);
            for (; k!=0; k--) {
                mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) + seeds[j] + (ulong)j; /* non linear */
                mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
                i++; j++;
                if (i>=N) { mt[0] = mt[N-1]; i=1; }
                if (j>=seeds.Count) j=0;
            }
            for (k=N-1; k!=0; k--) {
                mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - (ulong)i; /* non linear */
                mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
                i++;
                if (i>=N) { mt[0] = mt[N-1]; i=1; }
            }

            mt[0] = 0x80000000UL; /*MSB is 1; assuring non-zero initial array*/
        }
        // Instrument interface
        public override void calculate() {
            if (discountCurve_.empty()) throw new ArgumentException("no discounting term structure set");

            results_.value = results_.cash = 0;
            results_.errorEstimate = null;
            results_.legNPV = new InitializedList<double?>(arguments_.legs.Count);
            results_.legBPS = new InitializedList<double?>(arguments_.legs.Count);
            List<double?> startDiscounts = new InitializedList<double?>(arguments_.legs.Count);
            for (int i=0; i<arguments_.legs.Count; ++i) {
                results_.legNPV[i] = arguments_.payer[i] * CashFlows.npv(arguments_.legs[i], discountCurve_);
                results_.legBPS[i] = arguments_.payer[i] * CashFlows.bps(arguments_.legs[i], discountCurve_);
                results_.value += results_.legNPV[i];
                results_.cash += arguments_.payer[i] * CashFlows.cash(arguments_.legs[i]);
                try {
                    Date d = CashFlows.startDate(arguments_.legs[i]);
                    startDiscounts[i] = discountCurve_.link.discount(d);
                } catch {
                    startDiscounts[i] = null;
                }
            }
            results_.additionalResults.Add("startDiscounts", startDiscounts);
        }
Ejemplo n.º 18
0
         public void setMarketData()
         {
            tenors = new SwaptionTenors();
            //tenors.options.resize(6);
            tenors.options = new InitializedList<Period>(6);
            tenors.options[0] = new Period(1, TimeUnit.Months);
            tenors.options[1] = new Period(6, TimeUnit.Months);
            tenors.options[2] = new Period(1, TimeUnit.Years);
            tenors.options[3] = new Period(5, TimeUnit.Years);
            tenors.options[4] = new Period(10, TimeUnit.Years);
            tenors.options[5] = new Period(30, TimeUnit.Years);
            //tenors.swaps.resize(4);
            tenors.swaps = new InitializedList<Period>(4);
            tenors.swaps[0] = new Period(1, TimeUnit.Years);
            tenors.swaps[1] = new Period(5, TimeUnit.Years);
            tenors.swaps[2] = new Period(10, TimeUnit.Years);
            tenors.swaps[3] = new Period(30, TimeUnit.Years);

            vols = new Matrix(tenors.options.Count, tenors.swaps.Count);
            vols[0, 0] = 0.1300; vols[0, 1] = 0.1560; vols[0, 2] = 0.1390; vols[0, 3] = 0.1220;
            vols[1, 0] = 0.1440; vols[1, 1] = 0.1580; vols[1, 2] = 0.1460; vols[1, 3] = 0.1260;
            vols[2, 0] = 0.1600; vols[2, 1] = 0.1590; vols[2, 2] = 0.1470; vols[2, 3] = 0.1290;
            vols[3, 0] = 0.1640; vols[3, 1] = 0.1470; vols[3, 2] = 0.1370; vols[3, 3] = 0.1220;
            vols[4, 0] = 0.1400; vols[4, 1] = 0.1300; vols[4, 2] = 0.1250; vols[4, 3] = 0.1100;
            vols[5, 0] = 0.1130; vols[5, 1] = 0.1090; vols[5, 2] = 0.1070; vols[5, 3] = 0.0930;
            volsHandle = new InitializedList<List<Handle<Quote>>>(tenors.options.Count);

            for (int i = 0; i < tenors.options.Count; i++)
            {
               volsHandle[i] = new InitializedList<Handle<Quote>>(tenors.swaps.Count);
               for (int j = 0; j < tenors.swaps.Count; j++)
                  // every handle must be reassigned, as the ones created by
                  // default are all linked together.
                  volsHandle[i][j] = new Handle<Quote>(new SimpleQuote(vols[i, j]));
            }
         }
Ejemplo n.º 19
0
        public override void update()
        {
            Vector tmp = new Vector(size_);
            List<double> dx = new InitializedList<double>(size_ - 1),
                         S = new InitializedList<double>(size_ - 1);

            for (int i = 0; i < size_ - 1; ++i) {
                dx[i] = xBegin_[i+1] - xBegin_[i];
                S[i] = (yBegin_[i+1] - yBegin_[i])/dx[i];
            }

            // first derivative approximation
            if (da_==CubicInterpolation.DerivativeApprox.Spline) {
                TridiagonalOperator L = new TridiagonalOperator(size_);
                for (int i = 1; i < size_ - 1; ++i) {
                    L.setMidRow(i, dx[i], 2.0*(dx[i]+dx[i-1]), dx[i-1]);
                    tmp[i] = 3.0*(dx[i]*S[i-1] + dx[i-1]*S[i]);
                }

                // left boundary condition
                switch (leftType_) {
                    case CubicInterpolation.BoundaryCondition.NotAKnot:
                        // ignoring end condition value
                        L.setFirstRow(dx[1]*(dx[1]+dx[0]), (dx[0]+dx[1])*(dx[0]+dx[1]));
                        tmp[0] = S[0]*dx[1]*(2.0*dx[1]+3.0*dx[0]) + S[1]*dx[0]*dx[0];
                        break;
                    case CubicInterpolation.BoundaryCondition.FirstDerivative:
                        L.setFirstRow(1.0, 0.0);
                        tmp[0] = leftValue_;
                        break;
                    case CubicInterpolation.BoundaryCondition.SecondDerivative:
                        L.setFirstRow(2.0, 1.0);
                        tmp[0] = 3.0*S[0] - leftValue_*dx[0]/2.0;
                        break;
                    case CubicInterpolation.BoundaryCondition.Periodic:
                    case CubicInterpolation.BoundaryCondition.Lagrange:
                        // ignoring end condition value
                        throw new NotImplementedException("this end condition is not implemented yet");
                    default:
                        throw new ArgumentException("unknown end condition");
                }

                // right boundary condition
                switch (rightType_) {
                    case CubicInterpolation.BoundaryCondition.NotAKnot:
                        // ignoring end condition value
                        L.setLastRow(-(dx[size_ - 2] + dx[size_ - 3]) * (dx[size_ - 2] + dx[size_ - 3]),
                                     -dx[size_ - 3] * (dx[size_ - 3] + dx[size_ - 2]));
                        tmp[size_ - 1] = -S[size_ - 3] * dx[size_ - 2] * dx[size_ - 2] -
                                     S[size_ - 2] * dx[size_ - 3] * (3.0 * dx[size_ - 2] + 2.0 * dx[size_ - 3]);
                        break;
                    case CubicInterpolation.BoundaryCondition.FirstDerivative:
                        L.setLastRow(0.0, 1.0);
                        tmp[size_ - 1] = rightValue_;
                        break;
                    case CubicInterpolation.BoundaryCondition.SecondDerivative:
                        L.setLastRow(1.0, 2.0);
                        tmp[size_ - 1] = 3.0 * S[size_ - 2] + rightValue_ * dx[size_ - 2] / 2.0;
                        break;
                    case CubicInterpolation.BoundaryCondition.Periodic:
                    case CubicInterpolation.BoundaryCondition.Lagrange:
                        // ignoring end condition value
                        throw new NotImplementedException("this end condition is not implemented yet");
                    default:
                        throw new ArgumentException("unknown end condition");
                }

                // solve the system
                tmp = L.solveFor(tmp);
            } else { // local schemes
                if (size_ == 2)
                    tmp[0] = tmp[1] = S[0];
                else {
                    switch (da_) {
                        case CubicInterpolation.DerivativeApprox.FourthOrder:
                            throw new NotImplementedException("FourthOrder not implemented yet");
                            break;
                        case CubicInterpolation.DerivativeApprox.Parabolic:
                            // intermediate points
                            for (int i = 1; i < size_ - 1; ++i) {
                                tmp[i] = (dx[i - 1] * S[i] + dx[i] * S[i - 1]) / (dx[i] + dx[i - 1]);
                            }
                            // end points
                            tmp[0] = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                            tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                            break;
                            break;
                        case CubicInterpolation.DerivativeApprox.FritschButland:
                            // intermediate points
                            for (int i=1; i<size_-1; ++i) {
                                double Smin = Math.Min(S[i-1], S[i]);
                                double Smax = Math.Max(S[i-1], S[i]);
                                tmp[i] = 3.0*Smin*Smax/(Smax+2.0*Smin);
                            }
                            // end points
                            tmp[0]    = ((2.0*dx[   0]+dx[   1])*S[   0] - dx[   0]*S[   1]) / (dx[   0]+dx[   1]);
                            tmp[size_-1] = ((2.0*dx[size_-2]+dx[size_-3])*S[size_-2] - dx[size_-2]*S[size_-3]) / (dx[size_-2]+dx[size_-3]);
                            break;
                        case CubicInterpolation.DerivativeApprox.Akima:
                            throw new NotImplementedException("Akima not implemented yet");
                            // end points
                            tmp[0] = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                            tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                            break;
                        case CubicInterpolation.DerivativeApprox.Kruger:
                            // intermediate points
                            for (int i = 1; i < size_ - 1; ++i) {
                                if (S[i-1]*S[i]<0.0)
                                    // slope changes sign at point
                                    tmp[i] = 0.0;
                                else
                                    // slope will be between the slopes of the adjacent
                                    // straight lines and should approach zero if the
                                    // slope of either line approaches zero
                                    tmp[i] = 2.0/(1.0/S[i-1]+1.0/S[i]);
                            }
                            // end points
                            tmp[0] = (3.0*S[0]-tmp[1])/2.0;
                            tmp[size_ - 1] = (3.0 * S[size_ - 2] - tmp[size_ - 2]) / 2.0;
                            break;
                        default:
                            throw new ArgumentException("unknown scheme");
                    }
                }
            }

            monotonicityAdjustments_.Erase();

            // Hyman monotonicity constrained filter
            if (monotonic_) {
                double correction;
                double pm, pu, pd, M;
                for (int i = 0; i < size_; ++i) {
                    if (i==0) {
                        if (tmp[i]*S[0]>0.0) {
                            correction = tmp[i]/Math.Abs(tmp[i]) *
                                Math.Min(Math.Abs(tmp[i]),
                                               Math.Abs(3.0*S[0]));
                        } else {
                            correction = 0.0;
                        }
                        if (correction!=tmp[i]) {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    } else if (i == size_ - 1) {
                        if (tmp[i] * S[size_ - 2] > 0.0) {
                            correction = tmp[i]/Math.Abs(tmp[i]) *
                                Math.Min(Math.Abs(tmp[i]), Math.Abs(3.0 * S[size_ - 2]));
                        } else {
                            correction = 0.0;
                        }
                        if (correction!=tmp[i]) {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    } else {
                        pm=(S[i-1]*dx[i]+S[i]*dx[i-1])/
                            (dx[i-1]+dx[i]);
                        M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i-1]), Math.Abs(S[i])),
                                           Math.Abs(pm));
                        if (i>1) {
                            if ((S[i-1]-S[i-2])*(S[i]-S[i-1])>0.0) {
                                pd=(S[i-1]*(2.0*dx[i-1]+dx[i-2])
                                    -S[i-2]*dx[i-1])/
                                    (dx[i-2]+dx[i-1]);
                                if (pm*pd>0.0 && pm*(S[i-1]-S[i-2])>0.0) {
                                    M = Math.Max(M, 1.5*Math.Min(
                                            Math.Abs(pm),Math.Abs(pd)));
                                }
                            }
                        }
                        if (i < size_ - 2) {
                            if ((S[i]-S[i-1])*(S[i+1]-S[i])>0.0) {
                                pu=(S[i]*(2.0*dx[i]+dx[i+1])-S[i+1]*dx[i])/
                                    (dx[i]+dx[i+1]);
                                if (pm*pu>0.0 && -pm*(S[i]-S[i-1])>0.0) {
                                    M = Math.Max(M, 1.5*Math.Min(
                                            Math.Abs(pm),Math.Abs(pu)));
                                }
                            }
                        }
                        if (tmp[i]*pm>0.0) {
                            correction = tmp[i]/Math.Abs(tmp[i]) *
                                Math.Min(Math.Abs(tmp[i]), M);
                        } else {
                            correction = 0.0;
                        }
                        if (correction!=tmp[i]) {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                }
            }

            // cubic coefficients
            for (int i = 0; i < size_ - 1; ++i) {
                a_[i] = tmp[i];
                b_[i] = (3.0*S[i] - tmp[i+1] - 2.0*tmp[i])/dx[i];
                c_[i] = (tmp[i+1] + tmp[i] - 2.0*S[i])/(dx[i]*dx[i]);
            }

            primitiveConst_[0] = 0.0;
            for (int i = 1; i < size_ - 1; ++i) {
                primitiveConst_[i] = primitiveConst_[i-1]
                    + dx[i-1] *
                    (yBegin_[i-1] + dx[i-1] *
                     (a_[i-1]/2.0 + dx[i-1] *
                      (b_[i-1]/3.0 + dx[i-1] * c_[i-1]/4.0)));
            }
        }
Ejemplo n.º 20
0
        public void testFdmLinearOpLayout()
        {
            int[]      dims = new int[] { 5, 7, 8 };
            List <int> dim  = new List <int>(dims);

            FdmLinearOpLayout layout = new FdmLinearOpLayout(dim);

            int calculatedDim = layout.dim().Count;
            int expectedDim   = dim.Count;

            if (calculatedDim != expectedDim)
            {
                QAssert.Fail("index.dimensions() should be " + expectedDim
                             + ", but is " + calculatedDim);
            }

            int calculatedSize = layout.size();
            int expectedSize   = dim.accumulate(0, 3, 1, (x, y) => (x * y));

            if (calculatedSize != expectedSize)
            {
                QAssert.Fail("index.size() should be "
                             + expectedSize + ", but is " + calculatedSize);
            }

            for (int k = 0; k < dim[0]; ++k)
            {
                for (int l = 0; l < dim[1]; ++l)
                {
                    for (int m = 0; m < dim[2]; ++m)
                    {
                        List <int> tmp = new InitializedList <int>(3);
                        tmp[0] = k; tmp[1] = l; tmp[2] = m;

                        int calculatedIndex = layout.index(tmp);
                        int expectedIndex   = k + l * dim[0] + m * dim[0] * dim[1];

                        if (expectedIndex != layout.index(tmp))
                        {
                            QAssert.Fail("index.size() should be " + expectedIndex
                                         + ", but is " + calculatedIndex);
                        }
                    }
                }
            }

            FdmLinearOpIterator iter = layout.begin();

            for (int m = 0; m < dim[2]; ++m)
            {
                for (int l = 0; l < dim[1]; ++l)
                {
                    for (int k = 0; k < dim[0]; ++k, ++iter)
                    {
                        for (int n = 1; n < 4; ++n)
                        {
                            int nn = layout.neighbourhood(iter, 1, n);
                            int calculatedIndex = k + m * dim[0] * dim[1]
                                                  + ((l < dim[1] - n)? l + n
                                              : dim[1] - 1 - (l + n - (dim[1] - 1))) * dim[0];

                            if (nn != calculatedIndex)
                            {
                                QAssert.Fail("next neighbourhood index is " + nn
                                             + " but should be " + calculatedIndex);
                            }
                        }

                        for (int n = 1; n < 7; ++n)
                        {
                            int nn = layout.neighbourhood(iter, 2, -n);
                            int calculatedIndex = k + l * dim[0]
                                                  + ((m < n) ? n - m : m - n) * dim[0] * dim[1];
                            if (nn != calculatedIndex)
                            {
                                QAssert.Fail("next neighbourhood index is " + nn
                                             + " but should be " + calculatedIndex);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 21
0
      protected List<double> sinkingNotionals(Period maturityTenor,
                                    Frequency sinkingFrequency,
                                    double couponRate,
                                    double initialNotional) 
      {
            Period freqPeriod = new Period(sinkingFrequency);
            int nPeriods = 0;
            Utils.QL_REQUIRE(isSubPeriod(freqPeriod, maturityTenor, out nPeriods),() =>
                       "Bond frequency is incompatible with the maturity tenor");

            List<double> notionals = new InitializedList<double>(nPeriods+1);
            notionals[0] = initialNotional;
            double coupon = couponRate / (double)sinkingFrequency;
            double compoundedInterest = 1.0;
            double totalValue = Math.Pow(1.0+coupon, nPeriods);
            for(int i = 0; i < (int)nPeriods-1; ++i) 
            {
                compoundedInterest *= (1.0 + coupon);
                double currentNotional = 0.0;
                if(coupon < 1.0e-12) {
                    currentNotional =
                       initialNotional*(1.0 - (i+1.0)/nPeriods);
                }
                else {
                    currentNotional =
                       initialNotional*(compoundedInterest - (compoundedInterest-1.0)/(1.0 - 1.0/totalValue));
                }
                notionals[i+1] = currentNotional;
            }
            notionals[notionals.Count-1] = 0.0;
            return notionals;
   }
Ejemplo n.º 22
0
        public void testMonteCarloCapletPricing()
        {
            //"Testing caplet LMM Monte-Carlo caplet pricing..."

            //SavedSettings backup;

            /* factor loadings are taken from Hull & White article
               plus extra normalisation to get orthogonal eigenvectors
               http://www.rotman.utoronto.ca/~amackay/fin/libormktmodel2.pdf */
            double[] compValues = {0.85549771, 0.46707264, 0.22353259,
                                 0.91915359, 0.37716089, 0.11360610,
                                 0.96438280, 0.26413316,-0.01412414,
                                 0.97939148, 0.13492952,-0.15028753,
                                 0.95970595,-0.00000000,-0.28100621,
                                 0.97939148,-0.13492952,-0.15028753,
                                 0.96438280,-0.26413316,-0.01412414,
                                 0.91915359,-0.37716089, 0.11360610,
                                 0.85549771,-0.46707264, 0.22353259};

            Matrix volaComp=new Matrix(9,3);
            List<double> lcompValues=new InitializedList<double>(27,0);
            List<double> ltemp = new InitializedList<double>(3, 0);
            lcompValues=compValues.ToList();
            //std::copy(compValues, compValues+9*3, volaComp.begin());
            for (int i = 0; i < 9; i++)
            {
                ltemp = lcompValues.GetRange(3*i, 3);
                for (int j = 0; j < 3; j++)
                    volaComp[i, j] = ltemp[j];
            }
            LiborForwardModelProcess process1 = makeProcess();
            LiborForwardModelProcess process2 = makeProcess(volaComp);

            List<double> tmp = process1.fixingTimes();
            TimeGrid grid=new TimeGrid(tmp ,12);

            List<int> location=new List<int>();
            for (int i=0; i < tmp.Count; ++i) {
                location.Add(grid.index(tmp[i])) ;
            }

            // set-up a small Monte-Carlo simulation to price caplets
            // and ratchet caps using a one- and a three factor libor market model

             ulong seed = 42;
             LowDiscrepancy.icInstance = new InverseCumulativeNormal();
             IRNG rsg1 = (IRNG)new LowDiscrepancy().make_sequence_generator(
                                                            process1.factors()*(grid.size()-1), seed);
             IRNG rsg2 = (IRNG)new LowDiscrepancy().make_sequence_generator(
                                                            process2.factors()*(grid.size()-1), seed);

            MultiPathGenerator<IRNG> generator1=new MultiPathGenerator<IRNG> (process1, grid, rsg1, false);
            MultiPathGenerator<IRNG> generator2=new MultiPathGenerator<IRNG> (process2, grid, rsg2, false);

            const int nrTrails = 250000;
            List<GeneralStatistics> stat1 = new InitializedList<GeneralStatistics>(process1.size());
            List<GeneralStatistics> stat2 = new InitializedList<GeneralStatistics>(process2.size());
            List<GeneralStatistics> stat3 = new InitializedList<GeneralStatistics>(process2.size() - 1);
            for (int i=0; i<nrTrails; ++i) {
                Sample<MultiPath> path1 = generator1.next();
                Sample<MultiPath> path2 = generator2.next();

                List<double> rates1=new InitializedList<double>(len);
                List<double> rates2 = new InitializedList<double>(len);
                for (int j=0; j<process1.size(); ++j) {
                    rates1[j] = path1.value[j][location[j]];
                    rates2[j] = path2.value[j][location[j]];
                }

                List<double> dis1 = process1.discountBond(rates1);
                List<double> dis2 = process2.discountBond(rates2);

                for (int k=0; k<process1.size(); ++k) {
                    double accrualPeriod =  process1.accrualEndTimes()[k]
                                        - process1.accrualStartTimes()[k];
                    // caplet payoff function, cap rate at 4%
                    double payoff1 = Math.Max(rates1[k] - 0.04, 0.0) * accrualPeriod;

                    double payoff2 = Math.Max(rates2[k] - 0.04, 0.0) * accrualPeriod;
                    stat1[k].add(dis1[k] * payoff1);
                    stat2[k].add(dis2[k] * payoff2);

                    if (k != 0) {
                        // ratchet cap payoff function
                        double payoff3 =  Math.Max(rates2[k] - (rates2[k-1]+0.0025), 0.0)
                                      * accrualPeriod;
                        stat3[k-1].add(dis2[k] * payoff3);
                    }
                }

            }

            double[] capletNpv = {0.000000000000, 0.000002841629, 0.002533279333,
                                0.009577143571, 0.017746502618, 0.025216116835,
                                0.031608230268, 0.036645683881, 0.039792254012,
                                0.041829864365};

            double[] ratchetNpv = {0.0082644895, 0.0082754754, 0.0082159966,
                                 0.0082982822, 0.0083803357, 0.0084366961,
                                 0.0084173270, 0.0081803406, 0.0079533814};

            for (int k=0; k < process1.size(); ++k) {

                double calculated1 = stat1[k].mean();
                double tolerance1  = stat1[k].errorEstimate();
                double expected    = capletNpv[k];

                if (Math.Abs(calculated1 - expected) > tolerance1) {
                    Assert.Fail("Failed to reproduce expected caplet NPV"
                                + "\n    calculated: " + calculated1
                                + "\n    error int:  " + tolerance1
                                + "\n    expected:   " + expected);
                }

                double calculated2 = stat2[k].mean();
                double tolerance2  = stat2[k].errorEstimate();

                if (Math.Abs(calculated2 - expected) > tolerance2) {
                    Assert.Fail("Failed to reproduce expected caplet NPV"
                                + "\n    calculated: " + calculated2
                                + "\n    error int:  " + tolerance2
                                + "\n    expected:   " + expected);
                }

                if (k != 0) {
                    double calculated3 = stat3[k-1].mean();
                    double tolerance3  = stat3[k-1].errorEstimate();
                    expected    = ratchetNpv[k-1];

                    double refError = 1e-5; // 1e-5. error bars of the reference values

                    if (Math.Abs(calculated3 - expected) > tolerance3 + refError) {
                        Assert.Fail("Failed to reproduce expected caplet NPV"
                                    + "\n    calculated: " + calculated3
                                    + "\n    error int:  " + tolerance3 + refError
                                    + "\n    expected:   " + expected);
                    }
                }
            }
        }
Ejemplo n.º 23
0
        public void testCachedFloating()
        {
            // "Testing floating-rate bond prices against cached values...");

            CommonVars vars = new CommonVars();

            Date today = new Date(22, Month.November, 2004);

            Settings.setEvaluationDate(today);

            int settlementDays = 1;

            var riskFreeRate  = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.025, new Actual360()));
            var discountCurve = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.03, new Actual360()));

            IborIndex index      = new USDLibor(new Period(6, TimeUnit.Months), riskFreeRate);
            int       fixingDays = 1;

            double tolerance = 1.0e-6;

            IborCouponPricer pricer = new BlackIborCouponPricer(new Handle <OptionletVolatilityStructure>());

            // plain
            Schedule sch = new Schedule(new Date(30, Month.November, 2004), new Date(30, Month.November, 2008),
                                        new Period(Frequency.Semiannual), new UnitedStates(UnitedStates.Market.GovernmentBond),
                                        BusinessDayConvention.ModifiedFollowing, BusinessDayConvention.ModifiedFollowing,
                                        DateGeneration.Rule.Backward, false);

            FloatingRateBond bond1 = new FloatingRateBond(settlementDays, vars.faceAmount, sch,
                                                          index, new ActualActual(ActualActual.Convention.ISMA),
                                                          BusinessDayConvention.ModifiedFollowing, fixingDays,
                                                          new List <double>(), new List <double>(),
                                                          new List <double>(), new List <double>(),
                                                          false,
                                                          100.0, new Date(30, Month.November, 2004));

            IPricingEngine bondEngine = new DiscountingBondEngine(riskFreeRate);

            bond1.setPricingEngine(bondEngine);

            Utils.setCouponPricer(bond1.cashflows(), pricer);

#if QL_USE_INDEXED_COUPON
            double cachedPrice1 = 99.874645;
#else
            double cachedPrice1 = 99.874646;
#endif


            double price = bond1.cleanPrice();
            if (Math.Abs(price - cachedPrice1) > tolerance)
            {
                Assert.Fail("failed to reproduce cached price:\n"
                            + "    calculated: " + price + "\n"
                            + "    expected:   " + cachedPrice1 + "\n"
                            + "    error:      " + (price - cachedPrice1));
            }

            // different risk-free and discount curve
            FloatingRateBond bond2 = new FloatingRateBond(settlementDays, vars.faceAmount, sch,
                                                          index, new ActualActual(ActualActual.Convention.ISMA),
                                                          BusinessDayConvention.ModifiedFollowing, fixingDays,
                                                          new List <double>(), new List <double>(),
                                                          new List <double>(), new List <double>(),
                                                          false,
                                                          100.0, new Date(30, Month.November, 2004));

            IPricingEngine bondEngine2 = new DiscountingBondEngine(discountCurve);
            bond2.setPricingEngine(bondEngine2);

            Utils.setCouponPricer(bond2.cashflows(), pricer);

#if QL_USE_INDEXED_COUPON
            double cachedPrice2 = 97.955904;
#else
            double cachedPrice2 = 97.955904;
#endif

            price = bond2.cleanPrice();
            if (Math.Abs(price - cachedPrice2) > tolerance)
            {
                Assert.Fail("failed to reproduce cached price:\n"
                            + "    calculated: " + price + "\n"
                            + "    expected:   " + cachedPrice2 + "\n"
                            + "    error:      " + (price - cachedPrice2));
            }

            // varying spread
            InitializedList <double> spreads = new InitializedList <double>(4);
            spreads[0] = 0.001;
            spreads[1] = 0.0012;
            spreads[2] = 0.0014;
            spreads[3] = 0.0016;

            FloatingRateBond bond3 = new FloatingRateBond(settlementDays, vars.faceAmount, sch,
                                                          index, new ActualActual(ActualActual.Convention.ISMA),
                                                          BusinessDayConvention.ModifiedFollowing, fixingDays,
                                                          new List <double>(), spreads,
                                                          new List <double>(), new List <double>(),
                                                          false,
                                                          100.0, new Date(30, Month.November, 2004));

            bond3.setPricingEngine(bondEngine2);

            Utils.setCouponPricer(bond3.cashflows(), pricer);

#if QL_USE_INDEXED_COUPON
            double cachedPrice3 = 98.495458;
#else
            double cachedPrice3 = 98.495459;
#endif

            price = bond3.cleanPrice();
            if (Math.Abs(price - cachedPrice3) > tolerance)
            {
                Assert.Fail("failed to reproduce cached price:\n"
                            + "    calculated: " + price + "\n"
                            + "    expected:   " + cachedPrice3 + "\n"
                            + "    error:      " + (price - cachedPrice3));
            }
        }
Ejemplo n.º 24
0
        public void testStrikeDependency()
        {
            //("Testing swaption dependency on strike......");

            CommonVars vars = new CommonVars();
            double[] strikes = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 };

            for (int i = 0; i <  exercises.Length; i++)  {
                for (int j = 0; j < lengths.Length; j++) {
                    for (int k=0; k < type.Length ; k++) {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                          exercises[i]);
                        Date startDate = vars.calendar.advance(exerciseDate,
                                         vars.settlementDays, TimeUnit.Days);
                        // store the results for different rates...
                        List<double> values = new InitializedList<double>(strikes.Length);
                        List<double> values_cash = new InitializedList<double>(strikes.Length);
                        double vol = 0.20;

                        for (int l=0; l< strikes.Length ; l++) {
                            VanillaSwap swap    = new MakeVanillaSwap(lengths[j], vars.index, strikes[l])
                                                    .withEffectiveDate(startDate)
                                                    .withFloatingLegSpread(0.0)
                                                    .withType(type[k]);
                            Swaption swaption   = vars.makeSwaption(swap,exerciseDate,vol);
                            // FLOATING_POINT_EXCEPTION
                            values[l]=swaption.NPV();
                            Swaption swaption_cash = vars.makeSwaption( swap,exerciseDate,vol,
                                                                        Settlement.Type.Cash);
                            values_cash[l]=swaption_cash.NPV();
                        }

                        // and check that they go the right way
                        if (type[k]==VanillaSwap.Type.Payer) {
                            for (int z = 0; z < values.Count - 1; z++)
                            {
                                if( values[z]<values[z+1]){
                                Assert.Fail("NPV of Payer swaption with delivery settlement"+
                                            "is increasing with the strike:" +
                                            "\noption tenor: " + exercises[i] +
                                            "\noption date:  " + exerciseDate +
                                            "\nvolatility:   " + vol +
                                            "\nswap tenor:   " + lengths[j] +
                                            "\nvalue:        " + values[z  ] +" at strike: " + strikes[z  ] +
                                            "\nvalue:        " + values[z+1] + " at strike: " + strikes[z+1]);
                                }
                            }
                            for (int z = 0; z < values_cash.Count - 1; z++)
                            {
                                if (values_cash[z] < values_cash[z + 1])
                                {
                                    Assert.Fail("NPV of Payer swaption with cash settlement" +
                                        "is increasing with the strike:" +
                                        "\noption tenor: " + exercises[i] +
                                        "\noption date:  " + exerciseDate +
                                        "\nvolatility:   " + vol +
                                        "\nswap tenor:   " + lengths[j] +
                                        "\nvalue:        " + values_cash[z] + " at strike: " + strikes[z] +
                                        "\nvalue:        " + values_cash[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                        }
                        else {
                            for (int z = 0; z < values.Count - 1; z++){
                                if (values[z] > values[z+1]){
                                    Assert.Fail("NPV of Receiver swaption with delivery settlement" +
                                                "is increasing with the strike:" +
                                                "\noption tenor: " + exercises[i] +
                                                "\noption date:  " + exerciseDate +
                                                "\nvolatility:   " + vol +
                                                "\nswap tenor:   " + lengths[j] +
                                                "\nvalue:        " + values[z] + " at strike: " + strikes[z] +
                                                "\nvalue:        " + values[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                            for (int z = 0; z < values_cash.Count - 1; z++)
                            {
                                if (values[z] > values[z+1])
                                {
                                    Assert.Fail("NPV of Receiver swaption with cash settlement" +
                                        "is increasing with the strike:" +
                                        "\noption tenor: " + exercises[i] +
                                        "\noption date:  " + exerciseDate +
                                        "\nvolatility:   " + vol +
                                        "\nswap tenor:   " + lengths[j] +
                                        "\nvalue:        " + values_cash[z] + " at strike: " + strikes[z] +
                                        "\nvalue:        " + values_cash[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 25
0
        public void testCachedFixed()
        {
            // "Testing fixed-coupon bond prices against cached values...");

             CommonVars vars = new CommonVars();

             Date today = new Date(22, Month.November, 2004);
             Settings.setEvaluationDate(today);

             int settlementDays = 1;

             var discountCurve = new Handle<YieldTermStructure>(Utilities.flatRate(today, 0.03, new Actual360()));

             double tolerance = 1.0e-6;

             // plain
             Schedule sch = new Schedule(new Date(30, Month.November, 2004),
                      new Date(30, Month.November, 2008), new Period(Frequency.Semiannual),
                      new UnitedStates(UnitedStates.Market.GovernmentBond),
                      BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

             FixedRateBond bond1 = new FixedRateBond(settlementDays, vars.faceAmount, sch, new List<double>() { 0.02875 },
                             new ActualActual(ActualActual.Convention.ISMA), BusinessDayConvention.ModifiedFollowing,
                             100.0, new Date(30, Month.November, 2004));

             IPricingEngine bondEngine = new DiscountingBondEngine(discountCurve);
             bond1.setPricingEngine(bondEngine);

             double cachedPrice1 = 99.298100;

             double price = bond1.cleanPrice();
             if (Math.Abs(price - cachedPrice1) > tolerance)
             {
            Console.WriteLine("failed to reproduce cached price:\n"
                       + "    calculated: " + price + "\n"
                       + "    expected:   " + cachedPrice1 + "\n"
                       + "    error:      " + (price - cachedPrice1));
             }

             // varying coupons
             InitializedList<double> couponRates = new InitializedList<double>(4);
             couponRates[0] = 0.02875;
             couponRates[1] = 0.03;
             couponRates[2] = 0.03125;
             couponRates[3] = 0.0325;

             FixedRateBond bond2 = new FixedRateBond(settlementDays, vars.faceAmount, sch, couponRates,
                               new ActualActual(ActualActual.Convention.ISMA),
                               BusinessDayConvention.ModifiedFollowing,
                               100.0, new Date(30, Month.November, 2004));

             bond2.setPricingEngine(bondEngine);

             double cachedPrice2 = 100.334149;

             price = bond2.cleanPrice();
             if (Math.Abs(price - cachedPrice2) > tolerance)
             {
            Console.WriteLine("failed to reproduce cached price:\n"
                       + "    calculated: " + price + "\n"
                       + "    expected:   " + cachedPrice2 + "\n"
                       + "    error:      " + (price - cachedPrice2));
             }

             // stub date
             Schedule sch3 = new Schedule(new Date(30, Month.November, 2004),
                       new Date(30, Month.March, 2009), new Period(Frequency.Semiannual),
                       new UnitedStates(UnitedStates.Market.GovernmentBond),
                       BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false,
                       null, new Date(30, Month.November, 2008));

             FixedRateBond bond3 = new FixedRateBond(settlementDays, vars.faceAmount, sch3,
                               couponRates, new ActualActual(ActualActual.Convention.ISMA),
                               BusinessDayConvention.ModifiedFollowing,
                               100.0, new Date(30, Month.November, 2004));

             bond3.setPricingEngine(bondEngine);

             double cachedPrice3 = 100.382794;

             price = bond3.cleanPrice();
             if (Math.Abs(price - cachedPrice3) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:\n"
                       + "    calculated: " + price + "\n"
                       + "    expected:   " + cachedPrice3 + "\n"
                       + "    error:      " + (price - cachedPrice3));
             }
        }
Ejemplo n.º 26
0
        public void testObservability()
        {
            // Testing volatility cube observability
            CommonVars vars = new CommonVars();

            List <List <Handle <Quote> > > parametersGuess =
                new InitializedList <List <Handle <Quote> > >(vars.cube.tenors.options.Count * vars.cube.tenors.swaps.Count);

            for (int i = 0; i < vars.cube.tenors.options.Count * vars.cube.tenors.swaps.Count; i++)
            {
                parametersGuess[i]    = new InitializedList <Handle <Quote> >(4);
                parametersGuess[i][0] = new Handle <Quote>(new SimpleQuote(0.2));
                parametersGuess[i][1] = new Handle <Quote>(new SimpleQuote(0.5));
                parametersGuess[i][2] = new Handle <Quote>(new SimpleQuote(0.4));
                parametersGuess[i][3] = new Handle <Quote>(new SimpleQuote(0.0));
            }
            List <bool> isParameterFixed = new InitializedList <bool>(4, false);

            SwaptionVolCube1x volCube1_0, volCube1_1;

            // VolCube created before change of reference date
            volCube1_0 = new SwaptionVolCube1x(vars.atmVolMatrix,
                                               vars.cube.tenors.options,
                                               vars.cube.tenors.swaps,
                                               vars.cube.strikeSpreads,
                                               vars.cube.volSpreadsHandle,
                                               vars.swapIndexBase,
                                               vars.shortSwapIndexBase,
                                               vars.vegaWeighedSmileFit,
                                               parametersGuess,
                                               isParameterFixed,
                                               true);

            Date referenceDate = Settings.evaluationDate();

            Settings.setEvaluationDate(vars.conventions.calendar.advance(referenceDate, new Period(1, TimeUnit.Days),
                                                                         vars.conventions.optionBdc));

            // VolCube created after change of reference date
            volCube1_1 = new SwaptionVolCube1x(vars.atmVolMatrix,
                                               vars.cube.tenors.options,
                                               vars.cube.tenors.swaps,
                                               vars.cube.strikeSpreads,
                                               vars.cube.volSpreadsHandle,
                                               vars.swapIndexBase,
                                               vars.shortSwapIndexBase,
                                               vars.vegaWeighedSmileFit,
                                               parametersGuess,
                                               isParameterFixed,
                                               true);
            double dummyStrike = 0.03;

            for (int i = 0; i < vars.cube.tenors.options.Count; i++)
            {
                for (int j = 0; j < vars.cube.tenors.swaps.Count; j++)
                {
                    for (int k = 0; k < vars.cube.strikeSpreads.Count; k++)
                    {
                        double v0 = volCube1_0.volatility(vars.cube.tenors.options[i],
                                                          vars.cube.tenors.swaps[j],
                                                          dummyStrike + vars.cube.strikeSpreads[k],
                                                          false);
                        double v1 = volCube1_1.volatility(vars.cube.tenors.options[i],
                                                          vars.cube.tenors.swaps[j],
                                                          dummyStrike + vars.cube.strikeSpreads[k],
                                                          false);
                        if (Math.Abs(v0 - v1) > 1e-14)
                        {
                            QAssert.Fail(" option tenor = " + vars.cube.tenors.options[i] +
                                         " swap tenor = " + vars.cube.tenors.swaps[j] +
                                         " strike = " + (dummyStrike + vars.cube.strikeSpreads[k]) +
                                         "  v0 = " + (v0) +
                                         "  v1 = " + (v1) +
                                         "  error = " + Math.Abs(v1 - v0));
                        }
                    }
                }
            }

            Settings.setEvaluationDate(referenceDate);

            SwaptionVolCube2 volCube2_0, volCube2_1;

            // VolCube created before change of reference date
            volCube2_0 = new SwaptionVolCube2(vars.atmVolMatrix,
                                              vars.cube.tenors.options,
                                              vars.cube.tenors.swaps,
                                              vars.cube.strikeSpreads,
                                              vars.cube.volSpreadsHandle,
                                              vars.swapIndexBase,
                                              vars.shortSwapIndexBase,
                                              vars.vegaWeighedSmileFit);
            Settings.setEvaluationDate(vars.conventions.calendar.advance(referenceDate, new Period(1, TimeUnit.Days),
                                                                         vars.conventions.optionBdc));

            // VolCube created after change of reference date
            volCube2_1 = new SwaptionVolCube2(vars.atmVolMatrix,
                                              vars.cube.tenors.options,
                                              vars.cube.tenors.swaps,
                                              vars.cube.strikeSpreads,
                                              vars.cube.volSpreadsHandle,
                                              vars.swapIndexBase,
                                              vars.shortSwapIndexBase,
                                              vars.vegaWeighedSmileFit);

            for (int i = 0; i < vars.cube.tenors.options.Count; i++)
            {
                for (int j = 0; j < vars.cube.tenors.swaps.Count; j++)
                {
                    for (int k = 0; k < vars.cube.strikeSpreads.Count; k++)
                    {
                        double v0 = volCube2_0.volatility(vars.cube.tenors.options[i],
                                                          vars.cube.tenors.swaps[j],
                                                          dummyStrike + vars.cube.strikeSpreads[k],
                                                          false);
                        double v1 = volCube2_1.volatility(vars.cube.tenors.options[i],
                                                          vars.cube.tenors.swaps[j],
                                                          dummyStrike + vars.cube.strikeSpreads[k],
                                                          false);
                        if (Math.Abs(v0 - v1) > 1e-14)
                        {
                            QAssert.Fail(" option tenor = " + vars.cube.tenors.options[i] +
                                         " swap tenor = " + vars.cube.tenors.swaps[j] +
                                         " strike = " + (dummyStrike + vars.cube.strikeSpreads[k]) +
                                         "  v0 = " + (v0) +
                                         "  v1 = " + (v1) +
                                         "  error = " + Math.Abs(v1 - v0));
                        }
                    }
                }
            }

            Settings.setEvaluationDate(referenceDate);
        }
Ejemplo n.º 27
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            ////////////////  DATES  //////////////////////////////////////////////

            Calendar calendar       = new TARGET();
            Date     todaysDate     = new Date(15, Month.January, 2017);
            Date     settlementDate = new Date(todaysDate);

            Settings.setEvaluationDate(todaysDate);
            DayCounter dayCounter = new Actual365Fixed();


            ////////////////  MARKET  //////////////////////////////////////////////

            // Spot
            double         underlying  = 1.0;
            Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying));

            // Curves
            double riskFreeRate  = 0.01;
            double dividendYield = 0.035;
            double cstVol        = 0.2;
            double hazardRate    = 0.02;

            Handle <YieldTermStructure>              flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter));
            Handle <YieldTermStructure>              flatDividendTS    = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter));
            Handle <BlackVolTermStructure>           mySurfaceH        = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, cstVol, dayCounter));
            Handle <DefaultProbabilityTermStructure> defaultTSH        = new Handle <DefaultProbabilityTermStructure>(new FlatHazardRate(settlementDate, hazardRate, dayCounter));

            // Process
            GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, flatDividendTS, flatTermStructure, mySurfaceH);


            ////////////////  INSTRUMENT  //////////////////////////////////////////////

            List <Date> fixings = new InitializedList <Date>();

            for (int i = 1; i <= 8; i++)
            {
                fixings.Add(settlementDate + new Period(i * 3, TimeUnit.Months));
            }

            double couponBond   = 0.0525;
            double couponBinary = 0.077;
            double barrierlvl   = 0.7;
            double strike       = 1.0;
            double recovery     = 0.4;

            double absoluteTolerance = 0.0001;

            GenericScriptRepack repack   = new GenericScriptRepack(fixings, couponBond, couponBinary, barrierlvl, strike, recovery);
            IPricingEngine      mcengine = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess)
                                           .withAbsoluteTolerance(absoluteTolerance)
                                           .withStepsPerYear(52)
                                           .withSeed(50)
                                           .withCredit(defaultTSH)
                                           .value();

            repack.setPricingEngine(mcengine);
            Console.WriteLine("Repack pricing = {0:0.0000}", repack.NPV());
            repack.inspout(5, true);

            ////////////////  END TEST  //////////////////////////////////////////////
            Console.WriteLine();
            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
        public void testRegression()
        {
            //("Testing linear least-squares regression...");

            //SavedSettings backup;

            const int nr = 100000;

            var rng = new InverseCumulativeRng <MersenneTwisterUniformRng, InverseCumulativeNormal>(
                new MersenneTwisterUniformRng(1234u));

            List <Func <double, double> > v = new List <Func <double, double> >();

            v.Add(x => 1.0);
            v.Add(x => x);
            v.Add(x => x * x);
            v.Add(Math.Sin);

            List <Func <double, double> > w = new List <Func <double, double> >(v);

            w.Add(x => x * x);

            for (int k = 0; k < 3; ++k)
            {
                int      i;
                double[] a = { rng.next().value,
                               rng.next().value,
                               rng.next().value,
                               rng.next().value };

                List <double> x = new InitializedList <double>(nr), y = new InitializedList <double>(nr);
                for (i = 0; i < nr; ++i)
                {
                    x[i] = rng.next().value;

                    // regression in y = a_1 + a_2*x + a_3*x^2 + a_4*sin(x) + eps
                    y[i] = a[0] * v[0](x[i]) + a[1] * v[1](x[i]) + a[2] * v[2](x[i])
                           + a[3] * v[3](x[i]) + rng.next().value;
                }

                LinearLeastSquaresRegression m = new LinearLeastSquaresRegression(x, y, v);

                for (i = 0; i < v.Count; ++i)
                {
                    if (m.standardErrors()[i] > tolerance)
                    {
                        Assert.Fail("Failed to reproduce linear regression coef."
                                    + "\n    error:     " + m.standardErrors()[i]
                                    + "\n    tolerance: " + tolerance);
                    }
                    if (Math.Abs(m.coefficients()[i] - a[i]) > 3 * m.error()[i])
                    {
                        Assert.Fail("Failed to reproduce linear regression coef."
                                    + "\n    calculated: " + m.coefficients()[i]
                                    + "\n    error:      " + m.standardErrors()[i]
                                    + "\n    expected:   " + a[i]);
                    }
                }

                m = new LinearLeastSquaresRegression(x, y, w);

                double[] ma  = { m.coefficients()[0], m.coefficients()[1], m.coefficients()[2] + m.coefficients()[4], m.coefficients()[3] };
                double[] err = { m.standardErrors()[0],                                      m.standardErrors()[1],
                                 Math.Sqrt(m.standardErrors()[2] * m.standardErrors()[2]
                                           + m.standardErrors()[4] * m.standardErrors()[4]),
                                 m.standardErrors()[3] };
                for (i = 0; i < v.Count; ++i)
                {
                    if (Math.Abs(ma[i] - a[i]) > 3 * err[i])
                    {
                        Assert.Fail("Failed to reproduce linear regression coef."
                                    + "\n    calculated: " + ma[i]
                                    + "\n    error:      " + err[i]
                                    + "\n    expected:   " + a[i]);
                    }
                }
            }
        }
Ejemplo n.º 29
0
        public void testSpreadedCube()
        {
            // Testing spreaded swaption volatility cube
            CommonVars vars = new CommonVars();

            List <List <Handle <Quote> > > parametersGuess =
                new InitializedList <List <Handle <Quote> > >(vars.cube.tenors.options.Count * vars.cube.tenors.swaps.Count);

            for (int i = 0; i < vars.cube.tenors.options.Count * vars.cube.tenors.swaps.Count; i++)
            {
                parametersGuess[i]    = new InitializedList <Handle <Quote> >(4);
                parametersGuess[i][0] = new Handle <Quote>(new SimpleQuote(0.2));
                parametersGuess[i][1] = new Handle <Quote>(new SimpleQuote(0.5));
                parametersGuess[i][2] = new Handle <Quote>(new SimpleQuote(0.4));
                parametersGuess[i][3] = new Handle <Quote>(new SimpleQuote(0.0));
            }
            List <bool> isParameterFixed = new InitializedList <bool>(4, false);

            Handle <SwaptionVolatilityStructure> volCube = new Handle <SwaptionVolatilityStructure>(
                new SwaptionVolCube1x(vars.atmVolMatrix,
                                      vars.cube.tenors.options,
                                      vars.cube.tenors.swaps,
                                      vars.cube.strikeSpreads,
                                      vars.cube.volSpreadsHandle,
                                      vars.swapIndexBase,
                                      vars.shortSwapIndexBase,
                                      vars.vegaWeighedSmileFit,
                                      parametersGuess,
                                      isParameterFixed,
                                      true));

            SimpleQuote    spread       = new SimpleQuote(0.0001);
            Handle <Quote> spreadHandle = new Handle <Quote>(spread);
            SwaptionVolatilityStructure spreadedVolCube = new SpreadedSwaptionVolatility(volCube, spreadHandle);
            List <double> strikes = new List <double>();

            for (int k = 1; k < 100; k++)
            {
                strikes.Add(k * .01);
            }
            for (int i = 0; i < vars.cube.tenors.options.Count; i++)
            {
                for (int j = 0; j < vars.cube.tenors.swaps.Count; j++)
                {
                    SmileSection smileSectionByCube = volCube.link.smileSection(vars.cube.tenors.options[i],
                                                                                vars.cube.tenors.swaps[j]);
                    SmileSection smileSectionBySpreadedCube = spreadedVolCube.smileSection(vars.cube.tenors.options[i],
                                                                                           vars.cube.tenors.swaps[j]);
                    for (int k = 0; k < strikes.Count; k++)
                    {
                        double strike = strikes[k];
                        double diff   = spreadedVolCube.volatility(vars.cube.tenors.options[i], vars.cube.tenors.swaps[j], strike)
                                        - volCube.link.volatility(vars.cube.tenors.options[i], vars.cube.tenors.swaps[j], strike);
                        if (Math.Abs(diff - spread.value()) > 1e-16)
                        {
                            QAssert.Fail("\ndiff!=spread in volatility method:" +
                                         "\nexpiry time = " + vars.cube.tenors.options[i] +
                                         "\nswap length = " + vars.cube.tenors.swaps[j] +
                                         "\n atm strike = " + (strike) +
                                         "\ndiff = " + diff +
                                         "\nspread = " + spread.value());
                        }

                        diff = smileSectionBySpreadedCube.volatility(strike) - smileSectionByCube.volatility(strike);
                        if (Math.Abs(diff - spread.value()) > 1e-16)
                        {
                            QAssert.Fail("\ndiff!=spread in smile section method:" +
                                         "\nexpiry time = " + vars.cube.tenors.options[i] +
                                         "\nswap length = " + vars.cube.tenors.swaps[j] +
                                         "\n atm strike = " + (strike) +
                                         "\ndiff = " + diff +
                                         "\nspread = " + spread.value());
                        }
                    }
                }
            }

            //testing observability
            Flag f = new Flag();

            spreadedVolCube.registerWith(f.update);
            volCube.link.update();
            if (!f.isUp())
            {
                QAssert.Fail("SpreadedSwaptionVolatilityStructure does not propagate notifications");
            }

            f.lower();
            spread.setValue(.001);
            if (!f.isUp())
            {
                QAssert.Fail("SpreadedSwaptionVolatilityStructure does not propagate notifications");
            }
        }
        public void testMultiDimRegression()
        {
            //BOOST_MESSAGE("Testing linear least-squares regression...");

            //SavedSettings backup;

            const int    nr        = 100000;
            const int    dims      = 4;
            const double tolerance = 0.01;

            var rng = new InverseCumulativeRng <MersenneTwisterUniformRng, InverseCumulativeNormal>(
                new MersenneTwisterUniformRng(1234u));

            List <Func <Vector, double> > v = new List <Func <Vector, double> >();

            v.Add(xx => 1.0);
            for (int i = 0; i < dims; ++i)
            {
                int jj = i;     // c# delegate work-around vs. boost bind; jj has to be evaluted before add delegate to the list
                v.Add(vv => vv[jj]);
            }

            Vector coeff = new Vector(v.Count);

            for (int i = 0; i < v.Count; ++i)
            {
                coeff[i] = rng.next().value;
            }

            List <double> y = new InitializedList <double>(nr, 0.0);
            List <Vector> x = new InitializedList <Vector>(nr);

            for (int i = 0; i < nr; ++i)
            {
                x[i] = new Vector(dims);
                for (int j = 0; j < dims; ++j)
                {
                    x[i][j] = rng.next().value;
                }

                for (int j = 0; j < v.Count; ++j)
                {
                    y[i] += coeff[j] * v[j](x[i]);
                }
                y[i] += rng.next().value;
            }

            LinearLeastSquaresRegression <Vector> m = new LinearLeastSquaresRegression <Vector>(x, y, v);

            for (int i = 0; i < v.Count; ++i)
            {
                if (m.standardErrors()[i] > tolerance)
                {
                    Assert.Fail("Failed to reproduce linear regression coef."
                                + "\n    error:     " + m.standardErrors()[i]
                                + "\n    tolerance: " + tolerance);
                }

                if (Math.Abs(m.coefficients()[i] - coeff[i]) > 3 * tolerance)
                {
                    Assert.Fail("Failed to reproduce linear regression coef."
                                + "\n    calculated: " + m.coefficients()[i]
                                + "\n    error:      " + m.standardErrors()[i]
                                + "\n    expected:   " + coeff[i]);
                }
            }
        }
        public void testCallableEquityPricing()
        {
            // Testing the pricing of a callable equity product

            /*
             * For the definition of the example product see
             * Alexander Giese, On the Pricing of Auto-Callable Equity
             * Structures in the Presence of Stochastic Volatility and
             * Stochastic Interest Rates .
             * http://workshop.mathfinance.de/2006/papers/giese/slides.pdf
             */

            int        maturity = 7;
            DayCounter dc       = new Actual365Fixed();
            Date       today    = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            Handle <Quote> spot             = new Handle <Quote>(new SimpleQuote(100.0));
            SimpleQuote    qRate            = new SimpleQuote(0.04);
            Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, qRate, dc));
            SimpleQuote rRate = new SimpleQuote(0.04);
            Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(today, rRate, dc));

            HestonProcess hestonProcess = new HestonProcess(rTS, qTS, spot, 0.0625, 1.0, 0.24 * 0.24, 1e-4, 0.0);
            // FLOATING_POINT_EXCEPTION
            HullWhiteForwardProcess hwProcess = new HullWhiteForwardProcess(rTS, 0.00883, 0.00526);

            hwProcess.setForwardMeasureTime(dc.yearFraction(today, today + new Period(maturity + 1, TimeUnit.Years)));

            HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess, hwProcess, -0.4);

            Schedule schedule = new Schedule(today, today + new Period(maturity, TimeUnit.Years), new Period(1, TimeUnit.Years),
                                             new TARGET(), BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false);

            List <double> times = new InitializedList <double>(maturity + 1);

            for (int i = 0; i <= maturity; ++i)
            {
                times[i] = i;
            }

            TimeGrid grid = new TimeGrid(times, times.Count);

            List <double> redemption = new InitializedList <double>(maturity);

            for (int i = 0; i < maturity; ++i)
            {
                redemption[i] = 1.07 + 0.03 * i;
            }

            ulong seed = 42;
            IRNG  rsg  = (InverseCumulativeRsg <RandomSequenceGenerator <MersenneTwisterUniformRng>
                                                , InverseCumulativeNormal>)
                         new PseudoRandom().make_sequence_generator(jointProcess.factors() * (grid.size() - 1), seed);

            MultiPathGenerator <IRNG> generator = new MultiPathGenerator <IRNG>(jointProcess, grid, rsg, false);
            GeneralStatistics         stat      = new GeneralStatistics();

            double antitheticPayoff = 0;
            int    nrTrails         = 40000;

            for (int i = 0; i < nrTrails; ++i)
            {
                bool antithetic = (i % 2) != 0;

                Sample <IPath> path  = antithetic ? generator.antithetic() : generator.next();
                MultiPath      value = path.value as MultiPath;
                Utils.QL_REQUIRE(value != null, () => "Invalid Path");

                double payoff = 0;
                for (int j = 1; j <= maturity; ++j)
                {
                    if (value[0][j] > spot.link.value())
                    {
                        Vector states = new Vector(3);
                        for (int k = 0; k < 3; ++k)
                        {
                            states[k] = value[k][j];
                        }
                        payoff = redemption[j - 1] / jointProcess.numeraire(grid[j], states);
                        break;
                    }
                    else if (j == maturity)
                    {
                        Vector states = new Vector(3);
                        for (int k = 0; k < 3; ++k)
                        {
                            states[k] = value[k][j];
                        }
                        payoff = 1.0 / jointProcess.numeraire(grid[j], states);
                    }
                }

                if (antithetic)
                {
                    stat.add(0.5 * (antitheticPayoff + payoff));
                }
                else
                {
                    antitheticPayoff = payoff;
                }
            }

            double expected   = 0.938;
            double calculated = stat.mean();
            double error      = stat.errorEstimate();

            if (Math.Abs(expected - calculated) > 3 * error)
            {
                QAssert.Fail("Failed to reproduce auto-callable equity structure price"
                             + "\n   calculated: " + calculated
                             + "\n   error:      " + error
                             + "\n   expected:   " + expected);
            }
        }
        public void testZeroBondPricing()
        {
            // Testing Monte-Carlo zero bond pricing

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            Settings.Instance.setEvaluationDate(today);

            // construct a strange yield curve to check drifts and discounting
            // of the joint stochastic process

            List <Date>   dates = new List <Date>();
            List <double> times = new List <double>();
            List <double> rates = new List <double>();

            dates.Add(today);
            rates.Add(0.02);
            times.Add(0.0);
            for (int i = 120; i < 240; ++i)
            {
                dates.Add(today + new Period(i, TimeUnit.Months));
                rates.Add(0.02 + 0.0002 * Math.Exp(Math.Sin(i / 8.0)));
                times.Add(dc.yearFraction(today, dates.Last()));
            }

            Date maturity = dates.Last() + new Period(10, TimeUnit.Years);

            dates.Add(maturity);
            rates.Add(0.04);
            //times.Add(dc.yearFraction(today, dates.Last()));

            Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100));

            Handle <YieldTermStructure> ts = new Handle <YieldTermStructure>(new InterpolatedZeroCurve <Linear>(dates, rates, dc));
            Handle <YieldTermStructure> ds = new Handle <YieldTermStructure>(Utilities.flatRate(today, 0.0, dc));

            HestonProcess           hestonProcess = new HestonProcess(ts, ds, s0, 0.02, 1.0, 0.2, 0.5, -0.8);
            HullWhiteForwardProcess hwProcess     = new HullWhiteForwardProcess(ts, 0.05, 0.05);

            hwProcess.setForwardMeasureTime(dc.yearFraction(today, maturity));
            HullWhite hwModel = new HullWhite(ts, 0.05, 0.05);

            HybridHestonHullWhiteProcess jointProcess = new HybridHestonHullWhiteProcess(hestonProcess, hwProcess, -0.4);

            TimeGrid grid = new TimeGrid(times);

            int factors = jointProcess.factors();
            int steps   = grid.size() - 1;
            SobolBrownianBridgeRsg rsg = new SobolBrownianBridgeRsg(factors, steps);
            MultiPathGenerator <SobolBrownianBridgeRsg> generator = new MultiPathGenerator <SobolBrownianBridgeRsg>(
                jointProcess, grid, rsg, false);

            int m = 90;
            List <GeneralStatistics> zeroStat   = new InitializedList <GeneralStatistics>(m);
            List <GeneralStatistics> optionStat = new InitializedList <GeneralStatistics>(m);

            int    nrTrails    = 8191;
            int    optionTenor = 24;
            double strike      = 0.5;

            for (int i = 0; i < nrTrails; ++i)
            {
                Sample <IPath> path  = generator.next();
                MultiPath      value = path.value as MultiPath;
                Utils.QL_REQUIRE(value != null, () => "Invalid Path");

                for (int j = 1; j < m; ++j)
                {
                    double t = grid[j];               // zero end and option maturity
                    double T = grid[j + optionTenor]; // maturity of zero bond
                    // of option

                    Vector states       = new Vector(3);
                    Vector optionStates = new Vector(3);
                    for (int k = 0; k < jointProcess.size(); ++k)
                    {
                        states[k]       = value[k][j];
                        optionStates[k] = value[k][j + optionTenor];
                    }

                    double zeroBond
                        = 1.0 / jointProcess.numeraire(t, states);
                    double zeroOption = zeroBond * Math.Max(0.0, hwModel.discountBond(t, T, states[2]) - strike);

                    zeroStat[j].add(zeroBond);
                    optionStat[j].add(zeroOption);
                }
            }

            for (int j = 1; j < m; ++j)
            {
                double t          = grid[j];
                double calculated = zeroStat[j].mean();
                double expected   = ts.link.discount(t);

                if (Math.Abs(calculated - expected) > 0.03)
                {
                    QAssert.Fail("Failed to reproduce expected zero bond prices"
                                 + "\n   t:          " + t
                                 + "\n   calculated: " + calculated
                                 + "\n   expected:   " + expected);
                }

                double T = grid[j + optionTenor];

                calculated = optionStat[j].mean();
                expected   = hwModel.discountBondOption(Option.Type.Call, strike, t, T);

                if (Math.Abs(calculated - expected) > 0.0035)
                {
                    QAssert.Fail("Failed to reproduce expected zero bond option prices"
                                 + "\n   t:          " + t
                                 + "\n   T:          " + T
                                 + "\n   calculated: " + calculated
                                 + "\n   expected:   " + expected);
                }
            }
        }
Ejemplo n.º 33
0
        public void cpibondconsistency()
        {
            CommonVars common = new CommonVars();

            // ZeroInflationSwap aka CPISwap

            CPISwap.Type type    = CPISwap.Type.Payer;
            double       nominal = 1000000.0;
            bool         subtractInflationNominal = true;
            // float+spread leg
            double                spread                 = 0.0;
            DayCounter            floatDayCount          = new Actual365Fixed();
            BusinessDayConvention floatPaymentConvention = BusinessDayConvention.ModifiedFollowing;
            int       fixingDays = 0;
            IborIndex floatIndex = new GBPLibor(new Period(6, TimeUnit.Months), common.nominalUK);

            // fixed x inflation leg
            double                fixedRate                = 0.1;   //1% would be 0.01
            double                baseCPI                  = 206.1; // would be 206.13871 if we were interpolating
            DayCounter            fixedDayCount            = new Actual365Fixed();
            BusinessDayConvention fixedPaymentConvention   = BusinessDayConvention.ModifiedFollowing;
            Calendar              fixedPaymentCalendar     = new UnitedKingdom();
            ZeroInflationIndex    fixedIndex               = common.ii;
            Period                contractObservationLag   = common.contractObservationLag;
            InterpolationType     observationInterpolation = common.contractObservationInterpolation;

            // set the schedules
            Date     startDate     = new Date(2, Month.October, 2007);
            Date     endDate       = new Date(2, Month.October, 2052);
            Schedule floatSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(floatPaymentConvention)
                                     .backwards().value();
            Schedule fixedSchedule = new MakeSchedule().from(startDate).to(endDate)
                                     .withTenor(new Period(6, TimeUnit.Months))
                                     .withCalendar(new UnitedKingdom())
                                     .withConvention(BusinessDayConvention.Unadjusted)
                                     .backwards().value();

            CPISwap zisV = new CPISwap(type, nominal, subtractInflationNominal,
                                       spread, floatDayCount, floatSchedule,
                                       floatPaymentConvention, fixingDays, floatIndex,
                                       fixedRate, baseCPI, fixedDayCount, fixedSchedule,
                                       fixedPaymentConvention, contractObservationLag,
                                       fixedIndex, observationInterpolation);

            double[] floatFix = { 0.06255, 0.05975, 0.0637, 0.018425, 0.0073438, -1, -1 };
            double[] cpiFix   = { 211.4, 217.2, 211.4, 213.4, -2, -2 };
            for (int i = 0; i < floatSchedule.Count; i++)
            {
                if (floatSchedule[i] < common.evaluationDate)
                {
                    floatIndex.addFixing(floatSchedule[i], floatFix[i], true);//true=overwrite
                }

                CPICoupon zic = zisV.cpiLeg()[i] as CPICoupon;
                if (zic != null)
                {
                    if (zic.fixingDate() < (common.evaluationDate - new Period(1, TimeUnit.Months)))
                    {
                        fixedIndex.addFixing(zic.fixingDate(), cpiFix[i], true);
                    }
                }
            }

            // simple structure so simple pricing engine - most work done by index
            DiscountingSwapEngine dse = new DiscountingSwapEngine(common.nominalUK);

            zisV.setPricingEngine(dse);

            // now do the bond equivalent
            List <double> fixedRates     = new InitializedList <double>(1, fixedRate);
            int           settlementDays = 1;// cannot be zero!
            bool          growthOnly     = true;
            CPIBond       cpiB           = new CPIBond(settlementDays, nominal, growthOnly,
                                                       baseCPI, contractObservationLag, fixedIndex,
                                                       observationInterpolation, fixedSchedule,
                                                       fixedRates, fixedDayCount, fixedPaymentConvention);

            DiscountingBondEngine dbe = new DiscountingBondEngine(common.nominalUK);

            cpiB.setPricingEngine(dbe);

            QAssert.IsTrue(Math.Abs(cpiB.NPV() - zisV.legNPV(0).GetValueOrDefault()) < 1e-5,
                           "cpi bond does not equal equivalent cpi swap leg");
            // remove circular refernce
            common.hcpi.linkTo(null);
        }
Ejemplo n.º 34
0
 public LoanPricingEngineResults()
 {
     legNPV = new InitializedList <double?>();
 }
Ejemplo n.º 35
0
        public void testSpreadDependency()
        {
            //"Testing swaption dependency on spread...";

            CommonVars vars = new CommonVars();

            double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 };

            for (int i=0; i<exercises.Length ; i++) {
                for (int j=0; j<lengths.Length ; j++) {
                    for (int k=0; k<type.Length ; k++) {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                                  exercises[i]);
                        Date startDate =
                            vars.calendar.advance(exerciseDate,
                                                  vars.settlementDays,TimeUnit.Days);
                        // store the results for different rates...
                        List<double> values=new InitializedList<double>(spreads.Length);
                        List<double> values_cash = new InitializedList<double>(spreads.Length);
                        for (int l=0; l<spreads.Length; l++) {
                             VanillaSwap swap =
                               new MakeVanillaSwap(lengths[j], vars.index, 0.06)
                                        .withEffectiveDate(startDate)
                                        .withFloatingLegSpread(spreads[l])
                                        .withType(type[k]);
                             Swaption swaption =
                                vars.makeSwaption(swap,exerciseDate,0.20);
                            // FLOATING_POINT_EXCEPTION
                            values[l]=swaption.NPV();
                            Swaption swaption_cash =
                                vars.makeSwaption(swap,exerciseDate,0.20,
                                                  Settlement.Type.Cash);
                            values_cash[l]=swaption_cash.NPV();
                        }
                        // and check that they go the right way
                        if (type[k]==VanillaSwap.Type.Payer) {
                            for (int n = 0; n < spreads.Length - 1; n++)
                            {
                                if (values[n] > values[n + 1])
                                    Assert.Fail("NPV is decreasing with the spread " +
                                        "in a payer swaption (physical delivered):" +
                                        "\nexercise date: " + exerciseDate +
                                        "\nlength:        " + lengths[j] +
                                        "\nvalue:         " + values[n] + " for spread: " + spreads[n] +
                                        "\nvalue:         " + values[n + 1] + " for spread: " + spreads[n + 1]);

                                if (values_cash[n] > values_cash[n + 1])
                                    Assert.Fail("NPV is decreasing with the spread " +
                                        "in a payer swaption (cash delivered):" +
                                        "\nexercise date: " + exerciseDate +
                                        "\nlength: " + lengths[j] +
                                        "\nvalue:  " + values_cash[n] + " for spread: " + spreads[n] +
                                        "\nvalue:  " + values_cash[n + 1] + " for spread: " + spreads[n + 1]);
                            }
                        }
                        else
                        {
                            for (int n = 0; n < spreads.Length - 1; n++)
                            {
                                if (values[n] < values[n + 1])
                                    Assert.Fail("NPV is increasing with the spread " +
                                        "in a receiver swaption (physical delivered):" +
                                        "\nexercise date: " + exerciseDate +
                                        "\nlength: " + lengths[j] +
                                        "\nvalue:  " + values[n] + " for spread: " + spreads[n] +
                                        "\nvalue:  " + values[n + 1] + " for spread: " + spreads[n + 1]);

                                if (values_cash[n] < values_cash[n+1])
                                Assert.Fail("NPV is increasing with the spread " +
                                    "in a receiver swaption (cash delivered):" +
                                    "\nexercise date: " + exerciseDate +
                                    "\nlength: " + lengths[j] +
                                    "\nvalue:  " + values_cash[n  ] + " for spread: " + spreads[n] +
                                    "\nvalue:  " + values_cash[n+1] + " for spread: " + spreads[n+1]);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 36
0
        public void testSwaptionPricing()
        {
            // Testing forward swap and swaption pricing
            const int size  = 10;
            const int steps = 8 * size;

#if QL_USE_INDEXED_COUPON
            const double tolerance = 1e-6;
#else
            const double tolerance = 1e-12;
#endif

            List <Date>   dates = new List <Date>();
            List <double> rates = new List <double>();
            dates.Add(new Date(4, 9, 2005));
            dates.Add(new Date(4, 9, 2011));
            rates.Add(0.04);
            rates.Add(0.08);

            IborIndex index = makeIndex(dates, rates);

            LiborForwardModelProcess process = new LiborForwardModelProcess(size, index);

            LmCorrelationModel corrModel = new LmExponentialCorrelationModel(size, 0.5);

            LmVolatilityModel volaModel = new LmLinearExponentialVolatilityModel(process.fixingTimes(),
                                                                                 0.291, 1.483, 0.116, 0.00001);

            // set-up pricing engine
            process.setCovarParam((LfmCovarianceParameterization)
                                  new LfmCovarianceProxy(volaModel, corrModel));

            // set-up a small Monte-Carlo simulation to price swations
            List <double> tmp = process.fixingTimes();

            TimeGrid grid = new TimeGrid(tmp, tmp.Count, steps);

            List <int> location = new List <int>();
            for (int i = 0; i < tmp.Count; ++i)
            {
                location.Add(grid.index(tmp[i]));
            }

            ulong     seed     = 42;
            const int nrTrails = 5000;
            LowDiscrepancy.icInstance = new InverseCumulativeNormal();

            IRNG rsg = (InverseCumulativeRsg <RandomSequenceGenerator <MersenneTwisterUniformRng>
                                              , InverseCumulativeNormal>)
                       new PseudoRandom().make_sequence_generator(process.factors() * (grid.size() - 1), seed);



            MultiPathGenerator <IRNG> generator = new MultiPathGenerator <IRNG>(process,
                                                                                grid,
                                                                                rsg, false);

            LiborForwardModel liborModel = new LiborForwardModel(process, volaModel, corrModel);

            Calendar              calendar   = index.fixingCalendar();
            DayCounter            dayCounter = index.forwardingTermStructure().link.dayCounter();
            BusinessDayConvention convention = index.businessDayConvention();

            Date settlement = index.forwardingTermStructure().link.referenceDate();

            SwaptionVolatilityMatrix m = liborModel.getSwaptionVolatilityMatrix();

            for (int i = 1; i < size; ++i)
            {
                for (int j = 1; j <= size - i; ++j)
                {
                    Date fwdStart    = settlement + new Period(6 * i, TimeUnit.Months);
                    Date fwdMaturity = fwdStart + new Period(6 * j, TimeUnit.Months);

                    Schedule schedule = new Schedule(fwdStart, fwdMaturity, index.tenor(), calendar,
                                                     convention, convention, DateGeneration.Rule.Forward, false);

                    double      swapRate    = 0.0404;
                    VanillaSwap forwardSwap = new VanillaSwap(VanillaSwap.Type.Receiver, 1.0,
                                                              schedule, swapRate, dayCounter,
                                                              schedule, index, 0.0, index.dayCounter());
                    forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure()));

                    // check forward pricing first
                    double expected   = forwardSwap.fairRate();
                    double calculated = liborModel.S_0(i - 1, i + j - 1);

                    if (Math.Abs(expected - calculated) > tolerance)
                    {
                        QAssert.Fail("Failed to reproduce fair forward swap rate"
                                     + "\n    calculated: " + calculated
                                     + "\n    expected:   " + expected);
                    }

                    swapRate    = forwardSwap.fairRate();
                    forwardSwap =
                        new VanillaSwap(VanillaSwap.Type.Receiver, 1.0,
                                        schedule, swapRate, dayCounter,
                                        schedule, index, 0.0, index.dayCounter());
                    forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure()));

                    if (i == j && i <= size / 2)
                    {
                        IPricingEngine engine =
                            new LfmSwaptionEngine(liborModel, index.forwardingTermStructure());
                        Exercise exercise =
                            new EuropeanExercise(process.fixingDates()[i]);

                        Swaption swaption =
                            new Swaption(forwardSwap, exercise);
                        swaption.setPricingEngine(engine);

                        GeneralStatistics stat = new GeneralStatistics();

                        for (int n = 0; n < nrTrails; ++n)
                        {
                            Sample <IPath> path = (n % 2 != 0) ? generator.antithetic()
                                          : generator.next();
                            MultiPath value = path.value as MultiPath;
                            Utils.QL_REQUIRE(value != null, () => "Invalid Path");
                            //Sample<MultiPath> path = generator.next();
                            List <double> rates_ = new InitializedList <double>(size);
                            for (int k = 0; k < process.size(); ++k)
                            {
                                rates_[k] = value[k][location[i]];
                            }
                            List <double> dis = process.discountBond(rates_);

                            double npv = 0.0;
                            for (int k = i; k < i + j; ++k)
                            {
                                npv += (swapRate - rates_[k])
                                       * (process.accrualEndTimes()[k]
                                          - process.accrualStartTimes()[k]) * dis[k];
                            }
                            stat.add(Math.Max(npv, 0.0));
                        }

                        if (Math.Abs(swaption.NPV() - stat.mean())
                            > stat.errorEstimate() * 2.35)
                        {
                            QAssert.Fail("Failed to reproduce swaption npv"
                                         + "\n    calculated: " + stat.mean()
                                         + "\n    expected:   " + swaption.NPV());
                        }
                    }
                }
            }
        }
Ejemplo n.º 37
0
        public void testBrazilianCached()
        {
            //("Testing Brazilian public bond prices against cached values...");

             CommonVars vars = new CommonVars();

             double faceAmount = 1000.0;
             double redemption = 100.0;
             Date issueDate = new Date(1, Month.January, 2007);

             Date today = new Date(6, Month.June, 2007);
             Settings.setEvaluationDate(today);

             // NTN-F maturity dates
             InitializedList<Date> maturityDates = new InitializedList<Date>(6);
             maturityDates[0] = new Date(1, Month.January, 2008);
             maturityDates[1] = new Date(1, Month.January, 2010);
             maturityDates[2] = new Date(1, Month.July, 2010);
             maturityDates[3] = new Date(1, Month.January, 2012);
             maturityDates[4] = new Date(1, Month.January, 2014);
             maturityDates[5] = new Date(1, Month.January, 2017);

             // NTN-F yields
             InitializedList<double> yields = new InitializedList<double>(6);
             yields[0] = 0.114614;
             yields[1] = 0.105726;
             yields[2] = 0.105328;
             yields[3] = 0.104283;
             yields[4] = 0.103218;
             yields[5] = 0.102948;

             // NTN-F prices
             InitializedList<double> prices = new InitializedList<double>(6);
             prices[0] = 1034.63031372;
             prices[1] = 1030.09919487;
             prices[2] = 1029.98307160;
             prices[3] = 1028.13585068;
             prices[4] = 1028.33383817;
             prices[5] = 1026.19716497;

             int settlementDays = 1;
             vars.faceAmount = 1000.0;

             // The tolerance is high because Andima truncate yields
             double tolerance = 1.0e-4;

             InitializedList<InterestRate> couponRates = new InitializedList<InterestRate>(1);
             couponRates[0] = new InterestRate(0.1, new Thirty360(), Compounding.Compounded, Frequency.Annual);

             for (int bondIndex = 0; bondIndex < maturityDates.Count; bondIndex++)
             {

            // plain
            InterestRate yield = new InterestRate(yields[bondIndex], new Business252(new Brazil()),
                                                  Compounding.Compounded, Frequency.Annual);

            Schedule schedule = new Schedule(new Date(1, Month.January, 2007),
                              maturityDates[bondIndex], new Period(Frequency.Semiannual),
                              new Brazil(Brazil.Market.Settlement),
                              BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                              DateGeneration.Rule.Backward, false);

            FixedRateBond bond = new FixedRateBond(settlementDays,
                                                   faceAmount,
                                                   schedule,
                                                   couponRates,
                                                   BusinessDayConvention.Following,
                                                   redemption,
                                                   issueDate);

            double cachedPrice = prices[bondIndex];

            double price = vars.faceAmount * (bond.cleanPrice(yield.rate(),
                                                         yield.dayCounter(),
                                                         yield.compounding(),
                                                         yield.frequency(),
                                                         today) + bond.accruedAmount(today)) / 100;
            if (Math.Abs(price - cachedPrice) > tolerance)
            {
               Assert.Fail("failed to reproduce cached price:\n"
                           + "    calculated: " + price + "\n"
                           + "    expected:   " + cachedPrice + "\n"
                           + "    error:      " + (price - cachedPrice) + "\n"
                           );
            }
             }
        }
Ejemplo n.º 38
0
        static void Main(string[] args)
        {
            DateTime timer = DateTime.Now;

            /*********************
            ***  MARKET DATA  ***
            *********************/

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(18, Month.September, 2008);

            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int fixingDays     = 3;
            int settlementDays = 3;

            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);

            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);

            Console.WriteLine("Today: {0}, {1}", todaysDate.DayOfWeek, todaysDate);
            Console.WriteLine("Settlement date: {0}, {1}", settlementDate.DayOfWeek, settlementDate);


            // Building of the bonds discounting yield curve

            /*********************
            ***  RATE HELPERS ***
            *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // Common data

            // ZC rates for the short end
            double zc3mQuote = 0.0096;
            double zc6mQuote = 0.0145;
            double zc1yQuote = 0.0194;

            Quote zc3mRate = new SimpleQuote(zc3mQuote);
            Quote zc6mRate = new SimpleQuote(zc6mQuote);
            Quote zc1yRate = new SimpleQuote(zc1yQuote);

            DayCounter zcBondsDayCounter = new Actual365Fixed();

            RateHelper zc3m = new DepositRateHelper(new Handle <Quote>(zc3mRate),
                                                    new Period(3, TimeUnit.Months), fixingDays,
                                                    calendar, BusinessDayConvention.ModifiedFollowing,
                                                    true, zcBondsDayCounter);
            RateHelper zc6m = new DepositRateHelper(new Handle <Quote>(zc6mRate),
                                                    new Period(6, TimeUnit.Months), fixingDays,
                                                    calendar, BusinessDayConvention.ModifiedFollowing,
                                                    true, zcBondsDayCounter);
            RateHelper zc1y = new DepositRateHelper(new Handle <Quote>(zc1yRate),
                                                    new Period(1, TimeUnit.Years), fixingDays,
                                                    calendar, BusinessDayConvention.ModifiedFollowing,
                                                    true, zcBondsDayCounter);

            // setup bonds
            double redemption = 100.0;

            const int numberOfBonds = 5;

            Date[] issueDates =
            {
                new Date(15, Month.March,    2005),
                new Date(15, Month.June,     2005),
                new Date(30, Month.June,     2006),
                new Date(15, Month.November, 2002),
                new Date(15, Month.May, 1987)
            };

            Date[] maturities =
            {
                new Date(31, Month.August, 2010),
                new Date(31, Month.August, 2011),
                new Date(31, Month.August, 2013),
                new Date(15, Month.August, 2018),
                new Date(15, Month.May, 2038)
            };

            double[] couponRates =
            {
                0.02375,
                0.04625,
                0.03125,
                0.04000,
                0.04500
            };

            double[] marketQuotes =
            {
                100.390625,
                106.21875,
                100.59375,
                101.6875,
                102.140625
            };

            List <SimpleQuote> quote = new List <SimpleQuote>();

            for (int i = 0; i < numberOfBonds; i++)
            {
                SimpleQuote cp = new SimpleQuote(marketQuotes[i]);
                quote.Add(cp);
            }

            List <RelinkableHandle <Quote> > quoteHandle = new InitializedList <RelinkableHandle <Quote> >(numberOfBonds);

            for (int i = 0; i < numberOfBonds; i++)
            {
                quoteHandle[i].linkTo(quote[i]);
            }

            // Definition of the rate helpers
            List <FixedRateBondHelper> bondsHelpers = new List <FixedRateBondHelper>();

            for (int i = 0; i < numberOfBonds; i++)
            {
                Schedule schedule = new Schedule(issueDates[i], maturities[i], new Period(Frequency.Semiannual),
                                                 new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                                 DateGeneration.Rule.Backward, false);

                FixedRateBondHelper bondHelper = new FixedRateBondHelper(quoteHandle[i],
                                                                         settlementDays,
                                                                         100.0,
                                                                         schedule,
                                                                         new List <double>()
                {
                    couponRates[i]
                },
                                                                         new ActualActual(ActualActual.Convention.Bond),
                                                                         BusinessDayConvention.Unadjusted,
                                                                         redemption,
                                                                         issueDates[i]);

                bondsHelpers.Add(bondHelper);
            }

            /*********************
            **  CURVE BUILDING **
            *********************/

            // Any DayCounter would be fine.
            // ActualActual::ISDA ensures that 30 years is 30.0
            DayCounter termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA);

            double tolerance = 1.0e-15;

            // A depo-bond curve
            List <RateHelper> bondInstruments = new List <RateHelper>();

            // Adding the ZC bonds to the curve for the short end
            bondInstruments.Add(zc3m);
            bondInstruments.Add(zc6m);
            bondInstruments.Add(zc1y);

            // Adding the Fixed rate bonds to the curve for the long end
            for (int i = 0; i < numberOfBonds; i++)
            {
                bondInstruments.Add(bondsHelpers[i]);
            }

            YieldTermStructure bondDiscountingTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, bondInstruments,
                termStructureDayCounter,
                new List <Handle <Quote> >(),
                new List <Date>(),
                tolerance);

            // Building of the Libor forecasting curve
            // deposits
            double d1wQuote = 0.043375;
            double d1mQuote = 0.031875;
            double d3mQuote = 0.0320375;
            double d6mQuote = 0.03385;
            double d9mQuote = 0.0338125;
            double d1yQuote = 0.0335125;
            // swaps
            double s2yQuote  = 0.0295;
            double s3yQuote  = 0.0323;
            double s5yQuote  = 0.0359;
            double s10yQuote = 0.0412;
            double s15yQuote = 0.0433;


            /********************
            ***    QUOTES    ***
            ********************/

            // SimpleQuote stores a value which can be manually changed;
            // other Quote subclasses could read the value from a database
            // or some kind of data feed.

            // deposits
            Quote d1wRate = new SimpleQuote(d1wQuote);
            Quote d1mRate = new SimpleQuote(d1mQuote);
            Quote d3mRate = new SimpleQuote(d3mQuote);
            Quote d6mRate = new SimpleQuote(d6mQuote);
            Quote d9mRate = new SimpleQuote(d9mQuote);
            Quote d1yRate = new SimpleQuote(d1yQuote);
            // swaps
            Quote s2yRate  = new SimpleQuote(s2yQuote);
            Quote s3yRate  = new SimpleQuote(s3yQuote);
            Quote s5yRate  = new SimpleQuote(s5yQuote);
            Quote s10yRate = new SimpleQuote(s10yQuote);
            Quote s15yRate = new SimpleQuote(s15yQuote);

            /*********************
            ***  RATE HELPERS ***
            *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // deposits
            DayCounter depositDayCounter = new Actual360();

            RateHelper d1w = new DepositRateHelper(
                new Handle <Quote>(d1wRate),
                new Period(1, TimeUnit.Weeks), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d1m = new DepositRateHelper(
                new Handle <Quote>(d1mRate),
                new Period(1, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d3m = new DepositRateHelper(
                new Handle <Quote>(d3mRate),
                new Period(3, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d6m = new DepositRateHelper(
                new Handle <Quote>(d6mRate),
                new Period(6, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d9m = new DepositRateHelper(
                new Handle <Quote>(d9mRate),
                new Period(9, TimeUnit.Months), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);
            RateHelper d1y = new DepositRateHelper(
                new Handle <Quote>(d1yRate),
                new Period(1, TimeUnit.Years), fixingDays,
                calendar, BusinessDayConvention.ModifiedFollowing,
                true, depositDayCounter);

            // setup swaps
            Frequency             swFixedLegFrequency  = Frequency.Annual;
            BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
            DayCounter            swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
            IborIndex             swFloatingLegIndex   = new Euribor6M();

            Period forwardStart = new Period(1, TimeUnit.Days);

            RateHelper s2y = new SwapRateHelper(
                new Handle <Quote>(s2yRate), new Period(2, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s3y = new SwapRateHelper(
                new Handle <Quote>(s3yRate), new Period(3, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s5y = new SwapRateHelper(
                new Handle <Quote>(s5yRate), new Period(5, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s10y = new SwapRateHelper(
                new Handle <Quote>(s10yRate), new Period(10, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);
            RateHelper s15y = new SwapRateHelper(
                new Handle <Quote>(s15yRate), new Period(15, TimeUnit.Years),
                calendar, swFixedLegFrequency,
                swFixedLegConvention, swFixedLegDayCounter,
                swFloatingLegIndex, new Handle <Quote>(), forwardStart);


            /*********************
            **  CURVE BUILDING **
            *********************/

            // Any DayCounter would be fine.
            // ActualActual::ISDA ensures that 30 years is 30.0

            // A depo-swap curve
            List <RateHelper> depoSwapInstruments = new List <RateHelper>();

            depoSwapInstruments.Add(d1w);
            depoSwapInstruments.Add(d1m);
            depoSwapInstruments.Add(d3m);
            depoSwapInstruments.Add(d6m);
            depoSwapInstruments.Add(d9m);
            depoSwapInstruments.Add(d1y);
            depoSwapInstruments.Add(s2y);
            depoSwapInstruments.Add(s3y);
            depoSwapInstruments.Add(s5y);
            depoSwapInstruments.Add(s10y);
            depoSwapInstruments.Add(s15y);
            YieldTermStructure depoSwapTermStructure = new PiecewiseYieldCurve <Discount, LogLinear>(
                settlementDate, depoSwapInstruments,
                termStructureDayCounter,
                new List <Handle <Quote> >(),
                new List <Date>(),
                tolerance);

            // Term structures that will be used for pricing:
            // the one used for discounting cash flows
            RelinkableHandle <YieldTermStructure> discountingTermStructure = new RelinkableHandle <YieldTermStructure>();
            // the one used for forward rate forecasting
            RelinkableHandle <YieldTermStructure> forecastingTermStructure = new RelinkableHandle <YieldTermStructure>();

            /*********************
             * BONDS TO BE PRICED *
             **********************/

            // Common data
            double faceAmount = 100;

            // Pricing engine
            IPricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);

            // Zero coupon bond
            ZeroCouponBond zeroCouponBond = new ZeroCouponBond(
                settlementDays,
                new UnitedStates(UnitedStates.Market.GovernmentBond),
                faceAmount,
                new Date(15, Month.August, 2013),
                BusinessDayConvention.Following,
                116.92,
                new Date(15, Month.August, 2003));

            zeroCouponBond.setPricingEngine(bondEngine);

            // Fixed 4.5% US Treasury Note
            Schedule fixedBondSchedule = new Schedule(new Date(15, Month.May, 2007),
                                                      new Date(15, Month.May, 2017), new Period(Frequency.Semiannual),
                                                      new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                      BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

            FixedRateBond fixedRateBond = new FixedRateBond(
                settlementDays,
                faceAmount,
                fixedBondSchedule,
                new List <double>()
            {
                0.045
            },
                new ActualActual(ActualActual.Convention.Bond),
                BusinessDayConvention.ModifiedFollowing,
                100.0, new Date(15, Month.May, 2007));

            fixedRateBond.setPricingEngine(bondEngine);

            // Floating rate bond (3M USD Libor + 0.1%)
            // Should and will be priced on another curve later...

            RelinkableHandle <YieldTermStructure> liborTermStructure = new RelinkableHandle <YieldTermStructure>();
            IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);

            libor3m.addFixing(new Date(17, Month.July, 2008), 0.0278625);

            Schedule floatingBondSchedule = new Schedule(new Date(21, Month.October, 2005),
                                                         new Date(21, Month.October, 2010), new Period(Frequency.Quarterly),
                                                         new UnitedStates(UnitedStates.Market.NYSE),
                                                         BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true);

            FloatingRateBond floatingRateBond = new FloatingRateBond(
                settlementDays,
                faceAmount,
                floatingBondSchedule,
                libor3m,
                new Actual360(),
                BusinessDayConvention.ModifiedFollowing,
                2,
                // Gearings
                new List <double>()
            {
                1.0
            },
                // Spreads
                new List <double>()
            {
                0.001
            },
                // Caps
                new List <double?>(),
                // Floors
                new List <double?>(),
                // Fixing in arrears
                true,
                100.0,
                new Date(21, Month.October, 2005));

            floatingRateBond.setPricingEngine(bondEngine);

            // Coupon pricers
            IborCouponPricer pricer = new BlackIborCouponPricer();

            // optionLet volatilities
            double volatility = 0.0;
            Handle <OptionletVolatilityStructure> vol;

            vol = new Handle <OptionletVolatilityStructure>(
                new ConstantOptionletVolatility(
                    settlementDays,
                    calendar,
                    BusinessDayConvention.ModifiedFollowing,
                    volatility,
                    new Actual365Fixed()));

            pricer.setCapletVolatility(vol);
            Utils.setCouponPricer(floatingRateBond.cashflows(), pricer);

            // Yield curve bootstrapping
            forecastingTermStructure.linkTo(depoSwapTermStructure);
            discountingTermStructure.linkTo(bondDiscountingTermStructure);

            // We are using the depo & swap curve to estimate the future Libor rates
            liborTermStructure.linkTo(depoSwapTermStructure);

            /***************
             * BOND PRICING *
             ****************/

            // write column headings
            int[] widths = { 18, 10, 10, 10 };

            Console.WriteLine("{0,18}{1,10}{2,10}{3,10}", "", "ZC", "Fixed", "Floating");

            int width = widths[0]
                        + widths[1]
                        + widths[2]
                        + widths[3];
            string rule = "".PadLeft(width, '-'), dblrule = "".PadLeft(width, '=');
            string tab = "".PadLeft(8, ' ');

            Console.WriteLine(rule);

            Console.WriteLine("Net present value".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.NPV(),
                              fixedRateBond.NPV(),
                              floatingRateBond.NPV());

            Console.WriteLine("Clean price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.cleanPrice(),
                              fixedRateBond.cleanPrice(),
                              floatingRateBond.cleanPrice());

            Console.WriteLine("Dirty price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.dirtyPrice(),
                              fixedRateBond.dirtyPrice(),
                              floatingRateBond.dirtyPrice());

            Console.WriteLine("Accrued coupon".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                              zeroCouponBond.accruedAmount(),
                              fixedRateBond.accruedAmount(),
                              floatingRateBond.accruedAmount());

            Console.WriteLine("Previous coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.previousCouponRate(),
                              floatingRateBond.previousCouponRate());

            Console.WriteLine("Next coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.nextCouponRate(),
                              floatingRateBond.nextCouponRate());

            Console.WriteLine("Yield".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual));

            Console.WriteLine();

            // Other computations
            Console.WriteLine("Sample indirect computations (for the floating rate bond): ");
            Console.WriteLine(rule);

            Console.WriteLine("Yield to Clean Price: {0:n2}",
                              floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                                                          new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                          settlementDate));

            Console.WriteLine("Clean Price to Yield: {0:0.00%}",
                              floatingRateBond.yield(floatingRateBond.cleanPrice(), new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                     settlementDate));

            /* "Yield to Price"
            *  "Price to Yield" */

            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Ejemplo n.º 39
0
        public void testCachedFloating()
        {
            // "Testing floating-rate bond prices against cached values...");

             CommonVars vars = new CommonVars();

             Date today = new Date(22, Month.November, 2004);
             Settings.setEvaluationDate(today);

             int settlementDays = 1;

             var riskFreeRate = new Handle<YieldTermStructure>(Utilities.flatRate(today, 0.025, new Actual360()));
             var discountCurve = new Handle<YieldTermStructure>(Utilities.flatRate(today, 0.03, new Actual360()));

             IborIndex index = new USDLibor(new Period(6, TimeUnit.Months), riskFreeRate);
             int fixingDays = 1;

             double tolerance = 1.0e-6;

             IborCouponPricer pricer = new BlackIborCouponPricer(new Handle<OptionletVolatilityStructure>());

             // plain
             Schedule sch = new Schedule(new Date(30, Month.November, 2004), new Date(30, Month.November, 2008),
                                     new Period(Frequency.Semiannual), new UnitedStates(UnitedStates.Market.GovernmentBond),
                                     BusinessDayConvention.ModifiedFollowing, BusinessDayConvention.ModifiedFollowing,
                                     DateGeneration.Rule.Backward, false);

             FloatingRateBond bond1 = new FloatingRateBond(settlementDays, vars.faceAmount, sch,
                                index, new ActualActual(ActualActual.Convention.ISMA),
                                BusinessDayConvention.ModifiedFollowing, fixingDays,
                                new List<double>(), new List<double>(),
                                new List<double>(), new List<double>(),
                                false,
                                100.0, new Date(30, Month.November, 2004));

             IPricingEngine bondEngine = new DiscountingBondEngine(riskFreeRate);
             bond1.setPricingEngine(bondEngine);

             Utils.setCouponPricer(bond1.cashflows(), pricer);

            #if QL_USE_INDEXED_COUPON
            double cachedPrice1 = 99.874645;
            #else
             double cachedPrice1 = 99.874646;
            #endif

             double price = bond1.cleanPrice();
             if (Math.Abs(price - cachedPrice1) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:\n"
                       + "    calculated: " + price + "\n"
                       + "    expected:   " + cachedPrice1 + "\n"
                       + "    error:      " + (price - cachedPrice1));
             }

             // different risk-free and discount curve
             FloatingRateBond bond2 = new FloatingRateBond(settlementDays, vars.faceAmount, sch,
                                index, new ActualActual(ActualActual.Convention.ISMA),
                                BusinessDayConvention.ModifiedFollowing, fixingDays,
                                new List<double>(), new List<double>(),
                                new List<double>(), new List<double>(),
                                false,
                                100.0, new Date(30, Month.November, 2004));

             IPricingEngine bondEngine2 = new DiscountingBondEngine(discountCurve);
             bond2.setPricingEngine(bondEngine2);

             Utils.setCouponPricer(bond2.cashflows(), pricer);

            #if QL_USE_INDEXED_COUPON
            double cachedPrice2 = 97.955904;
            #else
             double cachedPrice2 = 97.955904;
            #endif

             price = bond2.cleanPrice();
             if (Math.Abs(price - cachedPrice2) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:\n"
                       + "    calculated: " + price + "\n"
                       + "    expected:   " + cachedPrice2 + "\n"
                       + "    error:      " + (price - cachedPrice2));
             }

             // varying spread
             InitializedList<double> spreads = new InitializedList<double>(4);
             spreads[0] = 0.001;
             spreads[1] = 0.0012;
             spreads[2] = 0.0014;
             spreads[3] = 0.0016;

             FloatingRateBond bond3 = new FloatingRateBond(settlementDays, vars.faceAmount, sch,
                                index, new ActualActual(ActualActual.Convention.ISMA),
                                BusinessDayConvention.ModifiedFollowing, fixingDays,
                                new List<double>(), spreads,
                                new List<double>(), new List<double>(),
                                false,
                                100.0, new Date(30, Month.November, 2004));

             bond3.setPricingEngine(bondEngine2);

             Utils.setCouponPricer(bond3.cashflows(), pricer);

            #if QL_USE_INDEXED_COUPON
            double cachedPrice3 = 98.495458;
            #else
             double cachedPrice3 = 98.495459;
            #endif

             price = bond3.cleanPrice();
             if (Math.Abs(price - cachedPrice3) > tolerance)
             {
            Assert.Fail("failed to reproduce cached price:\n"
                       + "    calculated: " + price + "\n"
                       + "    expected:   " + cachedPrice3 + "\n"
                       + "    error:      " + (price - cachedPrice3));
             }
        }
Ejemplo n.º 40
0
        public void testDecomposition()
        {
            // Testing collared coupon against its decomposition...

            CommonVars vars = new CommonVars();

            double        tolerance = 1e-10;
            double        npvVanilla, npvCappedLeg, npvFlooredLeg, npvCollaredLeg, npvCap, npvFloor, npvCollar;
            double        error;
            double        floorstrike = 0.05;
            double        capstrike   = 0.10;
            List <double> caps        = new InitializedList <double>(vars.length, capstrike);
            List <double> caps0       = new List <double>();
            List <double> floors      = new InitializedList <double>(vars.length, floorstrike);
            List <double> floors0     = new List <double>();
            double        gearing_p   = 0.5;
            double        spread_p    = 0.002;
            double        gearing_n   = -1.5;
            double        spread_n    = 0.12;
            // fixed leg with zero rate
            List <CashFlow> fixedLeg = vars.makeFixedLeg(vars.startDate, vars.length);
            // floating leg with gearing=1 and spread=0
            List <CashFlow> floatLeg = vars.makeYoYLeg(vars.startDate, vars.length);
            // floating leg with positive gearing (gearing_p) and spread<>0
            List <CashFlow> floatLeg_p = vars.makeYoYLeg(vars.startDate, vars.length, gearing_p, spread_p);
            // floating leg with negative gearing (gearing_n) and spread<>0
            List <CashFlow> floatLeg_n = vars.makeYoYLeg(vars.startDate, vars.length, gearing_n, spread_n);
            // Swap with null fixed leg and floating leg with gearing=1 and spread=0
            Swap vanillaLeg = new Swap(fixedLeg, floatLeg);
            // Swap with null fixed leg and floating leg with positive gearing and spread<>0
            Swap vanillaLeg_p = new Swap(fixedLeg, floatLeg_p);
            // Swap with null fixed leg and floating leg with negative gearing and spread<>0
            Swap vanillaLeg_n = new Swap(fixedLeg, floatLeg_n);

            IPricingEngine engine = new DiscountingSwapEngine(vars.nominalTS);

            vanillaLeg.setPricingEngine(engine); // here use the autoset feature
            vanillaLeg_p.setPricingEngine(engine);
            vanillaLeg_n.setPricingEngine(engine);

            // CAPPED coupon - Decomposition of payoff
            // Payoff = Nom * Min(rate,strike) * accrualperiod =
            // = Nom * [rate + Min(0,strike-rate)] * accrualperiod =
            // = Nom * rate * accrualperiod - Nom * Max(rate-strike,0) * accrualperiod =
            // = VanillaFloatingLeg - Call
            //

            int whichPricer = 0;

            // Case gearing = 1 and spread = 0
            List <CashFlow> cappedLeg = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length,
                                                                  caps, floors0, vars.volatility);
            Swap capLeg = new Swap(fixedLeg, cappedLeg);

            capLeg.setPricingEngine(engine);
            YoYInflationCap cap = new YoYInflationCap(floatLeg, new List <double>()
            {
                capstrike
            });

            cap.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla   = vanillaLeg.NPV();
            npvCappedLeg = capLeg.NPV();
            npvCap       = cap.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=1, spread=0%, strike=" + capstrike * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = 1 and spread = 0
            // FLOORED coupon - Decomposition of payoff
            // Payoff = Nom * Max(rate,strike) * accrualperiod =
            // = Nom * [rate + Max(0,strike-rate)] * accrualperiod =
            // = Nom * rate * accrualperiod + Nom * Max(strike-rate,0) * accrualperiod =
            // = VanillaFloatingLeg + Put
            //

            List <CashFlow> flooredLeg = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length,
                                                                   caps0, floors, vars.volatility);
            Swap floorLeg = new Swap(fixedLeg, flooredLeg);

            floorLeg.setPricingEngine(engine);
            YoYInflationFloor floor = new YoYInflationFloor(floatLeg, new List <double>()
            {
                floorstrike
            });

            floor.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvFlooredLeg = floorLeg.NPV();
            npvFloor      = floor.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("YoY Floored Leg: gearing=1, spread=0%, strike=" + floorstrike * 100 +
                             "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = 1 and spread = 0
            // COLLARED coupon - Decomposition of payoff
            // Payoff = Nom * Min(strikem,Max(rate,strikeM)) * accrualperiod =
            // = VanillaFloatingLeg - Collar
            //

            List <CashFlow> collaredLeg = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length,
                                                                    caps, floors, vars.volatility);
            Swap collarLeg = new Swap(fixedLeg, collaredLeg);

            collarLeg.setPricingEngine(engine);
            YoYInflationCollar collar = new YoYInflationCollar(floatLeg,
                                                               new List <double>()
            {
                capstrike
            },
                                                               new List <double>()
            {
                floorstrike
            });

            collar.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvCollaredLeg = collarLeg.NPV();
            npvCollar      = collar.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Collared Leg: gearing=1, spread=0%, strike=" +
                             floorstrike * 100 + "% and " + capstrike * 100 + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = a and spread = b
            // CAPPED coupon - Decomposition of payoff
            // Payoff
            // = Nom * Min(a*rate+b,strike) * accrualperiod =
            // = Nom * [a*rate+b + Min(0,strike-a*rate-b)] * accrualperiod =
            // = Nom * a*rate+b * accrualperiod + Nom * Min(strike-b-a*rate,0) * accrualperiod
            // --> If a>0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg - Call(a*rate+b,strike)
            // --> If a<0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Nom * Min(strike-b+|a|*rate+,0) * accrualperiod =
            // = VanillaFloatingLeg + Put(|a|*rate+b,strike)
            //

            // Positive gearing
            List <CashFlow> cappedLeg_p = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors0,
                                                                    vars.volatility, gearing_p, spread_p);
            Swap capLeg_p = new Swap(fixedLeg, cappedLeg_p);

            capLeg_p.setPricingEngine(engine);
            YoYInflationCap cap_p = new YoYInflationCap(floatLeg_p, new List <double>()
            {
                capstrike
            });

            cap_p.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla   = vanillaLeg_p.NPV();
            npvCappedLeg = capLeg_p.NPV();
            npvCap       = cap_p.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=" + gearing_p + ", " +
                             "spread= " + spread_p * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + (capstrike - spread_p) / gearing_p * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Vanilla Leg NPV: " + npvVanilla + "\n" +
                             "  Cap NPV: " + npvCap + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            // Negative gearing
            List <CashFlow> cappedLeg_n = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors0,
                                                                    vars.volatility, gearing_n, spread_n);
            Swap capLeg_n = new Swap(fixedLeg, cappedLeg_n);

            capLeg_n.setPricingEngine(engine);
            YoYInflationFloor floor_n = new YoYInflationFloor(floatLeg, new List <double>()
            {
                (capstrike - spread_n) / gearing_n
            });

            floor_n.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla   = vanillaLeg_n.NPV();
            npvCappedLeg = capLeg_n.NPV();
            npvFloor     = floor_n.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla + gearing_n * npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + ((capstrike - spread_n) / gearing_n * 100) +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  npv Vanilla: " + npvVanilla + "\n" +
                             "  npvFloor: " + npvFloor + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla + gearing_n * npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            // gearing = a and spread = b
            // FLOORED coupon - Decomposition of payoff
            // Payoff
            // = Nom * Max(a*rate+b,strike) * accrualperiod =
            // = Nom * [a*rate+b + Max(0,strike-a*rate-b)] * accrualperiod =
            // = Nom * a*rate+b * accrualperiod + Nom * Max(strike-b-a*rate,0) * accrualperiod
            // --> If a>0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Put(a*rate+b,strike)
            // --> If a<0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Nom * Max(strike-b+|a|*rate+,0) * accrualperiod =
            // = VanillaFloatingLeg - Call(|a|*rate+b,strike)
            //

            // Positive gearing
            List <CashFlow> flooredLeg_p1 = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps0, floors,
                                                                      vars.volatility, gearing_p, spread_p);
            Swap floorLeg_p1 = new Swap(fixedLeg, flooredLeg_p1);

            floorLeg_p1.setPricingEngine(engine);
            YoYInflationFloor floor_p1 = new YoYInflationFloor(floatLeg_p, new List <double>()
            {
                floorstrike
            });

            floor_p1.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla    = vanillaLeg_p.NPV();
            npvFlooredLeg = floorLeg_p1.NPV();
            npvFloor      = floor_p1.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Floored Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike=" + floorstrike * 100 + "%, "
                             + "effective strike= " + (floorstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg
                             + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> flooredLeg_n = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps0, floors,
                                                                     vars.volatility, gearing_n, spread_n);
            Swap floorLeg_n = new Swap(fixedLeg, flooredLeg_n);

            floorLeg_n.setPricingEngine(engine);
            YoYInflationCap cap_n = new YoYInflationCap(floatLeg, new List <double>()
            {
                (floorstrike - spread_n) / gearing_n
            });

            cap_n.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla    = vanillaLeg_n.NPV();
            npvFlooredLeg = floorLeg_n.NPV();
            npvCap        = cap_n.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla - gearing_n * npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Capped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + floorstrike * 100 + "%, " +
                             "effective strike= " + (floorstrike - spread_n) / gearing_n * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - gearing_n * npvCap) + "\n" +
                             "  Diff: " + error);
            }
            // gearing = a and spread = b
            // COLLARED coupon - Decomposition of payoff
            // Payoff = Nom * Min(caprate,Max(a*rate+b,floorrate)) * accrualperiod
            // --> If a>0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg - Collar(a*rate+b, floorrate, caprate)
            // --> If a<0 (assuming positive effective strike):
            // Payoff = VanillaFloatingLeg + Collar(|a|*rate+b, caprate, floorrate)
            //
            // Positive gearing
            List <CashFlow> collaredLeg_p = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors,
                                                                      vars.volatility, gearing_p, spread_p);
            Swap collarLeg_p1 = new Swap(fixedLeg, collaredLeg_p);

            collarLeg_p1.setPricingEngine(engine);
            YoYInflationCollar collar_p = new YoYInflationCollar(floatLeg_p,
                                                                 new List <double>()
            {
                capstrike
            },
                                                                 new List <double>()
            {
                floorstrike
            });

            collar_p.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla     = vanillaLeg_p.NPV();
            npvCollaredLeg = collarLeg_p1.NPV();
            npvCollar      = collar_p.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Collared Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_p) / gearing_p * 100
                             + "% and " + (capstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> collaredLeg_n = vars.makeYoYCapFlooredLeg(whichPricer, vars.startDate, vars.length, caps, floors,
                                                                      vars.volatility, gearing_n, spread_n);
            Swap collarLeg_n1 = new Swap(fixedLeg, collaredLeg_n);

            collarLeg_n1.setPricingEngine(engine);
            YoYInflationCollar collar_n = new YoYInflationCollar(floatLeg,
                                                                 new List <double>()
            {
                (floorstrike - spread_n) / gearing_n
            },
                                                                 new List <double>()
            {
                (capstrike - spread_n) / gearing_n
            });

            collar_n.setPricingEngine(vars.makeEngine(vars.volatility, whichPricer));
            npvVanilla     = vanillaLeg_n.NPV();
            npvCollaredLeg = collarLeg_n1.NPV();
            npvCollar      = collar_n.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - gearing_n * npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nYoY Collared Leg: gearing=" + gearing_n + ", "
                             + "spread= " + spread_n * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_n) / gearing_n * 100
                             + "% and " + (capstrike - spread_n) / gearing_n * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - gearing_n * npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
            // remove circular refernce
            vars.hy.linkTo(null);
        }
Ejemplo n.º 41
0
        void checkSequence <S>(string name, int dimension) where S : IGeneralStatistics, new ()
        {
            GenericSequenceStatistics <S> ss = new GenericSequenceStatistics <S>(dimension);
            int i;

            for (i = 0; i < data.Length; i++)
            {
                List <double> temp = new InitializedList <double>(dimension, data[i]);
                ss.add(temp, weights[i]);
            }

            List <double> calculated;
            double        expected, tolerance;

            if (ss.samples() != data.Length)
            {
                QAssert.Fail("SequenceStatistics<" + name + ">: "
                             + "wrong number of samples\n"
                             + "    calculated: " + ss.samples() + "\n"
                             + "    expected:   " + data.Length);
            }

            expected = weights.Sum();
            if (ss.weightSum() != expected)
            {
                QAssert.Fail("SequenceStatistics<" + name + ">: "
                             + "wrong sum of weights\n"
                             + "    calculated: " + ss.weightSum() + "\n"
                             + "    expected:   " + expected);
            }

            expected   = data.Min();
            calculated = ss.min();
            for (i = 0; i < dimension; i++)
            {
                if (calculated[i] != expected)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong minimum value\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }

            expected   = data.Max();
            calculated = ss.max();
            for (i = 0; i < dimension; i++)
            {
                if (calculated[i] != expected)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong maximun value\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }

            expected   = 4.3;
            tolerance  = 1.0e-9;
            calculated = ss.mean();
            for (i = 0; i < dimension; i++)
            {
                if (Math.Abs(calculated[i] - expected) > tolerance)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong mean value\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }

            expected   = 2.23333333333;
            calculated = ss.variance();
            for (i = 0; i < dimension; i++)
            {
                if (Math.Abs(calculated[i] - expected) > tolerance)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong variance\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }

            expected   = 1.4944341181;
            calculated = ss.standardDeviation();
            for (i = 0; i < dimension; i++)
            {
                if (Math.Abs(calculated[i] - expected) > tolerance)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong standard deviation\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }

            expected   = 0.359543071407;
            calculated = ss.skewness();
            for (i = 0; i < dimension; i++)
            {
                if (Math.Abs(calculated[i] - expected) > tolerance)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong skewness\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }

            expected   = -0.151799637209;
            calculated = ss.kurtosis();
            for (i = 0; i < dimension; i++)
            {
                if (Math.Abs(calculated[i] - expected) > tolerance)
                {
                    QAssert.Fail("SequenceStatistics<" + name + ">: "
                                 + (i + 1) + " dimension: "
                                 + "wrong kurtosis\n"
                                 + "    calculated: " + calculated[i] + "\n"
                                 + "    expected:   " + expected);
                }
            }
        }
Ejemplo n.º 42
0
        public void testCalibration()
        {
            double forward = 0.03;
            double tau     = 1.0;

            //Real a = 0.04;
            //Real b = 0.1;
            //Real rho = -0.5;
            //Real sigma = 0.1;
            //Real m  = 0.0;
            double a     = 0.1;
            double b     = 0.06;
            double rho   = -0.9;
            double m     = 0.24;
            double sigma = 0.06;

            List <double> strikes = new List <double>();

            strikes.Add(0.01);
            strikes.Add(0.015);
            strikes.Add(0.02);
            strikes.Add(0.025);
            strikes.Add(0.03);
            strikes.Add(0.035);
            strikes.Add(0.04);
            strikes.Add(0.045);
            strikes.Add(0.05);

            List <double> vols = new InitializedList <double>(strikes.Count, 0.20); //dummy vols (we do not calibrate here)

            SviInterpolation svi = new SviInterpolation(strikes, strikes.Count, vols, tau,
                                                        forward, a, b, sigma, rho, m, true, true, true,
                                                        true, true);

            svi.enableExtrapolation();

            List <double> sviVols = new InitializedList <double>(strikes.Count, 0.0);

            for (int i = 0; i < strikes.Count; ++i)
            {
                sviVols[i] = svi.value(strikes[i]);
            }

            SviInterpolation svi2 = new SviInterpolation(strikes, strikes.Count, sviVols, tau,
                                                         forward, null, null, null,
                                                         null, null, false, false, false,
                                                         false, false, false, null,
                                                         null, 1E-8, false,
                                                         0); //don't allow for random start values

            svi2.enableExtrapolation();
            svi2.update();

            Console.WriteLine("a=" + svi2.a());
            if (!Utils.close_enough(a, svi2.a(), 100))
            {
                QAssert.Fail("error in a coefficient estimation");
            }

            Console.WriteLine("b=" + svi2.b());
            if (!Utils.close_enough(b, svi2.b(), 100))
            {
                QAssert.Fail("error in b coefficient estimation");
            }

            Console.WriteLine("sigma=" + svi2.sigma());
            if (!Utils.close_enough(sigma, svi2.sigma(), 100))
            {
                QAssert.Fail("error in sigma coefficient estimation");
            }

            Console.WriteLine("rho=" + svi2.rho());
            if (!Utils.close_enough(rho, svi2.rho(), 100))
            {
                QAssert.Fail("error in rho coefficient estimation");
            }

            Console.WriteLine("m=" + svi2.m());
            if (!Utils.close_enough(m, svi2.m(), 100))
            {
                QAssert.Fail("error in m coefficient estimation");
            }

            Console.WriteLine("error=" + svi2.rmsError());
        }
Ejemplo n.º 43
0
        public void testDecomposition()
        {
            // Testing collared coupon against its decomposition

            CommonVars vars = new CommonVars();

            double         tolerance = 1e-12;
            double         npvVanilla, npvCappedLeg, npvFlooredLeg, npvCollaredLeg, npvCap, npvFloor, npvCollar;
            double         error;
            double         floorstrike = 0.05;
            double         capstrike   = 0.10;
            List <double?> caps        = new InitializedList <double?>(vars.length, capstrike);
            List <double?> caps0       = new List <double?>();
            List <double?> floors      = new InitializedList <double?>(vars.length, floorstrike);
            List <double?> floors0     = new List <double?>();
            double         gearing_p   = 0.5;
            double         spread_p    = 0.002;
            double         gearing_n   = -1.5;
            double         spread_n    = 0.12;
            // fixed leg with zero rate
            List <CashFlow> fixedLeg = vars.makeFixedLeg(vars.startDate, vars.length);
            // floating leg with gearing=1 and spread=0
            List <CashFlow> floatLeg = vars.makeFloatingLeg(vars.startDate, vars.length);
            // floating leg with positive gearing (gearing_p) and spread<>0
            List <CashFlow> floatLeg_p = vars.makeFloatingLeg(vars.startDate, vars.length, gearing_p, spread_p);
            // floating leg with negative gearing (gearing_n) and spread<>0
            List <CashFlow> floatLeg_n = vars.makeFloatingLeg(vars.startDate, vars.length, gearing_n, spread_n);
            // Swap with null fixed leg and floating leg with gearing=1 and spread=0
            Swap vanillaLeg = new Swap(fixedLeg, floatLeg);
            // Swap with null fixed leg and floating leg with positive gearing and spread<>0
            Swap vanillaLeg_p = new Swap(fixedLeg, floatLeg_p);
            // Swap with null fixed leg and floating leg with negative gearing and spread<>0
            Swap vanillaLeg_n = new Swap(fixedLeg, floatLeg_n);

            IPricingEngine engine = new DiscountingSwapEngine(vars.termStructure);

            vanillaLeg.setPricingEngine(engine);
            vanillaLeg_p.setPricingEngine(engine);
            vanillaLeg_n.setPricingEngine(engine);

            /* CAPPED coupon - Decomposition of payoff
             * Payoff = Nom * Min(rate,strike) * accrualperiod =
             *       = Nom * [rate + Min(0,strike-rate)] * accrualperiod =
             *       = Nom * rate * accrualperiod - Nom * Max(rate-strike,0) * accrualperiod =
             *       = VanillaFloatingLeg - Call
             */

            // Case gearing = 1 and spread = 0
            List <CashFlow> cappedLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors0, vars.volatility);
            Swap            capLeg    = new Swap(fixedLeg, cappedLeg);

            capLeg.setPricingEngine(engine);
            Cap cap = new Cap(floatLeg, new InitializedList <double>(1, capstrike));

            cap.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla   = vanillaLeg.NPV();
            npvCappedLeg = capLeg.NPV();
            npvCap       = cap.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=1, spread=0%, strike=" + capstrike * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = 1 and spread = 0
             * FLOORED coupon - Decomposition of payoff
             * Payoff = Nom * Max(rate,strike) * accrualperiod =
             *       = Nom * [rate + Max(0,strike-rate)] * accrualperiod =
             *       = Nom * rate * accrualperiod + Nom * Max(strike-rate,0) * accrualperiod =
             *       = VanillaFloatingLeg + Put
             */

            List <CashFlow> flooredLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps0, floors, vars.volatility);
            Swap            floorLeg   = new Swap(fixedLeg, flooredLeg);

            floorLeg.setPricingEngine(engine);
            Floor floor = new Floor(floatLeg, new InitializedList <double>(1, floorstrike));

            floor.setPricingEngine(vars.makeEngine(vars.volatility));
            npvFlooredLeg = floorLeg.NPV();
            npvFloor      = floor.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("Floored Leg: gearing=1, spread=0%, strike=" + floorstrike * 100 +
                             "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = 1 and spread = 0
             * COLLARED coupon - Decomposition of payoff
             * Payoff = Nom * Min(strikem,Max(rate,strikeM)) * accrualperiod =
             *       = VanillaFloatingLeg - Collar
             */

            List <CashFlow> collaredLeg = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors, vars.volatility);
            Swap            collarLeg   = new Swap(fixedLeg, collaredLeg);

            collarLeg.setPricingEngine(engine);
            Collar collar = new Collar(floatLeg, new InitializedList <double>(1, capstrike),
                                       new InitializedList <double>(1, floorstrike));

            collar.setPricingEngine(vars.makeEngine(vars.volatility));
            npvCollaredLeg = collarLeg.NPV();
            npvCollar      = collar.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nCollared Leg: gearing=1, spread=0%, strike=" +
                             floorstrike * 100 + "% and " + capstrike * 100 + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = a and spread = b
             * CAPPED coupon - Decomposition of payoff
             * Payoff
             * = Nom * Min(a*rate+b,strike) * accrualperiod =
             * = Nom * [a*rate+b + Min(0,strike-a*rate-b)] * accrualperiod =
             * = Nom * a*rate+b * accrualperiod + Nom * Min(strike-b-a*rate,0) * accrualperiod
             * --> If a>0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg - Call(a*rate+b,strike)
             * --> If a<0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Nom * Min(strike-b+|a|*rate+,0) * accrualperiod =
             *          = VanillaFloatingLeg + Put(|a|*rate+b,strike)
             */

            // Positive gearing
            List <CashFlow> cappedLeg_p = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors0,
                                                                 vars.volatility, gearing_p, spread_p);
            Swap capLeg_p = new Swap(fixedLeg, cappedLeg_p);

            capLeg_p.setPricingEngine(engine);
            Cap cap_p = new Cap(floatLeg_p, new InitializedList <double>(1, capstrike));

            cap_p.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla   = vanillaLeg_p.NPV();
            npvCappedLeg = capLeg_p.NPV();
            npvCap       = cap_p.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla - npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=" + gearing_p + ", " +
                             "spread= " + spread_p * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + (capstrike - spread_p) / gearing_p * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  Vanilla Leg NPV: " + npvVanilla + "\n" +
                             "  Cap NPV: " + npvCap + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - npvCap) + "\n" +
                             "  Diff: " + error);
            }

            // Negative gearing
            List <CashFlow> cappedLeg_n = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors0,
                                                                 vars.volatility, gearing_n, spread_n);
            Swap capLeg_n = new Swap(fixedLeg, cappedLeg_n);

            capLeg_n.setPricingEngine(engine);
            Floor floor_n = new Floor(floatLeg, new InitializedList <double>(1, (capstrike - spread_n) / gearing_n));

            floor_n.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla   = vanillaLeg_n.NPV();
            npvCappedLeg = capLeg_n.NPV();
            npvFloor     = floor_n.NPV();
            error        = Math.Abs(npvCappedLeg - (npvVanilla + gearing_n * npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + capstrike * 100 + "%, " +
                             "effective strike= " + (capstrike - spread_n) / gearing_n * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvCappedLeg + "\n" +
                             "  npv Vanilla: " + npvVanilla + "\n" +
                             "  npvFloor: " + npvFloor + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla + gearing_n * npvFloor) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = a and spread = b
             * FLOORED coupon - Decomposition of payoff
             * Payoff
             * = Nom * Max(a*rate+b,strike) * accrualperiod =
             * = Nom * [a*rate+b + Max(0,strike-a*rate-b)] * accrualperiod =
             * = Nom * a*rate+b * accrualperiod + Nom * Max(strike-b-a*rate,0) * accrualperiod
             * --> If a>0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Put(a*rate+b,strike)
             * --> If a<0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Nom * Max(strike-b+|a|*rate+,0) * accrualperiod =
             *          = VanillaFloatingLeg - Call(|a|*rate+b,strike)
             */

            // Positive gearing
            List <CashFlow> flooredLeg_p1 = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps0, floors,
                                                                   vars.volatility, gearing_p, spread_p);
            Swap floorLeg_p1 = new Swap(fixedLeg, flooredLeg_p1);

            floorLeg_p1.setPricingEngine(engine);
            Floor floor_p1 = new Floor(floatLeg_p, new InitializedList <double>(1, floorstrike));

            floor_p1.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla    = vanillaLeg_p.NPV();
            npvFlooredLeg = floorLeg_p1.NPV();
            npvFloor      = floor_p1.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla + npvFloor));
            if (error > tolerance)
            {
                QAssert.Fail("\nFloored Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike=" + floorstrike * 100 + "%, "
                             + "effective strike= " + (floorstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Floored Floating Leg NPV: " + npvFlooredLeg
                             + "\n" +
                             "  Floating Leg NPV + Floor NPV: " + (npvVanilla + npvFloor)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> flooredLeg_n = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps0, floors,
                                                                  vars.volatility, gearing_n, spread_n);
            Swap floorLeg_n = new Swap(fixedLeg, flooredLeg_n);

            floorLeg_n.setPricingEngine(engine);
            Cap cap_n = new Cap(floatLeg, new InitializedList <double>(1, (floorstrike - spread_n) / gearing_n));

            cap_n.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla    = vanillaLeg_n.NPV();
            npvFlooredLeg = floorLeg_n.NPV();
            npvCap        = cap_n.NPV();
            error         = Math.Abs(npvFlooredLeg - (npvVanilla - gearing_n * npvCap));
            if (error > tolerance)
            {
                QAssert.Fail("\nCapped Leg: gearing=" + gearing_n + ", " +
                             "spread= " + spread_n * 100 +
                             "%, strike=" + floorstrike * 100 + "%, " +
                             "effective strike= " + (floorstrike - spread_n) / gearing_n * 100 +
                             "%\n" +
                             "  Capped Floating Leg NPV: " + npvFlooredLeg + "\n" +
                             "  Floating Leg NPV - Cap NPV: " + (npvVanilla - gearing_n * npvCap) + "\n" +
                             "  Diff: " + error);
            }

            /* gearing = a and spread = b
             * COLLARED coupon - Decomposition of payoff
             * Payoff = Nom * Min(caprate,Max(a*rate+b,floorrate)) * accrualperiod
             * --> If a>0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg - Collar(a*rate+b, floorrate, caprate)
             * --> If a<0 (assuming positive effective strike):
             *    Payoff = VanillaFloatingLeg + Collar(|a|*rate+b, caprate, floorrate)
             */
            // Positive gearing
            List <CashFlow> collaredLeg_p = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors,
                                                                   vars.volatility, gearing_p, spread_p);
            Swap collarLeg_p1 = new Swap(fixedLeg, collaredLeg_p);

            collarLeg_p1.setPricingEngine(engine);
            Collar collar_p = new Collar(floatLeg_p, new InitializedList <double>(1, capstrike),
                                         new InitializedList <double>(1, floorstrike));

            collar_p.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla     = vanillaLeg_p.NPV();
            npvCollaredLeg = collarLeg_p1.NPV();
            npvCollar      = collar_p.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nCollared Leg: gearing=" + gearing_p + ", "
                             + "spread= " + spread_p * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_p) / gearing_p * 100
                             + "% and " + (capstrike - spread_p) / gearing_p * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
            // Negative gearing
            List <CashFlow> collaredLeg_n = vars.makeCapFlooredLeg(vars.startDate, vars.length, caps, floors,
                                                                   vars.volatility, gearing_n, spread_n);
            Swap collarLeg_n1 = new Swap(fixedLeg, collaredLeg_n);

            collarLeg_n1.setPricingEngine(engine);
            Collar collar_n = new Collar(floatLeg, new InitializedList <double>(1, (floorstrike - spread_n) / gearing_n),
                                         new InitializedList <double>(1, (capstrike - spread_n) / gearing_n));

            collar_n.setPricingEngine(vars.makeEngine(vars.volatility));
            npvVanilla     = vanillaLeg_n.NPV();
            npvCollaredLeg = collarLeg_n1.NPV();
            npvCollar      = collar_n.NPV();
            error          = Math.Abs(npvCollaredLeg - (npvVanilla - gearing_n * npvCollar));
            if (error > tolerance)
            {
                QAssert.Fail("\nCollared Leg: gearing=" + gearing_n + ", "
                             + "spread= " + spread_n * 100 + "%, strike="
                             + floorstrike * 100 + "% and " + capstrike * 100
                             + "%, "
                             + "effective strike=" + (floorstrike - spread_n) / gearing_n * 100
                             + "% and " + (capstrike - spread_n) / gearing_n * 100
                             + "%\n" +
                             "  Collared Floating Leg NPV: " + npvCollaredLeg
                             + "\n" +
                             "  Floating Leg NPV - Collar NPV: " + (npvVanilla - gearing_n * npvCollar)
                             + "\n" +
                             "  Diff: " + error);
            }
        }
Ejemplo n.º 44
0
            // setup
            public CommonVars()
            {
                backup = new SavedSettings();

                Calendar calendar = new TARGET();

                Date referenceDate = calendar.adjust(Date.Today);

                Settings.Instance.setEvaluationDate(referenceDate);

                termStructure = new RelinkableHandle <YieldTermStructure>();
                termStructure.linkTo(Utilities.flatRate(referenceDate, 0.05, new Actual365Fixed()));

                // ATM Volatility structure
                List <Period> atmOptionTenors = new List <Period>();

                atmOptionTenors.Add(new Period(1, TimeUnit.Months));
                atmOptionTenors.Add(new Period(6, TimeUnit.Months));
                atmOptionTenors.Add(new Period(1, TimeUnit.Years));
                atmOptionTenors.Add(new Period(5, TimeUnit.Years));
                atmOptionTenors.Add(new Period(10, TimeUnit.Years));
                atmOptionTenors.Add(new Period(30, TimeUnit.Years));

                List <Period> atmSwapTenors = new List <Period>();

                atmSwapTenors.Add(new Period(1, TimeUnit.Years));
                atmSwapTenors.Add(new Period(5, TimeUnit.Years));
                atmSwapTenors.Add(new Period(10, TimeUnit.Years));
                atmSwapTenors.Add(new Period(30, TimeUnit.Years));

                Matrix m = new Matrix(atmOptionTenors.Count, atmSwapTenors.Count);

                m[0, 0] = 0.1300; m[0, 1] = 0.1560; m[0, 2] = 0.1390; m[0, 3] = 0.1220;
                m[1, 0] = 0.1440; m[1, 1] = 0.1580; m[1, 2] = 0.1460; m[1, 3] = 0.1260;
                m[2, 0] = 0.1600; m[2, 1] = 0.1590; m[2, 2] = 0.1470; m[2, 3] = 0.1290;
                m[3, 0] = 0.1640; m[3, 1] = 0.1470; m[3, 2] = 0.1370; m[3, 3] = 0.1220;
                m[4, 0] = 0.1400; m[4, 1] = 0.1300; m[4, 2] = 0.1250; m[4, 3] = 0.1100;
                m[5, 0] = 0.1130; m[5, 1] = 0.1090; m[5, 2] = 0.1070; m[5, 3] = 0.0930;

                atmVol = new Handle <SwaptionVolatilityStructure>(
                    new SwaptionVolatilityMatrix(calendar, BusinessDayConvention.Following, atmOptionTenors,
                                                 atmSwapTenors, m, new Actual365Fixed()));

                // Vol cubes
                List <Period> optionTenors = new List <Period>();

                optionTenors.Add(new Period(1, TimeUnit.Years));
                optionTenors.Add(new Period(10, TimeUnit.Years));
                optionTenors.Add(new Period(30, TimeUnit.Years));

                List <Period> swapTenors = new List <Period>();

                swapTenors.Add(new Period(2, TimeUnit.Years));
                swapTenors.Add(new Period(10, TimeUnit.Years));
                swapTenors.Add(new Period(30, TimeUnit.Years));

                List <double> strikeSpreads = new List <double>();

                strikeSpreads.Add(-0.020);
                strikeSpreads.Add(-0.005);
                strikeSpreads.Add(+0.000);
                strikeSpreads.Add(+0.005);
                strikeSpreads.Add(+0.020);

                int    nRows            = optionTenors.Count * swapTenors.Count;
                int    nCols            = strikeSpreads.Count;
                Matrix volSpreadsMatrix = new Matrix(nRows, nCols);

                volSpreadsMatrix[0, 0] = 0.0599;
                volSpreadsMatrix[0, 1] = 0.0049;
                volSpreadsMatrix[0, 2] = 0.0000;
                volSpreadsMatrix[0, 3] = -0.0001;
                volSpreadsMatrix[0, 4] = 0.0127;

                volSpreadsMatrix[1, 0] = 0.0729;
                volSpreadsMatrix[1, 1] = 0.0086;
                volSpreadsMatrix[1, 2] = 0.0000;
                volSpreadsMatrix[1, 3] = -0.0024;
                volSpreadsMatrix[1, 4] = 0.0098;

                volSpreadsMatrix[2, 0] = 0.0738;
                volSpreadsMatrix[2, 1] = 0.0102;
                volSpreadsMatrix[2, 2] = 0.0000;
                volSpreadsMatrix[2, 3] = -0.0039;
                volSpreadsMatrix[2, 4] = 0.0065;

                volSpreadsMatrix[3, 0] = 0.0465;
                volSpreadsMatrix[3, 1] = 0.0063;
                volSpreadsMatrix[3, 2] = 0.0000;
                volSpreadsMatrix[3, 3] = -0.0032;
                volSpreadsMatrix[3, 4] = -0.0010;

                volSpreadsMatrix[4, 0] = 0.0558;
                volSpreadsMatrix[4, 1] = 0.0084;
                volSpreadsMatrix[4, 2] = 0.0000;
                volSpreadsMatrix[4, 3] = -0.0050;
                volSpreadsMatrix[4, 4] = -0.0057;

                volSpreadsMatrix[5, 0] = 0.0576;
                volSpreadsMatrix[5, 1] = 0.0083;
                volSpreadsMatrix[5, 2] = 0.0000;
                volSpreadsMatrix[5, 3] = -0.0043;
                volSpreadsMatrix[5, 4] = -0.0014;

                volSpreadsMatrix[6, 0] = 0.0437;
                volSpreadsMatrix[6, 1] = 0.0059;
                volSpreadsMatrix[6, 2] = 0.0000;
                volSpreadsMatrix[6, 3] = -0.0030;
                volSpreadsMatrix[6, 4] = -0.0006;

                volSpreadsMatrix[7, 0] = 0.0533;
                volSpreadsMatrix[7, 1] = 0.0078;
                volSpreadsMatrix[7, 2] = 0.0000;
                volSpreadsMatrix[7, 3] = -0.0045;
                volSpreadsMatrix[7, 4] = -0.0046;

                volSpreadsMatrix[8, 0] = 0.0545;
                volSpreadsMatrix[8, 1] = 0.0079;
                volSpreadsMatrix[8, 2] = 0.0000;
                volSpreadsMatrix[8, 3] = -0.0042;
                volSpreadsMatrix[8, 4] = -0.0020;

                List <List <Handle <Quote> > > volSpreads = new InitializedList <List <Handle <Quote> > >(nRows);

                for (int i = 0; i < nRows; ++i)
                {
                    volSpreads[i] = new InitializedList <Handle <Quote> >(nCols);
                    for (int j = 0; j < nCols; ++j)
                    {
                        volSpreads[i][j] = new Handle <Quote>(new SimpleQuote(volSpreadsMatrix[i, j]));
                    }
                }

                iborIndex = new Euribor6M(termStructure);
                SwapIndex swapIndexBase      = new EuriborSwapIsdaFixA(new Period(10, TimeUnit.Years), termStructure);
                SwapIndex shortSwapIndexBase = new EuriborSwapIsdaFixA(new Period(2, TimeUnit.Years), termStructure);

                bool vegaWeightedSmileFit = false;

                SabrVolCube2 = new Handle <SwaptionVolatilityStructure>(
                    new SwaptionVolCube2(atmVol,
                                         optionTenors,
                                         swapTenors,
                                         strikeSpreads,
                                         volSpreads,
                                         swapIndexBase,
                                         shortSwapIndexBase,
                                         vegaWeightedSmileFit));
                SabrVolCube2.link.enableExtrapolation();

                List <List <Handle <Quote> > > guess = new InitializedList <List <Handle <Quote> > >(nRows);

                for (int i = 0; i < nRows; ++i)
                {
                    guess[i]    = new InitializedList <Handle <Quote> >(4);
                    guess[i][0] = new Handle <Quote>(new SimpleQuote(0.2));
                    guess[i][1] = new Handle <Quote>(new SimpleQuote(0.5));
                    guess[i][2] = new Handle <Quote>(new SimpleQuote(0.4));
                    guess[i][3] = new Handle <Quote>(new SimpleQuote(0.0));
                }
                List <bool> isParameterFixed = new InitializedList <bool>(4, false);

                isParameterFixed[1] = true;

                // FIXME
                bool isAtmCalibrated = false;

                SabrVolCube1 = new Handle <SwaptionVolatilityStructure>(
                    new SwaptionVolCube1x(atmVol,
                                          optionTenors,
                                          swapTenors,
                                          strikeSpreads,
                                          volSpreads,
                                          swapIndexBase,
                                          shortSwapIndexBase,
                                          vegaWeightedSmileFit,
                                          guess,
                                          isParameterFixed,
                                          isAtmCalibrated));
                SabrVolCube1.link.enableExtrapolation();

                yieldCurveModels = new List <GFunctionFactory.YieldCurveModel>();
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.Standard);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.ExactYield);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.ParallelShifts);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.NonParallelShifts);
                yieldCurveModels.Add(GFunctionFactory.YieldCurveModel.NonParallelShifts); // for linear tsr model

                Handle <Quote> zeroMeanRev = new Handle <Quote>(new SimpleQuote(0.0));

                numericalPricers = new List <CmsCouponPricer>();
                analyticPricers  = new List <CmsCouponPricer>();
                for (int j = 0; j < yieldCurveModels.Count; ++j)
                {
                    if (j < yieldCurveModels.Count - 1)
                    {
                        numericalPricers.Add(new NumericHaganPricer(atmVol, yieldCurveModels[j], zeroMeanRev));
                    }
                    else
                    {
                        numericalPricers.Add(new LinearTsrPricer(atmVol, zeroMeanRev));
                    }

                    analyticPricers.Add(new AnalyticHaganPricer(atmVol, yieldCurveModels[j], zeroMeanRev));
                }
            }
Ejemplo n.º 45
0
        public void testCrankNicolsonWithDamping()
        {
            SavedSettings backup = new SavedSettings();

            DayCounter dc    = new Actual360();
            Date       today = Date.Today;

            SimpleQuote           spot  = new SimpleQuote(100.0);
            YieldTermStructure    qTS   = Utilities.flatRate(today, 0.06, dc);
            YieldTermStructure    rTS   = Utilities.flatRate(today, 0.06, dc);
            BlackVolTermStructure volTS = Utilities.flatVol(today, 0.35, dc);

            StrikedTypePayoff payoff =
                new CashOrNothingPayoff(Option.Type.Put, 100, 10.0);

            double   maturity = 0.75;
            Date     exDate   = today + Convert.ToInt32(maturity * 360 + 0.5);
            Exercise exercise = new EuropeanExercise(exDate);

            BlackScholesMertonProcess process = new
                                                BlackScholesMertonProcess(new Handle <Quote>(spot),
                                                                          new Handle <YieldTermStructure>(qTS),
                                                                          new Handle <YieldTermStructure>(rTS),
                                                                          new Handle <BlackVolTermStructure>(volTS));
            IPricingEngine engine =
                new AnalyticEuropeanEngine(process);

            VanillaOption opt = new VanillaOption(payoff, exercise);

            opt.setPricingEngine(engine);
            double expectedPV    = opt.NPV();
            double expectedGamma = opt.gamma();

            // fd pricing using implicit damping steps and Crank Nicolson
            int        csSteps = 25, dampingSteps = 3, xGrid = 400;
            List <int> dim = new InitializedList <int>(1, xGrid);

            FdmLinearOpLayout layout       = new FdmLinearOpLayout(dim);
            Fdm1dMesher       equityMesher =
                new FdmBlackScholesMesher(
                    dim[0], process, maturity, payoff.strike(),
                    null, null, 0.0001, 1.5,
                    new Pair <double?, double?>(payoff.strike(), 0.01));

            FdmMesher mesher =
                new FdmMesherComposite(equityMesher);

            FdmBlackScholesOp map =
                new FdmBlackScholesOp(mesher, process, payoff.strike());

            FdmInnerValueCalculator calculator =
                new FdmLogInnerValue(payoff, mesher, 0);

            object rhs = new Vector(layout.size());
            Vector x   = new Vector(layout.size());
            FdmLinearOpIterator endIter = layout.end();

            for (FdmLinearOpIterator iter = layout.begin(); iter != endIter;
                 ++iter)
            {
                (rhs as Vector)[iter.index()] = calculator.avgInnerValue(iter, maturity);
                x[iter.index()] = mesher.location(iter, 0);
            }

            FdmBackwardSolver solver = new FdmBackwardSolver(map, new FdmBoundaryConditionSet(),
                                                             new FdmStepConditionComposite(),
                                                             new FdmSchemeDesc().Douglas());

            solver.rollback(ref rhs, maturity, 0.0, csSteps, dampingSteps);

            MonotonicCubicNaturalSpline spline = new MonotonicCubicNaturalSpline(x, x.Count, rhs as Vector);

            double s               = spot.value();
            double calculatedPV    = spline.value(Math.Log(s));
            double calculatedGamma = (spline.secondDerivative(Math.Log(s))
                                      - spline.derivative(Math.Log(s))) / (s * s);

            double relTol = 2e-3;

            if (Math.Abs(calculatedPV - expectedPV) > relTol * expectedPV)
            {
                QAssert.Fail("Error calculating the PV of the digital option" +
                             "\n rel. tolerance:  " + relTol +
                             "\n expected:        " + expectedPV +
                             "\n calculated:      " + calculatedPV);
            }
            if (Math.Abs(calculatedGamma - expectedGamma) > relTol * expectedGamma)
            {
                QAssert.Fail("Error calculating the Gamma of the digital option" +
                             "\n rel. tolerance:  " + relTol +
                             "\n expected:        " + expectedGamma +
                             "\n calculated:      " + calculatedGamma);
            }
        }
Ejemplo n.º 46
0
        public void testStrikeDependency()
        {
            //("Testing swaption dependency on strike......");

            CommonVars vars = new CommonVars();

            double[] strikes = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 };

            for (int i = 0; i < exercises.Length; i++)
            {
                for (int j = 0; j < lengths.Length; j++)
                {
                    for (int k = 0; k < type.Length; k++)
                    {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                                  exercises[i]);
                        Date startDate = vars.calendar.advance(exerciseDate,
                                                               vars.settlementDays, TimeUnit.Days);
                        // store the results for different rates...
                        List <double> values      = new InitializedList <double>(strikes.Length);
                        List <double> values_cash = new InitializedList <double>(strikes.Length);
                        double        vol         = 0.20;

                        for (int l = 0; l < strikes.Length; l++)
                        {
                            VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[l])
                                               .withEffectiveDate(startDate)
                                               .withFloatingLegSpread(0.0)
                                               .withType(type[k]);
                            Swaption swaption = vars.makeSwaption(swap, exerciseDate, vol);
                            // FLOATING_POINT_EXCEPTION
                            values[l] = swaption.NPV();
                            Swaption swaption_cash = vars.makeSwaption(swap, exerciseDate, vol,
                                                                       Settlement.Type.Cash);
                            values_cash[l] = swaption_cash.NPV();
                        }

                        // and check that they go the right way
                        if (type[k] == VanillaSwap.Type.Payer)
                        {
                            for (int z = 0; z < values.Count - 1; z++)
                            {
                                if (values[z] < values[z + 1])
                                {
                                    Assert.Fail("NPV of Payer swaption with delivery settlement" +
                                                "is increasing with the strike:" +
                                                "\noption tenor: " + exercises[i] +
                                                "\noption date:  " + exerciseDate +
                                                "\nvolatility:   " + vol +
                                                "\nswap tenor:   " + lengths[j] +
                                                "\nvalue:        " + values[z] + " at strike: " + strikes[z] +
                                                "\nvalue:        " + values[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                            for (int z = 0; z < values_cash.Count - 1; z++)
                            {
                                if (values_cash[z] < values_cash[z + 1])
                                {
                                    Assert.Fail("NPV of Payer swaption with cash settlement" +
                                                "is increasing with the strike:" +
                                                "\noption tenor: " + exercises[i] +
                                                "\noption date:  " + exerciseDate +
                                                "\nvolatility:   " + vol +
                                                "\nswap tenor:   " + lengths[j] +
                                                "\nvalue:        " + values_cash[z] + " at strike: " + strikes[z] +
                                                "\nvalue:        " + values_cash[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                        }
                        else
                        {
                            for (int z = 0; z < values.Count - 1; z++)
                            {
                                if (values[z] > values[z + 1])
                                {
                                    Assert.Fail("NPV of Receiver swaption with delivery settlement" +
                                                "is increasing with the strike:" +
                                                "\noption tenor: " + exercises[i] +
                                                "\noption date:  " + exerciseDate +
                                                "\nvolatility:   " + vol +
                                                "\nswap tenor:   " + lengths[j] +
                                                "\nvalue:        " + values[z] + " at strike: " + strikes[z] +
                                                "\nvalue:        " + values[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                            for (int z = 0; z < values_cash.Count - 1; z++)
                            {
                                if (values[z] > values[z + 1])
                                {
                                    Assert.Fail("NPV of Receiver swaption with cash settlement" +
                                                "is increasing with the strike:" +
                                                "\noption tenor: " + exercises[i] +
                                                "\noption date:  " + exerciseDate +
                                                "\nvolatility:   " + vol +
                                                "\nswap tenor:   " + lengths[j] +
                                                "\nvalue:        " + values_cash[z] + " at strike: " + strikes[z] +
                                                "\nvalue:        " + values_cash[z + 1] + " at strike: " + strikes[z + 1]);
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 47
0
        public CubicInterpolationImpl(List<double> xBegin, int size, List<double> yBegin,
            CubicInterpolation.DerivativeApprox da,
            bool monotonic,
            CubicInterpolation.BoundaryCondition leftCondition,
            double leftConditionValue,
            CubicInterpolation.BoundaryCondition rightCondition,
            double rightConditionValue)
            : base(xBegin, size, yBegin)
        {
            da_ = da;
            monotonic_ = monotonic;
            leftType_ = leftCondition;
            rightType_ = rightCondition;
            leftValue_ = leftConditionValue;
            rightValue_ = rightConditionValue;

            // coefficients
            primitiveConst_ = new InitializedList<double>(size - 1);
            a_ = new InitializedList<double>(size - 1);
            b_ = new InitializedList<double>(size - 1);
            c_ = new InitializedList<double>(size - 1);
            monotonicityAdjustments_ = new InitializedList<bool>(size);
        }
Ejemplo n.º 48
0
 public double value(Vector p, List<CalibrationHelper> instruments)
 {
     List<double> w = new InitializedList<double>(instruments.Count, 1.0);
     CalibrationFunction f = new CalibrationFunction(this, instruments, w);
     return f.value(p);
 }
Ejemplo n.º 49
0
            public List <CashFlow> makeYoYCapFlooredLeg(int which, Date startDate,
                                                        int length,
                                                        List <double> caps,
                                                        List <double> floors,
                                                        double volatility,
                                                        double gearing = 1.0,
                                                        double spread  = 0.0)
            {
                Handle <YoYOptionletVolatilitySurface> vol = new Handle <YoYOptionletVolatilitySurface>(
                    new ConstantYoYOptionletVolatility(volatility,
                                                       settlementDays,
                                                       calendar,
                                                       convention,
                                                       dc,
                                                       observationLag,
                                                       frequency,
                                                       iir.interpolated()));

                YoYInflationCouponPricer pricer = null;

                switch (which)
                {
                case 0:
                    pricer = new BlackYoYInflationCouponPricer(vol);
                    break;

                case 1:
                    pricer = new UnitDisplacedBlackYoYInflationCouponPricer(vol);
                    break;

                case 2:
                    pricer = new BachelierYoYInflationCouponPricer(vol);
                    break;

                default:
                    QAssert.Fail("unknown coupon pricer request: which = " + which
                                 + "should be 0=Black,1=DD,2=Bachelier");
                    break;
                }


                List <double> gearingVector = new InitializedList <double>(length, gearing);
                List <double> spreadVector  = new InitializedList <double>(length, spread);

                YoYInflationIndex ii = iir as YoYInflationIndex;
                Date     endDate     = calendar.advance(startDate, new Period(length, TimeUnit.Years), BusinessDayConvention.Unadjusted);
                Schedule schedule    = new Schedule(startDate, endDate, new Period(frequency), calendar,
                                                    BusinessDayConvention.Unadjusted,
                                                    BusinessDayConvention.Unadjusted,// ref periods & acc periods
                                                    DateGeneration.Rule.Forward, false);

                List <CashFlow> yoyLeg = new yoyInflationLeg(schedule, calendar, ii, observationLag)
                                         .withPaymentDayCounter(dc)
                                         .withGearings(gearingVector)
                                         .withSpreads(spreadVector)
                                         .withCaps(caps)
                                         .withFloors(floors)
                                         .withNotionals(nominals)
                                         .withPaymentAdjustment(convention);

                for (int i = 0; i < yoyLeg.Count; i++)
                {
                    ((YoYInflationCoupon)(yoyLeg[i])).setPricer(pricer);
                }

                //setCouponPricer(iborLeg, pricer);
                return(yoyLeg);
            }
Ejemplo n.º 50
0
        public void testBrazilianCached()
        {
            //("Testing Brazilian public bond prices against cached values...");

            CommonVars vars = new CommonVars();

            double faceAmount = 1000.0;
            double redemption = 100.0;
            Date   issueDate  = new Date(1, Month.January, 2007);

            Date today = new Date(6, Month.June, 2007);

            Settings.setEvaluationDate(today);

            // NTN-F maturity dates
            InitializedList <Date> maturityDates = new InitializedList <Date>(6);

            maturityDates[0] = new Date(1, Month.January, 2008);
            maturityDates[1] = new Date(1, Month.January, 2010);
            maturityDates[2] = new Date(1, Month.July, 2010);
            maturityDates[3] = new Date(1, Month.January, 2012);
            maturityDates[4] = new Date(1, Month.January, 2014);
            maturityDates[5] = new Date(1, Month.January, 2017);

            // NTN-F yields
            InitializedList <double> yields = new InitializedList <double>(6);

            yields[0] = 0.114614;
            yields[1] = 0.105726;
            yields[2] = 0.105328;
            yields[3] = 0.104283;
            yields[4] = 0.103218;
            yields[5] = 0.102948;

            // NTN-F prices
            InitializedList <double> prices = new InitializedList <double>(6);

            prices[0] = 1034.63031372;
            prices[1] = 1030.09919487;
            prices[2] = 1029.98307160;
            prices[3] = 1028.13585068;
            prices[4] = 1028.33383817;
            prices[5] = 1026.19716497;

            int settlementDays = 1;

            vars.faceAmount = 1000.0;

            // The tolerance is high because Andima truncate yields
            double tolerance = 1.0e-4;

            InitializedList <InterestRate> couponRates = new InitializedList <InterestRate>(1);

            couponRates[0] = new InterestRate(0.1, new Thirty360(), Compounding.Compounded, Frequency.Annual);

            for (int bondIndex = 0; bondIndex < maturityDates.Count; bondIndex++)
            {
                // plain
                InterestRate yield = new InterestRate(yields[bondIndex], new Business252(new Brazil()),
                                                      Compounding.Compounded, Frequency.Annual);

                Schedule schedule = new Schedule(new Date(1, Month.January, 2007),
                                                 maturityDates[bondIndex], new Period(Frequency.Semiannual),
                                                 new Brazil(Brazil.Market.Settlement),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                                                 DateGeneration.Rule.Backward, false);


                FixedRateBond bond = new FixedRateBond(settlementDays,
                                                       faceAmount,
                                                       schedule,
                                                       couponRates,
                                                       BusinessDayConvention.Following,
                                                       redemption,
                                                       issueDate);

                double cachedPrice = prices[bondIndex];

                double price = vars.faceAmount * (bond.cleanPrice(yield.rate(),
                                                                  yield.dayCounter(),
                                                                  yield.compounding(),
                                                                  yield.frequency(),
                                                                  today) + bond.accruedAmount(today)) / 100;
                if (Math.Abs(price - cachedPrice) > tolerance)
                {
                    Assert.Fail("failed to reproduce cached price:\n"
                                + "    calculated: " + price + "\n"
                                + "    expected:   " + cachedPrice + "\n"
                                + "    error:      " + (price - cachedPrice) + "\n"
                                );
                }
            }
        }
Ejemplo n.º 51
0
 public EuropeanExercise(Date date)
     : base(Type.European)
 {
     dates_ = new InitializedList<Date>(1, date);
 }
Ejemplo n.º 52
0
        public void testRegression()
        {
            // Testing fixed-coupon convertible bond in known regression case

            Date today    = new Date(23, Month.December, 2008);
            Date tomorrow = today + 1;

            Settings.Instance.setEvaluationDate(tomorrow);

            Handle <Quote> u = new Handle <Quote>(new SimpleQuote(2.9084382818797443));

            List <Date>   dates    = new InitializedList <Date>(25);
            List <double> forwards = new InitializedList <double>(25);

            dates[0]  = new Date(29, Month.December, 2008);  forwards[0] = 0.0025999342800;
            dates[1]  = new Date(5, Month.January, 2009);   forwards[1] = 0.0025999342800;
            dates[2]  = new Date(29, Month.January, 2009);   forwards[2] = 0.0053123275500;
            dates[3]  = new Date(27, Month.February, 2009);  forwards[3] = 0.0197049598721;
            dates[4]  = new Date(30, Month.March, 2009);     forwards[4] = 0.0220524845296;
            dates[5]  = new Date(29, Month.June, 2009);      forwards[5] = 0.0217076395643;
            dates[6]  = new Date(29, Month.December, 2009);  forwards[6] = 0.0230349627478;
            dates[7]  = new Date(29, Month.December, 2010);  forwards[7] = 0.0087631647476;
            dates[8]  = new Date(29, Month.December, 2011);  forwards[8] = 0.0219084299499;
            dates[9]  = new Date(31, Month.December, 2012);  forwards[9] = 0.0244798766219;
            dates[10] = new Date(30, Month.December, 2013);  forwards[10] = 0.0267885498456;
            dates[11] = new Date(29, Month.December, 2014);  forwards[11] = 0.0266922867562;
            dates[12] = new Date(29, Month.December, 2015);  forwards[12] = 0.0271052126386;
            dates[13] = new Date(29, Month.December, 2016);  forwards[13] = 0.0268829891648;
            dates[14] = new Date(29, Month.December, 2017);  forwards[14] = 0.0264594744498;
            dates[15] = new Date(31, Month.December, 2018);  forwards[15] = 0.0273450367424;
            dates[16] = new Date(30, Month.December, 2019);  forwards[16] = 0.0294852614749;
            dates[17] = new Date(29, Month.December, 2020);  forwards[17] = 0.0285556119719;
            dates[18] = new Date(29, Month.December, 2021);  forwards[18] = 0.0305557764659;
            dates[19] = new Date(29, Month.December, 2022);  forwards[19] = 0.0292244738422;
            dates[20] = new Date(29, Month.December, 2023);  forwards[20] = 0.0263917004194;
            dates[21] = new Date(29, Month.December, 2028);  forwards[21] = 0.0239626970243;
            dates[22] = new Date(29, Month.December, 2033);  forwards[22] = 0.0216417108090;
            dates[23] = new Date(29, Month.December, 2038);  forwards[23] = 0.0228343838422;
            dates[24] = new Date(31, Month.December, 2199);  forwards[24] = 0.0228343838422;

            Handle <YieldTermStructure> r = new Handle <YieldTermStructure>(new InterpolatedForwardCurve <BackwardFlat>(dates, forwards, new Actual360()));

            Handle <BlackVolTermStructure> sigma = new Handle <BlackVolTermStructure>(new BlackConstantVol(tomorrow, new NullCalendar(), 21.685235548092248,
                                                                                                           new Thirty360(Thirty360.Thirty360Convention.BondBasis)));

            BlackProcess process = new BlackProcess(u, r, sigma);

            Handle <Quote> spread = new Handle <Quote>(new SimpleQuote(0.11498700678012874));

            Date     issueDate    = new Date(23, Month.July, 2008);
            Date     maturityDate = new Date(1, Month.August, 2013);
            Calendar calendar     = new UnitedStates();
            Schedule schedule     = new MakeSchedule().from(issueDate)
                                    .to(maturityDate)
                                    .withTenor(new Period(6, TimeUnit.Months))
                                    .withCalendar(calendar)
                                    .withConvention(BusinessDayConvention.Unadjusted).value();
            int                 settlementDays  = 3;
            Exercise            exercise        = new EuropeanExercise(maturityDate);
            double              conversionRatio = 100.0 / 20.3175;
            List <double>       coupons         = new InitializedList <double>(schedule.size() - 1, 0.05);
            DayCounter          dayCounter      = new Thirty360(Thirty360.Thirty360Convention.BondBasis);
            CallabilitySchedule no_callability  = new CallabilitySchedule();
            DividendSchedule    no_dividends    = new DividendSchedule();
            double              redemption      = 100.0;

            ConvertibleFixedCouponBond bond = new ConvertibleFixedCouponBond(exercise, conversionRatio,
                                                                             no_dividends, no_callability,
                                                                             spread, issueDate, settlementDays,
                                                                             coupons, dayCounter,
                                                                             schedule, redemption);

            bond.setPricingEngine(new BinomialConvertibleEngine <CoxRossRubinstein> (process, 600));

            try
            {
                double x = bond.NPV(); // should throw; if not, an INF was not detected.
                QAssert.Fail("INF result was not detected: " + x + " returned");
            }
            catch (Exception)
            {
                // as expected. Do nothing.

                // Note: we're expecting an Error we threw, not just any
                // exception.  If something else is thrown, then there's
                // another problem and the test must fail.
            }
        }
Ejemplo n.º 53
0
        public void testBond()
        {
            /* when deeply out-of-the-money, the value of the convertible bond
             * should equal that of the underlying plain-vanilla bond. */

            // Testing out-of-the-money convertible bonds against vanilla bonds

            CommonVars vars = new CommonVars();

            vars.conversionRatio = 1.0e-16;

            Exercise euExercise = new EuropeanExercise(vars.maturityDate);
            Exercise amExercise = new AmericanExercise(vars.issueDate, vars.maturityDate);

            int            timeSteps = 1001;
            IPricingEngine engine    = new BinomialConvertibleEngine <CoxRossRubinstein>(vars.process, timeSteps);

            Handle <YieldTermStructure> discountCurve = new Handle <YieldTermStructure>(new ForwardSpreadedTermStructure(vars.riskFreeRate, vars.creditSpread));

            // zero-coupon

            Schedule schedule = new MakeSchedule().from(vars.issueDate)
                                .to(vars.maturityDate)
                                .withFrequency(Frequency.Once)
                                .withCalendar(vars.calendar)
                                .backwards().value();

            ConvertibleZeroCouponBond euZero = new ConvertibleZeroCouponBond(euExercise, vars.conversionRatio,
                                                                             vars.no_dividends, vars.no_callability,
                                                                             vars.creditSpread,
                                                                             vars.issueDate, vars.settlementDays,
                                                                             vars.dayCounter, schedule,
                                                                             vars.redemption);

            euZero.setPricingEngine(engine);

            ConvertibleZeroCouponBond amZero = new ConvertibleZeroCouponBond(amExercise, vars.conversionRatio,
                                                                             vars.no_dividends, vars.no_callability,
                                                                             vars.creditSpread,
                                                                             vars.issueDate, vars.settlementDays,
                                                                             vars.dayCounter, schedule,
                                                                             vars.redemption);

            amZero.setPricingEngine(engine);

            ZeroCouponBond zero = new ZeroCouponBond(vars.settlementDays, vars.calendar,
                                                     100.0, vars.maturityDate,
                                                     BusinessDayConvention.Following, vars.redemption, vars.issueDate);

            IPricingEngine bondEngine = new DiscountingBondEngine(discountCurve);

            zero.setPricingEngine(bondEngine);

            double tolerance = 1.0e-2 * (vars.faceAmount / 100.0);

            double error = Math.Abs(euZero.NPV() - zero.settlementValue());

            if (error > tolerance)
            {
                QAssert.Fail("failed to reproduce zero-coupon bond price:"
                             + "\n    calculated: " + euZero.NPV()
                             + "\n    expected:   " + zero.settlementValue()
                             + "\n    error:      " + error);
            }

            error = Math.Abs(amZero.NPV() - zero.settlementValue());
            if (error > tolerance)
            {
                QAssert.Fail("failed to reproduce zero-coupon bond price:"
                             + "\n    calculated: " + amZero.NPV()
                             + "\n    expected:   " + zero.settlementValue()
                             + "\n    error:      " + error);
            }

            // coupon

            List <double> coupons = new InitializedList <double>(1, 0.05);

            schedule = new MakeSchedule().from(vars.issueDate)
                       .to(vars.maturityDate)
                       .withFrequency(vars.frequency)
                       .withCalendar(vars.calendar)
                       .backwards().value();

            ConvertibleFixedCouponBond euFixed = new ConvertibleFixedCouponBond(euExercise, vars.conversionRatio,
                                                                                vars.no_dividends, vars.no_callability,
                                                                                vars.creditSpread,
                                                                                vars.issueDate, vars.settlementDays,
                                                                                coupons, vars.dayCounter,
                                                                                schedule, vars.redemption);

            euFixed.setPricingEngine(engine);

            ConvertibleFixedCouponBond amFixed = new ConvertibleFixedCouponBond(amExercise, vars.conversionRatio,
                                                                                vars.no_dividends, vars.no_callability,
                                                                                vars.creditSpread,
                                                                                vars.issueDate, vars.settlementDays,
                                                                                coupons, vars.dayCounter,
                                                                                schedule, vars.redemption);

            amFixed.setPricingEngine(engine);

            FixedRateBond fixedBond = new FixedRateBond(vars.settlementDays, vars.faceAmount, schedule,
                                                        coupons, vars.dayCounter, BusinessDayConvention.Following,
                                                        vars.redemption, vars.issueDate);

            fixedBond.setPricingEngine(bondEngine);

            tolerance = 2.0e-2 * (vars.faceAmount / 100.0);

            error = Math.Abs(euFixed.NPV() - fixedBond.settlementValue());
            if (error > tolerance)
            {
                QAssert.Fail("failed to reproduce fixed-coupon bond price:"
                             + "\n    calculated: " + euFixed.NPV()
                             + "\n    expected:   " + fixedBond.settlementValue()
                             + "\n    error:      " + error);
            }

            error = Math.Abs(amFixed.NPV() - fixedBond.settlementValue());
            if (error > tolerance)
            {
                QAssert.Fail("failed to reproduce fixed-coupon bond price:"
                             + "\n    calculated: " + amFixed.NPV()
                             + "\n    expected:   " + fixedBond.settlementValue()
                             + "\n    error:      " + error);
            }

            // floating-rate

            IborIndex     index      = new Euribor1Y(discountCurve);
            int           fixingDays = 2;
            List <double> gearings   = new InitializedList <double>(1, 1.0);
            List <double> spreads    = new List <double>();

            ConvertibleFloatingRateBond euFloating = new ConvertibleFloatingRateBond(euExercise, vars.conversionRatio,
                                                                                     vars.no_dividends, vars.no_callability,
                                                                                     vars.creditSpread,
                                                                                     vars.issueDate, vars.settlementDays,
                                                                                     index, fixingDays, spreads,
                                                                                     vars.dayCounter, schedule,
                                                                                     vars.redemption);

            euFloating.setPricingEngine(engine);

            ConvertibleFloatingRateBond amFloating = new ConvertibleFloatingRateBond(amExercise, vars.conversionRatio,
                                                                                     vars.no_dividends, vars.no_callability,
                                                                                     vars.creditSpread,
                                                                                     vars.issueDate, vars.settlementDays,
                                                                                     index, fixingDays, spreads,
                                                                                     vars.dayCounter, schedule,
                                                                                     vars.redemption);

            amFloating.setPricingEngine(engine);

            IborCouponPricer pricer = new BlackIborCouponPricer(new Handle <OptionletVolatilityStructure>());

            Schedule floatSchedule = new Schedule(vars.issueDate, vars.maturityDate,
                                                  new Period(vars.frequency),
                                                  vars.calendar, BusinessDayConvention.Following, BusinessDayConvention.Following,
                                                  DateGeneration.Rule.Backward, false);

            FloatingRateBond floating = new FloatingRateBond(vars.settlementDays, vars.faceAmount, floatSchedule,
                                                             index, vars.dayCounter, BusinessDayConvention.Following, fixingDays,
                                                             gearings, spreads,
                                                             new List <double?>(), new List <double?>(),
                                                             false,
                                                             vars.redemption, vars.issueDate);

            floating.setPricingEngine(bondEngine);
            Utils.setCouponPricer(floating.cashflows(), pricer);

            tolerance = 2.0e-2 * (vars.faceAmount / 100.0);

            error = Math.Abs(euFloating.NPV() - floating.settlementValue());
            if (error > tolerance)
            {
                QAssert.Fail("failed to reproduce floating-rate bond price:"
                             + "\n    calculated: " + euFloating.NPV()
                             + "\n    expected:   " + floating.settlementValue()
                             + "\n    error:      " + error);
            }

            error = Math.Abs(amFloating.NPV() - floating.settlementValue());
            if (error > tolerance)
            {
                QAssert.Fail("failed to reproduce floating-rate bond price:"
                             + "\n    calculated: " + amFloating.NPV()
                             + "\n    expected:   " + floating.settlementValue()
                             + "\n    error:      " + error);
            }
        }
Ejemplo n.º 54
0
        public List<double> discountBond(List<double> rates)
        {
            List<double> discountFactors = new InitializedList<double>(size_);
            discountFactors[0] = 1.0 / (1.0 + rates[0] * accrualPeriod_[0]);

            for (int i = 1; i < size_; ++i) {
                discountFactors[i] =
                    discountFactors[i - 1] / (1.0 + rates[i] * accrualPeriod_[i]);
            }
            return discountFactors;
        }
Ejemplo n.º 55
0
        public void testSimpleCovarianceModels()
        {
            // Testing simple covariance models
            const int    size      = 10;
            const double tolerance = 1e-14;
            int          i;

            LmCorrelationModel corrModel = new LmExponentialCorrelationModel(size, 0.1);

            Matrix recon = corrModel.correlation(0.0, null)
                           - corrModel.pseudoSqrt(0.0, null) * Matrix.transpose(corrModel.pseudoSqrt(0.0, null));

            for (i = 0; i < size; ++i)
            {
                for (int j = 0; j < size; ++j)
                {
                    if (Math.Abs(recon[i, j]) > tolerance)
                    {
                        QAssert.Fail("Failed to reproduce correlation matrix"
                                     + "\n    calculated: " + recon[i, j]
                                     + "\n    expected:   " + 0);
                    }
                }
            }

            List <double> fixingTimes = new InitializedList <double>(size);

            for (i = 0; i < size; ++i)
            {
                fixingTimes[i] = 0.5 * i;
            }

            const double a = 0.2;
            const double b = 0.1;
            const double c = 2.1;
            const double d = 0.3;

            LmVolatilityModel volaModel = new LmLinearExponentialVolatilityModel(fixingTimes, a, b, c, d);

            LfmCovarianceProxy covarProxy = new LfmCovarianceProxy(volaModel, corrModel);

            LiborForwardModelProcess process = new LiborForwardModelProcess(size, makeIndex());

            LiborForwardModel liborModel = new LiborForwardModel(process, volaModel, corrModel);

            for (double t = 0; t < 4.6; t += 0.31)
            {
                recon = covarProxy.covariance(t, null)
                        - covarProxy.diffusion(t, null) * Matrix.transpose(covarProxy.diffusion(t, null));

                for (int k = 0; k < size; ++k)
                {
                    for (int j = 0; j < size; ++j)
                    {
                        if (Math.Abs(recon[k, j]) > tolerance)
                        {
                            QAssert.Fail("Failed to reproduce correlation matrix"
                                         + "\n    calculated: " + recon[k, j]
                                         + "\n    expected:   " + 0);
                        }
                    }
                }

                Vector volatility = volaModel.volatility(t, null);

                for (int k = 0; k < size; ++k)
                {
                    double expected = 0;
                    if (k > 2 * t)
                    {
                        double T = fixingTimes[k];
                        expected = (a * (T - t) + d) * Math.Exp(-b * (T - t)) + c;
                    }

                    if (Math.Abs(expected - volatility[k]) > tolerance)
                    {
                        QAssert.Fail("Failed to reproduce volatities"
                                     + "\n    calculated: " + volatility[k]
                                     + "\n    expected:   " + expected);
                    }
                }
            }
        }
Ejemplo n.º 56
0
        public void testSpreadDependency()
        {
            //"Testing swaption dependency on spread...";

            CommonVars vars = new CommonVars();

            double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 };

            for (int i = 0; i < exercises.Length; i++)
            {
                for (int j = 0; j < lengths.Length; j++)
                {
                    for (int k = 0; k < type.Length; k++)
                    {
                        Date exerciseDate = vars.calendar.advance(vars.today,
                                                                  exercises[i]);
                        Date startDate =
                            vars.calendar.advance(exerciseDate,
                                                  vars.settlementDays, TimeUnit.Days);
                        // store the results for different rates...
                        List <double> values      = new InitializedList <double>(spreads.Length);
                        List <double> values_cash = new InitializedList <double>(spreads.Length);
                        for (int l = 0; l < spreads.Length; l++)
                        {
                            VanillaSwap swap =
                                new MakeVanillaSwap(lengths[j], vars.index, 0.06)
                                .withEffectiveDate(startDate)
                                .withFloatingLegSpread(spreads[l])
                                .withType(type[k]);
                            Swaption swaption =
                                vars.makeSwaption(swap, exerciseDate, 0.20);
                            // FLOATING_POINT_EXCEPTION
                            values[l] = swaption.NPV();
                            Swaption swaption_cash =
                                vars.makeSwaption(swap, exerciseDate, 0.20,
                                                  Settlement.Type.Cash);
                            values_cash[l] = swaption_cash.NPV();
                        }
                        // and check that they go the right way
                        if (type[k] == VanillaSwap.Type.Payer)
                        {
                            for (int n = 0; n < spreads.Length - 1; n++)
                            {
                                if (values[n] > values[n + 1])
                                {
                                    Assert.Fail("NPV is decreasing with the spread " +
                                                "in a payer swaption (physical delivered):" +
                                                "\nexercise date: " + exerciseDate +
                                                "\nlength:        " + lengths[j] +
                                                "\nvalue:         " + values[n] + " for spread: " + spreads[n] +
                                                "\nvalue:         " + values[n + 1] + " for spread: " + spreads[n + 1]);
                                }

                                if (values_cash[n] > values_cash[n + 1])
                                {
                                    Assert.Fail("NPV is decreasing with the spread " +
                                                "in a payer swaption (cash delivered):" +
                                                "\nexercise date: " + exerciseDate +
                                                "\nlength: " + lengths[j] +
                                                "\nvalue:  " + values_cash[n] + " for spread: " + spreads[n] +
                                                "\nvalue:  " + values_cash[n + 1] + " for spread: " + spreads[n + 1]);
                                }
                            }
                        }
                        else
                        {
                            for (int n = 0; n < spreads.Length - 1; n++)
                            {
                                if (values[n] < values[n + 1])
                                {
                                    Assert.Fail("NPV is increasing with the spread " +
                                                "in a receiver swaption (physical delivered):" +
                                                "\nexercise date: " + exerciseDate +
                                                "\nlength: " + lengths[j] +
                                                "\nvalue:  " + values[n] + " for spread: " + spreads[n] +
                                                "\nvalue:  " + values[n + 1] + " for spread: " + spreads[n + 1]);
                                }

                                if (values_cash[n] < values_cash[n + 1])
                                {
                                    Assert.Fail("NPV is increasing with the spread " +
                                                "in a receiver swaption (cash delivered):" +
                                                "\nexercise date: " + exerciseDate +
                                                "\nlength: " + lengths[j] +
                                                "\nvalue:  " + values_cash[n] + " for spread: " + spreads[n] +
                                                "\nvalue:  " + values_cash[n + 1] + " for spread: " + spreads[n + 1]);
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 57
0
        public void RiskStatisticsTest()
        {
            //    ("Testing risk measures...");

            IncrementalGaussianStatistics igs = new IncrementalGaussianStatistics();
            RiskStatistics s = new RiskStatistics();

            double[] averages = { -100.0, -1.0, 0.0, 1.0, 100.0 };
            double[] sigmas = { 0.1, 1.0, 100.0 };
            int      i, j, k, N;

            N = (int)Math.Pow(2, 16) - 1;
            double        dataMin, dataMax;
            List <double> data = new InitializedList <double>(N), weights = new InitializedList <double>(N);

            for (i = 0; i < averages.Length; i++)
            {
                for (j = 0; j < sigmas.Length; j++)
                {
                    NormalDistribution           normal     = new NormalDistribution(averages[i], sigmas[j]);
                    CumulativeNormalDistribution cumulative = new CumulativeNormalDistribution(averages[i], sigmas[j]);
                    InverseCumulativeNormal      inverseCum = new InverseCumulativeNormal(averages[i], sigmas[j]);

                    SobolRsg rng = new SobolRsg(1);
                    dataMin = double.MaxValue;
                    dataMax = double.MinValue;
                    for (k = 0; k < N; k++)
                    {
                        data[k]    = inverseCum.value(rng.nextSequence().value[0]);
                        dataMin    = Math.Min(dataMin, data[k]);
                        dataMax    = Math.Max(dataMax, data[k]);
                        weights[k] = 1.0;
                    }

                    igs.addSequence(data, weights);
                    s.addSequence(data, weights);

                    // checks
                    double calculated, expected;
                    double tolerance;

                    if (igs.samples() != N)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong number of samples\n"
                                     + "    calculated: " + igs.samples() + "\n"
                                     + "    expected:   " + N);
                    }
                    if (s.samples() != N)
                    {
                        QAssert.Fail("RiskStatistics: wrong number of samples\n"
                                     + "    calculated: " + s.samples() + "\n"
                                     + "    expected:   " + N);
                    }


                    // weightSum()
                    tolerance  = 1e-10;
                    expected   = weights.Sum();
                    calculated = igs.weightSum();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong sum of weights\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.weightSum();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong sum of weights\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // min
                    tolerance  = 1e-12;
                    expected   = dataMin;
                    calculated = igs.min();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong minimum value\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.min();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: "
                                     + "wrong minimum value\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // max
                    expected   = dataMax;
                    calculated = igs.max();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong maximum value\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.max();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: "
                                     + "wrong maximum value\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // mean
                    expected  = averages[i];
                    tolerance = (expected == 0.0 ? 1.0e-13 :
                                 Math.Abs(expected) * 1.0e-13);
                    calculated = igs.mean();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong mean value"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.mean();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong mean value"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // variance
                    expected   = sigmas[j] * sigmas[j];
                    tolerance  = expected * 1.0e-1;
                    calculated = igs.variance();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong variance"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.variance();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong variance"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // standardDeviation
                    expected   = sigmas[j];
                    tolerance  = expected * 1.0e-1;
                    calculated = igs.standardDeviation();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong standard deviation"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.standardDeviation();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong standard deviation"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // missing errorEstimate() test

                    // skewness
                    expected   = 0.0;
                    tolerance  = 1.0e-4;
                    calculated = igs.skewness();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong skewness"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.skewness();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong skewness"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // kurtosis
                    expected   = 0.0;
                    tolerance  = 1.0e-1;
                    calculated = igs.kurtosis();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong kurtosis"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.kurtosis();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong kurtosis"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // percentile
                    expected  = averages[i];
                    tolerance = (expected == 0.0 ? 1.0e-3 :
                                 Math.Abs(expected * 1.0e-3));
                    calculated = igs.gaussianPercentile(0.5);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian percentile"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianPercentile(0.5);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong Gaussian percentile"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.percentile(0.5);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong percentile"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }



                    // potential upside
                    double upper_tail = averages[i] + 2.0 * sigmas[j],
                           lower_tail = averages[i] - 2.0 * sigmas[j];
                    double twoSigma   = cumulative.value(upper_tail);

                    expected  = Math.Max(upper_tail, 0.0);
                    tolerance = (expected == 0.0 ? 1.0e-3 :
                                 Math.Abs(expected * 1.0e-3));
                    calculated = igs.gaussianPotentialUpside(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian potential upside"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianPotentialUpside(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong Gaussian potential upside"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.potentialUpside(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong potential upside"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // just to check that GaussianStatistics<StatsHolder> does work
                    StatsHolder h = new StatsHolder(s.mean(), s.standardDeviation());
                    GenericGaussianStatistics <StatsHolder> test = new GenericGaussianStatistics <StatsHolder>(h);
                    expected   = s.gaussianPotentialUpside(twoSigma);
                    calculated = test.gaussianPotentialUpside(twoSigma);
                    if (calculated != expected)
                    {
                        QAssert.Fail("GenericGaussianStatistics<StatsHolder> fails"
                                     + "\n  calculated: " + calculated
                                     + "\n  expected: " + expected);
                    }


                    // value-at-risk
                    expected  = -Math.Min(lower_tail, 0.0);
                    tolerance = (expected == 0.0 ? 1.0e-3 :
                                 Math.Abs(expected * 1.0e-3));
                    calculated = igs.gaussianValueAtRisk(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian value-at-risk"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianValueAtRisk(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong Gaussian value-at-risk"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.valueAtRisk(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong value-at-risk"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }

                    if (averages[i] > 0.0 && sigmas[j] < averages[i])
                    {
                        // no data will miss the targets:
                        // skip the rest of this iteration
                        igs.reset();
                        s.reset();
                        continue;
                    }


                    // expected shortfall
                    expected = -Math.Min(averages[i]
                                         - sigmas[j] * sigmas[j]
                                         * normal.value(lower_tail) / (1.0 - twoSigma),
                                         0.0);
                    tolerance = (expected == 0.0 ? 1.0e-4
                                            : Math.Abs(expected) * 1.0e-2);
                    calculated = igs.gaussianExpectedShortfall(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian expected shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianExpectedShortfall(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong Gaussian expected shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.expectedShortfall(twoSigma);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong expected shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // shortfall
                    expected  = 0.5;
                    tolerance = (expected == 0.0 ? 1.0e-3 :
                                 Math.Abs(expected * 1.0e-3));
                    calculated = igs.gaussianShortfall(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianShortfall(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong Gaussian shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.shortfall(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // average shortfall
                    expected   = sigmas[j] / Math.Sqrt(2.0 * Const.M_PI) * 2.0;
                    tolerance  = expected * 1.0e-3;
                    calculated = igs.gaussianAverageShortfall(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian average shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianAverageShortfall(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong Gaussian average shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.averageShortfall(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: wrong average shortfall"
                                     + " for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // regret
                    expected   = sigmas[j] * sigmas[j];
                    tolerance  = expected * 1.0e-1;
                    calculated = igs.gaussianRegret(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian regret(" + averages[i] + ") "
                                     + "for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.gaussianRegret(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: "
                                     + "wrong Gaussian regret(" + averages[i] + ") "
                                     + "for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = s.regret(averages[i]);
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("RiskStatistics: "
                                     + "wrong regret(" + averages[i] + ") "
                                     + "for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }


                    // downsideVariance
                    expected  = s.downsideVariance();
                    tolerance = (expected == 0.0 ? 1.0e-3 :
                                 Math.Abs(expected * 1.0e-3));
                    calculated = igs.downsideVariance();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong downside variance"
                                     + "for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }
                    calculated = igs.gaussianDownsideVariance();
                    if (Math.Abs(calculated - expected) > tolerance)
                    {
                        QAssert.Fail("IncrementalGaussianStatistics: "
                                     + "wrong Gaussian downside variance"
                                     + "for N(" + averages[i] + ", "
                                     + sigmas[j] + ")\n"
                                     + "    calculated: " + calculated + "\n"
                                     + "    expected:   " + expected + "\n"
                                     + "    tolerance:  " + tolerance);
                    }

                    // downsideVariance
                    if (averages[i] == 0.0)
                    {
                        expected   = sigmas[j] * sigmas[j];
                        tolerance  = expected * 1.0e-3;
                        calculated = igs.downsideVariance();
                        if (Math.Abs(calculated - expected) > tolerance)
                        {
                            QAssert.Fail("IncrementalGaussianStatistics: "
                                         + "wrong downside variance"
                                         + "for N(" + averages[i] + ", "
                                         + sigmas[j] + ")\n"
                                         + "    calculated: " + calculated + "\n"
                                         + "    expected:   " + expected + "\n"
                                         + "    tolerance:  " + tolerance);
                        }
                        calculated = igs.gaussianDownsideVariance();
                        if (Math.Abs(calculated - expected) > tolerance)
                        {
                            QAssert.Fail("IncrementalGaussianStatistics: "
                                         + "wrong Gaussian downside variance"
                                         + "for N(" + averages[i] + ", "
                                         + sigmas[j] + ")\n"
                                         + "    calculated: " + calculated + "\n"
                                         + "    expected:   " + expected + "\n"
                                         + "    tolerance:  " + tolerance);
                        }
                        calculated = s.downsideVariance();
                        if (Math.Abs(calculated - expected) > tolerance)
                        {
                            QAssert.Fail("RiskStatistics: wrong downside variance"
                                         + "for N(" + averages[i] + ", "
                                         + sigmas[j] + ")\n"
                                         + "    calculated: " + calculated + "\n"
                                         + "    expected:   " + expected + "\n"
                                         + "    tolerance:  " + tolerance);
                        }
                        calculated = s.gaussianDownsideVariance();
                        if (Math.Abs(calculated - expected) > tolerance)
                        {
                            QAssert.Fail("RiskStatistics: wrong Gaussian downside variance"
                                         + "for N(" + averages[i] + ", "
                                         + sigmas[j] + ")\n"
                                         + "    calculated: " + calculated + "\n"
                                         + "    expected:   " + expected + "\n"
                                         + "    tolerance:  " + tolerance);
                        }
                    }

                    igs.reset();
                    s.reset();
                }
            }
        }
Ejemplo n.º 58
0
        public void testMonteCarloCapletPricing()
        {
            //"Testing caplet LMM Monte-Carlo caplet pricing..."

            //SavedSettings backup;

            /* factor loadings are taken from Hull & White article
             * plus extra normalisation to get orthogonal eigenvectors
             * http://www.rotman.utoronto.ca/~amackay/fin/libormktmodel2.pdf */
            double[] compValues = { 0.85549771,  0.46707264,  0.22353259,
                                    0.91915359,  0.37716089,  0.11360610,
                                    0.96438280,  0.26413316, -0.01412414,
                                    0.97939148,  0.13492952, -0.15028753,
                                    0.95970595, -0.00000000, -0.28100621,
                                    0.97939148, -0.13492952, -0.15028753,
                                    0.96438280, -0.26413316, -0.01412414,
                                    0.91915359, -0.37716089,  0.11360610,
                                    0.85549771, -0.46707264, 0.22353259 };

            Matrix        volaComp    = new Matrix(9, 3);
            List <double> lcompValues = new InitializedList <double>(27, 0);
            List <double> ltemp       = new InitializedList <double>(3, 0);

            lcompValues = compValues.ToList();
            //std::copy(compValues, compValues+9*3, volaComp.begin());
            for (int i = 0; i < 9; i++)
            {
                ltemp = lcompValues.GetRange(3 * i, 3);
                for (int j = 0; j < 3; j++)
                {
                    volaComp[i, j] = ltemp[j];
                }
            }
            LiborForwardModelProcess process1 = makeProcess();
            LiborForwardModelProcess process2 = makeProcess(volaComp);

            List <double> tmp  = process1.fixingTimes();
            TimeGrid      grid = new TimeGrid(tmp, 12);

            List <int> location = new List <int>();

            for (int i = 0; i < tmp.Count; ++i)
            {
                location.Add(grid.index(tmp[i]));
            }

            // set-up a small Monte-Carlo simulation to price caplets
            // and ratchet caps using a one- and a three factor libor market model

            ulong seed = 42;

            LowDiscrepancy.icInstance = new InverseCumulativeNormal();
            IRNG rsg1 = (IRNG) new LowDiscrepancy().make_sequence_generator(
                process1.factors() * (grid.size() - 1), seed);
            IRNG rsg2 = (IRNG) new LowDiscrepancy().make_sequence_generator(
                process2.factors() * (grid.size() - 1), seed);

            MultiPathGenerator <IRNG> generator1 = new MultiPathGenerator <IRNG> (process1, grid, rsg1, false);
            MultiPathGenerator <IRNG> generator2 = new MultiPathGenerator <IRNG> (process2, grid, rsg2, false);

            const int nrTrails             = 250000;
            List <GeneralStatistics> stat1 = new InitializedList <GeneralStatistics>(process1.size());
            List <GeneralStatistics> stat2 = new InitializedList <GeneralStatistics>(process2.size());
            List <GeneralStatistics> stat3 = new InitializedList <GeneralStatistics>(process2.size() - 1);

            for (int i = 0; i < nrTrails; ++i)
            {
                Sample <MultiPath> path1 = generator1.next();
                Sample <MultiPath> path2 = generator2.next();

                List <double> rates1 = new InitializedList <double>(len);
                List <double> rates2 = new InitializedList <double>(len);
                for (int j = 0; j < process1.size(); ++j)
                {
                    rates1[j] = path1.value[j][location[j]];
                    rates2[j] = path2.value[j][location[j]];
                }

                List <double> dis1 = process1.discountBond(rates1);
                List <double> dis2 = process2.discountBond(rates2);

                for (int k = 0; k < process1.size(); ++k)
                {
                    double accrualPeriod = process1.accrualEndTimes()[k]
                                           - process1.accrualStartTimes()[k];
                    // caplet payoff function, cap rate at 4%
                    double payoff1 = Math.Max(rates1[k] - 0.04, 0.0) * accrualPeriod;

                    double payoff2 = Math.Max(rates2[k] - 0.04, 0.0) * accrualPeriod;
                    stat1[k].add(dis1[k] * payoff1);
                    stat2[k].add(dis2[k] * payoff2);

                    if (k != 0)
                    {
                        // ratchet cap payoff function
                        double payoff3 = Math.Max(rates2[k] - (rates2[k - 1] + 0.0025), 0.0)
                                         * accrualPeriod;
                        stat3[k - 1].add(dis2[k] * payoff3);
                    }
                }
            }

            double[] capletNpv = { 0.000000000000, 0.000002841629, 0.002533279333,
                                   0.009577143571, 0.017746502618, 0.025216116835,
                                   0.031608230268, 0.036645683881, 0.039792254012,
                                   0.041829864365 };

            double[] ratchetNpv = { 0.0082644895, 0.0082754754, 0.0082159966,
                                    0.0082982822, 0.0083803357, 0.0084366961,
                                    0.0084173270, 0.0081803406, 0.0079533814 };

            for (int k = 0; k < process1.size(); ++k)
            {
                double calculated1 = stat1[k].mean();
                double tolerance1  = stat1[k].errorEstimate();
                double expected    = capletNpv[k];

                if (Math.Abs(calculated1 - expected) > tolerance1)
                {
                    Assert.Fail("Failed to reproduce expected caplet NPV"
                                + "\n    calculated: " + calculated1
                                + "\n    error int:  " + tolerance1
                                + "\n    expected:   " + expected);
                }

                double calculated2 = stat2[k].mean();
                double tolerance2  = stat2[k].errorEstimate();

                if (Math.Abs(calculated2 - expected) > tolerance2)
                {
                    Assert.Fail("Failed to reproduce expected caplet NPV"
                                + "\n    calculated: " + calculated2
                                + "\n    error int:  " + tolerance2
                                + "\n    expected:   " + expected);
                }

                if (k != 0)
                {
                    double calculated3 = stat3[k - 1].mean();
                    double tolerance3  = stat3[k - 1].errorEstimate();
                    expected = ratchetNpv[k - 1];

                    double refError = 1e-5; // 1e-5. error bars of the reference values

                    if (Math.Abs(calculated3 - expected) > tolerance3 + refError)
                    {
                        Assert.Fail("Failed to reproduce expected caplet NPV"
                                    + "\n    calculated: " + calculated3
                                    + "\n    error int:  " + tolerance3 + refError
                                    + "\n    expected:   " + expected);
                    }
                }
            }
        }
Ejemplo n.º 59
0
        static void Main(string[] args) {

            DateTime timer = DateTime.Now;

            /*********************
             ***  MARKET DATA  ***
             *********************/

            Calendar calendar = new TARGET();

            Date settlementDate = new Date(18, Month.September, 2008);
            // must be a business day
            settlementDate = calendar.adjust(settlementDate);

            int fixingDays = 3;
            int settlementDays = 3;

            Date todaysDate = calendar.advance(settlementDate, -fixingDays, TimeUnit.Days);
            // nothing to do with Date::todaysDate
            Settings.setEvaluationDate(todaysDate);

            Console.WriteLine("Today: {0}, {1}", todaysDate.DayOfWeek, todaysDate);
            Console.WriteLine("Settlement date: {0}, {1}", settlementDate.DayOfWeek, settlementDate);


            // Building of the bonds discounting yield curve

            /*********************
             ***  RATE HELPERS ***
             *********************/

            // RateHelpers are built from the above quotes together with
            // other instrument dependant infos.  Quotes are passed in
            // relinkable handles which could be relinked to some other
            // data source later.

            // Common data

            // ZC rates for the short end
             double zc3mQuote=0.0096;
             double zc6mQuote=0.0145;
             double zc1yQuote=0.0194;

             Quote zc3mRate = new SimpleQuote(zc3mQuote);
             Quote zc6mRate = new SimpleQuote(zc6mQuote);
             Quote zc1yRate = new SimpleQuote(zc1yQuote);

             DayCounter zcBondsDayCounter = new Actual365Fixed();

             RateHelper zc3m = new DepositRateHelper(new Handle<Quote>(zc3mRate),
                                                          new Period(3, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc6m = new DepositRateHelper(new Handle<Quote>(zc6mRate),
                                                          new Period(6, TimeUnit.Months), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);
             RateHelper zc1y = new DepositRateHelper(new Handle<Quote>(zc1yRate),
                                                          new Period(1, TimeUnit.Years), fixingDays,
                                                          calendar, BusinessDayConvention.ModifiedFollowing,
                                                          true, zcBondsDayCounter);

            // setup bonds
            double redemption = 100.0;

            const int numberOfBonds = 5;

            Date[] issueDates = {
                    new Date (15, Month.March, 2005),
                    new Date (15, Month.June, 2005),
                    new Date (30, Month.June, 2006),
                    new Date (15, Month.November, 2002),
                    new Date (15, Month.May, 1987)
            };

            Date[] maturities = {
                    new Date (31, Month.August, 2010),
                    new Date (31, Month.August, 2011),
                    new Date (31, Month.August, 2013),
                    new Date (15, Month.August, 2018),
                    new Date (15, Month.May, 2038)
            };

            double[] couponRates = {
                    0.02375,
                    0.04625,
                    0.03125,
                    0.04000,
                    0.04500
            };

            double[] marketQuotes = {
                    100.390625,
                    106.21875,
                    100.59375,
                    101.6875,
                    102.140625
            };

            List<SimpleQuote> quote = new List<SimpleQuote>();
            for (int i=0; i<numberOfBonds; i++) {
                SimpleQuote cp = new SimpleQuote(marketQuotes[i]);
                quote.Add(cp);
            }

            List<RelinkableHandle<Quote>> quoteHandle = new InitializedList<RelinkableHandle<Quote>>(numberOfBonds);
            for (int i=0; i<numberOfBonds; i++) {
                quoteHandle[i].linkTo(quote[i]);
            }

            // Definition of the rate helpers
            List<FixedRateBondHelper> bondsHelpers = new List<FixedRateBondHelper>();
            for (int i=0; i<numberOfBonds; i++) {

                Schedule schedule = new Schedule(issueDates[i], maturities[i], new Period(Frequency.Semiannual), 
                                                 new UnitedStates(UnitedStates.Market.GovernmentBond),
                                                 BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, 
                                                 DateGeneration.Rule.Backward, false);

                FixedRateBondHelper bondHelper = new FixedRateBondHelper(quoteHandle[i],
                                                                         settlementDays,
                                                                         100.0,
                                                                         schedule,
                                                                         new List<double>() { couponRates[i] },
                                                                         new ActualActual(ActualActual.Convention.Bond),
                                                                         BusinessDayConvention.Unadjusted,
                                                                         redemption,
                                                                         issueDates[i]);

                bondsHelpers.Add(bondHelper);
            }

            /*********************
             **  CURVE BUILDING **
             *********************/

             // Any DayCounter would be fine.
             // ActualActual::ISDA ensures that 30 years is 30.0
             DayCounter termStructureDayCounter = new ActualActual(ActualActual.Convention.ISDA);

             double tolerance = 1.0e-15;

             // A depo-bond curve
             List<RateHelper> bondInstruments = new List<RateHelper>();

             // Adding the ZC bonds to the curve for the short end
             bondInstruments.Add(zc3m);
             bondInstruments.Add(zc6m);
             bondInstruments.Add(zc1y);

             // Adding the Fixed rate bonds to the curve for the long end
             for (int i=0; i<numberOfBonds; i++) {
                 bondInstruments.Add(bondsHelpers[i]);
             }

             YieldTermStructure bondDiscountingTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>(
                                                                     settlementDate, bondInstruments,
                                                                     termStructureDayCounter,
                                                                     new List<Handle<Quote>>(),
                                                                     new List<Date>(),
                                                                     tolerance);

             // Building of the Libor forecasting curve
             // deposits
             double d1wQuote=0.043375;
             double d1mQuote=0.031875;
             double d3mQuote=0.0320375;
             double d6mQuote=0.03385;
             double d9mQuote=0.0338125;
             double d1yQuote=0.0335125;
             // swaps
             double s2yQuote=0.0295;
             double s3yQuote=0.0323;
             double s5yQuote=0.0359;
             double s10yQuote=0.0412;
             double s15yQuote=0.0433;


             /********************
              ***    QUOTES    ***
              ********************/

             // SimpleQuote stores a value which can be manually changed;
             // other Quote subclasses could read the value from a database
             // or some kind of data feed.

             // deposits
             Quote d1wRate = new SimpleQuote(d1wQuote);
             Quote d1mRate = new SimpleQuote(d1mQuote);
             Quote d3mRate = new SimpleQuote(d3mQuote);
             Quote d6mRate = new SimpleQuote(d6mQuote);
             Quote d9mRate = new SimpleQuote(d9mQuote);
             Quote d1yRate = new SimpleQuote(d1yQuote);
             // swaps
             Quote s2yRate = new SimpleQuote(s2yQuote);
             Quote s3yRate = new SimpleQuote(s3yQuote);
             Quote s5yRate = new SimpleQuote(s5yQuote);
             Quote s10yRate = new SimpleQuote(s10yQuote);
             Quote s15yRate = new SimpleQuote(s15yQuote);

             /*********************
              ***  RATE HELPERS ***
              *********************/

             // RateHelpers are built from the above quotes together with
             // other instrument dependant infos.  Quotes are passed in
             // relinkable handles which could be relinked to some other
             // data source later.

             // deposits
             DayCounter depositDayCounter = new Actual360();

             RateHelper d1w = new DepositRateHelper(
                     new Handle<Quote>(d1wRate),
                     new Period(1, TimeUnit.Weeks), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d1m = new DepositRateHelper(
                     new Handle<Quote>(d1mRate),
                     new Period(1, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d3m = new DepositRateHelper(
                     new Handle<Quote>(d3mRate),
                     new Period(3, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d6m = new DepositRateHelper(
                     new Handle<Quote>(d6mRate),
                     new Period(6, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d9m = new DepositRateHelper(
                     new Handle<Quote>(d9mRate),
                     new Period(9, TimeUnit.Months), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);
             RateHelper d1y = new DepositRateHelper(
                     new Handle<Quote>(d1yRate),
                     new Period(1, TimeUnit.Years), fixingDays,
                     calendar, BusinessDayConvention.ModifiedFollowing,
                     true, depositDayCounter);

             // setup swaps
             Frequency swFixedLegFrequency =Frequency.Annual;
             BusinessDayConvention swFixedLegConvention = BusinessDayConvention.Unadjusted;
             DayCounter swFixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European);
             IborIndex swFloatingLegIndex = new Euribor6M();

             Period forwardStart = new Period(1, TimeUnit.Days);

             RateHelper s2y = new SwapRateHelper(
                     new Handle<Quote>(s2yRate), new Period(2, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s3y = new SwapRateHelper(
                     new Handle<Quote>(s3yRate), new Period(3, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s5y = new SwapRateHelper(
                     new Handle<Quote>(s5yRate), new Period(5, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s10y = new SwapRateHelper(
                     new Handle<Quote>(s10yRate), new Period(10, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);
             RateHelper s15y = new SwapRateHelper(
                     new Handle<Quote>(s15yRate), new Period(15, TimeUnit.Years),
                     calendar, swFixedLegFrequency,
                     swFixedLegConvention, swFixedLegDayCounter,
                     swFloatingLegIndex, new Handle<Quote>(),forwardStart);


             /*********************
              **  CURVE BUILDING **
              *********************/

             // Any DayCounter would be fine.
             // ActualActual::ISDA ensures that 30 years is 30.0

             // A depo-swap curve
             List<RateHelper> depoSwapInstruments = new List<RateHelper>();
             depoSwapInstruments.Add(d1w);
             depoSwapInstruments.Add(d1m);
             depoSwapInstruments.Add(d3m);
             depoSwapInstruments.Add(d6m);
             depoSwapInstruments.Add(d9m);
             depoSwapInstruments.Add(d1y);
             depoSwapInstruments.Add(s2y);
             depoSwapInstruments.Add(s3y);
             depoSwapInstruments.Add(s5y);
             depoSwapInstruments.Add(s10y);
             depoSwapInstruments.Add(s15y);
             YieldTermStructure depoSwapTermStructure = new PiecewiseYieldCurve<Discount,LogLinear>(
                             settlementDate, depoSwapInstruments,
                             termStructureDayCounter,
                             new List<Handle<Quote> >(),
                             new List<Date>(),
                             tolerance);

             // Term structures that will be used for pricing:
             // the one used for discounting cash flows
             RelinkableHandle<YieldTermStructure> discountingTermStructure = new RelinkableHandle<YieldTermStructure>();
             // the one used for forward rate forecasting
             RelinkableHandle<YieldTermStructure> forecastingTermStructure = new RelinkableHandle<YieldTermStructure>();

             /*********************
              * BONDS TO BE PRICED *
              **********************/

             // Common data
             double faceAmount = 100;

             // Pricing engine
             IPricingEngine bondEngine = new DiscountingBondEngine(discountingTermStructure);

             // Zero coupon bond
             ZeroCouponBond zeroCouponBond = new ZeroCouponBond(
                     settlementDays,
                     new UnitedStates(UnitedStates.Market.GovernmentBond),
                     faceAmount,
                     new Date(15, Month.August,2013),
                     BusinessDayConvention.Following,
                     116.92,
                     new Date(15, Month.August,2003));

             zeroCouponBond.setPricingEngine(bondEngine);

             // Fixed 4.5% US Treasury Note
             Schedule fixedBondSchedule = new Schedule(new Date(15, Month.May, 2007),
                     new Date(15,Month.May,2017), new Period(Frequency.Semiannual),
                     new UnitedStates(UnitedStates.Market.GovernmentBond),
                     BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, false);

             FixedRateBond fixedRateBond = new FixedRateBond(
                     settlementDays,
                     faceAmount,
                     fixedBondSchedule,
                     new List<double>() { 0.045 },
                     new ActualActual(ActualActual.Convention.Bond),
                     BusinessDayConvention.ModifiedFollowing,
                     100.0, new Date(15, Month.May, 2007));

             fixedRateBond.setPricingEngine(bondEngine);

             // Floating rate bond (3M USD Libor + 0.1%)
             // Should and will be priced on another curve later...

             RelinkableHandle<YieldTermStructure> liborTermStructure = new RelinkableHandle<YieldTermStructure>();
             IborIndex libor3m = new USDLibor(new Period(3, TimeUnit.Months), liborTermStructure);
             libor3m.addFixing(new Date(17, Month.July, 2008),0.0278625);

             Schedule floatingBondSchedule = new Schedule(new Date(21, Month.October, 2005),
                     new Date(21, Month.October, 2010), new Period(Frequency.Quarterly),
                     new UnitedStates(UnitedStates.Market.NYSE),
                     BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted, DateGeneration.Rule.Backward, true);

             FloatingRateBond floatingRateBond = new FloatingRateBond(
                     settlementDays,
                     faceAmount,
                     floatingBondSchedule,
                     libor3m,
                     new Actual360(),
                     BusinessDayConvention.ModifiedFollowing,
                     2,
                     // Gearings
                     new List<double>() { 1.0 },
                     // Spreads
                     new List<double>() { 0.001 },
                     // Caps
                     new List<double>(),
                     // Floors
                     new List<double>(),
                     // Fixing in arrears
                     true,
                     100.0,
                     new Date(21, Month.October, 2005));

             floatingRateBond.setPricingEngine(bondEngine);

             // Coupon pricers
             IborCouponPricer pricer = new BlackIborCouponPricer();

             // optionLet volatilities
             double volatility = 0.0;
             Handle<OptionletVolatilityStructure> vol;
             vol = new Handle<OptionletVolatilityStructure>(
                                new ConstantOptionletVolatility(
                                     settlementDays,
                                     calendar,
                                     BusinessDayConvention.ModifiedFollowing,
                                     volatility,
                                     new Actual365Fixed()));

             pricer.setCapletVolatility(vol);
             Utils.setCouponPricer(floatingRateBond.cashflows(),pricer);

             // Yield curve bootstrapping
             forecastingTermStructure.linkTo(depoSwapTermStructure);
             discountingTermStructure.linkTo(bondDiscountingTermStructure);

             // We are using the depo & swap curve to estimate the future Libor rates
             liborTermStructure.linkTo(depoSwapTermStructure);

             /***************
              * BOND PRICING *
              ****************/

             // write column headings
             int[] widths = { 18, 10, 10, 10 };

            Console.WriteLine("{0,18}{1,10}{2,10}{3,10}", "", "ZC", "Fixed", "Floating");

            string separator = " | ";
            int width = widths[0]
                                 + widths[1]
                                          + widths[2]
                                                   + widths[3];
            string rule = "".PadLeft(width, '-'), dblrule = "".PadLeft(width, '=');
            string tab = "".PadLeft(8, ' ');

            Console.WriteLine(rule);

            Console.WriteLine("Net present value".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}", 
                                zeroCouponBond.NPV(),
                                fixedRateBond.NPV(),
                                floatingRateBond.NPV());

            Console.WriteLine("Clean price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.cleanPrice(),
                                fixedRateBond.cleanPrice(),
                                floatingRateBond.cleanPrice());

            Console.WriteLine("Dirty price".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.dirtyPrice(),
                                fixedRateBond.dirtyPrice(),
                                floatingRateBond.dirtyPrice());

            Console.WriteLine("Accrued coupon".PadLeft(widths[0]) + "{0,10:n2}{1,10:n2}{2,10:n2}",
                                zeroCouponBond.accruedAmount(),
                                fixedRateBond.accruedAmount(),
                                floatingRateBond.accruedAmount());

            Console.WriteLine("Previous coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                                "N/A",
                                fixedRateBond.previousCoupon(),
                                floatingRateBond.previousCoupon());

            Console.WriteLine("Next coupon".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              "N/A",
                              fixedRateBond.nextCoupon(),
                              floatingRateBond.nextCoupon());

            Console.WriteLine("Yield".PadLeft(widths[0]) + "{0,10:0.00%}{1,10:0.00%}{2,10:0.00%}",
                              zeroCouponBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              fixedRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                              floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual));

            Console.WriteLine();

            // Other computations
            Console.WriteLine("Sample indirect computations (for the floating rate bond): ");
            Console.WriteLine(rule);

            Console.WriteLine("Yield to Clean Price: {0:n2}",
                floatingRateBond.cleanPrice(floatingRateBond.yield(new Actual360(), Compounding.Compounded, Frequency.Annual),
                                                                   new Actual360(), Compounding.Compounded, Frequency.Annual,
                                                                   settlementDate));

            Console.WriteLine("Clean Price to Yield: {0:0.00%}",
                floatingRateBond.yield(floatingRateBond.cleanPrice(),new Actual360(), Compounding.Compounded, Frequency.Annual,
                                       settlementDate));

            /* "Yield to Price"
               "Price to Yield" */

            Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer);
            Console.WriteLine();

            Console.Write("Press any key to continue ...");
            Console.ReadKey();
        }
Ejemplo n.º 60
0
        public void testLiborFixing()
        {
            // "Testing use of today's LIBOR fixings in swap curve...");

            CommonVars vars = new CommonVars();

            var       swapHelpers = new InitializedList <RateHelper>();
            IborIndex euribor6m   = new Euribor6M();

            for (int i = 0; i < vars.swaps; i++)
            {
                Handle <Quote> r = new Handle <Quote>(vars.rates[i + vars.deposits]);
                swapHelpers.Add(new SwapRateHelper(r, new Period(vars.swapData[i].n, vars.swapData[i].units),
                                                   vars.calendar,
                                                   vars.fixedLegFrequency, vars.fixedLegConvention,
                                                   vars.fixedLegDayCounter, euribor6m));
            }

            vars.termStructure = new PiecewiseYieldCurve <Discount, LogLinear>(vars.settlement, swapHelpers, new Actual360());

            Handle <YieldTermStructure> curveHandle = new Handle <YieldTermStructure>(vars.termStructure);

            IborIndex index = new Euribor6M(curveHandle);

            for (int i = 0; i < vars.swaps; i++)
            {
                Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units);

                VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0)
                                   .withEffectiveDate(vars.settlement)
                                   .withFixedLegDayCount(vars.fixedLegDayCounter)
                                   .withFixedLegTenor(new Period(vars.fixedLegFrequency))
                                   .withFixedLegConvention(vars.fixedLegConvention)
                                   .withFixedLegTerminationDateConvention(vars.fixedLegConvention)
                                   .value();

                double expectedRate  = vars.swapData[i].rate / 100,
                       estimatedRate = swap.fairRate();
                double tolerance     = 1.0e-9;
                if (Math.Abs(expectedRate - estimatedRate) > tolerance)
                {
                    QAssert.Fail("before LIBOR fixing:\n"
                                 + vars.swapData[i].n + " year(s) swap:\n"
                                 + "    estimated rate: "
                                 + (estimatedRate) + "\n"
                                 + "    expected rate:  "
                                 + (expectedRate));
                }
            }

            Flag f = new Flag();

            vars.termStructure.registerWith(f.update);
            f.lower();

            index.addFixing(vars.today, 0.0425);

            if (!f.isUp())
            {
                QAssert.Fail("Observer was not notified of rate fixing");
            }

            for (int i = 0; i < vars.swaps; i++)
            {
                Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units);

                VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0)
                                   .withEffectiveDate(vars.settlement)
                                   .withFixedLegDayCount(vars.fixedLegDayCounter)
                                   .withFixedLegTenor(new Period(vars.fixedLegFrequency))
                                   .withFixedLegConvention(vars.fixedLegConvention)
                                   .withFixedLegTerminationDateConvention(vars.fixedLegConvention)
                                   .value();

                double expectedRate  = vars.swapData[i].rate / 100,
                       estimatedRate = swap.fairRate();
                double tolerance     = 1.0e-9;
                if (Math.Abs(expectedRate - estimatedRate) > tolerance)
                {
                    QAssert.Fail("after LIBOR fixing:\n"
                                 + vars.swapData[i].n + " year(s) swap:\n"
                                 + "    estimated rate: "
                                 + (estimatedRate) + "\n"
                                 + "    expected rate:  "
                                 + (expectedRate));
                }
            }
        }