/// <summary> /// Create option pricer and other preparation. /// </summary> protected override InterestRateOptionPricer CreateOptionPricer(PriceFactorList factors) { CallableStructuredDeal deal = (CallableStructuredDeal)fDeal; LinearGaussMarkovFactor lgmPriceFactor = factors.Get <LinearGaussMarkovFactor>(fModelParametersId); return(new LinearGaussMarkovOptionPricer(deal.Option_Type, fExercises, fItems, fDiscountRate, fForecastRate, fInterestRateVol, fInterestYieldVol, fSurvivalProb, factors.NumScenarios, lgmPriceFactor, Driver_Space_Points, Standard_Deviations, Integration_Points)); }
/// <summary> /// Add dates to valuation grid. /// </summary> private void AddDatesToValuationGrid(double baseDate, bool cashRequired) { CallableStructuredDeal deal = (CallableStructuredDeal)fDeal; if (deal.Settlement_Style != SettlementType2.Cash) { // For callable and puttable and physical option, add dates from component deals Curve profile = new Curve(); fItems.GetValuationDates(profile, baseDate); foreach (float date in profile.X) { fT.Add(date); } } // Add exercise and settlement dates foreach (InterestRateOptionPricer.ExerciseItem item in fExercises) { fT.Add(item.ExerciseDate, true); if (item.SettlementDate > item.ExerciseDate) { fT.AddPayDate(item.SettlementDate, cashRequired); } } }
/// <summary> /// Prepare for valuation. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); SetModelParameters(fItems); PreValueDeals(fItems, factors); CallableStructuredDeal deal = (CallableStructuredDeal)Deal; // Set volatility price factors if they have been registered by model or underlying deals InterestVol.TryGet <IInterestRateVol>(factors, deal.Forecast_Rate_Cap_Volatility, fForecastCurrency, out fInterestRateVol); InterestVol.TryGet <IInterestYieldVol>(factors, deal.Forecast_Rate_Swaption_Volatility, fForecastCurrency, out fInterestYieldVol); bool needRating = Respect_Default == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); bool needSurvival = Use_Survival_Probability == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); if (needRating) { fCreditRating = factors.Get <CreditRating>(deal.Issuer); fRecoveryRate = factors.Get <RecoveryRate>(InterestRateUtils.GetRateId(deal.Recovery_Rate, deal.Issuer)); } if (needSurvival) { fSurvivalProb = factors.GetInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Issuer : deal.Survival_Probability); } }
/// <summary> /// Register price factors used in valuation. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); if (!string.IsNullOrEmpty(fForecastCurrency) && fForecastCurrency != fCurrency) { errors.Add(ErrorLevel.Error, "Settlement currency (Currency) and currency of Forecast_Rate must be the same"); } SetModelParameters(fItems); ValidateModels(fItems, errors); fItems.RegisterFactors(factors, errors); CallableStructuredDeal deal = (CallableStructuredDeal)fDeal; bool needRating = Respect_Default == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); bool needSurvival = Use_Survival_Probability == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); if (needRating) { factors.Register <CreditRating>(deal.Issuer); factors.Register <RecoveryRate>(InterestRateUtils.GetRateId(deal.Recovery_Rate, deal.Issuer)); } if (needSurvival) { factors.RegisterInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Issuer : deal.Survival_Probability); } }
/// <summary> /// Prepare for valuation anything that is not dependent upon the scenario. /// </summary> public override void PreCloneInitialize(PriceFactorList factors, BaseTimeGrid baseTimes, RequiredResults ResultsRequired) { base.PreCloneInitialize(factors, baseTimes, ResultsRequired); fItems.PreCloneInitialize(factors, baseTimes, ResultsRequired); CallableStructuredDeal deal = (CallableStructuredDeal)fDeal; // Create a list of sorted exercise items with exercise date >= baseDate and exercise date <= deal's end date. fExercises = CreateExerciseList(factors.BaseDate, deal.EndDate(), deal.Exercise_Dates, deal.Principal); AddDatesToValuationGrid(factors.BaseDate, ResultsRequired.CashRequired()); }
/// <summary> /// Register price factors used in valuation. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); CallableStructuredDeal deal = (CallableStructuredDeal)Deal; if (Model_Type == MarketModelTreeOptionPricer.ModelType.Libor_Rate) { InterestVol.Register <IInterestRateVol>(factors, deal.Forecast_Rate_Cap_Volatility, fForecastCurrency); } else { InterestVol.Register <IInterestYieldVol>(factors, deal.Forecast_Rate_Swaption_Volatility, fForecastCurrency); } }
/// <summary> /// Create option pricer and other preparation. /// </summary> protected override InterestRateOptionPricer CreateOptionPricer(PriceFactorList factors) { CallableStructuredDeal deal = (CallableStructuredDeal)fDeal; return(new MarketModelTreeOptionPricer(factors.BaseDate, deal.Option_Type, fExercises, fItems, fDiscountRate, fForecastRate, fInterestRateVol, fInterestYieldVol, fSurvivalProb, factors.NumScenarios, Model_Type, Time_Step_Size, Max_Time_Steps)); }
/// <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 cashAccumulator = valuationResults.Cash; double baseDate = factors.BaseDate; CallableStructuredDeal deal = (CallableStructuredDeal)fDeal; int buySellSign = deal.Buy_Sell == BuySell.Buy ? +1 : -1; int callPutSign = deal.Option_Type == OptionType.Call ? 1 : -1; InterestRateOptionPricer optionPricer = CreateOptionPricer(factors); CalcUtils.CreateDealProfilesIfRequired(valuationResults, fItems, factors); bool needRating = Respect_Default == YesNo.Yes && !string.IsNullOrEmpty(deal.Issuer); using (var cache = Vector.Cache(factors.NumScenarios)) { Vector exercised = cache.GetClear(); // vector taking value 0 or 1 indicating exercise before tgi.date Vector exercisedToday = cache.Get(); // vector taking value 0 or 1 indicating exercise at tgi.date Vector optionPv = cache.Get(); Vector pv = cache.Get(); Vector cash = cache.Get(); Vector settlementDateAtExercise = cache.GetClear(); Vector defaultDate = needRating ? cache.Get(CalcUtils.DateTimeMaxValueAsDouble) : null; var defaultedBeforeBaseDate = needRating && CreditRating.DefaultedBeforeBaseDate(fCreditRating, baseDate); while (tgi.Next()) { if (defaultedBeforeBaseDate) { pv.Clear(); result.AppendVector(tgi.Date, pv); break; } if (needRating) { UpdateDefaultDate(fCreditRating, tgi.Date, tgi.T, defaultDate); } double val; bool allExercised = exercised.AllElementsTheSame(out val) && val == 1.0; if (deal.Settlement_Style == SettlementType2.Physical) { // Calculate value of option (option value is zero after last exercise date) if (!allExercised) { optionPricer.Value(baseDate, tgi.Date, optionPv, exercised, exercisedToday, settlementDateAtExercise, defaultDate); } // Calculate value of underlying cashflows after settlementDateAtExercise pv.Clear(); cash.Clear(); InterestRateOptionPricer.ValueDeals(fItems, pv, cash, baseDate, tgi.Date, settlementDateAtExercise, defaultDate, fDiscountRate, fForecastRate, fRepoRate, fInterestRateVol, fInterestYieldVol, fSurvivalProb, fRecoveryRate); pv.MultiplyBy(callPutSign); cash.MultiplyBy(callPutSign); if (!allExercised) { // If exercised today the cashflow is the value of the option minus the value of the physically settled part // Else if already exercised, cash is the unnderlying cash. // Else (before exercise) there is no cash. cash.AssignConditional(exercisedToday, optionPv - pv, exercised * cash); // If already exercised, pv is the unnderlying pv. // Else (before exercise or exercised today), pv is the option pv. pv.AssignConditional(exercised, pv, optionPv); pv.AssignConditional(exercisedToday, optionPv, pv); } } else { if (allExercised) { // Already exercised on all scenarios result.AppendZeroVector(tgi.Date); continue; } if (deal.Settlement_Style == SettlementType2.Cash) { // Calculate value of option optionPricer.Value(baseDate, tgi.Date, pv, exercised, exercisedToday, settlementDateAtExercise, defaultDate); // If exercised today then option pv is settled today, otherwise there is no cash cash.AssignProduct(pv, exercisedToday); } else // Embedded option (callable or puttable) { // Calculate underlying value pv.Clear(); cash.Clear(); InterestRateOptionPricer.ValueDeals(fItems, pv, cash, baseDate, tgi.Date, null, defaultDate, fDiscountRate, fForecastRate, fRepoRate, fInterestRateVol, fInterestYieldVol, fSurvivalProb, fRecoveryRate); // Calculate value of option optionPricer.Value(baseDate, tgi.Date, optionPv, exercised, exercisedToday, settlementDateAtExercise, defaultDate); // Add or subtract value of embedded option pv.AddProduct(-callPutSign, optionPv); // Option payoff is Max(callPutSign * (underlyingPv - accruedInterest - discountedFee), 0) // Callable/puttable payoff on exercise is // underlyingPv - callPutSign * (callPutSign * (underlyingPv - accruedInterest - discountedFee)) // = accruedInterest + discountedFee // Set pv and cash to zero if already exercised. // If exercised today then the pv is settled today. pv.AssignConditional(exercised, exercisedToday * pv, pv); cash.AssignConditional(exercised, exercisedToday * pv, cash); } } pv.MultiplyBy(buySellSign); cash.MultiplyBy(buySellSign); result.AppendVector(tgi.Date, fFxRate.Get(tgi.T) * pv); cashAccumulator.Accumulate(fFxRate, tgi.Date, cash); } } result.Complete(fT); }