Beispiel #1
0
        public override void initialize(FloatingRateCoupon coupon)
        {
            gearing_       = coupon.gearing();
            spread_        = coupon.spread();
            accrualPeriod_ = coupon.accrualPeriod();
            Utils.QL_REQUIRE(accrualPeriod_.IsNotEqual(0.0), () => "null accrual period");

            index_ = coupon.index() as IborIndex;
            if (index_ == null)
            {
                // check if the coupon was right
                IborCoupon c = coupon as IborCoupon;
                Utils.QL_REQUIRE(c != null, () => "IborCoupon required");
                // coupon was right, index is not
                Utils.QL_FAIL("IborIndex required");
            }

            Handle <YieldTermStructure> rateCurve = index_.forwardingTermStructure();
            Date paymentDate = coupon.date();

            if (paymentDate > rateCurve.link.referenceDate())
            {
                discount_ = rateCurve.link.discount(paymentDate);
            }
            else
            {
                discount_ = 1.0;
            }

            spreadLegValue_ = spread_ * accrualPeriod_ * discount_;

            coupon_ = coupon;
        }
Beispiel #2
0
        // other
        public override void setupArguments(IPricingEngineArguments args)
        {
            base.setupArguments(args);

            AssetSwap.Arguments arguments = args as AssetSwap.Arguments;

            if (arguments == null) // it's a swap engine...
            {
                return;
            }

            List <CashFlow> fixedCoupons = bondLeg();

            arguments.fixedResetDates = arguments.fixedPayDates = new List <Date>(fixedCoupons.Count);
            arguments.fixedCoupons    = new List <double>(fixedCoupons.Count);

            for (int i = 0; i < fixedCoupons.Count; ++i)
            {
                FixedRateCoupon coupon = fixedCoupons[i] as FixedRateCoupon;

                arguments.fixedPayDates[i]   = coupon.date();
                arguments.fixedResetDates[i] = coupon.accrualStartDate();
                arguments.fixedCoupons[i]    = coupon.amount();
            }

            List <CashFlow> floatingCoupons = floatingLeg();

            arguments.floatingResetDates      = arguments.floatingPayDates =
                arguments.floatingFixingDates = new List <Date>(floatingCoupons.Count);
            arguments.floatingAccrualTimes    = new List <double>(floatingCoupons.Count);
            arguments.floatingSpreads         = new List <double>(floatingCoupons.Count);

            for (int i = 0; i < floatingCoupons.Count; ++i)
            {
                FloatingRateCoupon coupon = floatingCoupons[i] as FloatingRateCoupon;

                arguments.floatingResetDates[i]   = coupon.accrualStartDate();
                arguments.floatingPayDates[i]     = coupon.date();
                arguments.floatingFixingDates[i]  = coupon.fixingDate();
                arguments.floatingAccrualTimes[i] = coupon.accrualPeriod();
                arguments.floatingSpreads[i]      = coupon.spread();
            }
        }
        public CappedFlooredCoupon(FloatingRateCoupon underlying, double?cap = null, double?floor = null)
            : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears())
        {
            underlying_ = underlying;
            isCapped_   = false;
            isFloored_  = false;

            if (gearing_ > 0)
            {
                if (cap != null)
                {
                    isCapped_ = true;
                    cap_      = cap;
                }
                if (floor != null)
                {
                    floor_     = floor;
                    isFloored_ = true;
                }
            }
            else
            {
                if (cap != null)
                {
                    floor_     = cap;
                    isFloored_ = true;
                }
                if (floor != null)
                {
                    isCapped_ = true;
                    cap_      = floor;
                }
            }
            if (isCapped_ && isFloored_)
            {
                if (!(cap >= floor))
                {
                    throw new ApplicationException("cap level (" + cap + ") less than floor level (" + floor + ")");
                }
            }
            underlying.registerWith(update);
        }
Beispiel #4
0
      public CappedFlooredCoupon(FloatingRateCoupon underlying, double? cap = null, double? floor = null)
         : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears())
      {
         underlying_ = underlying;
         isCapped_ = false;
         isFloored_ = false;

         if (gearing_ > 0)
         {
            if (cap != null)
            {
               isCapped_ = true;
               cap_ = cap;
            }
            if (floor != null)
            {
               floor_ = floor;
               isFloored_ = true;
            }
         }
         else
         {
            if (cap != null)
            {
               floor_ = cap;
               isFloored_ = true;
            }
            if (floor != null)
            {
               isCapped_ = true;
               cap_ = floor;
            }
         }
         if (isCapped_ && isFloored_)
            if (!(cap >= floor))
               throw new ApplicationException("cap level (" + cap + ") less than floor level (" + floor + ")");
         underlying.registerWith(update);
      }
Beispiel #5
0
        //! \name Constructors
        //@{
        //! general constructor
        public DigitalCoupon(FloatingRateCoupon underlying,
                             double?callStrike              = null,
                             Position.Type callPosition     = Position.Type.Long,
                             bool isCallATMIncluded         = false,
                             double?callDigitalPayoff       = null,
                             double?putStrike               = null,
                             Position.Type putPosition      = Position.Type.Long,
                             bool isPutATMIncluded          = false,
                             double?putDigitalPayoff        = null,
                             DigitalReplication replication = null)
            : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears())
        {
            if (replication == null)
            {
                replication = new DigitalReplication();
            }

            underlying_          = underlying;
            callCsi_             = 0.0;
            putCsi_              = 0.0;
            isCallATMIncluded_   = isCallATMIncluded;
            isPutATMIncluded_    = isPutATMIncluded;
            isCallCashOrNothing_ = false;
            isPutCashOrNothing_  = false;
            callLeftEps_         = replication.gap() / 2.0;
            callRightEps_        = replication.gap() / 2.0;
            putLeftEps_          = replication.gap() / 2.0;
            putRightEps_         = replication.gap() / 2.0;
            hasPutStrike_        = false;
            hasCallStrike_       = false;
            replicationType_     = replication.replicationType();


            if (!(replication.gap() > 0.0))
            {
                throw new ApplicationException("Non positive epsilon not allowed");
            }

            if (putStrike == null)
            {
                if (!(putDigitalPayoff == null))
                {
                    throw new ApplicationException("Put Cash rate non allowed if put strike is null");
                }
            }

            if (callStrike == null)
            {
                if (!(callDigitalPayoff == null))
                {
                    throw new ApplicationException("Call Cash rate non allowed if call strike is null");
                }
            }
            if (callStrike != null)
            {
                if (!(callStrike >= 0.0))
                {
                    throw new ApplicationException("negative call strike not allowed");
                }

                hasCallStrike_ = true;
                callStrike_    = callStrike.GetValueOrDefault();
                if (!(callStrike_ >= replication.gap() / 2.0))
                {
                    throw new ApplicationException("call strike < eps/2");
                }

                switch (callPosition)
                {
                case Position.Type.Long:
                    callCsi_ = 1.0;
                    break;

                case Position.Type.Short:
                    callCsi_ = -1.0;
                    break;

                default:
                    throw new ApplicationException("unsupported position type");
                }
                if (callDigitalPayoff != null)
                {
                    callDigitalPayoff_   = callDigitalPayoff.GetValueOrDefault();
                    isCallCashOrNothing_ = true;
                }
            }
            if (putStrike != null)
            {
                if (!(putStrike >= 0.0))
                {
                    throw new ApplicationException("negative put strike not allowed");
                }

                hasPutStrike_ = true;
                putStrike_    = putStrike.GetValueOrDefault();
                switch (putPosition)
                {
                case Position.Type.Long:
                    putCsi_ = 1.0;
                    break;

                case Position.Type.Short:
                    putCsi_ = -1.0;
                    break;

                default:
                    throw new ApplicationException("unsupported position type");
                }
                if (putDigitalPayoff != null)
                {
                    putDigitalPayoff_   = putDigitalPayoff.GetValueOrDefault();
                    isPutCashOrNothing_ = true;
                }
            }

            switch (replicationType_)
            {
            case Replication.Type.Central:
                // do nothing
                break;

            case Replication.Type.Sub:
                if (hasCallStrike_)
                {
                    switch (callPosition)
                    {
                    case Position.Type.Long:
                        callLeftEps_  = 0.0;
                        callRightEps_ = replication.gap();
                        break;

                    case Position.Type.Short:
                        callLeftEps_  = replication.gap();
                        callRightEps_ = 0.0;
                        break;

                    default:
                        throw new ApplicationException("unsupported position type");
                    }
                }
                if (hasPutStrike_)
                {
                    switch (putPosition)
                    {
                    case Position.Type.Long:
                        putLeftEps_  = replication.gap();
                        putRightEps_ = 0.0;
                        break;

                    case Position.Type.Short:
                        putLeftEps_  = 0.0;
                        putRightEps_ = replication.gap();
                        break;

                    default:
                        throw new ApplicationException("unsupported position type");
                    }
                }
                break;

            case Replication.Type.Super:
                if (hasCallStrike_)
                {
                    switch (callPosition)
                    {
                    case Position.Type.Long:
                        callLeftEps_  = replication.gap();
                        callRightEps_ = 0.0;
                        break;

                    case Position.Type.Short:
                        callLeftEps_  = 0.0;
                        callRightEps_ = replication.gap();
                        break;

                    default:
                        throw new ApplicationException("unsupported position type");
                    }
                }
                if (hasPutStrike_)
                {
                    switch (putPosition)
                    {
                    case Position.Type.Long:
                        putLeftEps_  = 0.0;
                        putRightEps_ = replication.gap();
                        break;

                    case Position.Type.Short:
                        putLeftEps_  = replication.gap();
                        putRightEps_ = 0.0;
                        break;

                    default:
                        throw new ApplicationException("unsupported position type");
                    }
                }
                break;

            default:
                throw new ApplicationException("unsupported position type");
            }

            underlying.registerWith(update);
        }
Beispiel #6
0
        public override void setupArguments(IPricingEngineArguments args)
        {
            CapFloor.Arguments arguments = args as CapFloor.Arguments;

            if (arguments == null)
            {
                throw new ArgumentException("wrong argument type");
            }


            int n = floatingLeg_.Count;

            arguments.startDates   = new InitializedList <Date>(n);
            arguments.fixingDates  = new InitializedList <Date>(n);
            arguments.endDates     = new InitializedList <Date>(n);
            arguments.accrualTimes = new InitializedList <double>(n);
            arguments.forwards     = new InitializedList <double?>(n);
            arguments.nominals     = new InitializedList <double>(n);
            arguments.gearings     = new InitializedList <double>(n);
            arguments.capRates     = new InitializedList <double?>(n);
            arguments.floorRates   = new InitializedList <double?>(n);
            arguments.spreads      = new InitializedList <double>(n);

            arguments.type = type_;

            Date today = Settings.evaluationDate();

            for (int i = 0; i < n; ++i)
            {
                FloatingRateCoupon coupon = floatingLeg_[i] as FloatingRateCoupon;

                if (coupon == null)
                {
                    throw new ArgumentException("non-FloatingRateCoupon given");
                }

                arguments.startDates[i]  = coupon.accrualStartDate();
                arguments.fixingDates[i] = coupon.fixingDate();
                arguments.endDates[i]    = coupon.date();

                // this is passed explicitly for precision
                arguments.accrualTimes[i] = coupon.accrualPeriod();

                // this is passed explicitly for precision...
                if (arguments.endDates[i] >= today)
                {
                    // ...but only if needed
                    arguments.forwards[i] = coupon.adjustedFixing;
                }
                else
                {
                    arguments.forwards[i] = null;
                }

                arguments.nominals[i] = coupon.nominal();
                double spread  = coupon.spread();
                double gearing = coupon.gearing();
                arguments.gearings[i] = gearing;
                arguments.spreads[i]  = spread;

                if (type_ == CapFloorType.Cap || type_ == CapFloorType.Collar)
                {
                    arguments.capRates[i] = (capRates_[i] - spread) / gearing;
                }
                else
                {
                    arguments.capRates[i] = null;
                }

                if (type_ == CapFloorType.Floor || type_ == CapFloorType.Collar)
                {
                    arguments.floorRates[i] = (floorRates_[i] - spread) / gearing;
                }
                else
                {
                    arguments.floorRates[i] = null;
                }
            }
        }
Beispiel #7
0
        //! \name LazyObject interface
        //@{
        protected override void performCalculations()
        {
            // update dates
            Date                referenceDate = termVolSurface_.referenceDate();
            DayCounter          dc            = termVolSurface_.dayCounter();
            BlackCapFloorEngine dummy         = new BlackCapFloorEngine( // discounting does not matter here
                iborIndex_.forwardingTermStructure(), 0.20, dc);

            for (int i = 0; i < nOptionletTenors_; ++i)
            {
                CapFloor temp = new MakeCapFloor(CapFloorType.Cap,
                                                 capFloorLengths_[i],
                                                 iborIndex_,
                                                 0.04, // dummy strike
                                                 new Period(0, TimeUnit.Days))
                                .withPricingEngine(dummy);
                FloatingRateCoupon lFRC = temp.lastFloatingRateCoupon();
                optionletDates_[i]          = lFRC.fixingDate();
                optionletPaymentDates_[i]   = lFRC.date();
                optionletAccrualPeriods_[i] = lFRC.accrualPeriod();
                optionletTimes_[i]          = dc.yearFraction(referenceDate,
                                                              optionletDates_[i]);
                atmOptionletRate_[i] = lFRC.indexFixing();
            }

            if (floatingSwitchStrike_ && capFlooMatrixNotInitialized_)
            {
                double averageAtmOptionletRate = 0.0;
                for (int i = 0; i < nOptionletTenors_; ++i)
                {
                    averageAtmOptionletRate += atmOptionletRate_[i];
                }
                switchStrike_ = averageAtmOptionletRate / nOptionletTenors_;
            }

            Handle <YieldTermStructure> discountCurve = discount_.empty()
            ? iborIndex_.forwardingTermStructure()
            : discount_;

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

            // initialize CapFloorMatrix
            if (capFlooMatrixNotInitialized_)
            {
                for (int i = 0; i < nOptionletTenors_; ++i)
                {
                    capFloors_[i] = new List <CapFloor>(nStrikes_);
                }
                // construction might go here
                for (int j = 0; j < nStrikes_; ++j)
                {
                    // using out-of-the-money options
                    CapFloorType capFloorType = strikes[j] < switchStrike_
                  ? CapFloorType.Floor
                  : CapFloorType.Cap;
                    for (int i = 0; i < nOptionletTenors_; ++i)
                    {
                        //volQuotes_[i][j] = new SimpleQuote();
                        if (volatilityType_ == VolatilityType.ShiftedLognormal)
                        {
                            BlackCapFloorEngine engine = new BlackCapFloorEngine(discountCurve,
                                                                                 new Handle <Quote>(volQuotes_[i][j]), dc, displacement_);
                            capFloors_[i].Add(new MakeCapFloor(capFloorType, capFloorLengths_[i], iborIndex_, strikes[j],
                                                               new Period(0, TimeUnit.Days)).withPricingEngine(engine));
                        }
                        else if (volatilityType_ == VolatilityType.Normal)
                        {
                            BachelierCapFloorEngine engine = new BachelierCapFloorEngine(discountCurve,
                                                                                         new Handle <Quote>(volQuotes_[i][j]), dc);
                            capFloors_[i].Add(new MakeCapFloor(capFloorType, capFloorLengths_[i], iborIndex_, strikes[j],
                                                               new Period(0, TimeUnit.Days)).withPricingEngine(engine));
                        }
                        else
                        {
                            Utils.QL_FAIL("unknown volatility type: " + volatilityType_);
                        }
                    }
                }
                capFlooMatrixNotInitialized_ = false;
            }

            for (int j = 0; j < nStrikes_; ++j)
            {
                Option.Type optionletType = strikes[j] < switchStrike_ ? Option.Type.Put : Option.Type.Call;

                double previousCapFloorPrice = 0.0;
                for (int i = 0; i < nOptionletTenors_; ++i)
                {
                    capFloorVols_[i, j] = termVolSurface_.volatility(capFloorLengths_[i], strikes[j], true);
                    volQuotes_[i][j].setValue(capFloorVols_[i, j]);

                    capFloorPrices_[i, j]  = capFloors_[i][j].NPV();
                    optionletPrices_[i, j] = capFloorPrices_[i, j] - previousCapFloorPrice;
                    previousCapFloorPrice  = capFloorPrices_[i, j];
                    double d = discountCurve.link.discount(optionletPaymentDates_[i]);
                    double optionletAnnuity = optionletAccrualPeriods_[i] * d;
                    try
                    {
                        if (volatilityType_ == VolatilityType.ShiftedLognormal)
                        {
                            optionletStDevs_[i, j] = Utils.blackFormulaImpliedStdDev(optionletType, strikes[j], atmOptionletRate_[i],
                                                                                     optionletPrices_[i, j], optionletAnnuity, displacement_, optionletStDevs_[i, j], accuracy_,
                                                                                     maxIter_);
                        }
                        else if (volatilityType_ == VolatilityType.Normal)
                        {
                            optionletStDevs_[i, j] = Math.Sqrt(optionletTimes_[i]) *
                                                     Utils.bachelierBlackFormulaImpliedVol(
                                optionletType, strikes[j], atmOptionletRate_[i],
                                optionletTimes_[i], optionletPrices_[i, j],
                                optionletAnnuity);
                        }
                        else
                        {
                            Utils.QL_FAIL("Unknown volatility type: " + volatilityType_);
                        }
                    }
                    catch (Exception e)
                    {
                        if (dontThrow_)
                        {
                            optionletStDevs_[i, j] = 0.0;
                        }
                        else
                        {
                            Utils.QL_FAIL("could not bootstrap optionlet:" +
                                          "\n type:    " + optionletType +
                                          "\n strike:  " + (strikes[j]) +
                                          "\n atm:     " + (atmOptionletRate_[i]) +
                                          "\n price:   " + optionletPrices_[i, j] +
                                          "\n annuity: " + optionletAnnuity +
                                          "\n expiry:  " + optionletDates_[i] +
                                          "\n error:   " + e.Message);
                        }
                    }
                    optionletVolatilities_[i][j] = optionletStDevs_[i, j] / Math.Sqrt(optionletTimes_[i]);
                }
            }
        }
Beispiel #8
0
      //! \name Constructors
      //@{
      //! general constructor
      public DigitalCoupon(FloatingRateCoupon underlying, 
                           double? callStrike = null,
                           Position.Type callPosition = Position.Type.Long, 
                           bool isCallATMIncluded = false, 
                           double? callDigitalPayoff = null, 
                           double? putStrike = null,
                           Position.Type putPosition = Position.Type.Long, 
                           bool isPutATMIncluded = false, 
                           double? putDigitalPayoff = null, 
                           DigitalReplication replication = null)
         : base(underlying.nominal(), underlying.date(), underlying.accrualStartDate(), underlying.accrualEndDate(), underlying.fixingDays, underlying.index(), underlying.gearing(), underlying.spread(), underlying.refPeriodStart, underlying.refPeriodEnd, underlying.dayCounter(), underlying.isInArrears())
      {
         if (replication == null) replication = new DigitalReplication();

         underlying_ = underlying;
         callCsi_ = 0.0;
         putCsi_ = 0.0;
         isCallATMIncluded_ = isCallATMIncluded;
         isPutATMIncluded_ = isPutATMIncluded;
         isCallCashOrNothing_ = false;
         isPutCashOrNothing_ = false;
         callLeftEps_ = replication.gap() / 2.0;
         callRightEps_ = replication.gap() / 2.0;
         putLeftEps_ = replication.gap() / 2.0;
         putRightEps_ = replication.gap() / 2.0;
         hasPutStrike_ = false;
         hasCallStrike_ = false;
         replicationType_ = replication.replicationType();


         if (!(replication.gap() > 0.0))
            throw new ApplicationException("Non positive epsilon not allowed");

         if (putStrike == null)
            if (!(putDigitalPayoff == null))
               throw new ApplicationException("Put Cash rate non allowed if put strike is null");

         if (callStrike == null)
            if (!(callDigitalPayoff == null))
               throw new ApplicationException("Call Cash rate non allowed if call strike is null");
         if (callStrike != null)
         {
            if (!(callStrike >= 0.0))
               throw new ApplicationException("negative call strike not allowed");

            hasCallStrike_ = true;
            callStrike_ = callStrike.GetValueOrDefault();
            if (!(callStrike_ >= replication.gap() / 2.0))
               throw new ApplicationException("call strike < eps/2");

            switch (callPosition)
            {
               case Position.Type.Long:
                  callCsi_ = 1.0;
                  break;
               case Position.Type.Short:
                  callCsi_ = -1.0;
                  break;
               default:
                  throw new ApplicationException("unsupported position type");
            }
            if (callDigitalPayoff != null)
            {
               callDigitalPayoff_ = callDigitalPayoff.GetValueOrDefault();
               isCallCashOrNothing_ = true;
            }
         }
         if (putStrike != null)
         {
            if (!(putStrike >= 0.0))
               throw new ApplicationException("negative put strike not allowed");

            hasPutStrike_ = true;
            putStrike_ = putStrike.GetValueOrDefault();
            switch (putPosition)
            {
               case Position.Type.Long:
                  putCsi_ = 1.0;
                  break;
               case Position.Type.Short:
                  putCsi_ = -1.0;
                  break;
               default:
                  throw new ApplicationException("unsupported position type");
            }
            if (putDigitalPayoff != null)
            {
               putDigitalPayoff_ = putDigitalPayoff.GetValueOrDefault();
               isPutCashOrNothing_ = true;
            }
         }

         switch (replicationType_)
         {
            case Replication.Type.Central:
               // do nothing
               break;
            case Replication.Type.Sub:
               if (hasCallStrike_)
               {
                  switch (callPosition)
                  {
                     case Position.Type.Long:
                        callLeftEps_ = 0.0;
                        callRightEps_ = replication.gap();
                        break;
                     case Position.Type.Short:
                        callLeftEps_ = replication.gap();
                        callRightEps_ = 0.0;
                        break;
                     default:
                        throw new ApplicationException("unsupported position type");
                  }
               }
               if (hasPutStrike_)
               {
                  switch (putPosition)
                  {
                     case Position.Type.Long:
                        putLeftEps_ = replication.gap();
                        putRightEps_ = 0.0;
                        break;
                     case Position.Type.Short:
                        putLeftEps_ = 0.0;
                        putRightEps_ = replication.gap();
                        break;
                     default:
                        throw new ApplicationException("unsupported position type");
                  }
               }
               break;
            case Replication.Type.Super:
               if (hasCallStrike_)
               {
                  switch (callPosition)
                  {
                     case Position.Type.Long:
                        callLeftEps_ = replication.gap();
                        callRightEps_ = 0.0;
                        break;
                     case Position.Type.Short:
                        callLeftEps_ = 0.0;
                        callRightEps_ = replication.gap();
                        break;
                     default:
                        throw new ApplicationException("unsupported position type");
                  }
               }
               if (hasPutStrike_)
               {
                  switch (putPosition)
                  {
                     case Position.Type.Long:
                        putLeftEps_ = 0.0;
                        putRightEps_ = replication.gap();
                        break;
                     case Position.Type.Short:
                        putLeftEps_ = replication.gap();
                        putRightEps_ = 0.0;
                        break;
                     default:
                        throw new ApplicationException("unsupported position type");
                  }
               }
               break;
            default:
               throw new ApplicationException("unsupported position type");
         }

         underlying.registerWith(update);
      }
Beispiel #9
0
        // other
        public override void setupArguments(IPricingEngineArguments args)
        {
            base.setupArguments(args);

            Arguments arguments = args as Arguments;

            Utils.QL_REQUIRE(arguments != null, () => "argument type does not match");

            arguments.type     = type_;
            arguments.nominal1 = nominal1_;
            arguments.nominal2 = nominal2_;
            arguments.index1   = index1_;
            arguments.index2   = index2_;

            List <CashFlow> leg1Coupons = leg1();
            List <CashFlow> leg2Coupons = leg2();

            arguments.leg1ResetDates      = arguments.leg1PayDates =
                arguments.leg1FixingDates = new InitializedList <Date>(leg1Coupons.Count);
            arguments.leg2ResetDates      = arguments.leg2PayDates =
                arguments.leg2FixingDates = new InitializedList <Date>(leg2Coupons.Count);

            arguments.leg1Spreads      = arguments.leg1AccrualTimes =
                arguments.leg1Gearings = new InitializedList <double>(leg1Coupons.Count);
            arguments.leg2Spreads      = arguments.leg2AccrualTimes =
                arguments.leg2Gearings = new InitializedList <double>(leg2Coupons.Count);

            arguments.leg1Coupons = new InitializedList <double?>(leg1Coupons.Count, null);
            arguments.leg2Coupons = new InitializedList <double?>(leg2Coupons.Count, null);

            arguments.leg1IsRedemptionFlow = new InitializedList <bool>(leg1Coupons.Count, false);
            arguments.leg2IsRedemptionFlow = new InitializedList <bool>(leg2Coupons.Count, false);

            arguments.leg1CappedRates = arguments.leg1FlooredRates =
                new InitializedList <double?>(leg1Coupons.Count, null);
            arguments.leg2CappedRates = arguments.leg2FlooredRates =
                new InitializedList <double?>(leg2Coupons.Count, null);

            for (int i = 0; i < leg1Coupons.Count; ++i)
            {
                FloatingRateCoupon coupon = leg1Coupons[i] as FloatingRateCoupon;
                if (coupon != null)
                {
                    arguments.leg1AccrualTimes[i] = coupon.accrualPeriod();
                    arguments.leg1PayDates[i]     = coupon.date();
                    arguments.leg1ResetDates[i]   = coupon.accrualStartDate();
                    arguments.leg1FixingDates[i]  = coupon.fixingDate();
                    arguments.leg1Spreads[i]      = coupon.spread();
                    arguments.leg1Gearings[i]     = coupon.gearing();
                    try
                    {
                        arguments.leg1Coupons[i] = coupon.amount();
                    }
                    catch (Exception)
                    {
                        arguments.leg1Coupons[i] = null;
                    }
                    CappedFlooredCoupon cfcoupon = leg1Coupons[i] as CappedFlooredCoupon;
                    if (cfcoupon != null)
                    {
                        arguments.leg1CappedRates[i]  = cfcoupon.cap();
                        arguments.leg1FlooredRates[i] = cfcoupon.floor();
                    }
                }
                else
                {
                    CashFlow cashflow = leg1Coupons[i] as CashFlow;
                    int      j        = arguments.leg1PayDates.FindIndex(x => x == cashflow.date());
                    Utils.QL_REQUIRE(j != -1, () =>
                                     "nominal redemption on " + cashflow.date() + "has no corresponding coupon");
                    int jIdx = j; // Size jIdx = j - arguments->leg1PayDates.begin();
                    arguments.leg1IsRedemptionFlow[i] = true;
                    arguments.leg1Coupons[i]          = cashflow.amount();
                    arguments.leg1ResetDates[i]       = arguments.leg1ResetDates[jIdx];
                    arguments.leg1FixingDates[i]      = arguments.leg1FixingDates[jIdx];
                    arguments.leg1AccrualTimes[i]     = 0.0;
                    arguments.leg1Spreads[i]          = 0.0;
                    arguments.leg1Gearings[i]         = 1.0;
                    arguments.leg1PayDates[i]         = cashflow.date();
                }
            }

            for (int i = 0; i < leg2Coupons.Count; ++i)
            {
                FloatingRateCoupon coupon = leg2Coupons[i] as FloatingRateCoupon;
                if (coupon != null)
                {
                    arguments.leg2AccrualTimes[i] = coupon.accrualPeriod();
                    arguments.leg2PayDates[i]     = coupon.date();
                    arguments.leg2ResetDates[i]   = coupon.accrualStartDate();
                    arguments.leg2FixingDates[i]  = coupon.fixingDate();
                    arguments.leg2Spreads[i]      = coupon.spread();
                    arguments.leg2Gearings[i]     = coupon.gearing();
                    try
                    {
                        arguments.leg2Coupons[i] = coupon.amount();
                    }
                    catch (Exception)
                    {
                        arguments.leg2Coupons[i] = null;
                    }
                    CappedFlooredCoupon cfcoupon = leg2Coupons[i] as CappedFlooredCoupon;
                    if (cfcoupon != null)
                    {
                        arguments.leg2CappedRates[i]  = cfcoupon.cap();
                        arguments.leg2FlooredRates[i] = cfcoupon.floor();
                    }
                }
                else
                {
                    CashFlow cashflow = leg2Coupons[i] as CashFlow;
                    int      j        = arguments.leg2PayDates.FindIndex(x => x == cashflow.date());
                    Utils.QL_REQUIRE(j != -1, () =>
                                     "nominal redemption on " + cashflow.date() + "has no corresponding coupon");
                    int jIdx = j; // j - arguments->leg2PayDates.begin();
                    arguments.leg2IsRedemptionFlow[i] = true;
                    arguments.leg2Coupons[i]          = cashflow.amount();
                    arguments.leg2ResetDates[i]       = arguments.leg2ResetDates[jIdx];
                    arguments.leg2FixingDates[i]      =
                        arguments.leg2FixingDates[jIdx];
                    arguments.leg2AccrualTimes[i] = 0.0;
                    arguments.leg2Spreads[i]      = 0.0;
                    arguments.leg2Gearings[i]     = 1.0;
                    arguments.leg2PayDates[i]     = cashflow.date();
                }
            }
        }