public AmortizingFloatingRateBond(int settlementDays,
                                          List <double> notionals,
                                          Schedule schedule,
                                          IborIndex index,
                                          DayCounter accrualDayCounter,
                                          BusinessDayConvention paymentConvention = BusinessDayConvention.Following,
                                          int fixingDays         = 0,
                                          List <double> gearings = null,
                                          List <double> spreads  = null,
                                          List <double?> caps    = null,
                                          List <double?> floors  = null,
                                          bool inArrears         = false,
                                          Date issueDate         = null)
            : base(settlementDays, schedule.calendar(), issueDate)
        {
            if (gearings == null)
            {
                gearings = new List <double>()
                {
                    1, 1.0
                }
            }
            ;

            if (spreads == null)
            {
                spreads = new List <double>()
                {
                    1, 0.0
                }
            }
            ;

            if (caps == null)
            {
                caps = new List <double?>();
            }

            if (floors == null)
            {
                floors = new List <double?>();
            }

            maturityDate_ = schedule.endDate();


            cashflows_ = new IborLeg(schedule, index)
                         .withCaps(caps)
                         .withFloors(floors)
                         .inArrears(inArrears)
                         .withSpreads(spreads)
                         .withGearings(gearings)
                         .withFixingDays(fixingDays)
                         .withPaymentDayCounter(accrualDayCounter)
                         .withPaymentAdjustment(paymentConvention)
                         .withNotionals(notionals).value();

            addRedemptionsToCashflows();

            Utils.QL_REQUIRE(!cashflows().empty(), () => "bond with no cashflows!");

            index.registerWith(update);
        }
    }
}
Пример #2
0
        public FloatingLoan(Type type, double nominal,
                            Schedule floatingSchedule, double floatingSpread, DayCounter floatingDayCount,
                            Schedule principalSchedule, BusinessDayConvention?paymentConvention, IborIndex index) :
            base(2)
        {
            type_              = type;
            nominal_           = nominal;
            floatingSchedule_  = floatingSchedule;
            floatingSpread_    = floatingSpread;
            floatingDayCount_  = floatingDayCount;
            principalSchedule_ = principalSchedule;
            iborIndex_         = index;

            if (paymentConvention.HasValue)
            {
                paymentConvention_ = paymentConvention.Value;
            }
            else
            {
                paymentConvention_ = floatingSchedule_.businessDayConvention();
            }

            List <CashFlow> principalLeg = new PricipalLeg(principalSchedule, floatingDayCount)
                                           .withNotionals(nominal)
                                           .withPaymentAdjustment(paymentConvention_)
                                           .withSign(type == Type.Loan ? -1 : 1);

            // temporary
            for (int i = 0; i < principalLeg.Count - 1; i++)
            {
                Principal p = (Principal)principalLeg[i];
                notionals_.Add(p.nominal());
            }

            List <CashFlow> floatingLeg = new IborLeg(floatingSchedule, iborIndex_)
                                          .withPaymentDayCounter(floatingDayCount_)
                                          .withSpreads(floatingSpread_)
                                          .withPaymentAdjustment(paymentConvention_)
                                          .withNotionals(notionals_);


            legs_[0] = floatingLeg;
            legs_[1] = principalLeg;
            if (type_ == Type.Loan)
            {
                payer_[0] = -1;
                payer_[1] = +1;
            }
            else
            {
                payer_[0] = +1;
                payer_[1] = -1;
            }
        }
Пример #3
0
        public BasisSwap(Type type, double nominal,
                         Schedule float1Schedule, IborIndex iborIndex1, double spread1, DayCounter float1DayCount,
                         Schedule float2Schedule, IborIndex iborIndex2, double spread2, DayCounter float2DayCount,
                         BusinessDayConvention?paymentConvention) :
            base(2)
        {
            type_              = type;
            nominal_           = nominal;
            floating1Schedule_ = float1Schedule;
            spread1_           = spread1;
            floating1DayCount_ = float1DayCount;
            iborIndex1_        = iborIndex1;
            floating2Schedule_ = float2Schedule;
            spread2_           = spread2;
            floating2DayCount_ = float2DayCount;
            iborIndex2_        = iborIndex2;

            if (paymentConvention.HasValue)
            {
                paymentConvention_ = paymentConvention.Value;
            }
            else
            {
                paymentConvention_ = floating1Schedule_.businessDayConvention();
            }

            List <CashFlow> floating1Leg = new IborLeg(float1Schedule, iborIndex1)
                                           .withPaymentDayCounter(float1DayCount)
                                           .withSpreads(spread1)
                                           .withNotionals(nominal)
                                           .withPaymentAdjustment(paymentConvention_);

            List <CashFlow> floating2Leg = new IborLeg(float2Schedule, iborIndex2)
                                           .withPaymentDayCounter(float2DayCount)
                                           .withSpreads(spread2)
                                           .withNotionals(nominal)
                                           .withPaymentAdjustment(paymentConvention_);

            foreach (var cf in floating1Leg)
            {
                cf.registerWith(update);
            }
            foreach (var cf in floating2Leg)
            {
                cf.registerWith(update);
            }


            legs_[0] = floating1Leg;
            legs_[1] = floating2Leg;
            if (type_ == Type.Payer)
            {
                payer_[0]    = -1;
                payer_[1]    = +1;
                longNo_      = 1;
                longSpread_  = spread2;
                shortNo_     = 0;
                shortSpread_ = spread1;
            }
            else
            {
                payer_[0]    = +1;
                payer_[1]    = -1;
                longNo_      = 0;
                longSpread_  = spread1;
                shortNo_     = 1;
                shortSpread_ = spread2;
            }
        }
Пример #4
0
 public LiborForwardModelProcess(int size, IborIndex index)
     : this(size, index, new EulerDiscretization())
 {
 }
Пример #5
0
        public AssetSwap(bool parAssetSwap,
                         Bond bond,
                         double bondCleanPrice,
                         double nonParRepayment,
                         double gearing,
                         IborIndex iborIndex,
                         double spread = 0.0,
                         DayCounter floatingDayCount = null,
                         Date dealMaturity           = null,
                         bool payBondCoupon          = false)
            : base(2)
        {
            bond_            = bond;
            bondCleanPrice_  = bondCleanPrice;
            nonParRepayment_ = nonParRepayment;
            spread_          = spread;
            parSwap_         = parAssetSwap;

            Schedule tempSch = new Schedule(bond_.settlementDate(),
                                            bond_.maturityDate(),
                                            iborIndex.tenor(),
                                            iborIndex.fixingCalendar(),
                                            iborIndex.businessDayConvention(),
                                            iborIndex.businessDayConvention(),
                                            DateGeneration.Rule.Backward,
                                            false); // endOfMonth

            if (dealMaturity == null)
            {
                dealMaturity = bond_.maturityDate();
            }

            Utils.QL_REQUIRE(dealMaturity <= tempSch.dates().Last(), () =>
                             "deal maturity " + dealMaturity +
                             " cannot be later than (adjusted) bond maturity " +
                             tempSch.dates().Last());
            Utils.QL_REQUIRE(dealMaturity > tempSch.dates()[0], () =>
                             "deal maturity " + dealMaturity +
                             " must be later than swap start date " +
                             tempSch.dates()[0]);

            // the following might become an input parameter
            BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following;

            Date     finalDate = tempSch.calendar().adjust(dealMaturity, paymentAdjustment);
            Schedule schedule  = tempSch.until(finalDate);

            // bondCleanPrice must be the (forward) clean price
            // at the floating schedule start date
            upfrontDate_ = schedule.startDate();
            double dirtyPrice = bondCleanPrice_ +
                                bond_.accruedAmount(upfrontDate_);

            double notional = bond_.notional(upfrontDate_);

            /* In the market asset swap, the bond is purchased in return for
             * payment of the full price. The notional of the floating leg is
             * then scaled by the full price. */
            if (!parSwap_)
            {
                notional *= dirtyPrice / 100.0;
            }

            if (floatingDayCount == null)
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withGearings(gearing)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }
            else
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withGearings(gearing)
                           .withPaymentDayCounter(floatingDayCount)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }

            foreach (CashFlow c in legs_[1])
            {
                c.registerWith(update);
            }


            List <CashFlow> bondLeg = bond_.cashflows();
            // skip bond redemption
            int i;

            for (i = 0; i < bondLeg.Count && bondLeg[i].date() <= dealMaturity; ++i)
            {
                // whatever might be the choice for the discounting engine
                // bond flows on upfrontDate_ must be discarded
                bool upfrontDateBondFlows = false;
                if (!bondLeg[i].hasOccurred(upfrontDate_, upfrontDateBondFlows))
                {
                    legs_[0].Add(bondLeg[i]);
                }
            }
            // if the first skipped cashflow is not the redemption
            // and it is a coupon then add the accrued coupon
            if (i < bondLeg.Count - 1)
            {
                Coupon c = bondLeg[i] as Coupon;
                if (c != null)
                {
                    CashFlow accruedCoupon = new SimpleCashFlow(c.accruedAmount(dealMaturity), finalDate);
                    legs_[0].Add(accruedCoupon);
                }
            }
            // add the nonParRepayment_
            CashFlow nonParRepaymentFlow = new SimpleCashFlow(nonParRepayment_, finalDate);

            legs_[0].Add(nonParRepaymentFlow);

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with");

            // special flows
            if (parSwap_)
            {
                // upfront on the floating leg
                double   upfront         = (dirtyPrice - 100.0) / 100.0 * notional;
                CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_);
                legs_[1].Insert(0, upfrontCashFlow);
                // backpayment on the floating leg
                // (accounts for non-par redemption, if any)
                double   backPayment         = notional;
                CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate);
                legs_[1].Add(backPaymentCashFlow);
            }
            else
            {
                // final notional exchange
                CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate);
                legs_[1].Add(finalCashFlow);
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg");

            foreach (CashFlow c in legs_[0])
            {
                c.registerWith(update);
            }

            if (payBondCoupon)
            {
                payer_[0] = -1.0;
                payer_[1] = +1.0;
            }
            else
            {
                payer_[0] = +1.0;
                payer_[1] = -1.0;
            }
        }
Пример #6
0
        public AssetSwap(bool payBondCoupon,
                         Bond bond,
                         double bondCleanPrice,
                         IborIndex iborIndex,
                         double spread,
                         Schedule floatSchedule      = null,
                         DayCounter floatingDayCount = null,
                         bool parAssetSwap           = true)
            : base(2)
        {
            bond_            = bond;
            bondCleanPrice_  = bondCleanPrice;
            nonParRepayment_ = 100;
            spread_          = spread;
            parSwap_         = parAssetSwap;

            Schedule schedule = floatSchedule;

            if (floatSchedule == null)
            {
                schedule = new Schedule(bond_.settlementDate(),
                                        bond_.maturityDate(),
                                        iborIndex.tenor(),
                                        iborIndex.fixingCalendar(),
                                        iborIndex.businessDayConvention(),
                                        iborIndex.businessDayConvention(),
                                        DateGeneration.Rule.Backward,
                                        false); // endOfMonth
            }
            // the following might become an input parameter
            BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following;

            Date finalDate           = schedule.calendar().adjust(schedule.endDate(), paymentAdjustment);
            Date adjBondMaturityDate = schedule.calendar().adjust(bond_.maturityDate(), paymentAdjustment);

            Utils.QL_REQUIRE(finalDate == adjBondMaturityDate, () =>
                             "adjusted schedule end date (" +
                             finalDate +
                             ") must be equal to adjusted bond maturity date (" +
                             adjBondMaturityDate + ")");

            // bondCleanPrice must be the (forward) clean price
            // at the floating schedule start date
            upfrontDate_ = schedule.startDate();
            double dirtyPrice = bondCleanPrice_ +
                                bond_.accruedAmount(upfrontDate_);

            double notional = bond_.notional(upfrontDate_);

            /* In the market asset swap, the bond is purchased in return for
             * payment of the full price. The notional of the floating leg is
             * then scaled by the full price. */
            if (!parSwap_)
            {
                notional *= dirtyPrice / 100.0;
            }

            if (floatingDayCount == null)
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }
            else
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withPaymentDayCounter(floatingDayCount)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }

            foreach (CashFlow c in legs_[1])
            {
                c.registerWith(update);
            }

            List <CashFlow> bondLeg = bond_.cashflows();

            foreach (CashFlow c in bondLeg)
            {
                // whatever might be the choice for the discounting engine
                // bond flows on upfrontDate_ must be discarded
                bool upfrontDateBondFlows = false;
                if (!(c.hasOccurred(upfrontDate_, upfrontDateBondFlows)))
                {
                    legs_[0].Add(c);
                }
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with");

            // special flows
            if (parSwap_)
            {
                // upfront on the floating leg
                double   upfront         = (dirtyPrice - 100.0) / 100.0 * notional;
                CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_);
                legs_[1].Insert(0, upfrontCashFlow);
                // backpayment on the floating leg
                // (accounts for non-par redemption, if any)
                double   backPayment         = notional;
                CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate);
                legs_[1].Add(backPaymentCashFlow);
            }
            else
            {
                // final notional exchange
                CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate);
                legs_[1].Add(finalCashFlow);
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg");

            foreach (CashFlow c in legs_[0])
            {
                c.registerWith(update);
            }

            if (payBondCoupon)
            {
                payer_[0] = -1.0;
                payer_[1] = +1.0;
            }
            else
            {
                payer_[0] = +1.0;
                payer_[1] = -1.0;
            }
        }
Пример #7
0
        public CPISwap(Type type,
                       double nominal,
                       bool subtractInflationNominal,
                       // float+spread leg
                       double spread,
                       DayCounter floatDayCount,
                       Schedule floatSchedule,
                       BusinessDayConvention floatPaymentRoll,
                       int fixingDays,
                       IborIndex floatIndex,
                       // fixed x inflation leg
                       double fixedRate,
                       double baseCPI,
                       DayCounter fixedDayCount,
                       Schedule fixedSchedule,
                       BusinessDayConvention fixedPaymentRoll,
                       Period observationLag,
                       ZeroInflationIndex fixedIndex,
                       InterpolationType observationInterpolation = InterpolationType.AsIndex,
                       double?inflationNominal = null)
            : base(2)
        {
            type_    = type;
            nominal_ = nominal;
            subtractInflationNominal_ = subtractInflationNominal;
            spread_                   = spread;
            floatDayCount_            = floatDayCount;
            floatSchedule_            = floatSchedule;
            floatPaymentRoll_         = floatPaymentRoll;
            fixingDays_               = fixingDays;
            floatIndex_               = floatIndex;
            fixedRate_                = fixedRate;
            baseCPI_                  = baseCPI;
            fixedDayCount_            = fixedDayCount;
            fixedSchedule_            = fixedSchedule;
            fixedPaymentRoll_         = fixedPaymentRoll;
            fixedIndex_               = fixedIndex;
            observationLag_           = observationLag;
            observationInterpolation_ = observationInterpolation;

            Utils.QL_REQUIRE(floatSchedule_.Count > 0, () => "empty float schedule");
            Utils.QL_REQUIRE(fixedSchedule_.Count > 0, () => "empty fixed schedule");
            // todo if roll!=unadjusted then need calendars ...

            inflationNominal_ = inflationNominal ?? nominal_;

            List <CashFlow> floatingLeg;

            if (floatSchedule_.Count > 1)
            {
                floatingLeg = new IborLeg(floatSchedule_, floatIndex_)
                              .withFixingDays(fixingDays_)
                              .withPaymentDayCounter(floatDayCount_)
                              .withSpreads(spread_)
                              .withNotionals(nominal_)
                              .withPaymentAdjustment(floatPaymentRoll_);
            }
            else
            {
                floatingLeg = new List <CashFlow>();
            }

            if (floatSchedule_.Count == 1 ||
                !subtractInflationNominal_ ||
                (subtractInflationNominal && Math.Abs(nominal_ - inflationNominal_) > 0.00001)
                )
            {
                Date payNotional;
                if (floatSchedule_.Count == 1)
                {
                    // no coupons
                    payNotional = floatSchedule_[0];
                    payNotional = floatSchedule_.calendar().adjust(payNotional, floatPaymentRoll_);
                }
                else
                {
                    // use the pay date of the last coupon
                    payNotional = floatingLeg.Last().date();
                }

                double   floatAmount = subtractInflationNominal_ ? nominal_ - inflationNominal_ : nominal_;
                CashFlow nf          = new SimpleCashFlow(floatAmount, payNotional);
                floatingLeg.Add(nf);
            }

            // a CPIleg know about zero legs and inclusion of base inflation notional
            List <CashFlow> cpiLeg = new CPILeg(fixedSchedule_, fixedIndex_, baseCPI_, observationLag_)
                                     .withFixedRates(fixedRate_)
                                     .withPaymentDayCounter(fixedDayCount_)
                                     .withObservationInterpolation(observationInterpolation_)
                                     .withSubtractInflationNominal(subtractInflationNominal_)
                                     .withNotionals(inflationNominal_)
                                     .withPaymentAdjustment(fixedPaymentRoll_);

            foreach (CashFlow cashFlow in cpiLeg)
            {
                cashFlow.registerWith(update);
            }

            if (floatingLeg.Count > 0)
            {
                foreach (CashFlow cashFlow in floatingLeg)
                {
                    cashFlow.registerWith(update);
                }
            }

            legs_[0] = cpiLeg;
            legs_[1] = floatingLeg;


            if (type_ == Type.Payer)
            {
                payer_[0] = 1.0;
                payer_[1] = -1.0;
            }
            else
            {
                payer_[0] = -1.0;
                payer_[1] = 1.0;
            }
        }
Пример #8
0
        // calculating swaption volatility matrix using
        // Rebonatos approx. formula. Be aware that this
        // matrix is valid only for regular fixings and
        // assumes that the fix and floating leg have the
        // same frequency
        public SwaptionVolatilityMatrix getSwaptionVolatilityMatrix()
        {
            if (swaptionVola != null)
            {
                return(swaptionVola);
            }

            IborIndex index = process_.index();
            Date      today = process_.fixingDates()[0];

            int    size         = process_.size() / 2;
            Matrix volatilities = new Matrix(size, size);

            List <Date> exercises = new InitializedList <Date>(size);

            for (int i = 0; i < size; ++i)
            {
                exercises[i] = process_.fixingDates()[i + 1];
            }

            List <Period> lengths = new InitializedList <Period>(size);

            for (int i = 0; i < size; ++i)
            {
                lengths[i] = (i + 1) * index.tenor();
            }

            Vector f = process_.initialValues();

            for (int k = 0; k < size; ++k)
            {
                int    alpha   = k;
                double t_alpha = process_.fixingTimes()[alpha + 1];

                Matrix var = new Matrix(size, size);
                for (int i = alpha + 1; i <= k + size; ++i)
                {
                    for (int j = i; j <= k + size; ++j)
                    {
                        var[i - alpha - 1, j - alpha - 1] = var[j - alpha - 1, i - alpha - 1] =
                            covarProxy_.integratedCovariance(i, j, t_alpha, null);
                    }
                }

                for (int l = 1; l <= size; ++l)
                {
                    int    beta = l + k;
                    Vector w    = w_0(alpha, beta);

                    double sum = 0.0;
                    for (int i = alpha + 1; i <= beta; ++i)
                    {
                        for (int j = alpha + 1; j <= beta; ++j)
                        {
                            sum += w[i] * w[j] * f[i] * f[j] * var[i - alpha - 1, j - alpha - 1];
                        }
                    }
                    volatilities[k, l - 1] =
                        Math.Sqrt(sum / t_alpha) / S_0(alpha, beta);
                }
            }

            return(swaptionVola = new SwaptionVolatilityMatrix(today, exercises, lengths,
                                                               volatilities, index.dayCounter()));
        }
Пример #9
0
        public FloatingCatBond(int settlementDays,
                               double faceAmount,
                               Date startDate,
                               Date maturityDate,
                               Frequency couponFrequency,
                               Calendar calendar,
                               IborIndex iborIndex,
                               DayCounter accrualDayCounter,
                               NotionalRisk notionalRisk,
                               BusinessDayConvention accrualConvention = BusinessDayConvention.Following,
                               BusinessDayConvention paymentConvention = BusinessDayConvention.Following,
                               int fixingDays           = 0,
                               List <double> gearings   = null,
                               List <double> spreads    = null,
                               List <double?> caps      = null,
                               List <double?> floors    = null,
                               bool inArrears           = false,
                               double redemption        = 100.0,
                               Date issueDate           = null,
                               Date stubDate            = null,
                               DateGeneration.Rule rule = DateGeneration.Rule.Backward,
                               bool endOfMonth          = false)
            : base(settlementDays, calendar, issueDate, notionalRisk)
        {
            maturityDate_ = maturityDate;

            Date firstDate = null, nextToLastDate = null;

            switch (rule)
            {
            case DateGeneration.Rule.Backward:
                firstDate      = new Date();
                nextToLastDate = stubDate;
                break;

            case DateGeneration.Rule.Forward:
                firstDate      = stubDate;
                nextToLastDate = new Date();
                break;

            case DateGeneration.Rule.Zero:
            case DateGeneration.Rule.ThirdWednesday:
            case DateGeneration.Rule.Twentieth:
            case DateGeneration.Rule.TwentiethIMM:
                Utils.QL_FAIL("stub date (" + stubDate + ") not allowed with " +
                              rule + " DateGeneration.Rule");
                break;

            default:
                Utils.QL_FAIL("unknown DateGeneration::Rule (" + rule + ")");
                break;
            }

            Schedule schedule = new Schedule(startDate, maturityDate_, new Period(couponFrequency),
                                             calendar_, accrualConvention, accrualConvention,
                                             rule, endOfMonth, firstDate, nextToLastDate);

            cashflows_ = new IborLeg(schedule, iborIndex)
                         .withFixingDays(fixingDays)
                         .withGearings(gearings)
                         .withSpreads(spreads)
                         .withCaps(caps)
                         .withFloors(floors)
                         .inArrears(inArrears)
                         .withPaymentDayCounter(accrualDayCounter)
                         .withPaymentAdjustment(paymentConvention)
                         .withNotionals(faceAmount);

            addRedemptionsToCashflows(new InitializedList <double>(1, redemption));

            Utils.QL_REQUIRE(!cashflows().empty(), () => "bond with no cashflows!");
            Utils.QL_REQUIRE(redemptions_.Count == 1, () => "multiple redemptions created");

            iborIndex.registerWith(update);
        }
Пример #10
0
        public BMASwap(Type type, double nominal,
                       // Libor leg
                       Schedule liborSchedule, double liborFraction, double liborSpread, IborIndex liborIndex, DayCounter liborDayCount,
                       // BMA leg
                       Schedule bmaSchedule, BMAIndex bmaIndex, DayCounter bmaDayCount)
            : base(2)
        {
            type_          = type;
            nominal_       = nominal;
            liborFraction_ = liborFraction;
            liborSpread_   = liborSpread;

            BusinessDayConvention convention = liborSchedule.businessDayConvention();

            legs_[0] = new IborLeg(liborSchedule, liborIndex)
                       .withPaymentDayCounter(liborDayCount)
                       .withFixingDays(liborIndex.fixingDays())
                       .withGearings(liborFraction)
                       .withSpreads(liborSpread)
                       .withNotionals(nominal)
                       .withPaymentAdjustment(convention);

            legs_[1] = new AverageBMALeg(bmaSchedule, bmaIndex)
                       .withPaymentDayCounter(bmaDayCount)
                       .withNotionals(nominal)
                       .withPaymentAdjustment(bmaSchedule.businessDayConvention());

            for (int j = 0; j < 2; ++j)
            {
                for (int i = 0; i < legs_[j].Count; i++)
                {
                    legs_[j][i].registerWith(update);
                }
            }

            switch (type_)
            {
            case Type.Payer:
                payer_[0] = +1.0;
                payer_[1] = -1.0;
                break;

            case Type.Receiver:
                payer_[0] = -1.0;
                payer_[1] = +1.0;
                break;

            default:
                Utils.QL_FAIL("Unknown BMA-swap type");
                break;
            }
        }
Пример #11
0
        private void init(BusinessDayConvention?paymentConvention1, BusinessDayConvention?paymentConvention2)
        {
            Utils.QL_REQUIRE(nominal1_.Count == schedule1_.Count - 1, () =>
                             "nominal1 size (" + nominal1_.Count +
                             ") does not match schedule1 size (" + schedule1_.size() + ")");
            Utils.QL_REQUIRE(nominal2_.Count == schedule2_.Count - 1, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match schedule2 size ("
                             + nominal2_.Count + ")");
            Utils.QL_REQUIRE(gearing1_.Count == 0 || gearing1_.Count == nominal1_.Count, () =>
                             "nominal1 size (" + nominal1_.Count + ") does not match gearing1 size ("
                             + gearing1_.Count + ")");
            Utils.QL_REQUIRE(gearing2_.Count == 0 || gearing2_.Count == nominal2_.Count, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match gearing2 size ("
                             + gearing2_.Count + ")");
            Utils.QL_REQUIRE(cappedRate1_.Count == 0 || cappedRate1_.Count == nominal1_.Count, () =>
                             "nominal1 size (" + nominal1_.Count + ") does not match cappedRate1 size ("
                             + cappedRate1_.Count + ")");
            Utils.QL_REQUIRE(cappedRate2_.Count == 0 || cappedRate2_.Count == nominal2_.Count, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match cappedRate2 size ("
                             + cappedRate2_.Count + ")");
            Utils.QL_REQUIRE(flooredRate1_.Count == 0 || flooredRate1_.Count == nominal1_.Count, () =>
                             "nominal1 size (" + nominal1_.Count + ") does not match flooredRate1 size ("
                             + flooredRate1_.Count + ")");
            Utils.QL_REQUIRE(flooredRate2_.Count == 0 || flooredRate2_.Count == nominal2_.Count, () =>
                             "nominal2 size (" + nominal2_.Count + ") does not match flooredRate2 size ("
                             + flooredRate2_.Count + ")");

            if (paymentConvention1 != null)
            {
                paymentConvention1_ = paymentConvention1.Value;
            }
            else
            {
                paymentConvention1_ = schedule1_.businessDayConvention();
            }

            if (paymentConvention2 != null)
            {
                paymentConvention2_ = paymentConvention2.Value;
            }
            else
            {
                paymentConvention2_ = schedule2_.businessDayConvention();
            }

            if (gearing1_.Count == 0)
            {
                gearing1_ = new InitializedList <double>(nominal1_.Count, 1.0);
            }
            if (gearing2_.Count == 0)
            {
                gearing2_ = new InitializedList <double>(nominal2_.Count, 1.0);
            }
            if (spread1_.Count == 0)
            {
                spread1_ = new InitializedList <double>(nominal1_.Count, 0.0);
            }
            if (spread2_.Count == 0)
            {
                spread2_ = new InitializedList <double>(nominal2_.Count, 0.0);
            }
            if (cappedRate1_.Count == 0)
            {
                cappedRate1_ = new InitializedList <double?>(nominal1_.Count, null);
            }
            if (cappedRate2_.Count == 0)
            {
                cappedRate2_ = new InitializedList <double?>(nominal2_.Count, null);
            }
            if (flooredRate1_.Count == 0)
            {
                flooredRate1_ = new InitializedList <double?>(nominal1_.Count, null);
            }
            if (flooredRate2_.Count == 0)
            {
                flooredRate2_ = new InitializedList <double?>(nominal2_.Count, null);
            }

            bool isNull = cappedRate1_[0] == null;

            for (int i = 0; i < cappedRate1_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(cappedRate1_[i] == null, () =>
                                     "cappedRate1 must be null for all or none entry (" + (i + 1)
                                     + "th is " + cappedRate1_[i] + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(cappedRate1_[i] != null, () =>
                                     "cappedRate 1 must be null for all or none entry ("
                                     + "1st is " + cappedRate1_[0] + ")");
                }
            }
            isNull = cappedRate2_[0] == null;
            for (int i = 0; i < cappedRate2_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(cappedRate2_[i] == null, () =>
                                     "cappedRate2 must be null for all or none entry ("
                                     + (i + 1) + "th is " + cappedRate2_[i] + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(cappedRate2_[i] != null, () =>
                                     "cappedRate2 must be null for all or none entry ("
                                     + "1st is " + cappedRate2_[0] + ")");
                }
            }
            isNull = flooredRate1_[0] == null;
            for (int i = 0; i < flooredRate1_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(flooredRate1_[i] == null, () =>
                                     "flooredRate1 must be null for all or none entry ("
                                     + (i + 1) + "th is " + flooredRate1_[i]
                                     + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(flooredRate1_[i] != null, () =>
                                     "flooredRate 1 must be null for all or none entry ("
                                     + "1st is " + flooredRate1_[0] + ")");
                }
            }
            isNull = flooredRate2_[0] == null;
            for (int i = 0; i < flooredRate2_.Count; i++)
            {
                if (isNull)
                {
                    Utils.QL_REQUIRE(flooredRate2_[i] == null, () =>
                                     "flooredRate2 must be null for all or none entry ("
                                     + (i + 1) + "th is " + flooredRate2_[i]
                                     + ")");
                }
                else
                {
                    Utils.QL_REQUIRE(flooredRate2_[i] != null, () =>
                                     "flooredRate2 must be null for all or none entry ("
                                     + "1st is " + flooredRate2_[0] + ")");
                }
            }

            // if the gearing is zero then the ibor / cms leg will be set up with
            // fixed coupons which makes trouble here in this context. We therefore
            // use a dirty trick and enforce the gearing to be non zero.
            for (int i = 0; i < gearing1_.Count; i++)
            {
                if (Utils.close(gearing1_[i], 0.0))
                {
                    gearing1_[i] = Const.QL_EPSILON;
                }
            }
            for (int i = 0; i < gearing2_.Count; i++)
            {
                if (Utils.close(gearing2_[i], 0.0))
                {
                    gearing2_[i] = Const.QL_EPSILON;
                }
            }

            IborIndex       ibor1      = index1_ as IborIndex;
            IborIndex       ibor2      = index2_ as IborIndex;
            SwapIndex       cms1       = index1_ as SwapIndex;
            SwapIndex       cms2       = index2_ as SwapIndex;
            SwapSpreadIndex cmsspread1 = index1_ as SwapSpreadIndex;
            SwapSpreadIndex cmsspread2 = index2_ as SwapSpreadIndex;

            Utils.QL_REQUIRE(ibor1 != null || cms1 != null || cmsspread1 != null, () =>
                             "index1 must be ibor or cms or cms spread");
            Utils.QL_REQUIRE(ibor2 != null || cms2 != null || cmsspread2 != null, () =>
                             "index2 must be ibor or cms");

            if (ibor1 != null)
            {
                IborLeg leg = new IborLeg(schedule1_, ibor1);
                leg = (IborLeg)leg.withPaymentDayCounter(dayCount1_)
                      .withSpreads(spread1_)
                      .withGearings(gearing1_)
                      .withPaymentAdjustment(paymentConvention1_)
                      .withNotionals(nominal1_);

                if (cappedRate1_[0] != null)
                {
                    leg = (IborLeg)leg.withCaps(cappedRate1_);
                }
                if (flooredRate1_[0] != null)
                {
                    leg = (IborLeg)leg.withFloors(flooredRate1_);
                }
                legs_[0] = leg;
            }

            if (ibor2 != null)
            {
                IborLeg leg = new IborLeg(schedule2_, ibor2);
                leg = (IborLeg)leg.withPaymentDayCounter(dayCount2_)
                      .withSpreads(spread2_)
                      .withGearings(gearing2_)
                      .withPaymentAdjustment(paymentConvention2_)
                      .withNotionals(nominal2_);

                if (cappedRate2_[0] != null)
                {
                    leg = (IborLeg)leg.withCaps(cappedRate2_);
                }
                if (flooredRate2_[0] != null)
                {
                    leg = (IborLeg)leg.withFloors(flooredRate2_);
                }
                legs_[1] = leg;
            }

            if (cms1 != null)
            {
                CmsLeg leg = new CmsLeg(schedule1_, cms1);
                leg = (CmsLeg)leg.withPaymentDayCounter(dayCount1_)
                      .withSpreads(spread1_)
                      .withGearings(gearing1_)
                      .withNotionals(nominal1_)
                      .withPaymentAdjustment(paymentConvention1_);

                if (cappedRate1_[0] != null)
                {
                    leg = (CmsLeg)leg.withCaps(cappedRate1_);
                }
                if (flooredRate1_[0] != null)
                {
                    leg = (CmsLeg)leg.withFloors(flooredRate1_);
                }
                legs_[0] = leg;
            }

            if (cms2 != null)
            {
                CmsLeg leg = new CmsLeg(schedule2_, cms2);
                leg = (CmsLeg)leg.withPaymentDayCounter(dayCount2_)
                      .withSpreads(spread2_)
                      .withGearings(gearing2_)
                      .withNotionals(nominal2_)
                      .withPaymentAdjustment(paymentConvention2_);

                if (cappedRate2_[0] != null)
                {
                    leg = (CmsLeg)leg.withCaps(cappedRate2_);
                }
                if (flooredRate2_[0] != null)
                {
                    leg = (CmsLeg)leg.withFloors(flooredRate2_);
                }
                legs_[1] = leg;
            }

            if (cmsspread1 != null)
            {
                CmsSpreadLeg leg = new CmsSpreadLeg(schedule1_, cmsspread1);
                leg = (CmsSpreadLeg)leg.withPaymentDayCounter(dayCount1_)
                      .withSpreads(spread1_)
                      .withGearings(gearing1_)
                      .withNotionals(nominal1_)
                      .withPaymentAdjustment(paymentConvention1_);
                if (cappedRate1_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withCaps(cappedRate1_);
                }
                if (flooredRate1_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withFloors(flooredRate1_);
                }
                legs_[0] = leg;
            }

            if (cmsspread2 != null)
            {
                CmsSpreadLeg leg = new CmsSpreadLeg(schedule2_, cmsspread2);
                leg = (CmsSpreadLeg)leg.withPaymentDayCounter(dayCount2_)
                      .withSpreads(spread2_)
                      .withGearings(gearing2_)
                      .withNotionals(nominal2_)
                      .withPaymentAdjustment(paymentConvention2_);

                if (cappedRate2_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withCaps(cappedRate2_);
                }
                if (flooredRate2_[0] != null)
                {
                    leg = (CmsSpreadLeg)leg.withFloors(flooredRate2_);
                }
                legs_[1] = leg;
            }

            if (intermediateCapitalExchange_)
            {
                for (int i = 0; i < legs_[0].Count - 1; i++)
                {
                    double cap = nominal1_[i] - nominal1_[i + 1];
                    if (!Utils.close(cap, 0.0))
                    {
                        legs_[0].Insert(i + 1, new Redemption(cap, legs_[0][i].date()));
                        nominal1_.Insert(i + 1, nominal1_[i]);
                        i++;
                    }
                }
                for (int i = 0; i < legs_[1].Count - 1; i++)
                {
                    double cap = nominal2_[i] - nominal2_[i + 1];
                    if (!Utils.close(cap, 0.0))
                    {
                        legs_[1].Insert(i + 1, new Redemption(cap, legs_[1][i].date()));
                        nominal2_.Insert(i + 1, nominal2_[i]);
                        i++;
                    }
                }
            }

            if (finalCapitalExchange_)
            {
                legs_[0].Add(new Redemption(nominal1_.Last(), legs_[0].Last().date()));
                nominal1_.Add(nominal1_.Last());
                legs_[1].Add(new Redemption(nominal2_.Last(), legs_[1].Last().date()));
                nominal2_.Add(nominal2_.Last());
            }

            foreach (var c in legs_[0])
            {
                c.registerWith(update);
            }

            foreach (var c in legs_[1])
            {
                c.registerWith(update);
            }

            switch (type_)
            {
            case VanillaSwap.Type.Payer:
                payer_[0] = -1.0;
                payer_[1] = +1.0;
                break;

            case VanillaSwap.Type.Receiver:
                payer_[0] = +1.0;
                payer_[1] = -1.0;
                break;

            default:
                Utils.QL_FAIL("Unknown float float - swap type");
                break;
            }
        }
Пример #12
0
        public FloatingRateBond(int settlementDays, double faceAmount, Schedule schedule, IborIndex index, DayCounter paymentDayCounter,
                                BusinessDayConvention paymentConvention, int fixingDays, List <double> gearings, List <double> spreads,
                                List <double?> caps, List <double?> floors, bool inArrears, double redemption, Date issueDate)
            : base(settlementDays, schedule.calendar(), issueDate)
        {
            maturityDate_ = schedule.endDate();
            cashflows_    = new IborLeg(schedule, index)
                            .withPaymentDayCounter(paymentDayCounter)
                            .withFixingDays(fixingDays)
                            .withGearings(gearings)
                            .withSpreads(spreads)
                            .withCaps(caps)
                            .withFloors(floors)
                            .inArrears(inArrears)
                            .withNotionals(faceAmount)
                            .withPaymentAdjustment(paymentConvention);

            addRedemptionsToCashflows(new List <double>()
            {
                redemption
            });

            Utils.QL_REQUIRE(cashflows().Count != 0, () => "bond with no cashflows!");
            Utils.QL_REQUIRE(redemptions_.Count == 1, () => "multiple redemptions created");

            index.registerWith(update);
        }
Пример #13
0
 public FloatingRateBond(int settlementDays, double faceAmount, Schedule schedule, IborIndex index,
                         DayCounter paymentDayCounter, BusinessDayConvention paymentConvention, int fixingDays,
                         List <double> gearings, List <double> spreads)
     : this(settlementDays, faceAmount, schedule, index, paymentDayCounter, BusinessDayConvention.Following,
            fixingDays, gearings, spreads, new List <double?>(), new List <double?>(), false, 100, null)
 {
 }
Пример #14
0
 public FloatingRateBond(int settlementDays, double faceAmount, Schedule schedule, IborIndex index,
                         DayCounter paymentDayCounter)
     : this(settlementDays, faceAmount, schedule, index, paymentDayCounter, BusinessDayConvention.Following,
            0, new List <double>() { 1 }, new List <double>() { 0 }, new List <double?>(), new List <double?>(),
            false, 100, null)
 {
 }
Пример #15
0
        public override void calculate()
        {
            /* both DTS, YTS ref dates and pricing date consistency
             * checks? settlement... */
            Utils.QL_REQUIRE(!discountCurve_.empty(), () => "no discount term structure set");
            Utils.QL_REQUIRE(!defaultTS_.empty(), () => "no ctpty default term structure set");
            Utils.QL_REQUIRE(!swaptionletEngine_.empty(), () => "no swap option engine set");

            Date priceDate = defaultTS_.link.referenceDate();

            double cumOptVal = 0.0, cumPutVal = 0.0;
            // Vanilla swap so 0 leg is floater

            int  index        = 0;
            Date nextFD       = arguments_.fixedPayDates[index];
            Date swapletStart = priceDate;

            while (nextFD < priceDate)
            {
                index++;
                nextFD = arguments_.fixedPayDates[index];
            }


            // Compute fair spread for strike value:
            // copy args into the non risky engine
            Swap.Arguments noCVAArgs = baseSwapEngine_.link.getArguments() as Swap.Arguments;

            noCVAArgs.legs  = this.arguments_.legs;
            noCVAArgs.payer = this.arguments_.payer;

            baseSwapEngine_.link.calculate();

            double baseSwapRate = ((FixedRateCoupon)arguments_.legs[0][0]).rate();

            Swap.Results vSResults = baseSwapEngine_.link.getResults() as Swap.Results;

            double?baseSwapFairRate = -baseSwapRate * vSResults.legNPV[1] / vSResults.legNPV[0];
            double?baseSwapNPV      = vSResults.value;

            VanillaSwap.Type reversedType = arguments_.type == VanillaSwap.Type.Payer
                                         ? VanillaSwap.Type.Receiver
                                         : VanillaSwap.Type.Payer;

            // Swaplet options summatory:
            while (nextFD != arguments_.fixedPayDates.Last())
            {
                // iFD coupon not fixed, create swaptionlet:
                IborIndex swapIndex = ((FloatingRateCoupon)arguments_.legs[1][0]).index() as IborIndex;

                // Alternatively one could cap this period to, say, 1M
                Period baseSwapsTenor = new Period(arguments_.fixedPayDates.Last().serialNumber()
                                                   - swapletStart.serialNumber(), TimeUnit.Days);
                VanillaSwap swaplet = new MakeVanillaSwap(baseSwapsTenor, swapIndex, baseSwapFairRate)
                                      .withType(arguments_.type)
                                      .withNominal(arguments_.nominal)
                                      .withEffectiveDate(swapletStart)
                                      .withTerminationDate(arguments_.fixedPayDates.Last()).value();

                VanillaSwap revSwaplet = new MakeVanillaSwap(baseSwapsTenor, swapIndex, baseSwapFairRate)
                                         .withType(reversedType)
                                         .withNominal(arguments_.nominal)
                                         .withEffectiveDate(swapletStart)
                                         .withTerminationDate(arguments_.fixedPayDates.Last()).value();

                Swaption swaptionlet = new Swaption(swaplet, new EuropeanExercise(swapletStart));
                Swaption putSwaplet  = new Swaption(revSwaplet, new EuropeanExercise(swapletStart));
                swaptionlet.setPricingEngine(swaptionletEngine_.currentLink());
                putSwaplet.setPricingEngine(swaptionletEngine_.currentLink());

                // atm underlying swap means that the value of put = value
                // call so this double pricing is not needed
                cumOptVal += swaptionlet.NPV() * defaultTS_.link.defaultProbability(
                    swapletStart, nextFD);
                cumPutVal += putSwaplet.NPV() * invstDTS_.link.defaultProbability(swapletStart, nextFD);

                swapletStart = nextFD;
                index++;
                nextFD = arguments_.fixedPayDates[index];
            }

            results_.value    = baseSwapNPV - (1.0 - ctptyRecoveryRate_) * cumOptVal + (1.0 - invstRecoveryRate_) * cumPutVal;
            results_.fairRate = -baseSwapRate * (vSResults.legNPV[1] - (1.0 - ctptyRecoveryRate_) * cumOptVal +
                                                 (1.0 - invstRecoveryRate_) * cumPutVal) / vSResults.legNPV[0];
        }