public double Pv(IrCurve discountCurve, IrCurve forecastCurve, bool updateState, bool updateDF, bool updateEstimate) { var totalPV = 0.0; if (FlowScheduleFra.Flows.Count != 1) { throw new InvalidOperationException("FRA should have a sinlge flow"); } var flow = FlowScheduleFra.Flows.Single(); var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; double FV, DF; if (updateEstimate) { var RateFix = flow.FixedRateOrMargin; var RateFloat = forecastCurve.GetForwardRate(s, e, RateType.Linear, Basis); var YF = flow.NotionalByYearFraction; FV = ((RateFloat - RateFix) * YF) / (1 + RateFloat * YF) * flow.Notional; FV *= (PayRec == SwapPayReceiveType.Payer) ? 1.0 : -1.0; } else { FV = flow.Fv; } if (updateDF) { DF = discountCurve.Pv(1.0, flow.SettleDate); } else { DF = flow.Pv / flow.Fv; } totalPV = discountCurve.Pv(FV, flow.SettleDate); if (!updateState) { return(totalPV); } flow.Fv = FV; flow.Pv = totalPV; return(totalPV); }
public static double PV(this CashFlowSchedule schedule, IrCurve discountCurve, IrCurve forecastCurve, bool updateState, bool updateDf, bool updateEstimate, DayCountBasis basisFloat, DateTime?filterDate) { double totalPv = 0; for (var i = 0; i < schedule.Flows.Count; i++) { var flow = schedule.Flows[i]; if (filterDate.HasValue && flow.SettleDate < filterDate.Value) { continue; } double fv, pv, df; switch (flow.FlowType) { case FlowType.FixedRate: { if (updateState) { var rateLin = flow.FixedRateOrMargin; var yf = flow.YearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } break; } case FlowType.FloatRate: { if (updateEstimate) { var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; var rateLin = forecastCurve.GetForwardRate(s, e, RateType.Linear, basisFloat); rateLin += flow.FixedRateOrMargin; var yf = flow.YearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } break; } case FlowType.FixedAmount: { fv = flow.Notional; if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } break; } } } return(totalPv); }
private double PV(IrCurve discountCurve, IrCurve forecastCurve, bool updateState, bool updateDf, bool updateEstimate) { double totalPv = 0; for (var i = 0; i < FlowScheduleFixed.Flows.Count; i++) { var flow = FlowScheduleFixed.Flows[i]; double fv, df; if (updateState) { var rateLin = flow.FixedRateOrMargin; var yf = flow.NotionalByYearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } var pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } } for (var i = 0; i < FlowScheduleFloat.Flows.Count; i++) { var flow = FlowScheduleFloat.Flows[i]; double fv, df; if (updateEstimate) { var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; var rateLin = forecastCurve.GetForwardRate(s, e, RateType.Linear, BasisFloat); var yf = flow.NotionalByYearFraction; fv = rateLin * yf * flow.Notional; } else { fv = flow.Fv; } if (updateDf) { df = discountCurve.Pv(1, flow.SettleDate); } else { df = flow.Fv == flow.Pv ? 1.0 : flow.Pv / flow.Fv; } var pv = fv * df; totalPv += pv; if (updateState) { flow.Fv = fv; flow.Pv = pv; } } return(totalPv); }
public double Pv(IrCurve discountCurve, IrCurve forecastCurvePay, IrCurve forecastCurveRec, bool updateState, bool updateDF, bool updatePayEst, bool updateRecEst) { double totalPV = 0; for (var i = 0; i < FlowSchedulePay.Flows.Count; i++) { double FV, DF; var flow = FlowSchedulePay.Flows[i]; if (updatePayEst) { var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; var RateLin = forecastCurvePay.GetForwardRate(s, e, RateType.Linear, BasisPay) + flow.FixedRateOrMargin; var YF = flow.NotionalByYearFraction; FV = RateLin * YF * flow.Notional; } else { FV = flow.Fv; } if (updateDF) { DF = discountCurve.Pv(1, flow.SettleDate); } else { DF = (flow.Fv == flow.Pv) ? 1.0 : flow.Pv / flow.Fv; } var PV = DF * FV; if (updateState) { flow.Fv = FV; flow.Pv = PV; } totalPV += PV; } for (var i = 0; i < FlowScheduleRec.Flows.Count; i++) { double FV, DF; var flow = FlowScheduleRec.Flows[i]; if (updateRecEst) { var s = flow.AccrualPeriodStart; var e = flow.AccrualPeriodEnd; var RateLin = forecastCurveRec.GetForwardRate(s, e, RateType.Linear, BasisRec) + flow.FixedRateOrMargin; var YF = flow.NotionalByYearFraction; FV = RateLin * YF * flow.Notional; } else { FV = flow.Fv; } if (updateDF) { DF = discountCurve.Pv(1, flow.SettleDate); } else { DF = (flow.Fv == flow.Pv) ? 1.0 : flow.Pv / flow.Fv; } var PV = DF * FV; if (updateState) { flow.Fv = FV; flow.Pv = PV; } totalPV += PV; } return(totalPV); }