Skip to content

Commit

Permalink
Merge pull request amaggiulli#213 from amaggiulli/feature/callable.oas
Browse files Browse the repository at this point in the history
Feature/callable.oas
  • Loading branch information
amaggiulli authored Jul 25, 2018
2 parents 668dcdf + eb4b917 commit 0f24982
Show file tree
Hide file tree
Showing 3 changed files with 847 additions and 169 deletions.
149 changes: 52 additions & 97 deletions src/QLNet/Cashflows/CashFlows.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ public static double simpleDuration(Leg leg, InterestRate y, bool includeSettlem
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)
Expand All @@ -102,34 +101,13 @@ public static double simpleDuration(Leg leg, InterestRate y, bool includeSettlem
{
c = 0.0;
}
Date couponDate = leg[i].date();
Coupon coupon = leg[i] 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 = couponDate - new Period(1, TimeUnit.Years);
}
else
{
refStartDate = lastDate;
}
refEndDate = couponDate;
}

t += dc.yearFraction(lastDate, couponDate, refStartDate, refEndDate);
t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate);
double B = y.discountFactor(t);
P += c * B;
dPdy += t * c * B;

lastDate = couponDate;
lastDate = leg[i].date();
}

if (P.IsEqual(0.0)) // no cashflows
Expand All @@ -154,7 +132,6 @@ public static double modifiedDuration(Leg leg, InterestRate y, bool includeSettl
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)
Expand All @@ -167,29 +144,8 @@ public static double modifiedDuration(Leg leg, InterestRate y, bool includeSettl
{
c = 0.0;
}
Date couponDate = leg[i].date();
Coupon coupon = leg[i] 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 = couponDate - new Period(1, TimeUnit.Years);
}
else
{
refStartDate = lastDate;
}
refEndDate = couponDate;
}

t += dc.yearFraction(lastDate, couponDate, refStartDate, refEndDate);
t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate);

double B = y.discountFactor(t);
P += c * B;
Expand All @@ -214,7 +170,7 @@ public static double modifiedDuration(Leg leg, InterestRate y, bool includeSettl
Utils.QL_FAIL("unknown compounding convention (" + y.compounding() + ")");
break;
}
lastDate = couponDate;
lastDate = leg[i].date();
}

if (P.IsEqual(0.0)) // no cashflows
Expand All @@ -231,6 +187,47 @@ public static double macaulayDuration(Leg leg, InterestRate y, bool includeSettl
modifiedDuration(leg, y, includeSettlementDateFlows, settlementDate, npvDate);
}

// 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);
}
}


#endregion

#region Helper Classes
Expand Down Expand Up @@ -660,6 +657,7 @@ public static double accruedAmount(Leg leg, bool includeSettlementDateFlows, Dat
CashFlow cf = nextCashFlow(leg, includeSettlementDateFlows, settlementDate);
if (cf == null)
return 0;

Date paymentDate = cf.date();
double result = 0.0;

Expand Down Expand Up @@ -815,43 +813,22 @@ public static double npv(Leg leg, InterestRate yield, bool includeSettlementDate
double npv = 0.0;
double discount = 1.0;
Date lastDate = npvDate;
Date refStartDate, refEndDate;
DayCounter dc = yield.dayCounter();

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.referencePeriodStart;
refEndDate = coupon.referencePeriodEnd;
}
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);
double b = yield.discountFactor(getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate));
discount *= b;
lastDate = couponDate;
lastDate = leg[i].date();

npv += amount * discount;
}
Expand Down Expand Up @@ -1008,7 +985,7 @@ public static double convexity(Leg leg, InterestRate yield, bool includeSettleme
double r = yield.rate();
int N = (int)yield.frequency();
Date lastDate = npvDate;
Date refStartDate, refEndDate;


for (int i = 0; i < leg.Count; ++i)
{
Expand All @@ -1020,30 +997,8 @@ public static double convexity(Leg leg, InterestRate yield, bool includeSettleme
{
c = 0.0;
}
Date couponDate = leg[i].date();
Coupon coupon = leg[i] 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 = couponDate - new Period(1, TimeUnit.Years);
}
else
{
refStartDate = lastDate;
}
refEndDate = couponDate;
}

t += dc.yearFraction(lastDate, couponDate,
refStartDate, refEndDate);
t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate);

double B = yield.discountFactor(t);
P += c * B;
Expand All @@ -1068,7 +1023,7 @@ public static double convexity(Leg leg, InterestRate yield, bool includeSettleme
Utils.QL_FAIL("unknown compounding convention (" + yield.compounding() + ")");
break;
}
lastDate = couponDate;
lastDate = leg[i].date();
}

if (P.IsEqual(0.0))
Expand Down
Loading

0 comments on commit 0f24982

Please sign in to comment.