protected override Task <int> Execute() { OpenCoverReport.Execute(CoverageLoadedFileOption.GetValue(), OpenCoverOutputOption.GetValue(), ThresholdOption.GetValue()); var result = CalcUtils.IsHigherThanThreshold(CoverageLoadedFileOption.GetValue(), ThresholdOption.GetValue()); return(Task.FromResult(result)); }
/// <summary> /// Build matrix A and B for the current time step, for the explicit Euler /// scheme A = A^i+1 and B = B^i+1 and for other A = A^i and B = B^i. /// </summary> protected virtual void PrepareForTimeStep(int scenario, Mesh mesh, double dt, int indexTime, Vector[] shortRates, Vector[] dividendRates, Vector[][] volSurfaces, Vector[][] hazardRateSurfaces, double recoveryValue, double conversionRatio, double alpha) { double k = mesh.StepSizes[0]; double h; double rate = shortRates[indexTime][scenario]; double hPlusk = 0; double kMinush = 0; double hazard; double volSquared; double oneMinusAlpha = 1 - alpha; double conversionTimesAlpha = conversionRatio * alpha; double dividend = dividendRates[indexTime][scenario]; // borders are traited separately for (int j = 1; j < fEndIndex; ++j) { h = mesh.StepSizes[j]; hPlusk = h + k; kMinush = k - h; volSquared = CalcUtils.Sqr(volSurfaces[indexTime][j][scenario]); hazard = hazardRateSurfaces[indexTime][j][scenario]; double coefficientFirstDeriv = rate - dividend + hazard * oneMinusAlpha; fA0[j] = (-h * coefficientFirstDeriv + volSquared * (1 + h / 2)) / (k * hPlusk); fA1[j] = -rate - hazard - kMinush / (k * h) * coefficientFirstDeriv - (2 + kMinush) / (2 * h * k) * volSquared; fA2[j] = (k * coefficientFirstDeriv + volSquared * (1 - k / 2)) / (h * hPlusk); fB[j] = hazard * Math.Max(conversionTimesAlpha * mesh.ExpSpacePoints[j], recoveryValue); k = h; } }
/// <summary> /// Checks a sufficient condition for yStar to be the unique solution of F(y) = 0. /// </summary> private void IsSolutionUnique(Vector isYStarUnique, Vector yStar, Vector[] coefficient, Vector[] coupon, Vector[] stdDev) { using (var cache = Vector.CacheLike(yStar)) { Vector sum = cache.GetClear(); Vector haveNegative = cache.GetClear(); Vector positiveValue = cache.Get(); int count = coefficient.Length; // C_0 * f_0 (y*) - this term is negative. sum.Assign(CalcUtils.SafeExpMultiply(-stdDev[0] * yStar, coupon[0] * coefficient[0])); VectorEngine.For(1, count, LoopDirection.Backwards, i => { haveNegative.AssignConditional(coupon[i] <= -CalcUtils.TINY, 1.0, haveNegative); positiveValue.Assign(CalcUtils.SafeExpMultiply(-stdDev[i] * yStar, coupon[i] * coefficient[i] * haveNegative)); positiveValue.AssignMax(positiveValue, 0.0); sum.Add(positiveValue); return(LoopAction.Continue); }); isYStarUnique.AssignConditional(sum <= 0.0, 1.0, 0.0); } }
/// <summary> /// Generate CTD dates and set CTD coupon rate and conversion factor. /// </summary> protected void GenerateCTD(double baseDate, double issueDate, double maturityDate, double couponInterval, double firstCouponDate, double penultimateCouponDate, DayCount dayCount, IHolidayCalendar calendar, double couponRate, double conversionFactor) { if (conversionFactor <= 0.0) { return; // No CTD details or details invalid } BondFutureOption deal = (BondFutureOption)fDeal; // Validation of settlement date not done for CTD details on price factor if (deal.Settlement_Date >= maturityDate) { throw new AnalyticsException("Settlement date must be before cheapest-to-deliver maturity date."); } DateGenerationResults dateGenerationResults = deal.GetDateGenerationResults(issueDate, maturityDate, couponInterval, firstCouponDate, penultimateCouponDate, dayCount, calendar); fPayDates = dateGenerationResults.PayDates; fAccruals = dateGenerationResults.AccrualYearFractions; fIssueDate = issueDate; fMaturityDate = maturityDate; fCouponInterval = couponInterval; fCouponRate = couponRate; fConversionFactor = conversionFactor; fAccrual = PricingFunctions.AccruedInterest(deal.Settlement_Date, fIssueDate, fPayDates, fAccruals, fCouponRate, 1.0, null); double strike = PriceTransform(deal.Strike); double tSettle = CalcUtils.DaysToYears(deal.Settlement_Date - baseDate); double tMaturity = CalcUtils.DaysToYears(fMaturityDate - baseDate); fStrikeYield = PricingFunctions.BondYieldFromPrice(tSettle, tMaturity, couponRate, couponInterval, strike); }
protected override Task <int> Execute() { XmlReport.Execute(_coverageLoadedFileOption.Result, _nCoverOutputOption.Value, _thresholdOption.Value); var result = CalcUtils.IsHigherThanThreshold(_coverageLoadedFileOption.Result, _thresholdOption.Value); return(Task.FromResult(result)); }
/// <summary> /// Returns the payment amount on settlement date based on the cashflowlist. /// </summary> /// <remarks> /// The payment amount on settlement date will be either the dirty price of the bond or the clean price of the bond plus /// the accrued interest (two cashflows). Note that for a long position in a bond forward, this value is negative /// (indicating outgoing cashflow). /// </remarks> protected virtual void GetSettlementAmount(Vector amount, double valueDate, double baseDate, IInflationRate inflationRate, IPriceIndexVolatility indexVolatility) { amount.Clear(); using (var cache = Vector.CacheLike(amount)) { var deal = (IInflationCashflowListDeal)Deal; var cashflows = deal.GetCashflows(); Vector settlementPay = cache.Get(); for (int i = 0; i < cashflows.Count(); ++i) { if (cashflows.GetCashflow(i).Payment_Date < deal.Settlement_Date) { continue; } else if (cashflows.GetCashflow(i).Payment_Date == deal.Settlement_Date) { cashflows.GetCashflow(i).ExpectedAmount(settlementPay, CalcUtils.DaysToYears(valueDate - baseDate), inflationRate, indexVolatility, IntraValuationDiagnosticsWriterFactory.GetOrCreate(IntraValuationDiagnosticsLevel.None)); amount.Add(settlementPay); } else { break; } } } }
/// <inheritdoc /> public override void HeadNodeInitialize(PriceFactorList factors, BaseTimeGrid baseTimes, RequiredResults requiredResults) { base.HeadNodeInitialize(factors, baseTimes, requiredResults); BaseCliquetOption deal = (BaseCliquetOption)fDeal; DateList accrualDates = CashflowGeneration.GenerateStripOfDates(deal.Effective_Date, deal.Maturity_Date, deal.Frequency, deal.GetHolidayCalendar()); fTimes = new double[accrualDates.Count]; for (int i = 0; i < accrualDates.Count; ++i) { fTimes[i] = CalcUtils.DaysToYears(accrualDates[i] - factors.BaseDate); } // Get the asset price from the deal helper var dealHelper = (BaseAssetFxDealHelper)deal.GetDealHelper(); IAssetPrice assetPrice = dealHelper.GetAssetPrice(factors); fKnownPrices = deal.GetKnownPrices(accrualDates, factors, assetPrice); // Add expiry dates to valuation time grid. if (accrualDates.Count > 1) { DateList expiryDates = new DateList(accrualDates); expiryDates.RemoveAt(0); fT.AddPayDates(expiryDates, requiredResults.CashRequired()); } }
/// <summary> /// Gets the discount rate used in the option valuation formula. /// </summary> protected override void GetDiscountRate(Vector r, IInterestRate discountRate, double t, double tPay) { Double date = fBaseDate + CalcUtils.YearsToDays(t); Double payDate = fBaseDate + CalcUtils.YearsToDays(tPay); r.Assign(VectorMath.Log(discountRate.Get(t, tPay)) / CalcUtils.DayCountFraction(payDate, date, DayCount.BUS_252, ((IDIOptionDeal)Deal).Calendar())); }
/// <inheritdoc/> public override void Validate(ICalendarData calendar, ErrorList errors) { base.Validate(calendar, errors); if (Principal < 0.0) { AddToErrors(errors, ErrorLevel.Error, "Principal cannot be negative."); } CalcUtils.ValidateDates(errors, Accrual_Start_Date, Accrual_End_Date, false, "accrual start", "accrual end"); CalcUtils.ValidateDates(errors, Reset_Date, Rate_Start_Date, false, "reset", "rate start"); CalcUtils.ValidateDates(errors, Reset_Date, Payment_Date, false, "reset", "payment"); if (Rate_1_End_Date > 0.0) { CalcUtils.ValidateDates(errors, Rate_Start_Date, Rate_1_End_Date, true, "rate start", "first rate end"); } if (Rate_2_End_Date > 0.0) { CalcUtils.ValidateDates(errors, Rate_Start_Date, Rate_2_End_Date, true, "rate start", "second rate end"); } if (!Rate_1_Tenor.IsPositiveOrZero()) { AddToErrors(errors, ErrorLevel.Error, "First rate tenor must be positive or zero."); } if (!Rate_2_Tenor.IsPositiveOrZero()) { AddToErrors(errors, ErrorLevel.Error, "Second rate tenor must be positive or zero."); } }
/// <summary> /// Calculate forward price, discount factor and volatility. /// </summary> protected override void PriceAndVolatility(double baseDate, double valueDate, Vector forwardPrice, Vector discountFactor, Vector volatility) { CommodityFutureOption deal = (CommodityFutureOption)Deal; double t = CalcUtils.DaysToYears(valueDate - baseDate); double tSettle = CalcUtils.DaysToYears(deal.Settlement_Date - baseDate); // Get spot price in contract currency forwardPrice.Assign(fCommodityPrice.Get(t) / fFxRate.Get(t)); if (volatility != null) { double tExpiry = CalcUtils.DaysToYears(deal.Expiry_Date - baseDate); if (tExpiry > t) { // temporary use of discountFactor vector to store strike discountFactor.Assign(deal.Strike); // Get volatility using spot price and strike volatility.Assign(fCommodityPriceVol.Get(t, forwardPrice, discountFactor, tExpiry)); } else { volatility.Clear(); } } fDiscountRate.GetValue(discountFactor, t, tSettle); // Get forward factor and complete calculation of forward price forwardPrice.MultiplyBy(fCommodityPrice.ForwardFactor(t, tSettle, fFxRate)); }
/// <summary> /// Prepare for valuation anything that is not dependent upon the scenario. /// </summary> public override void HeadNodeInitialize(PriceFactorList factors, BaseTimeGrid baseTimes, RequiredResults resultsRequired) { base.HeadNodeInitialize(factors, baseTimes, resultsRequired); var deal = (AverageForwardExplicitDealBase)Deal; fScale = (deal.Buy_Sell == BuySell.Buy ? +1 : -1) * deal.GetUnits(); fSamplingTimes = new double[deal.Sampling_Data.Count]; fSamplingTimesPlusTenor = new double[deal.Sampling_Data.Count]; int index = 0; Term tenorAsTerm = Period.ValueToTerm(deal.Tenor); // Loop over sampling dates and generate relevant sampling times. foreach (SamplingEntryAsset sample in deal.Sampling_Data) { double endDate = DateAdjuster.Add(sample.Date, tenorAsTerm, deal.GetHolidayCalendar()); double sampleTime = CalcUtils.DaysToYears(sample.Date - factors.BaseDate); // Store the start time and the end time. fSamplingTimes[index] = sampleTime; // Discount Factor and Forward Factor times are in Act365. fSamplingTimesPlusTenor[index] = CalcUtils.DaysToYears(endDate - factors.BaseDate); index++; } // Create a deep copy of the sampling data list and replace missing values with data from the rate fixings file var assetPrice = ((BaseAssetFxDealHelper)deal.GetDealHelper()).GetAssetPrice(factors); string assetCurrency = fPayoffType == PayoffType.Compo ? fPayoffCurrency : fCurrency; fSamplingData = deal.Sampling_Data.FillMissingDataFromFixings(factors.RateFixings, factors, assetPrice, assetCurrency, deal, "calculation of asset average"); // Add to valuation time grid fT.AddPayDate(deal.Maturity_Date, resultsRequired.CashRequired()); }
/// <summary> /// Get carry rate from forward factor. /// </summary> protected override void GetCarryRate(Vector b, Vector forwardFactor, double t, double tPay) { Double date = fBaseDate + CalcUtils.YearsToDays(t); Double payDate = fBaseDate + CalcUtils.YearsToDays(tPay); b.Assign(VectorMath.Log(forwardFactor) / CalcUtils.DayCountFraction(date, payDate, DayCount.BUS_252, ((IDIOptionDeal)Deal).Calendar())); }
/// <summary> /// Calculate valuation profiles. /// </summary> public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes) { PreValue(factors); TimeGridIterator tgi = new TimeGridIterator(fT); PVProfiles result = valuationResults.Profile; CashAccumulators cashAccumulators = valuationResults.Cash; FixedCashflowBaseDeal deal = (FixedCashflowBaseDeal)fDeal; double payDate = deal.Payment_Date; double tPay = CalcUtils.DaysToYears(payDate - factors.BaseDate); VectorEngine.For(tgi, () => { if (tgi.Date == payDate) { result.AppendVector(tgi.Date, fFxRate.Get(tgi.T) * fAmount); } else { result.AppendVector(tgi.Date, fFxRate.Get(tgi.T) * fDiscountRate.Get(tgi.T, tPay) * fAmount); } }); if (!cashAccumulators.Ignore && factors.BaseDate <= payDate && payDate <= fT.fHorizon) { cashAccumulators.Accumulate(fFxRate, payDate, fAmount); } result.Complete(fT); }
private void Calc_LSR() { tables.CalcsHydro.AddColumnIfNotExist( tables.BazaInfoHydro.Column("OI_METEO")); CalcUtils.CalcMeteoAvg(tables.CalcsMeteo.GetRows(), "LR_Used", tables.CalcsHydro, "LSR", CellMapper.ZeroOrGreaterInt, tables.Result); }
/// <summary> /// Validate deal properties. /// </summary> public override void Validate(ICalendarData calendar, ErrorList errors) { base.Validate(calendar, errors); CalcUtils.ValidateDates(errors, Effective_Date, Maturity_Date, false); Amortisation.Validate(errors); }
private void Calc_kWSr() { tables.CalcsHydro.AddColumnIfNotExist( tables.BazaInfoHydro.Column("OI_METEO")); CalcUtils.CalcMeteoAvg(tables.CalcsMeteo.GetRows(), "kW", tables.CalcsHydro, "kWSR", CellMapper.Rounder2, tables.Result); }
/// <summary> /// Calculate forward price. /// </summary> protected override void ForwardPrice(double baseDate, double valueDate, Vector forwardPrice) { CommodityFuture deal = (CommodityFuture)Deal; double t = CalcUtils.DaysToYears(valueDate - baseDate); double tSettle = CalcUtils.DaysToYears(deal.Settlement_Date - baseDate); forwardPrice.Assign((fCommodityPrice.ForwardFactor(t, tSettle, fFxRate) * fCommodityPrice.Get(t)) / fFxRate.Get(t)); }
private void Calc_Tn_Hydro(int n) { tables.CalcsHydro.AddColumnIfNotExist( tables.BazaInfoHydro.Column("OI_METEO")); var columnName_T = "T" + n; CalcUtils.CalcMeteoAvg(tables.CalcsMeteo.GetRows(), columnName_T, tables.CalcsHydro, columnName_T, CellMapper.Rounder2); }
/// <summary> /// Modify the pv and cash taking the date of default into account. /// </summary> protected void GetDefaultValue(double baseDate, double valueDate, Vector defaultDate, IInflationRate inflationRate, IPriceIndexVolatility indexVolatility, IInterestRate repo, Vector pv, Vector cash) { IInflationCashflowListDeal deal = (IInflationCashflowListDeal)Deal; double settlementDate = deal.Settlement_Date; double t = CalcUtils.DaysToYears(valueDate - baseDate); double buySellSign = deal.Buy_Sell == BuySell.Buy ? 1.0 : -1.0; if (repo == null) { repo = fDiscountRate; } using (var cache = Vector.CacheLike(pv)) { Vector principal = cache.Get(); GetCurrentExposure(principal, t, valueDate, inflationRate); // Approximation: recover only principal, neglecting accrued interest. Vector recovery = cache.Get(buySellSign * principal * fRecoveryRate.Get(t)); if (valueDate <= settlementDate) { // Set the pv to (recovery - |settlementAmount|) * df when defaultDate <= valueDate <= settlementDate. // Set cash to (recovery - |settlementAmount|) when defaultDate <= valueDate = settlementDate (cash is always zero before settlementDate). // Note that GetSettlementAmount(...) will return a negative value for a long bond position, indicating an outgoing cashflow. double tSettle = CalcUtils.DaysToYears(settlementDate - baseDate); Vector settlementAmount = cache.Get(); GetSettlementAmount(settlementAmount, valueDate, baseDate, inflationRate, indexVolatility); settlementAmount.MultiplyBy(buySellSign); Vector hasDefaulted = cache.Get(defaultDate <= valueDate); pv.AssignConditional(hasDefaulted, repo.Get(t, tSettle) * (recovery + settlementAmount), pv); if (cash != null && valueDate == settlementDate) { cash.AssignConditional(hasDefaulted, pv, cash); } } else { // after settlement date recovery.MultiplyBy(defaultDate >= valueDate); // set to zero if already defaulted Vector notDefaulted = cache.Get(defaultDate > valueDate); pv.AssignConditional(notDefaulted, pv, recovery); if (cash != null) { cash.AssignConditional(notDefaulted, cash, recovery); } } } }
private void Calc_SSR() { tables.CalcsHydro.AddColumnIfNotExist( tables.BazaInfoHydro.Column("OI_METEO")); var meteoRows = tables.OperInfoMeteo.GetRows(); var columnName_S = Calc_SSR_GetColumnName_S(); CalcUtils.CalcMeteoAvg(meteoRows, columnName_S, tables.CalcsHydro, "SSR", CellMapper.RounderInt, tables.Result); }
/// <summary> /// Prepare for valuation anything that will be shared between scenarios. /// </summary> public override void PreCloneInitialize(PriceFactorList factors, BaseTimeGrid baseTimes, RequiredResults requiredResults) { base.PreCloneInitialize(factors, baseTimes, requiredResults); FixedInterestCashflowDeal deal = (FixedInterestCashflowDeal)fDeal; int sign = (deal.Buy_Sell == BuySell.Buy ? +1 : -1); double accrualDayCountFraction = CalcUtils.DayCountFraction(deal.Accrual_Start_Date, deal.Accrual_End_Date, deal.Accrual_Day_Count, deal.GetHolidayCalendar()); fAmount = sign * deal.Notional * accrualDayCountFraction * deal.Fixed_Rate; }
/// <summary> /// Validate deal properties. /// </summary> public override void Validate(ICalendarData calendar, ErrorList errors) { base.Validate(calendar, errors); CalcUtils.ValidateDates(errors, Effective_Date, Maturity_Date, true); if (Moneyness <= 0.0) { AddToErrors(errors, "Moneyness must be greater than zero"); } }
/// <summary> /// Calculate vector valuation profile and vector realised cash profile. /// </summary> public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes) { PreValue(factors); CalcUtils.CreateDealProfilesIfRequired(valuationResults, fItems, factors); double paySign = fSwaptionDeal.Payer_Receiver == PayerReceiver.Payer ? +1 : -1; double buySign = fSwaptionDeal.Buy_Sell == BuySell.Buy ? +1 : -1; bool isCashSettled = fSwaptionDeal.Settlement_Style == SettlementType.Cash; bool isPhysicallySettled = fSwaptionDeal.Settlement_Style == SettlementType.Physical; bool cashRequired = !valuationResults.Cash.Ignore; TimeGridIterator tgi = new TimeGridIterator(fT); PVProfiles result = valuationResults.Profile; using (IntraValuationDiagnosticsHelper.StartDeal(fIntraValuationDiagnosticsWriter, Deal)) { using (var outerCache = Vector.Cache(factors.NumScenarios)) { Vector pv = outerCache.Get(); Vector exerciseWeight = outerCache.GetClear(); Vector cash = cashRequired ? outerCache.GetClear() : null; // For a cash settled swaption, Settlement amount to be paid on Settlement Date. Vector settlementCash = isCashSettled ? outerCache.GetClear() : null; VectorEngine.For(tgi, () => { // Work out the PV if (tgi.Date < fSwaptionDeal.Option_Expiry_Date) { ValueBeforeExpiry(pv, factors, isCashSettled, tgi); } else { ValueOnOrAfterExpiry(pv, exerciseWeight, settlementCash, cash, factors, isCashSettled, isPhysicallySettled, cashRequired, tgi, paySign); } result.AppendVector(tgi.Date, buySign * pv * fFxRate.Get(tgi.T)); if (cashRequired) { valuationResults.Cash.Accumulate(fFxRate, tgi.Date, buySign * cash); } }); } result.Complete(fT); } }
private void ValueOnOrAfterExpiry(Vector pv, Vector exerciseWeight, Vector settlementCash, Vector cash, PriceFactorList factors, bool isCashSettled, bool isPhysicallySettled, bool cashRequired, TimeGridIterator tgi, double paySign) { double baseDate = factors.BaseDate; double tSettlement = isCashSettled ? CalcUtils.DaysToYears(fSwaptionDeal.Settlement_Date - baseDate) : 0.0; using (var cache = Vector.Cache(factors.NumScenarios)) { Vector fixedPv = cache.Get(); Vector fixedCash = cache.Get(); Vector floatPv = cache.Get(); Vector floatCash = cache.Get(); ValueFixedAndFloatingLegs(tgi, fixedPv, fixedCash, baseDate, floatPv, floatCash); if (tgi.Date == fSwaptionDeal.Option_Expiry_Date) { pv.Assign(VectorMath.Max(0.0, paySign * (floatPv - fixedPv))); if (isPhysicallySettled) { exerciseWeight.Assign(pv > 0.0); // 1 if exercised and otherwise 0 } else if (isCashSettled) { settlementCash.Assign(pv); // Records cash settlement amount on Option Expiry Date. pv.Assign(settlementCash * fDiscountRate.Get(tgi.T, tSettlement)); // Factor in time value of money due to settlement delay. } } else { // After expiry if (isPhysicallySettled) { pv.Assign(paySign * (floatPv - fixedPv) * exerciseWeight); if (cashRequired) { cash.Assign(paySign * (floatCash - fixedCash) * exerciseWeight); } } else if (isCashSettled) { pv.Assign(settlementCash * fDiscountRate.Get(tgi.T, tSettlement)); if (tgi.Date == fSwaptionDeal.Settlement_Date && cashRequired) { cash.Assign(settlementCash); } } } } }
/// <summary> /// Value the swaption before expiry using a Jamshidian style decomposition to value the swaption analytically. /// Checks for the validity of the decomposition and falls back on numerical integration when necessary. /// </summary> private void ValueBeforeExpiry(Vector pv, PriceFactorList factors, bool isCashSettled, TimeGridIterator tgi) { double baseDate = factors.BaseDate; double tExpiry = fSwaptionDeal.GetTimeToExpiry(baseDate); double tValue = CalcUtils.DaysToYears(tgi.Date - baseDate); int count = fDates.Count; using (var cache = Vector.Cache(factors.NumScenarios)) { Vector dfTExpiry = cache.Get(); Vector yStar = cache.Get(); Vector isUnique = cache.Get(); Vector analyticPv = cache.GetClear(); Vector numericalPv = cache.GetClear(); // Theory guide mappings for the vector arrays are: // df <=> D(0, T_i) // coupons <=> C_i // stdDev <=> v_i // coefficient <=> D(0, T_i)/D(0, T) exp (- v_i^2 / 2) Vector[] df = new Vector[count]; Vector[] coupons = new Vector[count]; Vector[] stdDev = new Vector[count]; Vector[] coefficient = new Vector[count]; CreateVectorArrays(df, cache, coupons, coefficient, stdDev); fDiscountRate.GetValue(dfTExpiry, tValue, tExpiry); GetSwapQuantities(coupons, stdDev, coefficient, df, tValue, tExpiry, baseDate, dfTExpiry); // Find the value of y which makes the underlying swap value to 0, used for Jamshidian style decomposition SolveForYStar(yStar, coefficient, coupons, stdDev); // Calculate the scenarios in which the yStar values are guaranteed unique IsSolutionUnique(isUnique, yStar, coefficient, coupons, stdDev); CalculateAnalyticPV(analyticPv, isUnique, stdDev, yStar, coefficient, coupons, dfTExpiry, df); CalculateNumericalPV(numericalPv, isUnique, stdDev, coefficient, coupons); pv.AssignConditional(isUnique >= 1.0, analyticPv, numericalPv); if (isCashSettled) { double tSettlement = CalcUtils.DaysToYears(fSwaptionDeal.Settlement_Date - baseDate); // Factor in time value of money due to settlement delay. pv.MultiplyBy(fDiscountRate.Get(tgi.T, tSettlement) / fDiscountRate.Get(tgi.T, tExpiry)); } } }
/// <summary> /// This method Adjusts the bond price vector by taking the default into account give the default time vector. /// </summary> public static void AdjustForDefault(double baseDate, double valueDate, Vector bondPrice, TDate expiryDate, bool respectDefault, Vector underlyingIsAlive, Vector historicalRecovery, Vector defaultTime, IInterestRate discountRate, RecoveryRate recoveryRate) { // Adjust the bond price for default: check scenario by scenario for defaults, overwriting bondPrice as necessary if (!respectDefault) { return; } double currentTime = CalcUtils.DaysToYears(valueDate - baseDate); double tExpiry = CalcUtils.DaysToYears(expiryDate - baseDate); BondOptionValuation.AdjustBondValueForDefault(1.0, tExpiry, bondPrice, underlyingIsAlive, historicalRecovery, defaultTime, currentTime, discountRate, recoveryRate); }
/// <summary> /// Modify the pv and cash taking the date of default into account. /// </summary> public override void GetDefaultValue(double baseDate, double valueDate, Vector defaultDate, RecoveryRate recoveryRate, Vector pv, Vector cash) { var deal = (CFFloatingInterestListDeal)Deal; double principal = GetPrincipal(fCashflows, valueDate); double settlementDate = deal.Settlement_Date; double t = CalcUtils.DaysToYears(valueDate - baseDate); using (var cache = Vector.CacheLike(pv)) { // Approximation: recover only principal, neglecting accrued interest Vector recovery = cache.Get(fBuySellSign * principal * recoveryRate.Get(t)); if (valueDate <= settlementDate) { // Set the pv to (recovery - settlementAmount) * df when defaultDate <= valueDate <= settlementDate. // Set cash to (recovery - settlementAmount) when defaultDate <= valueDate = settlementDate (cash is always zero before settlementDate). double tSettle = CalcUtils.DaysToYears(settlementDate - baseDate); Vector settlementAmount = cache.GetClear(); if (deal.Settlement_Amount_Is_Clean == YesNo.Yes) { fCashflows.CalculateAccrual(settlementAmount, baseDate, settlementDate, false, deal.AccrualHolidayCalendar(), fForecastRate); } settlementAmount.Add(deal.Settlement_Amount); Vector hasDefaulted = cache.Get(defaultDate <= valueDate); pv.AssignConditional(hasDefaulted, fRepoRate.Get(t, tSettle) * (recovery - fBuySellSign * settlementAmount), pv); if (cash != null && valueDate == settlementDate) { cash.AssignConditional(hasDefaulted, pv, cash); } } else { // after settlement date recovery.MultiplyBy(defaultDate >= valueDate); // set to zero if already defaulted Vector notDefaulted = cache.Get(defaultDate > valueDate); pv.AssignConditional(notDefaulted, pv, recovery); if (cash != null) { cash.AssignConditional(notDefaulted, cash, recovery); } } } }
private void Restore_LR() { tables.CalcsMeteo.AddColumn(tables.BazaInfoMeteo.Column("Hr1")); tables.CalcsMeteo.IterateRows( row => { row.Set("Hr1-50", row["Hr1"].DoubleValue - 50, CellMapper.Rounder2); }, "Hr1-50"); var column_Hr1_minus_50 = tables.CalcsMeteo.Column("Hr1-50"); var column_LR = tables.CalcsMeteo.Column("LR"); var equationName = "LR = a + b * (Hr1 - 50)"; CalcUtils.RestoreColumn(tables.CoeffsTable, column_Hr1_minus_50, column_LR, new RoundDoubleCellMapper(5), equationName); }
/// <summary> /// Validate deal properties. /// </summary> public override void Validate(ICalendarData calendar, ErrorList errors) { base.Validate(calendar, errors); if (Notional < CalcUtils.MinAssetPrice) { AddToErrors(errors, string.Format("Bond Notional must be at least {0}", CalcUtils.MinAssetPrice)); } CalcUtils.ValidateDates(errors, Issue_Date, Bond_Maturity_Date, First_Coupon_Date, Penultimate_Coupon_Date, false, "Issue", "bond maturity"); Coupon_Rate_Schedule.Validate(errors, false, "Fixed rate schedule"); Amortisation.Validate(errors); CalcUtils.ValidateDates(errors, Issue_Date, Bond_Maturity_Date, true, "Issue", "bond maturity"); if (Settlement_Date != 0.0) { CalcUtils.ValidateDates(errors, Settlement_Date, Bond_Maturity_Date, true, "Settlement", "bond maturity"); } CalcUtils.ValidateDates(errors, First_Call_Date, Last_Call_Date, false, "First call", "last call"); Call_Prices.Validate(errors, true, "Call prices"); if (IsForward()) { if (Settlement_Date == 0.0) { AddToErrors(errors, "Settlement_Date must be specified"); } if (Price == 0.0) { AddToErrors(errors, ErrorLevel.Info, "Settlement price (Price) is zero."); } } else { if (Price != 0.0 && Settlement_Date == 0.0) { AddToErrors(errors, ErrorLevel.Warning, "Settlement price (Price) is not zero but Settlement_Date is not specified so Price has been ignored."); } } }
/// <summary> /// Calculate valuation profiles. /// </summary> public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes) { base.PreValue(factors); IAssetPrice commodityPrice; ISpotProcessVol dummyAssetPriceVol; ((BaseAssetFxDealHelper)GetDealHelper()).PreValueAsset(out commodityPrice, out dummyAssetPriceVol, out fBasketPricer, ref fQuantoCompo, factors); CommodityForwardDealBase deal = (CommodityForwardDealBase)fDeal; double scale = (deal.Buy_Sell == BuySell.Buy ? +1 : -1) * deal.Units; double tMaturity = CalcUtils.DaysToYears(deal.Maturity_Date - factors.BaseDate); TimeGridIterator tgi = new TimeGridIterator(fT); CashAccumulators cash = valuationResults.Cash; PVProfiles result = valuationResults.Profile; VectorEngine.For(tgi, () => { using (var cache = Vector.Cache(factors.NumScenarios)) { Vector pv = cache.Get(); if (tgi.Date <= deal.Maturity_Date) { pv.Assign(commodityPrice.ForwardFactor(tgi.T, tMaturity, fFxRate) * commodityPrice.Get(tgi.T)); // assign forward * fxRate to pv pv.Assign((pv - deal.Forward_Price * fFxRate.Get(tgi.T)) * fDiscountRate.Get(tgi.T, tMaturity) * scale); } else { pv.Clear(); } result.AppendVector(tgi.Date, pv); if (tgi.Date == deal.Maturity_Date) { cash.Accumulate(fFxRate, deal.Maturity_Date, (commodityPrice.Get(tMaturity) / fFxRate.Get(tMaturity) - deal.Forward_Price) * scale); } } }); result.Complete(fT); }