public discountFactor ( Date d1, Date d2 ) : double | ||
d1 | Date | |
d2 | Date | |
return | double |
public static double simpleDuration(List <CashFlow> cashflows, InterestRate y, Date settlementDate) { if (cashflows.Count == 0) { return(0.0); } double P = 0, dPdy = 0; DayCounter dc = y.dayCounter(); foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) { double t = dc.yearFraction(settlementDate, cf.date()); double c = cf.amount(); double B = y.discountFactor(t); P += c * B; dPdy += t * c * B; } // no cashflows if (P == 0.0) { return(0.0); } return(dPdy / P); }
public static double modifiedDuration(List <CashFlow> cashflows, InterestRate y, Date settlementDate) { if (cashflows.Count == 0) { return(0.0); } double P = 0.0; double dPdy = 0.0; double r = y.rate(); int N = (int)y.frequency(); DayCounter dc = y.dayCounter(); foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) { double t = dc.yearFraction(settlementDate, cf.date()); double c = cf.amount(); double B = y.discountFactor(t); P += c * B; switch (y.compounding()) { case Compounding.Simple: dPdy -= c * B * B * t; break; case Compounding.Compounded: dPdy -= c * t * B / (1 + r / N); break; case Compounding.Continuous: dPdy -= c * B * t; break; case Compounding.SimpleThenCompounded: if (t <= 1.0 / N) { dPdy -= c * B * B * t; } else { dPdy -= c * t * B / (1 + r / N); } break; default: throw new ArgumentException("unknown compounding convention (" + y.compounding() + ")"); } } if (P == 0.0) // no cashflows { return(0.0); } return(-dPdy / P); // reverse derivative sign }
public static double simpleDuration(Leg leg, InterestRate y, bool includeSettlementDateFlows, Date settlementDate, Date npvDate) { if (leg.empty()) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } double P = 0.0; double dPdy = 0.0; double t = 0.0; Date lastDate = npvDate; DayCounter dc = y.dayCounter(); for (int i = 0; i < leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) { continue; } double c = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { c = 0.0; } t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate); double B = y.discountFactor(t); P += c * B; dPdy += t * c * B; lastDate = leg[i].date(); } if (P.IsEqual(0.0)) // no cashflows { return(0.0); } return(dPdy / P); }
// NPV of the cash flows. // The NPV is the sum of the cash flows, each discounted // according to the given constant interest rate. The result // is affected by the choice of the interest-rate compounding // and the relative frequency and day counter. public static double npv(Leg leg, InterestRate yield, bool includeSettlementDateFlows, Date settlementDate = null, Date npvDate = null) { if (leg.empty()) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } double npv = 0.0; double discount = 1.0; Date lastDate = npvDate; DayCounter dc = yield.dayCounter(); for (int i = 0; i < leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) { continue; } double amount = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { amount = 0.0; } double b = yield.discountFactor(getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate)); discount *= b; lastDate = leg[i].date(); npv += amount * discount; } return(npv); }
public static double simpleDuration(List<CashFlow> cashflows, InterestRate y, Date settlementDate) { if (cashflows.Count == 0) return 0.0; double P = 0, dPdy = 0; DayCounter dc = y.dayCounter(); foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) { double t = dc.yearFraction(settlementDate, cf.date()); double c = cf.amount(); double B = y.discountFactor(t); P += c * B; dPdy += t * c * B; } // no cashflows if (P == 0.0) return 0.0; return dPdy / P; }
public static double modifiedDuration(Leg leg,InterestRate y, bool includeSettlementDateFlows, Date settlementDate,Date npvDate) { if (leg.empty()) return 0.0; if (settlementDate == null) settlementDate = Settings.evaluationDate(); if (npvDate == null) npvDate = settlementDate; double P = 0.0; double t = 0.0; double dPdy = 0.0; double r = y.rate(); int N = (int)y.frequency(); Date lastDate = npvDate; Date refStartDate, refEndDate; DayCounter dc = y.dayCounter(); for (int i=0; i<leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) continue; double c = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { c = 0.0; } Date couponDate = leg[i].date(); Coupon coupon = leg[i] as Coupon; if (coupon != null) { refStartDate = coupon.refPeriodStart; refEndDate = coupon.refPeriodEnd; } else { if (lastDate == npvDate) { // we don't have a previous coupon date, // so we fake it refStartDate = couponDate - new Period(1,TimeUnit.Years); } else { refStartDate = lastDate; } refEndDate = couponDate; } t += dc.yearFraction(lastDate, couponDate, refStartDate, refEndDate); double B = y.discountFactor(t); P += c * B; switch (y.compounding()) { case Compounding.Simple: dPdy -= c * B*B * t; break; case Compounding.Compounded: dPdy -= c * t * B/(1+r/N); break; case Compounding.Continuous: dPdy -= c * B * t; break; case Compounding.SimpleThenCompounded: if (t<=1.0/N) dPdy -= c * B*B * t; else dPdy -= c * t * B/(1+r/N); break; default: Utils.QL_FAIL("unknown compounding convention (" + y.compounding() + ")"); break; } lastDate = couponDate; } if (P == 0.0) // no cashflows return 0.0; return -dPdy/P; // reverse derivative sign }
public void testConversions() { InterestRateData[] cases = { // data from "Option Pricing Formulas", Haug, pag.181-182 // Rate,Compounding, Frequency, Time, Compounding2, Frequency2, Rate2, precision new InterestRateData(0.0800, Compounding.Compounded, Frequency.Quarterly, 1.00, Compounding.Continuous, Frequency.Annual, 0.0792, 4), new InterestRateData(0.1200, Compounding.Continuous, Frequency.Annual, 1.00, Compounding.Compounded, Frequency.Annual, 0.1275, 4), new InterestRateData(0.0800, Compounding.Compounded, Frequency.Quarterly, 1.00, Compounding.Compounded, Frequency.Annual, 0.0824, 4), new InterestRateData(0.0700, Compounding.Compounded, Frequency.Quarterly, 1.00, Compounding.Compounded, Frequency.Semiannual, 0.0706, 4), // undocumented, but reasonable :) new InterestRateData(0.0100, Compounding.Compounded, Frequency.Annual, 1.00, Compounding.Simple, Frequency.Annual, 0.0100, 4), new InterestRateData(0.0200, Compounding.Simple, Frequency.Annual, 1.00, Compounding.Compounded, Frequency.Annual, 0.0200, 4), new InterestRateData(0.0300, Compounding.Compounded, Frequency.Semiannual, 0.50, Compounding.Simple, Frequency.Annual, 0.0300, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Annual, 0.50, Compounding.Compounded, Frequency.Semiannual, 0.0400, 4), new InterestRateData(0.0500, Compounding.Compounded, Frequency.EveryFourthMonth, 1.0/3, Compounding.Simple, Frequency.Annual, 0.0500, 4), new InterestRateData(0.0600, Compounding.Simple, Frequency.Annual, 1.0/3, Compounding.Compounded, Frequency.EveryFourthMonth, 0.0600, 4), new InterestRateData(0.0500, Compounding.Compounded, Frequency.Quarterly, 0.25, Compounding.Simple, Frequency.Annual, 0.0500, 4), new InterestRateData(0.0600, Compounding.Simple, Frequency.Annual, 0.25, Compounding.Compounded, Frequency.Quarterly, 0.0600, 4), new InterestRateData(0.0700, Compounding.Compounded, Frequency.Bimonthly, 1.0/6, Compounding.Simple, Frequency.Annual, 0.0700, 4), new InterestRateData(0.0800, Compounding.Simple, Frequency.Annual, 1.0/6, Compounding.Compounded, Frequency.Bimonthly, 0.0800, 4), new InterestRateData(0.0900, Compounding.Compounded, Frequency.Monthly, 1.0/12, Compounding.Simple, Frequency.Annual, 0.0900, 4), new InterestRateData(0.1000, Compounding.Simple, Frequency.Annual, 1.0/12, Compounding.Compounded, Frequency.Monthly, 0.1000, 4), new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.25, Compounding.Simple, Frequency.Annual, 0.0300, 4), new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.25, Compounding.Simple, Frequency.Semiannual, 0.0300, 4), new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.25, Compounding.Simple, Frequency.Quarterly, 0.0300, 4), new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.50, Compounding.Simple, Frequency.Annual, 0.0300, 4), new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.50, Compounding.Simple, Frequency.Semiannual, 0.0300, 4), new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.75, Compounding.Compounded, Frequency.Semiannual, 0.0300, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.25, Compounding.SimpleThenCompounded, Frequency.Quarterly, 0.0400, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.25, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.0400, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.25, Compounding.SimpleThenCompounded, Frequency.Annual, 0.0400, 4), new InterestRateData(0.0400, Compounding.Compounded, Frequency.Quarterly, 0.50, Compounding.SimpleThenCompounded, Frequency.Quarterly, 0.0400, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.50, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.0400, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.50, Compounding.SimpleThenCompounded, Frequency.Annual, 0.0400, 4), new InterestRateData(0.0400, Compounding.Compounded, Frequency.Quarterly, 0.75, Compounding.SimpleThenCompounded, Frequency.Quarterly, 0.0400, 4), new InterestRateData(0.0400, Compounding.Compounded, Frequency.Semiannual, 0.75, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.0400, 4), new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.75, Compounding.SimpleThenCompounded, Frequency.Annual, 0.0400, 4) }; Rounding roundingPrecision; double r3; double r2; Date d1 = Date.Today; Date d2; InterestRate ir; InterestRate ir2; InterestRate ir3; InterestRate expectedIR; double compoundf; double error; double disc; for (int i = 0; i < cases.Length-1 ; i++) { ir = new InterestRate(cases[i].r, new Actual360(), cases[i].comp, cases[i].freq); d2 = d1 + new Period((int)(360 * cases[i].t + 0.5) ,TimeUnit.Days); roundingPrecision = new Rounding(cases[i].precision); // check that the compound factor is the inverse of the discount factor compoundf = ir.compoundFactor(d1, d2); disc = ir.discountFactor(d1, d2); error = Math.Abs(disc - 1.0 / compoundf); if (error > 1e-15) Assert.Fail(ir + " 1.0/compound_factor: " + 1.0 / compoundf); // check that the equivalent InterestRate with *same* daycounter, // compounding, and frequency is the *same* InterestRate ir2 = ir.equivalentRate(d1, d2, ir.dayCounter(), ir.compounding(), ir.frequency()); error = Math.Abs(ir.rate() - ir2.rate()); if (error > 1e-15) Assert.Fail("original interest rate: " + ir + " equivalent interest rate: " + ir2 + " rate error: " + error); if (ir.dayCounter() != ir2.dayCounter()) Assert.Fail("day counter error original interest rate: " + ir + " equivalent interest rate: " + ir2); if (ir.compounding() != ir2.compounding()) Assert.Fail("compounding error original interest rate: " + ir + " equivalent interest rate: " + ir2); if (ir.frequency() != ir2.frequency()) Assert.Fail("frequency error original interest rate: " + ir + " equivalent interest rate: " + ir2); // check that the equivalent rate with *same* daycounter, // compounding, and frequency is the *same* rate r2 = ir.equivalentRate(d1, d2, ir.dayCounter(), ir.compounding(), ir.frequency()).rate(); error = Math.Abs(ir.rate() - r2); if (error > 1e-15) Assert.Fail("original rate: " + ir + " equivalent rate: " + r2 + " error: " + error); // check that the equivalent InterestRate with *different* // compounding, and frequency is the *expected* InterestRate ir3 = ir.equivalentRate(d1, d2, ir.dayCounter(), cases[i].comp2, cases[i].freq2); expectedIR = new InterestRate(cases[i].expected, ir.dayCounter(), cases[i].comp2, cases[i].freq2); r3 = roundingPrecision.Round(ir3.rate()); error = Math.Abs(r3 - expectedIR.rate()); if (error > 1.0e-17) Assert.Fail("original interest rate: " + ir + " calculated equivalent interest rate: " + ir3 + " truncated equivalent rate: " + r3 + " expected equivalent interest rate: " + expectedIR + " rate error: " + error); if (ir3.dayCounter() != expectedIR.dayCounter()) Assert.Fail("day counter error original interest rate: " + ir3 + " equivalent interest rate: " + expectedIR); if (ir3.compounding() != expectedIR.compounding()) Assert.Fail("compounding error original interest rate: " + ir3 + " equivalent interest rate: " + expectedIR); if (ir3.frequency() != expectedIR.frequency()) Assert.Fail("frequency error original interest rate: " + ir3 + " equivalent interest rate: " + expectedIR); // check that the equivalent rate with *different* // compounding, and frequency is the *expected* rate r3 = ir.equivalentRate(d1, d2, ir.dayCounter(), cases[i].comp2, cases[i].freq2).rate(); r3 = roundingPrecision.Round(r3); error = Math.Abs(r3 - cases[i].expected); if (error > 1.0e-17) Assert.Fail("calculated equivalent rate: " + r3 + " expected equivalent rate: " + cases[i].expected + " error: " + error); } }
//! Cash-flow convexity /*! The convexity of a string of cash flows is defined as * \f[ * C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2} * \f] * where \f$ P \f$ is the present value of the cash flows according to the given IRR \f$ y \f$. */ public static double convexity(List <CashFlow> cashflows, InterestRate rate, Date settlementDate = null) { if (cashflows.Count == 0) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } DayCounter dayCounter = rate.dayCounter(); double P = 0; double d2Pdy2 = 0; double y = rate.rate(); int N = (int)rate.frequency(); foreach (CashFlow cashflow in cashflows.Where(cashflow => !cashflow.hasOccurred(settlementDate))) { double t = dayCounter.yearFraction(settlementDate, cashflow.date()); double c = cashflow.amount(); double B = rate.discountFactor(t); P += c * B; switch (rate.compounding()) { case Compounding.Simple: d2Pdy2 += c * 2.0 * B * B * B * t * t; break; case Compounding.Compounded: d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N)); break; case Compounding.Continuous: d2Pdy2 += c * B * t * t; break; case Compounding.SimpleThenCompounded: if (t <= 1.0 / N) { d2Pdy2 += c * 2.0 * B * B * B * t * t; } else { d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N)); } break; default: throw new ArgumentException("unknown compounding convention (" + rate.compounding() + ")"); } } // no cashflows if (P == 0) { return(0); } return(d2Pdy2 / P); }
public static double npv(List <CashFlow> leg, InterestRate y, bool includeSettlementDateFlows, Date settlementDate = null, Date npvDate = null) { if (leg == null || leg.empty()) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } double npv = 0.0; double discount = 1.0; Date lastDate = npvDate; Date refStartDate, refEndDate; for (int i = 0; i < leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) { continue; } Date couponDate = leg[i].date(); double amount = leg[i].amount(); Coupon coupon = leg[i] as Coupon; if (coupon != null) { refStartDate = coupon.accrualStartDate(); refEndDate = coupon.accrualEndDate(); } else { if (lastDate == npvDate) { // we don't have a previous coupon date, // so we fake it refStartDate = couponDate - new Period(1, TimeUnit.Years); } else { refStartDate = lastDate; } refEndDate = couponDate; } double b = y.discountFactor(lastDate, couponDate, refStartDate, refEndDate); discount *= b; lastDate = couponDate; npv += amount * discount; } return(npv); }
public static double modifiedDuration(Leg leg, InterestRate y, bool includeSettlementDateFlows, Date settlementDate, Date npvDate) { if (leg.empty()) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } double P = 0.0; double t = 0.0; double dPdy = 0.0; double r = y.rate(); int N = (int)y.frequency(); Date lastDate = npvDate; DayCounter dc = y.dayCounter(); for (int i = 0; i < leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) { continue; } double c = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { c = 0.0; } t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate); double B = y.discountFactor(t); P += c * B; switch (y.compounding()) { case Compounding.Simple: dPdy -= c * B * B * t; break; case Compounding.Compounded: dPdy -= c * t * B / (1 + r / N); break; case Compounding.Continuous: dPdy -= c * B * t; break; case Compounding.SimpleThenCompounded: if (t <= 1.0 / N) { dPdy -= c * B * B * t; } else { dPdy -= c * t * B / (1 + r / N); } break; default: Utils.QL_FAIL("unknown compounding convention (" + y.compounding() + ")"); break; } lastDate = leg[i].date(); } if (P.IsEqual(0.0)) // no cashflows { return(0.0); } return(-dPdy / P); // reverse derivative sign }
//! Cash-flow convexity public static double convexity(Leg leg, InterestRate yield, bool includeSettlementDateFlows, Date settlementDate = null, Date npvDate = null) { if (leg.empty()) { return(0.0); } if (settlementDate == null) { settlementDate = Settings.evaluationDate(); } if (npvDate == null) { npvDate = settlementDate; } DayCounter dc = yield.dayCounter(); double P = 0.0; double t = 0.0; double d2Pdy2 = 0.0; double r = yield.rate(); int N = (int)yield.frequency(); Date lastDate = npvDate; for (int i = 0; i < leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) { continue; } double c = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { c = 0.0; } t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate); double B = yield.discountFactor(t); P += c * B; switch (yield.compounding()) { case Compounding.Simple: d2Pdy2 += c * 2.0 * B * B * B * t * t; break; case Compounding.Compounded: d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + r / N) * (1 + r / N)); break; case Compounding.Continuous: d2Pdy2 += c * B * t * t; break; case Compounding.SimpleThenCompounded: if (t <= 1.0 / N) { d2Pdy2 += c * 2.0 * B * B * B * t * t; } else { d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + r / N) * (1 + r / N)); } break; default: Utils.QL_FAIL("unknown compounding convention (" + yield.compounding() + ")"); break; } lastDate = leg[i].date(); } if (P.IsEqual(0.0)) { // no cashflows return(0.0); } return(d2Pdy2 / P); }
public static double modifiedDuration(List<CashFlow> cashflows, InterestRate y, Date settlementDate) { if (cashflows.Count == 0) return 0.0; double P = 0.0; double dPdy = 0.0; double r = y.rate(); int N = (int)y.frequency(); DayCounter dc = y.dayCounter(); foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) { double t = dc.yearFraction(settlementDate, cf.date()); double c = cf.amount(); double B = y.discountFactor(t); P += c * B; switch (y.compounding()) { case Compounding.Simple: dPdy -= c * B * B * t; break; case Compounding.Compounded: dPdy -= c * t * B / (1 + r / N); break; case Compounding.Continuous: dPdy -= c * B * t; break; case Compounding.SimpleThenCompounded: if (t <= 1.0 / N) dPdy -= c * B * B * t; else dPdy -= c * t * B / (1 + r / N); break; default: throw new ArgumentException("unknown compounding convention (" + y.compounding() + ")"); } } if (P == 0.0) // no cashflows return 0.0; return -dPdy / P; // reverse derivative sign }
//! Cash-flow convexity /*! The convexity of a string of cash flows is defined as \f[ C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2} \f] where \f$ P \f$ is the present value of the cash flows according to the given IRR \f$ y \f$. */ public static double convexity(List<CashFlow> cashflows, InterestRate rate, Date settlementDate = null) { if (cashflows.Count == 0) return 0.0; if (settlementDate == null) settlementDate = Settings.evaluationDate(); DayCounter dayCounter = rate.dayCounter(); double P = 0; double d2Pdy2 = 0; double y = rate.rate(); int N = (int)rate.frequency(); foreach (CashFlow cashflow in cashflows.Where(cashflow => !cashflow.hasOccurred(settlementDate))) { double t = dayCounter.yearFraction(settlementDate, cashflow.date()); double c = cashflow.amount(); double B = rate.discountFactor(t); P += c * B; switch (rate.compounding()) { case Compounding.Simple: d2Pdy2 += c * 2.0 * B * B * B * t * t; break; case Compounding.Compounded: d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N)); break; case Compounding.Continuous: d2Pdy2 += c * B * t * t; break; case Compounding.SimpleThenCompounded: if (t <= 1.0 / N) d2Pdy2 += c * 2.0 * B * B * B * t * t; else d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N)); break; default: throw new ArgumentException("unknown compounding convention (" + rate.compounding() + ")"); } } // no cashflows if (P == 0) return 0; return d2Pdy2 / P; }
public static double simpleDuration(Leg leg,InterestRate y, bool includeSettlementDateFlows, Date settlementDate,Date npvDate) { if (leg.empty()) return 0.0; if (settlementDate == null) settlementDate = Settings.evaluationDate(); if (npvDate == null) npvDate = settlementDate; double P = 0.0; double dPdy = 0.0; double t = 0.0; Date lastDate = npvDate; Date refStartDate, refEndDate; DayCounter dc = y.dayCounter(); for (int i=0; i<leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) continue; double c = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { c = 0.0; } Date couponDate = leg[i].date(); Coupon coupon = leg[i] as Coupon; if (coupon != null) { refStartDate = coupon.refPeriodStart; refEndDate = coupon.refPeriodEnd; } else { if (lastDate == npvDate) { // we don't have a previous coupon date, // so we fake it refStartDate = couponDate - new Period(1,TimeUnit.Years); } else { refStartDate = lastDate; } refEndDate = couponDate; } t += dc.yearFraction(lastDate, couponDate, refStartDate, refEndDate); double B = y.discountFactor(t); P += c * B; dPdy += t * c * B; lastDate = couponDate; } if (P == 0.0) // no cashflows return 0.0; return dPdy/P; }
protected override double discountImpl(double t) { calculate(); return(rate_.discountFactor(t)); }
// NPV of the cash flows. // The NPV is the sum of the cash flows, each discounted // according to the given constant interest rate. The result // is affected by the choice of the interest-rate compounding // and the relative frequency and day counter. public static double npv(Leg leg, InterestRate yield, bool includeSettlementDateFlows, Date settlementDate = null, Date npvDate = null) { if (leg.empty()) return 0.0; if (settlementDate == null) settlementDate = Settings.evaluationDate(); if (npvDate == null) npvDate = settlementDate; double npv = 0.0; double discount = 1.0; Date lastDate = npvDate; Date refStartDate, refEndDate; for (int i=0; i<leg.Count; ++i) { if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows)) continue; Date couponDate = leg[i].date(); double amount = leg[i].amount(); if (leg[i].tradingExCoupon(settlementDate)) { amount = 0.0; } Coupon coupon = leg[i] as Coupon; if (coupon != null ) { refStartDate = coupon.refPeriodStart; refEndDate = coupon.refPeriodEnd; } else { if (lastDate == npvDate) { // we don't have a previous coupon date, // so we fake it refStartDate = couponDate - new Period(1,TimeUnit.Years); } else { refStartDate = lastDate; } refEndDate = couponDate; } double b = yield.discountFactor(lastDate, couponDate, refStartDate, refEndDate); discount *= b; lastDate = couponDate; npv += amount * discount; } return npv; }
public static double dirtyPriceFromYield(double faceAmount, List <CashFlow> cashflows, double yield, DayCounter dayCounter, Compounding compounding, Frequency frequency, Date settlement) { if (frequency == Frequency.NoFrequency || frequency == Frequency.Once) { frequency = Frequency.Annual; } InterestRate y = new InterestRate(yield, dayCounter, compounding, frequency); double price = 0.0; double discount = 1.0; Date lastDate = null; for (int i = 0; i < cashflows.Count - 1; ++i) { if (cashflows[i].hasOccurred(settlement)) { continue; } Date couponDate = cashflows[i].Date; double amount = cashflows[i].amount(); if (lastDate == null) { // first not-expired coupon if (i > 0) { lastDate = cashflows[i - 1].Date; } else { if (cashflows[i].GetType().IsSubclassOf(typeof(Coupon))) { lastDate = ((Coupon)cashflows[i]).accrualStartDate(); } else { lastDate = couponDate - new Period(1, TimeUnit.Years); } } discount *= y.discountFactor(settlement, couponDate, lastDate, couponDate); } else { discount *= y.discountFactor(lastDate, couponDate); } lastDate = couponDate; price += amount * discount; } CashFlow redemption = cashflows.Last(); if (!redemption.hasOccurred(settlement)) { Date redemptionDate = redemption.Date; double amount = redemption.amount(); if (lastDate == null) { // no coupons lastDate = redemptionDate - new Period(1, TimeUnit.Years); discount *= y.discountFactor(settlement, redemptionDate, lastDate, redemptionDate); } else { discount *= y.discountFactor(lastDate, redemptionDate); } price += amount * discount; } return(price / faceAmount * 100.0); }