public static double accruedAmount(Leg leg, bool includeSettlementDateFlows, Date settlementDate = null) { if (settlementDate == null) { settlementDate = Settings.Instance.evaluationDate(); } CashFlow cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate); if (cf == null) { return(0); } Date paymentDate = cf.date(); double result = 0.0; foreach (CashFlow x in leg.Where(x => x.date() == paymentDate)) { Coupon cp = x as Coupon; if (cp != null) { result += cp.accruedAmount(settlementDate); } } return(result); }
//! NPV and BPS of the cash flows. // The NPV and BPS of the cash flows calculated together for performance reason public static void npvbps(Leg leg, YieldTermStructure discountCurve, bool includeSettlementDateFlows, Date settlementDate, Date npvDate, out double npv, out double bps) { npv = bps = 0.0; if (leg.empty()) { bps = 0.0; return; } for (int i = 0; i < leg.Count; ++i) { CashFlow cf = leg[i]; if (!cf.hasOccurred(settlementDate, includeSettlementDateFlows) && !cf.tradingExCoupon(settlementDate)) { Coupon cp = leg[i] as Coupon; double df = discountCurve.discount(cf.date()); npv += cf.amount() * df; if (cp != null) { bps += cp.nominal() * cp.accrualPeriod() * df; } } } double d = discountCurve.discount(npvDate); npv /= d; bps = Const.BASIS_POINT * bps / d; }
//! NPV of a single cash flows public static double npv(CashFlow cashflow, YieldTermStructure discountCurve, Date settlementDate = null, Date npvDate = null, int exDividendDays = 0) { double NPV = 0.0; if (cashflow == null) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.Instance.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } if (!cashflow.hasOccurred(settlementDate + exDividendDays)) { NPV = cashflow.amount() * discountCurve.discount(cashflow.date()); } return(NPV / discountCurve.discount(npvDate)); }
public static Date nextCashFlowDate(Leg leg, bool includeSettlementDateFlows, Date settlementDate = null) { CashFlow cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate); if (cf == null) { return(null); } return(cf.date()); }
public static double?nextCashFlowAmount(Leg leg, bool includeSettlementDateFlows, Date settlementDate = null) { CashFlow cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate); if (cf == null) { return(null); } Date paymentDate = cf.date(); double result = 0.0; result = leg.Where(cf1 => cf1.date() == paymentDate).Sum(cf1 => cf1.amount()); return(result); }
protected void setSingleRedemption(double notional, CashFlow redemption) { notionals_.Clear(); notionalSchedule_.Clear(); redemptions_.Clear(); notionalSchedule_.Add(new Date()); notionals_.Add(notional); notionalSchedule_.Add(redemption.date()); notionals_.Add(0.0); cashflows_.Add(redemption); redemptions_.Add(redemption); }
// At-the-money rate of the cash flows. // The result is the fixed rate for which a fixed rate cash flow vector, equivalent to the input vector, has the required NPV according to the given term structure. If the required NPV is // not given, the input cash flow vector's NPV is used instead. public static double atmRate(Leg leg, YieldTermStructure discountCurve, bool includeSettlementDateFlows, Date settlementDate = null, Date npvDate = null, double?targetNpv = null) { if (settlementDate == null) { settlementDate = Settings.Instance.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } double npv = 0.0; BPSCalculator calc = new BPSCalculator(discountCurve); for (int i = 0; i < leg.Count; ++i) { CashFlow cf = leg[i]; if (!cf.hasOccurred(settlementDate, includeSettlementDateFlows) && !cf.tradingExCoupon(settlementDate)) { npv += cf.amount() * discountCurve.discount(cf.date()); cf.accept(calc); } } if (targetNpv == null) { targetNpv = npv - calc.nonSensNPV(); } else { targetNpv *= discountCurve.discount(npvDate); targetNpv -= calc.nonSensNPV(); } if (targetNpv.IsEqual(0.0)) { return(0.0); } double bps = calc.bps(); Utils.QL_REQUIRE(bps.IsNotEqual(0.0), () => "null bps: impossible atm rate"); return(targetNpv.Value / bps); }
public static int accrualDays(Leg leg, bool includeSettlementDateFlows, Date settlementDate = null) { CashFlow cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate); if (cf == null) { return(0); } Date paymentDate = cf.date(); foreach (CashFlow x in leg.Where(x => x.date() == paymentDate)) { Coupon cp = x as Coupon; if (cp != null) { return(cp.accrualDays()); } } return(0); }
public static Date referencePeriodEnd(Leg leg, bool includeSettlementDateFlows, Date settlementDate = null) { CashFlow cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate); if (cf == null) { return(null); } Date paymentDate = cf.date(); foreach (CashFlow x in leg.Where(x => x.date() == paymentDate)) { Coupon cp = x as Coupon; if (cp != null) { return(cp.referencePeriodEnd); } } return(null); }
private static double aggregateRate(Leg leg, CashFlow cf) { if (cf == null) { return(0.0); } Date paymentDate = cf.date(); bool firstCouponFound = false; double nominal = 0.0; double accrualPeriod = 0.0; DayCounter dc = null; double result = 0.0; foreach (CashFlow x in leg.Where(x => x.date() == paymentDate)) { Coupon cp = x as Coupon; if (cp != null) { if (firstCouponFound) { Utils.QL_REQUIRE(nominal.IsEqual(cp.nominal()) && accrualPeriod.IsEqual(cp.accrualPeriod()) && dc == cp.dayCounter(), () => "cannot aggregate two different coupons on " + paymentDate); } else { firstCouponFound = true; nominal = cp.nominal(); accrualPeriod = cp.accrualPeriod(); dc = cp.dayCounter(); } result += cp.rate(); } } Utils.QL_REQUIRE(firstCouponFound, () => "no coupon paid at cashflow date " + paymentDate); return(result); }
// helper function used to calculate Time-To-Discount for each stage when calculating discount factor stepwisely public static double getStepwiseDiscountTime(CashFlow cashFlow, DayCounter dc, Date npvDate, Date lastDate) { Date cashFlowDate = cashFlow.date(); Date refStartDate, refEndDate; Coupon coupon = cashFlow as Coupon; if (coupon != null) { refStartDate = coupon.referencePeriodStart; refEndDate = coupon.referencePeriodEnd; } else { if (lastDate == npvDate) { // we don't have a previous coupon date, // so we fake it refStartDate = cashFlowDate - new Period(1, TimeUnit.Years); } else { refStartDate = lastDate; } refEndDate = cashFlowDate; } if (coupon != null && lastDate != coupon.accrualStartDate()) { double couponPeriod = dc.yearFraction(coupon.accrualStartDate(), cashFlowDate, refStartDate, refEndDate); double accruedPeriod = dc.yearFraction(coupon.accrualStartDate(), lastDate, refStartDate, refEndDate); return(couponPeriod - accruedPeriod); } else { return(dc.yearFraction(lastDate, cashFlowDate, refStartDate, refEndDate)); } }
public void visit(CashFlow cf) { nonSensNPV_ += cf.amount() * discountCurve_.discount(cf.date()); }
protected double cashFlowRiskyValue(CashFlow cf, NotionalPath notionalPath) { return(cf.amount() * notionalPath.notionalRate(cf.date())); //TODO: fix for more complicated cashflows }
// 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(); } } }