/// <summary> /// Prepare for valuation anything that is dependent upon the scenario. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); BondFutureOption deal = (BondFutureOption)Deal; fInterestYieldVol = InterestVolBase.GetYieldVol(factors, deal.Yield_Volatility, fCurrency); var bfb = (BondFuturesBasis)fFuturesBasis; GenerateCTD(factors.BaseDate, bfb.CTD_Issue_Date, bfb.CTD_Maturity_Date, bfb.CTD_Coupon_Interval, bfb.CTD_First_Coupon_Date, bfb.CTD_Penultimate_Coupon_Date, bfb.CTD_Day_Count, Deal.GetHolidayCalendar(), bfb.CTD_Coupon_Rate, bfb.CTD_Conversion_Factor); if (NeedRating(Respect_Default, deal.Issuer)) { fCreditRating = factors.Get <CreditRating>(deal.Issuer); fRecoveryRate = factors.Get <RecoveryRate>(InterestRateUtils.GetRateId(deal.Recovery_Rate, deal.Issuer)); } else { fCreditRating = null; fRecoveryRate = null; } if (NeedSurvivalProbability(Use_Survival_Probability, deal.Issuer)) { fSurvivalProb = factors.GetInterface <ISurvivalProb>(InterestRateUtils.GetRateId(deal.Survival_Probability, deal.Issuer)); } else { fSurvivalProb = null; } }
public ActionResult ClearingInvestment(string investmentGuid, string endTime, double gains, string accountingTime) { return(ActionUtils.Json(() => { CommUtils.AssertHasContent(investmentGuid, "Investment guid不能为空"); CommUtils.AssertHasContent(endTime, "[到期时间]不能为空"); CommUtils.AssertHasContent(accountingTime, "[到账时间]不能为空"); CommUtils.Assert(gains <= 1000000000000, "[收益金额]不能大于10,000亿元"); CommUtils.Assert(gains >= -1000000000000, "[收益金额]不能小于-10,000亿元"); var valEndTime = DateTime.Parse(endTime); var valAccountingTime = DateTime.Parse(accountingTime); CommUtils.Assert(DateTime.Compare(valAccountingTime, valEndTime) >= 0, "[到账时间]不能小于[到期时间]"); var investment = m_dbAdapter.Investment.GetInvestment(investmentGuid); CommUtils.Assert(DateTime.Compare(valEndTime, investment.StartTime) > 0, "[到期时间]必须大于[开始时间]"); CommUtils.Assert(!(gains <0 && System.Math.Abs(gains)> investment.Money), "[收益金额]不能亏损超过[投资金额]"); investment.Gains = gains; investment.EndTime = valEndTime; investment.AccountingTime = valAccountingTime; investment.Yield = InterestRateUtils.CalculateYield(investment.Gains.Value, investment.Money, investment.EndTime, investment.StartTime); var result = m_dbAdapter.Investment.UpdateInvestment(investment); return ActionUtils.Success(result); })); }
/// <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> /// Get price factors. /// </summary> private void PreValue(PriceFactorList factors) { var deal = (CalendarSpreadOption)Deal; // Get forward price samples. fForwardSample = factors.Get <ForwardPriceSample>(deal.Sampling_Type); // Get ReferencePrice price factors. fReferencePrice1 = factors.GetInterface <IReferencePrice>(deal.Reference_Type); fReferencePrice2 = factors.GetInterface <IReferencePrice>(deal.Reference_Type); // Get ReferenceVol price factors. // Default to Reference Type if Reference Vol Type is not set. if (string.IsNullOrEmpty(deal.Reference_Vol_Type)) { fReferenceVol1 = factors.Get <ReferenceVol>(deal.Reference_Type); fReferenceVol2 = factors.Get <ReferenceVol>(deal.Reference_Type); } else { fReferenceVol1 = factors.Get <ReferenceVol>(deal.Reference_Vol_Type); fReferenceVol2 = factors.Get <ReferenceVol>(deal.Reference_Vol_Type); } // Get correlation price factor based on the ID of the forward price. fCorrelations = factors.Get <ForwardPriceCorrelations>(fReferencePrice1.GetForwardPrice()); // Get FX rate price factors. fFxRate = factors.GetInterface <IFxRate>(deal.Currency); fFxPayoffRate = factors.GetInterface <IFxRate>(deal.DealCurrency()); fPriceFactorFxRate = factors.GetInterface <IFxRate>(fReferencePrice1.DomesticCurrency()); // Get discount rate price factor. fDiscountRate = factors.GetInterface <IInterestRate>(InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency)); }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { factors.Register <DiscountRate>(InterestRateUtils.GetRateId(fDeal.Discount_Rate, fDeal.Currency)); factors.RegisterInterface <IFxRate>(fDeal.Currency); factors.RegisterInterface <IExpectedLoss>(fDeal.Reference_Index); factors.RegisterInterface <IRealizedLoss>(fDeal.Reference_Index); }
public ActionResult ModifyInvestment(string investmentGuid, string name, string description, double money, string yieldDue, double?gains, string startTime, string endTime, string accountingTime) { return(ActionUtils.Json(() => { ValidateUtils.Name(name, "投资标的"); CommUtils.AssertHasContent(startTime, "[开始时间]不能为空"); CommUtils.AssertHasContent(endTime, "[到期时间]不能为空"); CommUtils.Assert(money <= 1000000000000, "[投资金额]不能大于10,000亿元"); CommUtils.Assert(money > 0, "[投资金额]必须大于0元"); var valStartTime = DateTime.Parse(startTime); var valEndTime = DateTime.Parse(endTime); CommUtils.Assert(DateTime.Compare(valEndTime, valStartTime) > 0, "[到期时间]必须大于[开始时间]"); var investment = m_dbAdapter.Investment.GetInvestment(investmentGuid); investment.Name = name; investment.Description = description; investment.Money = money; investment.StartTime = valStartTime; investment.EndTime = valEndTime; investment.YieldDue = null; if (investment.Gains.HasValue) { CommUtils.AssertNotNull(gains, "[收益金额]不能为空"); CommUtils.AssertHasContent(accountingTime, "[到账时间]不能为空"); CommUtils.Assert(gains <= 1000000000000, "[收益金额]不能大于10,000亿元"); CommUtils.Assert(gains >= -1000000000000, "[收益金额]不能小于-10,000亿元"); CommUtils.Assert(!(gains <0 && System.Math.Abs(gains.Value)> investment.Money), "[收益金额]不能亏损超过[投资金额]"); var valAccountingTime = DateTime.Parse(accountingTime); CommUtils.Assert(DateTime.Compare(valAccountingTime, valEndTime) >= 0, "[到账时间]不能小于[到期时间]"); investment.AccountingTime = valAccountingTime; investment.Gains = gains; investment.Yield = InterestRateUtils.CalculateYield(investment.Gains.Value, investment.Money, investment.EndTime, investment.StartTime); } if (!string.IsNullOrWhiteSpace(yieldDue) && yieldDue != "-") { var percentValue = 0.0; if (yieldDue.Contains('%')) { CommUtils.Assert(double.TryParse(yieldDue.Substring(0, yieldDue.Length - 1), out percentValue), "预计收益率必须为数字"); } else { CommUtils.Assert(double.TryParse(yieldDue, out percentValue), "预计收益率必须为数字"); } CommUtils.Assert(percentValue >= 365.00 * (-1) / (valEndTime - valStartTime).TotalDays, "预计收益率过低,请重新填写"); investment.YieldDue = percentValue / 100; } var result = m_dbAdapter.Investment.UpdateInvestment(investment); return ActionUtils.Success(result); })); }
public ActionResult Index(string projectGuid, string paymentDay) { var projectLogicModel = new ProjectLogicModel(CurrentUserName, projectGuid); var project = projectLogicModel.Instance; var datasetSchedule = projectLogicModel.DealSchedule.GetByPaymentDay(DateUtils.ParseDigitDate(paymentDay)); CommUtils.AssertNotNull(datasetSchedule.Dataset.Instance, "Dataset数据加载失败,projectGuid=[" + projectGuid + "] paymentDay=[" + paymentDay + "]"); var dataset = datasetSchedule.Dataset.Instance; var notes = m_dbAdapter.Dataset.GetNotes(project.ProjectId); var cnabsNotes = projectLogicModel.Notes; var noteDict = Toolkit.GetNoteDictionary(project, notes, cnabsNotes); var dealSchedule = NancyUtils.GetDealSchedule(project.ProjectId); var noteDatas = m_dbAdapter.Dataset.GetNoteDatas(dataset.DatasetId); var datasetViewModel = Toolkit.GetDatasetViewModel(dataset, dealSchedule.PaymentDates, noteDict, noteDatas); var datasetFolder = m_dbAdapter.Dataset.GetDatasetFolder(project, dataset.AsOfDate); VariablesHelper helper = new VariablesHelper(datasetFolder); var variables = helper.GetVariablesByDate(dataset.PaymentDate.Value); var rateResetRecords = InterestRateUtils.RateResetRecords(variables); //计算当期浮动利率 datasetViewModel.NoteDatas.ForEach(x => x.CurrentCouponRate = InterestRateUtils.CalculateCurrentCouponRate(x.NoteInfo.CouponString, rateResetRecords)); var viewModel = new CashflowDatasetViewModel(); viewModel.Dataset = datasetViewModel; viewModel.ProjectGuid = projectGuid; //添加今天之前所有已上传模型的支付日 var nowDate = DateTime.Today; viewModel.ValidPaymentDays = datasetSchedule.SelectPaymentDates( x => x.PaymentDate <= nowDate && x.Dataset != null && x.Dataset.Instance != null); if (project.CnabsDealId.HasValue) { viewModel.AllPaymentDays = m_dbAdapter.Model.GetPaymentDates(project.CnabsDealId.Value); } else { if (projectLogicModel.DealSchedule.Instanse != null) { viewModel.AllPaymentDays = projectLogicModel.DealSchedule.Instanse.PaymentDates.ToList(); } else { viewModel.AllPaymentDays = new List <DateTime>(); } } return(View(viewModel)); }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { var deal = (SwaptionDeal)Deal; // Get underlying cashflow lists SwaptionBaseValuation.SetCashflowLists(errors, deal, ref fFixedCashflowList, ref fFloatCashflowList); if (!IsVanillaSwaption()) { Deal.AddToErrors(errors, ErrorLevel.Error, "The Hull White swaption valuation model is for vanilla swaptions only."); } // Register deal currency factors.RegisterInterface <IFxRate>(deal.Currency); // Register discount rate var discountId = InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency); string discountRateCurrency = DiscountRate.Register(factors, discountId).GetCurrency(); if (!string.IsNullOrEmpty(discountRateCurrency) && discountRateCurrency != deal.Currency) { errors.Add(ErrorLevel.Error, "Settlement currency (Currency) and currency of Discount_Rate must be the same"); } // Register forecast rate var forecastId = InterestRateUtils.GetRateId(deal.Forecast_Rate, discountId); var forecastRateCurrency = factors.RegisterInterface <IInterestRate>(forecastId).GetCurrency(); if (forecastRateCurrency != deal.Currency) { errors.Add(ErrorLevel.Error, "Settlement currency (Currency) and currency of Forecast_Rate must be the same"); } // Register the HW model parameters fModelParametersId = string.IsNullOrWhiteSpace(Model_Parameters) ? forecastId : Model_Parameters; factors.Register <HullWhite1FactorModelParameters>(fModelParametersId); // Check that floating cashflow list is standard enough to be valued by ValueSwap if (fFloatCashflowList == null || fFixedCashflowList == null) { errors.Add(ErrorLevel.Error, "Deal must contain exactly one floating and one fixed leg."); } else { var characteristics = fFloatCashflowList.Analyze(factors.BaseDate); if (!characteristics.HasSwaplet || characteristics.HasOptionlet || !characteristics.IsStandardPayoff || characteristics.HasCms || !characteristics.IsStandardLibor || fFloatCashflowList.Compounding_Method != CompoundingMethod.None || fFixedCashflowList.Compounding == YesNo.Yes) { errors.Add(ErrorLevel.Error, "Underlying swap has non-standard floating cashflows."); } } }
/// <summary> /// Constructor. /// </summary> public CreditValuationParameters(DealCreditBase deal, CreditBaseValuation valuation, PriceFactorList factors, VectorScopedCache.Scope cache) { DF = DiscountRate.Get(factors, InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency)); X = factors.GetInterface <IFxRate>(deal.Currency); SP = factors.GetInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.Survival_Probability) ? deal.Name : deal.Survival_Probability); RR = null; CR = null; DefaultTime = null; Weights = null; NamesDefaultedBeforeBaseDate = null; if (valuation.Respect_Default == YesNo.Yes) { List <string> names = new List <string>(); if (deal.ProtectionReferenceType() == DealCreditBase.ReferenceType.Single_Name) { names.Add(deal.Name); Weights = new double[] { 1.0 }; } else { IndexCDSPool indexCds = factors.Get <IndexCDSPool>(deal.Name); Weights = new double[indexCds.Names.Count]; for (int i = 0; i < indexCds.Names.Count; ++i) { names.Add(indexCds.Names[i].Name); Weights[i] = indexCds.Names[i].Weight; } } if (valuation.RequiresRecoveryOnDefault()) { RR = new RecoveryRate[names.Count]; for (int i = 0; i < names.Count; ++i) { RR[i] = factors.Get <RecoveryRate>(string.IsNullOrEmpty(deal.Recovery_Rate) ? names[i] : deal.Recovery_Rate); } } CR = new CreditRating[names.Count]; NamesDefaultedBeforeBaseDate = new bool[names.Count]; DefaultTime = new Vector[names.Count]; for (int i = 0; i < names.Count; ++i) { DefaultTime[i] = cache.Get(); CR[i] = factors.Get <CreditRating>(names[i]); NamesDefaultedBeforeBaseDate[i] = CreditRating.DefaultedBeforeBaseDate(CR[i], factors.BaseDate); CR[i].DefaultTime(DefaultTime[i]); } } }
/// <inheritdoc /> public void PreValue(PriceFactorList factors) { var deal = (SwaptionDeal)Deal; var discountId = InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency); var forecastId = InterestRateUtils.GetRateId(deal.Forecast_Rate, discountId); fModelParameters = factors.Get <HullWhite1FactorModelParameters>(fModelParametersId); fFxRate = factors.GetInterface <IFxRate>(deal.Currency); fDiscountRate = DiscountRate.Get(factors, discountId); fForecastRate = factors.GetInterface <IInterestRate>(forecastId); fQuadrature = new Lazy <GaussHermiteNormalQuadrature>(() => new GaussHermiteNormalQuadrature(30)); }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { BondFuture deal = (BondFuture)Deal; base.RegisterFactors(factors, errors); if (NeedRating(Respect_Default, deal.Issuer)) { factors.Register <CreditRating>(deal.Issuer); // register realized recovery rate. factors.Register <RecoveryRate>(InterestRateUtils.GetRateId(deal.Recovery_Rate, deal.Issuer)); } if (NeedSurvivalProbability(Use_Survival_Probability, deal.Issuer)) { factors.RegisterInterface <ISurvivalProb>(InterestRateUtils.GetRateId(deal.Survival_Probability, deal.Issuer)); } }
// ----------------------------------------------------------------------------- // Description: Register price factors // ----------------------------------------------------------------------------- public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { factors.Register <DiscountRate>(InterestRateUtils.GetRateId(fCreditBaseDeal.Discount_Rate, fCreditBaseDeal.Currency)); factors.RegisterInterface <IFxRate>(fCreditBaseDeal.Currency); factors.RegisterInterface <ISurvivalProb>(string.IsNullOrEmpty(fCreditBaseDeal.Survival_Probability) ? fCreditBaseDeal.Name : fCreditBaseDeal.Survival_Probability); if (Respect_Default == YesNo.Yes) { if (fCreditBaseDeal.ProtectionReferenceType() == DealCreditBase.ReferenceType.Single_Name) { factors.Register <CreditRating>(fCreditBaseDeal.Name); if (RequiresRecoveryOnDefault()) { factors.Register <RecoveryRate>(string.IsNullOrEmpty(fCreditBaseDeal.Recovery_Rate) ? fCreditBaseDeal.Name : fCreditBaseDeal.Recovery_Rate); } } else { factors.Register <IndexCDSPool>(fCreditBaseDeal.Name); } } }
/// <summary> /// Prepare for valuation anything that is dependent upon the scenario. /// </summary> public override void PreValue(PriceFactorList factors) { base.PreValue(factors); CFListBaseDeal <TCashflowList> deal = (CFListBaseDeal <TCashflowList>)fDeal; if (string.IsNullOrEmpty(fDeal.GetIssuer())) { return; } if (UseSurvivalProbability()) { fSurvivalProb = factors.GetInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.GetSurvivalProbability()) ? deal.GetIssuer() : deal.GetSurvivalProbability()); } if (RespectDefault()) { fRecoveryRate = factors.Get <RecoveryRate>(InterestRateUtils.GetRateId(deal.GetRecoveryRate(), deal.GetIssuer())); fCreditRating = factors.Get <CreditRating>(deal.GetIssuer()); } }
public ActionResult GetInvestments(string projectGuid, int?page, int?pageSize) { return(ActionUtils.Json(() => { var project = m_dbAdapter.Project.GetProjectByGuid(projectGuid); var investments = m_dbAdapter.Investment.GetInvestmentsByProjectId(project.ProjectId); var investmentIds = investments.ConvertAll(x => x.Id).ToList(); var investmentsOfPage = m_dbAdapter.Investment.GetInvestments(page ?? 1, pageSize ?? 10, investmentIds); var result = new { Investments = investmentsOfPage.Items.ConvertAll(x => new { guid = x.Guid, name = x.Name, description = Toolkit.ToString(x.Description), money = x.Money.ToString("n2"), gains = (x.Gains.HasValue ? x.Gains.Value.ToString("n2") : "-"), yield = (x.Yield.HasValue ? x.Yield.Value.ToString("P") : "-"), yieldDue = (x.YieldDue.HasValue ? CommUtils.Percent(x.YieldDue.Value, 1) : "-"), gainsDue = x.YieldDue.HasValue ? InterestRateUtils.CalculateGains(x.YieldDue.Value, x.Money, x.EndTime, x.StartTime).ToString("n2") : "-", startTime = Toolkit.DateToString(x.StartTime), endTime = Toolkit.DateToString(x.EndTime), accountingTime = Toolkit.DateToString(x.AccountingTime), status = x.Gains.HasValue ? "Finished" : "Running", reminderInfo = m_dbAdapter.MessageReminding.GetResultByUid(x.Guid), }).ToList(), StatisticInfo = new { totalMoney = investments.Sum(x => x.Money).ToString("n2"), totalGains = investments.Sum(x => x.Gains ?? 0).ToString("n2"), totalCount = investments.Count.ToString("n0"), totalFinished = investments.Sum(x => x.Gains.HasValue ? 1 : 0).ToString("n0"), totalRunning = investments.Sum(x => x.Gains.HasValue ? 0 : 1).ToString("n0") } }; return ActionUtils.Success(result); })); }
/// <summary> /// Register price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { base.RegisterFactors(factors, errors); CFListBaseDeal <TCashflowList> deal = (CFListBaseDeal <TCashflowList>)fDeal; if (string.IsNullOrEmpty(fDeal.GetIssuer())) { return; } if (UseSurvivalProbability()) { factors.RegisterInterface <ISurvivalProb>(string.IsNullOrEmpty(deal.GetSurvivalProbability()) ? deal.GetIssuer() : deal.GetSurvivalProbability()); } if (RespectDefault()) { factors.Register <RecoveryRate>(InterestRateUtils.GetRateId(deal.GetRecoveryRate(), deal.GetIssuer())); factors.Register <CreditRating>(deal.GetIssuer()); } fSettlementOffsetHelper.ValidateHolidayCalendars(factors.CalendarData, errors); }
/// <summary> /// Validate the valuation models of the component deals. /// </summary> private void ValidateModels(ValuationList models, ErrorList errors) { const string Messsage = "{0} of underlying deals must be the same as {0} of {1}"; // Get properties of Callable Structured Deal string discount = InterestRateUtils.GetRateId(fDeal.GetDiscountRate(), fDeal.Currency); string forecast = InterestRateUtils.GetRateId(fDeal.GetForecastRate(), discount); string issuer = fDeal.GetIssuer(); string recovery = InterestRateUtils.GetRateId(fDeal.GetRecoveryRate(), issuer); foreach (Valuation model in models) { if (model.Deal.fIgnore) { continue; } else if (model.IsContainer()) { ValidateModels(model.fItems, errors); } else if (model.Deal is IRDealBase && model is ISingleDateValuation) { IRDealBase underlyingDeal = (IRDealBase)model.Deal; // Currency of underlying must match CSD if (underlyingDeal.Currency != fDeal.Currency) { errors.Add(ErrorLevel.Error, string.Format(Messsage, "Currency", fDeal.GetType().Name)); } // Discount_Rate and Forecast_Rate of underlying must either be left blank or match CSD string underlyingDiscount = underlyingDeal.GetDiscountRate(); if (!string.IsNullOrEmpty(underlyingDiscount) && underlyingDiscount != discount) { errors.Add(ErrorLevel.Error, string.Format(Messsage, "Discount_Rate", fDeal.GetType().Name)); } string underlyingForecast = underlyingDeal.GetForecastRate(); if (!string.IsNullOrEmpty(underlyingForecast) && underlyingForecast != forecast) { errors.Add(ErrorLevel.Error, string.Format(Messsage, "Forecast_Rate", fDeal.GetType().Name)); } if (Use_Survival_Probability == YesNo.Yes && !string.IsNullOrEmpty(issuer)) { // Issue and Recovery_Rate of underlying must either be left blank or match CSD string underlyingIssuer = underlyingDeal.GetIssuer(); if (!string.IsNullOrEmpty(underlyingIssuer) && underlyingIssuer != issuer) { errors.Add(ErrorLevel.Error, string.Format(Messsage, "Issuer", fDeal.GetType().Name)); } } if (Respect_Default == YesNo.Yes && !string.IsNullOrEmpty(issuer)) { string underlyingIssuer = underlyingDeal.GetIssuer(); string underlyingRecovery = InterestRateUtils.GetRateId(underlyingDeal.GetRecoveryRate(), underlyingIssuer); if (!string.IsNullOrEmpty(underlyingRecovery) && underlyingRecovery != recovery) { errors.Add(ErrorLevel.Error, string.Format(Messsage, "Recovery_Rate", fDeal.GetType().Name)); } } } else { // Underlying deal type must be IRDealBase and model must support ISingleDateValuation errors.Add(ErrorLevel.Error, string.Format("{0} cannot be used in {1}", model.Deal.GetType().Name, fDeal.GetType().Name)); } } }
protected override object MakeObjectInstance() { var logicModel = new ProjectLogicModel(m_userName, m_project); var schedule = logicModel.DealSchedule.Instanse; var firstNoteAccrualDates = schedule.NoteAccrualDates.First().Value; var firstNoteName = schedule.NoteAccrualDates.First().Key; foreach (var key in schedule.NoteAccrualDates.Keys) { var noteAccrualDates = schedule.NoteAccrualDates[key]; CommUtils.AssertEquals(firstNoteAccrualDates.Length, noteAccrualDates.Length, "检测到证券期数不一致,[{0}]={1},[{2}]={3}", firstNoteName, firstNoteAccrualDates.Length, key, noteAccrualDates.Length); for (int i = 0; i < firstNoteAccrualDates.Length; i++) { CommUtils.Assert(firstNoteAccrualDates[i] == noteAccrualDates[i], "检测到第[{0}]期证券Accrual date不一致,[{1}]={2},[{3}]={4}", i + 1, firstNoteName, firstNoteAccrualDates[i].ToShortDateString(), key, noteAccrualDates[i].ToShortDateString()); } } //从第N期开始模型数据时,getDealSchedule中不包含前几期的PaymentDate List <DateTime> paymentDates = schedule.PaymentDates.ToList(); if (m_project.CnabsDealId.HasValue) { paymentDates = m_dbAdapter.Model.GetPaymentDates(m_project.CnabsDealId.Value); } var datasets = m_dbAdapter.Dataset.GetDatasetByProjectId(m_project.ProjectId); var paymentDate = paymentDates.First(x => x == m_paymentDay); var sequence = paymentDates.FindIndex(x => x == m_paymentDay); datasets = datasets.Where(x => x.PaymentDate.HasValue && x.PaymentDate.Value <= paymentDate).ToList(); var findDatasets = datasets.Where(x => x.PaymentDate.HasValue && x.PaymentDate.Value == paymentDate).ToList(); findDatasets.Sort((l, r) => l.AsOfDate.CompareTo(r.AsOfDate)); CommUtils.Assert(findDatasets.Count >= 1, "找不到偿付期为 [{0}] 的数据模型", DateUtils.DateToString(paymentDate)); var dataset = findDatasets[0]; var datasetId = dataset.DatasetId; var notes = m_dbAdapter.Dataset.GetNotes(m_project.ProjectId); var noteDatas = m_dbAdapter.Dataset.GetNoteDatas(datasetId); //初始化note信息 List <Note> cnabsNotes = new ProjectLogicModel(m_userName, m_project).Notes; var datasetFolder = m_dbAdapter.Dataset.GetDatasetFolder(m_project, dataset.AsOfDate); var variablesCsv = new VariablesHelper(datasetFolder); var futureVariablesPath = Path.Combine(datasetFolder, "FutureVariables.csv"); var variables = variablesCsv.GetVariablesByDate(dataset.PaymentDate.Value); var rateResetRecords = InterestRateUtils.RateResetRecords(variables); var idrObj = new IncomeDistributionReport(); idrObj.Sequence = sequence + 1; idrObj.SequenceCN = idrObj.Sequence.ToCnString(); idrObj.Security = new Dictionary <string, PaymentDetail>(); idrObj.PriorSecurityList = new List <PaymentDetail>(); idrObj.SubSecurityList = new List <PaymentDetail>(); idrObj.SecurityList = new List <PaymentDetail>(); idrObj.BeginAccrualDate = sequence == 0 ? schedule.FirstAccrualDate : schedule.NoteAccrualDates.First().Value[sequence - 1]; idrObj.EndAccrualDate = schedule.NoteAccrualDates.First().Value[sequence]; idrObj.AccrualDateSum = (idrObj.EndAccrualDate - idrObj.BeginAccrualDate).Days; for (int i = 0; i < notes.Count; i++) { var note = notes[i]; note.CouponString = InterestRateUtils.CalculateCurrentCouponRate(cnabsNotes[i].CouponString, rateResetRecords); var noteData = noteDatas.Single(x => x.NoteId == note.NoteId); CommUtils.Assert(noteData.HasValue, "兑付日为[{0}]的偿付期内,证券端现金流类型的工作未核对", paymentDate.ToShortDateString()); idrObj.Security[note.ShortName] = GeneratePaymentDetail(note, noteData, idrObj.Security.Count + 1); if (note.IsEquity) { idrObj.SubSecurityList.Add(GeneratePaymentDetail(note, noteData, idrObj.SubSecurityList.Count + 1)); } else { idrObj.PriorSecurityList.Add(GeneratePaymentDetail(note, noteData, idrObj.PriorSecurityList.Count + 1)); } idrObj.SecurityList.Add(GeneratePaymentDetail(note, noteData, idrObj.SecurityList.Count(x => x.Money != 0) + 1)); } Func <IEnumerable <PaymentDetail>, PaymentDetail> sum = (values) => new PaymentDetail { Residual = values.Sum(x => x.Residual), Principal = values.Sum(x => x.Principal), Interest = values.Sum(x => x.Interest), Money = values.Sum(x => x.Money), UnitCount = values.Sum(x => x.UnitCount), SumPaymentAmount = values.Sum(x => x.SumPaymentAmount) }; idrObj.Sum = sum(idrObj.Security.Values); idrObj.SumPrior = sum(idrObj.Security.Values.Where(x => !x.IsEquity)); idrObj.SumSub = sum(idrObj.Security.Values.Where(x => x.IsEquity)); GeneratePercentTable(idrObj, datasets, notes, schedule.PaymentDates); idrObj.RepayDetail = GenerateRepayDetail(idrObj.SecurityList, x => x.NameCN); idrObj.RepayDetailWithHyphen = GenerateRepayDetail(idrObj.SecurityList, x => x.NameCNHyphen); idrObj.RepayDetailWithHyphenByJinTai = GenerateRepayDetailByJinTai(idrObj.SecurityList, x => x.NameCNHyphen); idrObj.RepayPrincipalDetail = GenerateRepayPrincipalDetail(idrObj.SecurityList); idrObj.DenominationDetail = GenerateDenominationDetail(idrObj.SecurityList); idrObj.EquityRegisterDetail = GenerateEquityRegisterDetail(idrObj.SecurityList, dataset.PaymentDate.Value); idrObj.EquityRegisterDetailByJinTai = GenerateEquityRegisterDetailByJinTai(idrObj.SecurityList, dataset.PaymentDate.Value); idrObj.EquityRegisterDetailByZhongGang = GenerateEquityRegisterDetailByZhongGang(idrObj.SecurityList, dataset.PaymentDate.Value); idrObj.EquityRegisterDetailByYingBinGuan = GenerateEquityRegisterDetailByYingBinGuan(idrObj.SecurityList, dataset.PaymentDate.Value); idrObj.T = dataset.PaymentDate.Value; if (paymentDates.First() == idrObj.T) { idrObj.PreviousT = schedule.ClosingDate; } else { var previousIndex = paymentDates.IndexOf(idrObj.T) - 1; idrObj.PreviousT = paymentDates[previousIndex]; } idrObj.DurationDayCount = (idrObj.T - idrObj.PreviousT).Days; var t_1 = dataset.PaymentDate.Value.AddDays(-1); while (!CalendarCache.IsTradingDay(t_1)) { t_1 = t_1.AddDays(-1); } idrObj.T_1 = t_1; idrObj.Date = DateTime.Today; idrObj.TaskEndTime = m_timeStamp; return(idrObj); }
/// <summary> /// Vector valuation function. /// </summary> public override void Value(ValuationResults valuationResults, PriceFactorList factors, BaseTimeGrid baseTimes) { PreValue(factors); TimeGridIterator tgi = new TimeGridIterator(fT); PVProfiles result = valuationResults.Profile; CashAccumulators accumulator = valuationResults.Cash; DealCreditLinkedNoteBase deal = (DealCreditLinkedNoteBase)fDeal; ISurvivalProb SP = GetSurvivalProbability(factors); RecoveryRate RR = GetRecoveryRate(factors); CreditRating CR = GetCreditRating(factors); double tEffective = CalcUtils.DaysToYears(deal.Effective_Date - factors.BaseDate); double scale = (deal.Buy_Sell == BuySell.Buy) ? +deal.Notional_Amount : -deal.Notional_Amount; double purchasePrice = Percentage.PercentagePoint * deal.Price; double couponRate = (deal.Coupon_Type == InterestRateType.Fixed) ? Percentage.PercentagePoint * deal.Coupon_Rate : 0.0; double couponSpread = (deal.Coupon_Type == InterestRateType.Fixed) ? 0.0 : BasisPoint.BasisPointValue * deal.Coupon_Spread; double indexTenor = (deal.Index_Tenor > 0.0) ? deal.Index_Tenor : deal.Coupon_Interval; using (var cache = Vector.Cache(factors.NumScenarios)) { bool[] hasDefaulted = (Respect_Default == YesNo.Yes) ? new bool[factors.NumScenarios] : null; Vector defaultTime = (Respect_Default == YesNo.Yes) ? cache.Get() : null; Vector historicalRecovery = (Respect_Default == YesNo.Yes) ? cache.GetClear() : null; if (hasDefaulted != null && CR != null) { DefaultTime(defaultTime, CR); } Vector npv = cache.Get(); Vector cash = cache.Get(); Vector pStart = cache.Get(); Vector pEnd = cache.Get(); Vector amount = cache.Get(); Vector recovery = cache.Get(); Vector dfLast = cache.Get(); Vector df = cache.Get(); cash.Clear(); var defaultedBeforeTheBaseDate = Respect_Default == YesNo.Yes && CreditRating.DefaultedBeforeBaseDate(CR, factors.BaseDate); while (tgi.Next()) { if (defaultedBeforeTheBaseDate) { npv.Clear(); result.AppendVector(tgi.Date, npv); break; } if (!deal.Principal_Guaranteed && Respect_Default == YesNo.Yes) { RealizedRecoveryRate(recovery, RR, tgi.T); } // Assume defaults are rare and start by valuing under all scenarios without realized defaults // Value of principal repayment SurvivalProbability(pEnd, factors, SP, tgi.T, fT.fLast); fDiscountRate.GetValue(dfLast, tgi.T, fT.fLast); if (deal.Principal_Guaranteed) { npv.Assign(dfLast); } else { npv.Assign(dfLast * pEnd); } if (accumulator != null && tgi.T == fT.fLast) { cash.Assign(npv); } // Value of coupons for (int i = PayDates.Count - 1; i >= 0 && tgi.Date <= PayDates[i]; --i) { double tPay = CalcUtils.DaysToYears(PayDates[i] - factors.BaseDate); double tReset = CalcUtils.DaysToYears(ResetDates[i] - factors.BaseDate); double tPrevious = Math.Max(tgi.T, tReset); SurvivalProbability(pStart, factors, SP, tgi.T, tPrevious); if (deal.Coupon_Type == InterestRateType.Floating) { // Forecast a coupon, add the spread InterestRateUtils.LiborRate(amount, fForecastRate, tgi.T, tReset, tReset, tReset + indexTenor, deal.Index_Day_Count); amount.Add(couponSpread); amount.MultiplyBy(Accruals[i]); } else { // Fixed coupon amount.Assign(couponRate * Accruals[i]); } // The value of the coupon if no default npv.Add(amount * fDiscountRate.Get(tgi.T, tPay) * pEnd); if (accumulator != null && tgi.T == tPay) { cash.Assign(amount); } // The recovery value on default - assume guaranteed principal paid at end, recovery paid immediately if (!deal.Principal_Guaranteed) { npv.Add(fDiscountRate.Get(tgi.T, 0.5 * (tPay + tPrevious)) * (pStart - pEnd) * PricingRecoveryRate(SP)); } pEnd.DestructiveAssign(pStart); } // Now check for realized default scenario by scenario, overwriting NPV and cash as appropriate if (Respect_Default == YesNo.Yes && defaultTime != null) { if (tgi.T < tEffective) { fDiscountRate.GetValue(df, tgi.T, tEffective); } for (int i = 0; i < npv.Count; ++i) { if (defaultTime[i] > tgi.T) { continue; } if (deal.Principal_Guaranteed) { npv[i] = dfLast[i]; // full principal paid at maturity } else { if (!hasDefaulted[i]) { historicalRecovery[i] = recovery[i]; // record the historical recovery rate } if (tgi.T < tEffective) { npv[i] = df[i] * historicalRecovery[i]; // The discounted recovery value of the principal will be paid out on the effective date } else if (tgi.T == tEffective || !hasDefaulted[i]) { npv[i] = historicalRecovery[i]; // The full recovery amount is paid out } else { npv[i] = 0.0; // default is in the past but we are after effective date; settlement has already occurred. } } hasDefaulted[i] = true; } } // Value of purchase price if (tgi.T < tEffective) { npv.Add(-purchasePrice * fDiscountRate.Get(tgi.T, tEffective)); } else if (tgi.T == tEffective) { npv.Add(-purchasePrice); if (accumulator != null) { cash.Add(-purchasePrice); } } result.AppendVector(tgi.Date, scale * npv * fFxRate.Get(tgi.T)); if (accumulator != null) { accumulator.Accumulate(fFxRate, tgi.Date, scale * cash); } } // After maturity result.Complete(fT); } }
/// <summary> /// Value the deal from given base date, price factors and time grid. /// </summary> public void Value(PVProfiles pvResults, CashAccumulators cashResults, double baseDate, IInterestRate discountRate, IInterestRate forecastRate1, IInterestRate forecastRate2, IFxRate fxRate, TimeGrid timeGrid, int numScenarios) { var tgi = new TimeGridIterator(timeGrid); var deal = (FloatingInterestCashflowInterpolatedDeal)Deal; bool hasRate1 = deal.HasRate1(); bool hasRate2 = deal.HasRate2(); double scale = deal.Buy_Sell == BuySell.Buy ? +deal.Principal : -deal.Principal; double tPay = CalcUtils.DaysToYears(fPaymentDate - baseDate); double tReset = CalcUtils.DaysToYears(deal.Reset_Date - baseDate); double tRateStart = CalcUtils.DaysToYears(deal.Rate_Start_Date - baseDate); double tRateEnd1 = hasRate1 ? CalcUtils.DaysToYears(fRate1EndDate - baseDate) : 0.0; double tRateEnd2 = hasRate2 ? CalcUtils.DaysToYears(fRate2EndDate - baseDate) : 0.0; double tRateEnd12 = tRateEnd2 - tRateEnd1; // Time from rate 1 end date to rate 2 end date. double tAccrualEnd = CalcUtils.DaysToYears(deal.Accrual_End_Date - baseDate); double interpCoefficient = Math.Abs(tRateEnd12) >= CalcUtils.MinTime ? (tAccrualEnd - tRateEnd1) / tRateEnd12 : 0.0; // Coefficient used to calculate interpolated rate. VectorEngine.For(tgi, () => { using (var cache = Vector.Cache(numScenarios)) { Vector pv = cache.Get(); if (tgi.Date <= fPaymentDate && fPaymentDate > fCutoffDate) { Vector interpRate = cache.GetClear(); Vector rate1 = cache.GetClear(); Vector rate2 = cache.GetClear(); if (hasRate1) { if (fKnownResetRate1.HasValue) { rate1.Assign(fKnownResetRate1.Value); } else { InterestRateUtils.LiborRate(rate1, forecastRate1, tgi.T, tReset, tRateStart, tRateEnd1, fRate1YearFraction); } } if (hasRate2) { if (fKnownResetRate2.HasValue) { rate2.Assign(fKnownResetRate2.Value); } else { InterestRateUtils.LiborRate(rate2, forecastRate2, tgi.T, tReset, tRateStart, tRateEnd2, fRate2YearFraction); } } if (hasRate1 && hasRate2) { if (Math.Abs(tRateEnd12) >= CalcUtils.MinTime) { interpRate.Assign(rate1 + interpCoefficient * (rate2 - rate1)); } else { interpRate.Assign(0.5 * rate1 + 0.5 * rate2); } } else { interpRate.Assign(hasRate1 ? rate1 : rate2); } // Round the calculated rate, regardless whether the valuation date is before or after the reset date. CFFloatingInterestList.RoundRateTo(deal.Interpolated_Rate_Rounding, interpRate); pv.Assign(scale * (interpRate + deal.Margin) * fAccrualYearFraction); CFFixedList.RoundCashflow(pv, Cashflow_Rounding); if (tgi.Date < fPaymentDate) { pv.MultiplyBy(discountRate.Get(tgi.T, tPay)); } else if (tgi.Date == fPaymentDate) { cashResults.Accumulate(fxRate, fPaymentDate, pv); } } else { pv.Clear(); } pvResults.AppendVector(tgi.Date, pv * fxRate.Get(tgi.T)); } }); // After maturity pvResults.Complete(timeGrid); }
protected CDOValuationParameters(DealCDO deal, PriceFactorList factors) { DF = DiscountRate.Get(factors, InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency)); X = factors.GetInterface <IFxRate>(deal.Currency); }
/// <summary> /// Register required price factors. /// </summary> public override void RegisterFactors(PriceFactorList factors, ErrorList errors) { var deal = (CalendarSpreadOption)Deal; // Register forward price factor - using a reference price. var referencePrice = factors.RegisterInterface <IReferencePrice>(deal.Reference_Type); // Register volatility price factor based on an explicit user-defined property. // Default to Reference Type if Reference Vol Type is not set. if (string.IsNullOrEmpty(deal.Reference_Vol_Type)) { factors.Register <ReferenceVol>(deal.Reference_Type); } else { factors.Register <ReferenceVol>(deal.Reference_Vol_Type); } // Register FX rate price factors. factors.RegisterInterface <IFxRate>(deal.Currency); factors.RegisterInterface <IFxRate>(deal.DealCurrency()); factors.RegisterInterface <IFxRate>(factors.BaseCcyCode); factors.RegisterInterface <IFxRate>(referencePrice.DomesticCurrency()); // Register correlation price factor. factors.Register <ForwardPriceCorrelations>(referencePrice.GetForwardPrice()); // Register forward price sample price factor for reference prices. var sample = factors.Register <ForwardPriceSample>(deal.Sampling_Type); if (!string.IsNullOrWhiteSpace(sample.Sampling_Convention)) { sample.Prepare(); // Validate period 1. IEnumerable <ContractPeriod> contractPeriods = deal.GetContractPeriods(deal.Period_Start_1, deal.Period_End_1); sample.ValidateRange(contractPeriods, "Set 1 of sample dates", deal, errors); // Validate period 2. contractPeriods = deal.GetContractPeriods(deal.Period_Start_2, deal.Period_End_2); sample.ValidateRange(contractPeriods, "Set 2 of sample dates", deal, errors); } // Register interest rate price factor to get discount factor. factors.RegisterInterface <IInterestRate>(deal.Currency); // Register interest rate price factor for discount rate currency. if (!string.IsNullOrEmpty(deal.Discount_Rate)) { string discountRateCurrency = factors.RegisterInterface <IInterestRate>(InterestRateUtils.GetRateId(deal.Discount_Rate, deal.Currency)).GetCurrency(); if (!string.IsNullOrEmpty(discountRateCurrency) && discountRateCurrency != deal.Currency) { errors.Add(ErrorLevel.Error, "Currency and currency of Discount_Rate must be the same"); } } }
/// <summary> /// Value a caplet or floorlet under the 1 factor Hull-White model. /// </summary> public override void Value(Vector pv, Vector cash, double baseDate, double valueDate, ISACCRResult saccrResult, IIntraValuationDiagnosticsWriter intraValuationDiagnosticsWriter) { int count = fCashflows.Count(); bool forecastIsDiscount = ReferenceEquals(fForecastRate, fDiscountRate); // time of dfStart and dfEnd double tDfStart = double.NegativeInfinity; double tDfEnd = double.NegativeInfinity; using (var cache = Vector.CacheLike(pv)) { // Shared between loops Vector dfStart = cache.Get(); Vector dfEnd = cache.Get(); VectorEngine.For(0, count, LoopDirection.Backwards, i => { using (var innerCache = Vector.CacheLike(pv)) { CFFloatingInterest cashflow = fCashflows[i]; if (cashflow.Payment_Date < valueDate || cashflow.Payment_Date <= fCutoffDate) { return(LoopAction.Break); } Vector rate = innerCache.Get(); Vector dfPay = innerCache.Get(); Vector stdDev = innerCache.GetClear(); Vector amount = innerCache.GetClear(); GeneralCashflowProperties properties = fCashflows.GetCashflowProperties(i); double tPay = CalcUtils.DaysToYears(cashflow.Payment_Date - baseDate); bool haveDfPay = false; if (forecastIsDiscount && tPay == tDfStart) { dfPay.Assign(dfStart); haveDfPay = true; } using (IntraValuationDiagnosticsHelper.StartCashflow(intraValuationDiagnosticsWriter)) using (var volatilitiesAtDateStore = IntraValuationDiagnosticsHelper.CreateVolatilitiesAtDateStore(intraValuationDiagnosticsWriter, pv.Count)) { cashflow.AddPropertiesToIntraValuationDiagnostics(intraValuationDiagnosticsWriter); // Standard Libor implies single reset. var reset = cashflow.Resets.Single(); if (reset.IsKnown(baseDate)) { rate.Assign(reset.Known_Rate); } else { double tValue = CalcUtils.DaysToYears(valueDate - baseDate); double tReset = CalcUtils.DaysToYears(reset.Reset_Date - baseDate); double tStart = CalcUtils.DaysToYears(reset.Rate_Start_Date - baseDate); double tEnd = CalcUtils.DaysToYears(reset.Rate_End_Date - baseDate); // Reset is a historical or forward Libor rate. InterestRateUtils.LiborRate(rate, fForecastRate, tValue, tReset, tStart, tEnd, reset.Rate_Year_Fraction, dfStart, ref tDfStart, dfEnd, ref tDfEnd); if (tReset > tValue) { GetStandardDeviation(stdDev, tValue, tReset, tStart, tEnd); volatilitiesAtDateStore.Add(valueDate, reset.Reset_Date, stdDev); } } if (!haveDfPay && forecastIsDiscount && tPay == tDfEnd) { dfPay.Assign(dfEnd); haveDfPay = true; } // Add swaplet value amount.AddProduct(properties.Swap_Multiplier, rate); double tau = reset.Rate_Year_Fraction; rate.Assign(1.0 + rate * tau); // Add cap and floor option values. AddOptionValue(amount, OptionType.Call, rate, properties.Cap_Strike, stdDev, tau, properties.Cap_Multiplier); AddOptionValue(amount, OptionType.Put, rate, properties.Floor_Strike, stdDev, tau, properties.Floor_Multiplier); amount.Assign(fBuySellSign * (cashflow.Fixed_Amount + cashflow.Notional * (amount + cashflow.Margin) * cashflow.Accrual_Year_Fraction)); IntraValuationDiagnosticsHelper.AddImpliedVolatilities(intraValuationDiagnosticsWriter, volatilitiesAtDateStore); CFFixedList.RoundCashflow(amount, Cashflow_Rounding); CFFixedList.UpdatePvAndCash(cashflow, baseDate, valueDate, haveDfPay ? null : fDiscountRate, null, amount, dfPay, pv, cash, intraValuationDiagnosticsWriter); } } return(LoopAction.Continue); }); } }