private Dictionary <string, Dictionary <string, RateRecord> > CalcMktFuturePrice(BondFutures bondFuture, IMarketCondition market) { var psDict = new Dictionary <string, Dictionary <string, RateRecord> >(); var fundingCurve = market.RiskfreeCurve.HasValue ? market.RiskfreeCurve.Value : YieldCurve.GetConstRateCurve(market.DiscountCurve.Value, 0.0); var reinvestmentCurve = market.DiscountCurve.HasValue ? market.DiscountCurve.Value : YieldCurve.GetConstRateCurve(market.RiskfreeCurve.Value, 0.0); var bonds = bondFuture.Deliverables; var length = bonds.Length; var aiAtStart = bonds.Select(x => x.GetAccruedInterest(market.ValuationDate, market, false)).ToArray(); var aiAtEnd = bonds.Select(x => x.GetAccruedInterest(bondFuture.UnderlyingMaturityDate, market, false)).ToArray(); var cf = bonds.Select(x => bondFuture.GetConversionFactor(x, market)).ToArray(); var coupons = new double[length]; var timeWeightedCoupon = new double[length]; var couponsAccruedByReinvestment = new double[length]; for (var i = 0; i < length; ++i) { var bond = bonds[i]; var cashflows = bond.GetCashflows(market, false).Where(x => x.PaymentDate > market.ValuationDate && x.PaymentDate <= bondFuture.UnderlyingMaturityDate).ToArray(); if (cashflows.Any()) { coupons[i] = cashflows.Sum(x => x.PaymentAmount); timeWeightedCoupon[i] = cashflows.Sum(x => x.PaymentAmount * bondFuture.DayCount.CalcDayCountFraction(x.PaymentDate, bondFuture.UnderlyingMaturityDate)); couponsAccruedByReinvestment[i] = cashflows.Sum(x => x.PaymentAmount * (reinvestmentCurve.GetCompoundedRate2(x.PaymentDate, bondFuture.UnderlyingMaturityDate) - 1.0)); } else { coupons[i] = 0.0; timeWeightedCoupon[i] = 0.0; couponsAccruedByReinvestment[i] = 0.0; } } var interestIncome = bonds.Select((x, i) => aiAtEnd[i] - aiAtStart[i] + coupons[i] + couponsAccruedByReinvestment[i]).ToArray(); //var interestIncome = bonds.Select((x, i) => aiAtEnd[i] - aiAtStart[i] + coupons[i]).ToArray(); var dirtyPrice = new double[length]; var cleanPrice = new double[length]; var ytm = new double[length]; var modifiedDuration = new double[length]; var bondEngine = new BondEngine(); for (var i = 0; i < length; ++i) { var bResult = bondEngine.Calculate(bonds[i], market, PricingRequest.Ytm | PricingRequest.ModifiedDuration); dirtyPrice[i] = bResult.DirtyPrice; cleanPrice[i] = bResult.CleanPrice; ytm[i] = bResult.Ytm; } var interestCostRate = fundingCurve.GetCompoundedRate2(market.ValuationDate, bondFuture.UnderlyingMaturityDate) - 1.0; var interestCost = dirtyPrice.Select(x => x * interestCostRate).ToArray(); var futurePrice = new double[length]; var irr = new double[length]; var basis = new double[length]; var pnl = new double[length]; var netBasis = new double[length]; var invoicePrice = new double[length]; var margin = new double[length]; var spread = new double[length]; var fundingRate = fundingCurve.GetSpotRate(0.0); var compoundedRate = fundingCurve.GetCompoundedRate2(market.ValuationDate, bondFuture.UnderlyingMaturityDate); var bondPricesCompounedByFunding = bonds.Select((x, i) => dirtyPrice[i] * compoundedRate).ToArray(); for (var i = 0; i < bonds.Length; ++i) { futurePrice[i] = (bondPricesCompounedByFunding[i] - aiAtEnd[i] - coupons[i]) / cf[i]; var newMarket = market.UpdateCondition( new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, market.MktQuote.Value.UpdateKey(bondFuture.Id, Tuple.Create(PriceQuoteType.Dirty, futurePrice[i])))); var yieldPricer = new BondFuturesYieldPricer(bondFuture, newMarket); var tmpResult = yieldPricer.CalcEquation("FromFuturesPriceAndBondPrice"); invoicePrice[i] = tmpResult["InvoicePrice"][bonds[i].Id].Rate; margin[i] = tmpResult["Margin"][bonds[i].Id].Rate; basis[i] = tmpResult["Basis"][bonds[i].Id].Rate; pnl[i] = tmpResult["PnL"][bonds[i].Id].Rate; netBasis[i] = tmpResult["NetBasis"][bonds[i].Id].Rate; irr[i] = tmpResult["Irr"][bonds[i].Id].Rate; spread[i] = irr[i] - fundingRate; } psDict["FuturesPrice"] = futurePrice.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["BondDirtyPrice"] = dirtyPrice.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["BondCleanPrice"] = cleanPrice.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["BondYieldToMaturity"] = ytm.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["ConversionFactor"] = cf.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["AiStart"] = aiAtStart.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["AiEnd"] = aiAtEnd.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["Coupon"] = coupons.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["InterestIncome"] = interestIncome.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["InterestCost"] = interestCost.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["PnL"] = pnl.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["InvoicePrice"] = invoicePrice.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["Margin"] = margin.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["Spread"] = spread.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["Irr"] = irr.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["Basis"] = basis.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["NetBasis"] = netBasis.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["ModifiedDuration"] = modifiedDuration.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); psDict["TimeWeightedCoupon"] = timeWeightedCoupon.Select((x, i) => Tuple.Create(bonds[i].Id, new RateRecord { Rate = x })).ToDictionary(x => x.Item1, x => x.Item2); return(psDict); }
public override IPricingResult GetRisks(Forward <Bond> trade, IMarketCondition market, PricingRequest pricingRequest) { var result = new PricingResult(market.ValuationDate, pricingRequest); var bondEngine = new BondEngine(); var bMarket = market.UpdateCondition(new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.UnderlyingDiscountCurve.Value)); if (result.IsRequested(PricingRequest.Dv01)) { var bondZeroSpread = BondPricingFunctions.ZeroSpread(trade.Underlying, bMarket); IMarketCondition bondMktUp; IMarketCondition bondMktDown; if (market.FixingCurve.HasValue) { bondMktUp = bMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, bMarket.FixingCurve.Value.Shift(1)), new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(1).GetSpreadedCurve(new ZeroSpread(bondZeroSpread))) ); bondMktDown = bMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, bMarket.FixingCurve.Value.Shift(-1)), new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(-1).GetSpreadedCurve(new ZeroSpread(bondZeroSpread))) ); } else { bondMktUp = bMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(1).GetSpreadedCurve(new ZeroSpread(bondZeroSpread))) ); bondMktDown = bMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(-1).GetSpreadedCurve(new ZeroSpread(bondZeroSpread))) ); } var fwdMarket = market.UpdateCondition(new UpdateMktConditionPack <ISpread>(x => x.CreditSpread, new ZeroSpread(bondZeroSpread))); var upPv = bondEngine.Calculate(trade.Underlying, bondMktUp, PricingRequest.Pv).Pv; var downPv = bondEngine.Calculate(trade.Underlying, bondMktDown, PricingRequest.Pv).Pv; if (fwdMarket.FixingCurve.HasValue) { var fwdMktUp = fwdMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, bMarket.FixingCurve.Value.Shift(1)), new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(1)), new UpdateMktConditionPack <IYieldCurve>(x => x.UnderlyingDiscountCurve, bMarket.UnderlyingDiscountCurve.Value.Shift(1)), new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, bMarket.MktQuote.Value.UpdateKey(trade.Underlying.Id, Tuple.Create(PriceQuoteType.Dirty, upPv))) ); var fwdMktDown = fwdMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, bMarket.FixingCurve.Value.Shift(-1)), new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(-1)), new UpdateMktConditionPack <IYieldCurve>(x => x.UnderlyingDiscountCurve, bMarket.UnderlyingDiscountCurve.Value.Shift(-1)), new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, bMarket.MktQuote.Value.UpdateKey(trade.Underlying.Id, Tuple.Create(PriceQuoteType.Dirty, downPv))) ); result.Dv01 = (CalcPv(trade, fwdMktDown) - CalcPv(trade, fwdMktUp)) / 2.0; } else { var fwdMktUp = fwdMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(1)), new UpdateMktConditionPack <IYieldCurve>(x => x.UnderlyingDiscountCurve, bMarket.UnderlyingDiscountCurve.Value.Shift(1)), new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, bMarket.MktQuote.Value.UpdateKey(trade.Underlying.Id, Tuple.Create(PriceQuoteType.Dirty, upPv))) ); var fwdMktDown = fwdMarket.UpdateCondition( new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, bMarket.DiscountCurve.Value.Shift(-1)), new UpdateMktConditionPack <IYieldCurve>(x => x.UnderlyingDiscountCurve, bMarket.UnderlyingDiscountCurve.Value.Shift(-1)), new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, bMarket.MktQuote.Value.UpdateKey(trade.Underlying.Id, Tuple.Create(PriceQuoteType.Dirty, downPv))) ); result.Dv01 = (CalcPv(trade, fwdMktDown) - CalcPv(trade, fwdMktUp)) / 2.0; } } if (result.IsRequested(PricingRequest.Dv01Underlying)) { var factor = trade.Notional / trade.Underlying.Notional; result.Dv01Underlying = bondEngine.Calculate(trade.Underlying, bMarket, PricingRequest.Dv01).Dv01 *factor; } return(result); }
public BondFuturesEngine(TInterestRateModel interestRateModel, int steps) { _interestRateModel = interestRateModel; _steps = steps; _bondEngine = new BondEngine(); }
public BondEngineCn(IBondYieldPricer bondYieldPricer = null) { _bondYieldPricer = bondYieldPricer ?? new BondYieldPricer(); _bondEngine = new BondEngine(_bondYieldPricer); }