public override IPricingResult Calculate(InterestRateSwap trade, IMarketCondition market, PricingRequest request) { var cfEngine = new CashflowProductEngine <SwapLeg>(); var leg1Result = cfEngine.Calculate(trade.FixedLeg, market, PricingRequest.All); var mkt4Leg2 = market.UpdateCondition(new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.FgnDiscountCurve.Value), new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, market.FgnFixingCurve.Value)); var leg2Result = cfEngine.Calculate(trade.FloatingLeg, mkt4Leg2, PricingRequest.All); var result = new PricingResult(market.ValuationDate, request); if (result.IsRequested(PricingRequest.Pv)) { result.Pv = leg1Result.Pv + leg2Result.Pv; } if (result.IsRequested(PricingRequest.Dv01)) { result.Dv01 = leg1Result.Dv01 + leg2Result.Dv01; } if (result.IsRequested(PricingRequest.Pv01)) { var bumpedIrs = trade.Bump(1); var bumpedPv = new CashflowProductEngine <InterestRateSwap>().Calculate(bumpedIrs, market, PricingRequest.Pv).Pv; result.Pv01 = bumpedPv - result.Pv; } if (result.IsRequested(PricingRequest.Ai)) { result.Ai = leg1Result.Ai + leg2Result.Ai; } if (result.IsRequested(PricingRequest.Cashflow)) { result.Cashflows = leg1Result.Cashflows.Union(leg2Result.Cashflows).ToArray(); } if (result.IsRequested(PricingRequest.KeyRateDv01)) { result.KeyRateDv01 = PricingResultExtension.Aggregate(leg1Result.KeyRateDv01, leg2Result.KeyRateDv01); } return(result); }
private static object AggregatedDataByType(Dictionary <string, IPricingResult> pricingResults, PropertyInfo propertyInfo) { object result = null; if (propertyInfo.PropertyType == typeof(Dictionary <string, double>)) { var propertyValuesArray = pricingResults.Select(x => propertyInfo.GetValue(x.Value, null)).ToArray(); var dicresult = propertyValuesArray.Cast <Dictionary <string, double> >().Aggregate <Dictionary <string, double>, Dictionary <string, double> >(null, (current, dic) => PricingResultExtension.Aggregate(current, dic)); result = dicresult.To2DArray(); } else if (propertyInfo.PropertyType == typeof(Double)) { var propertyValuesArray = pricingResults.Select(x => propertyInfo.GetValue(x.Value, null)).ToArray(); result = propertyValuesArray.Cast <double>().Aggregate <double, double>(double.NaN, (current, dic) => PricingResultExtension.Aggregate(current, dic)); } else if (propertyInfo.PropertyType == typeof(Cashflow[])) { var propertyValuesArray = pricingResults.Select(x => propertyInfo.GetValue(x.Value, null)).ToArray(); var cashflowArray = propertyValuesArray.Cast <Cashflow[]>().Aggregate <Cashflow[], Cashflow[]>(null, (current, cashflow) => PricingResultExtension.Aggregate(current, cashflow)); var removedPropertiesNames = new List <string>() { "CalculationDetails" }; result = cashflowArray.ToLableData(removedPropertiesNames, typeof(Cashflow).GetProperties().Length - removedPropertiesNames.Count); } else { throw new NotImplementedException(); } return(result); }
/// <summary> /// 计算一个金融衍生品交易的定价和风险指标 /// </summary> /// <param name="trade">交易</param> /// <param name="market">市场数据对象</param> /// <param name="request">计算请求类型</param> /// <returns>计算结果</returns> public override IPricingResult Calculate(TTrade trade, IMarketCondition market, PricingRequest request) { var result = new PricingResult(market.ValuationDate, request); if (result.IsRequested(PricingRequest.Pv)) { result.Pv = CalcPv(trade, market); } if (result.IsRequested(PricingRequest.Carry)) { result.Carry = CalcCarry(trade, market); } if (result.IsRequested(PricingRequest.Dv01)) { if (double.IsNaN(result.Pv)) { result.Pv = CalcPv(trade, market); } var mktDown = market.FixingCurve.HasValue ? market.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.DiscountCurve.Value.Shift(1)), new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, market.FixingCurve.Value.Shift(1))) : market.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.DiscountCurve.Value.Shift(1))); result.Dv01 = CalcPv(trade, mktDown) - result.Pv; } if (result.IsRequested(PricingRequest.Cashflow)) { result.Cashflows = trade.GetCashflows(market, false); } //Ai and AiEod are mutually exclusive requests var isEod = result.IsRequested(PricingRequest.AiEod); if (result.IsRequested(PricingRequest.Ai) || result.IsRequested(PricingRequest.AiEod)) { if (result.Cashflows == null || result.Cashflows.Length == 0) { result.Cashflows = trade.GetCashflows(market, false); } result.Ai = trade.GetAccruedInterest(market.ValuationDate, market, isEod); } if (result.IsRequested(PricingRequest.KeyRateDv01)) { if (double.IsNaN(result.Pv)) { result.Pv = CalcPv(trade, market); } var dc = new Dictionary <string, CurveRisk[]>(); var fc = new Dictionary <string, CurveRisk[]>(); Parallel.Invoke( () => CalcDiscountDv01(trade, market, result.Pv, ref dc), () => CalcResetDv01(trade, market, result.Pv, ref fc) ); result.KeyRateDv01 = PricingResultExtension.Aggregate(dc, fc); } if (result.IsRequested(PricingRequest.FairQuote)) { result.FairQuote = GetFairQuote(trade, market); } if (result.IsRequested(PricingRequest.MacDuration)) { if (result.Cashflows == null || result.Cashflows.Length == 0) { result.Cashflows = trade.GetCashflows(market, false); } var weightedCf = 0.0; var totalCf = 0.0; foreach (var cashflow in result.Cashflows) { if (cashflow.PaymentDate > market.ValuationDate) { var t = market.DiscountCurve.Value.DayCount.CalcDayCountFraction(market.ValuationDate, cashflow.PaymentDate); var df = market.DiscountCurve.Value.GetDf(market.ValuationDate, cashflow.PaymentDate); weightedCf += cashflow.PaymentAmount * df * t; totalCf += cashflow.PaymentAmount * df; } } result.MacDuration = weightedCf / totalCf; } if (result.IsRequested(PricingRequest.Pv01)) { result.Pv01 = CalcPv01(trade, market, result.Pv); } Date valueDate = result.ValuationDate; if (result.IsRequested(PricingRequest.ProductSpecific)) { var yieldCurve = market.DiscountCurve.Value; #region var psDict = new Dictionary <string, Dictionary <string, RateRecord> >(); var dayGap = new DayGap("+0BD"); var T = (trade is InterestRateSwap) ? (trade as InterestRateSwap).FloatingLeg : trade as SwapLeg; //forward rate points var tenors = new[] { "1D", "7D", "3M", "1Y" }; var fwdStartInTenors = new List <string> { "1D", "1W", "2W", "1M", "2M", "3M", "4M", "5M", "6M", "7M", "8M", "9M", "10M", "11M", "1Y" }; var totalMonths = Convert.ToInt16((yieldCurve.KeyPoints.Last().Item1 - yieldCurve.KeyPoints.First().Item1) / 30.0) + 1; for (var i = 15; i <= totalMonths; i += 3) { fwdStartInTenors.Add(i + "M"); } foreach (var tenor in tenors) { var fwdRates = new Dictionary <string, RateRecord>(); var fwdTerm = new Term(tenor); foreach (var fwdStartInTenor in fwdStartInTenors) { var fwdStartDate = dayGap.Get(T.Calendar, new Term(fwdStartInTenor).Next(valueDate)); var fwdEndDate = dayGap.Get(T.Calendar, fwdTerm.Next(fwdStartDate)); if (fwdEndDate < yieldCurve.KeyPoints.Last().Item1) { fwdRates[fwdStartInTenor] = new RateRecord() { Date = fwdStartDate.ToString(), Rate = yieldCurve.GetForwardRate(fwdStartDate, fwdTerm) }; } } psDict["forwardrates" + tenor] = fwdRates; } //spot rate var spotRates = new Dictionary <string, RateRecord>(); var spotInTenors = fwdStartInTenors; foreach (var spotInTenor in spotInTenors) { var spotDate = dayGap.Get(T.Calendar, new Term(spotInTenor).Next(valueDate)); if (spotDate <= yieldCurve.KeyPoints.Last().Item1) { spotRates[spotInTenor] = new RateRecord { Date = spotDate.ToString(), Rate = yieldCurve.ZeroRate(valueDate, spotDate, Compound.Simple) }; } } psDict["spotRates"] = spotRates; //key rates var rates = new Dictionary <string, RateRecord>(); var ccTenors = yieldCurve.GetKeyTenors().ToArray(); var mktInstruments = yieldCurve.MarketInstruments; if (mktInstruments != null) { if (mktInstruments.Length != ccTenors.Length) { throw new PricingBaseException("Number of calibration instruments mismatches number of calibrated points!"); } } for (var i = 0; i < ccTenors.Count(); ++i) { //var spotDate = mktInstruments != null ? mktInstruments[i].Instrument.GetClibrationDate() : dayGap.Get(T.Calendar, new Term(ccTenors[i]).Next(valueDate)); var spotDate = dayGap.Get(T.Calendar, new Term(ccTenors[i]).Next(valueDate)); rates[ccTenors[i]] = new RateRecord() { ContinuousRate = yieldCurve.ZeroRate(valueDate, spotDate), Date = spotDate.ToString(), DiscountFactor = yieldCurve.GetDf(valueDate, spotDate), Rate = mktInstruments == null?yieldCurve.GetSpotRate(spotDate) : mktInstruments[i].TargetValue, ProductType = mktInstruments == null ? "None" : (mktInstruments[i].Instrument is Deposit) ? "Index" : "Swap", ZeroRate = yieldCurve.ZeroRate(valueDate, spotDate, Compound.Simple), Term = ccTenors[i] }; } psDict["rates"] = rates; //discount at cash flow dates var dfs = new Dictionary <string, RateRecord>(); var dates = result.Cashflows.Select(x => x.PaymentDate); foreach (var date in dates) { dfs[date.ToString()] = new RateRecord { DiscountFactor = yieldCurve.GetDf(date) }; } psDict["discountfactor"] = dfs; //qb rate return result.ProductSpecific = psDict; #endregion } return(result); }