Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #3
0
 public BondFuturesEngine(TInterestRateModel interestRateModel, int steps)
 {
     _interestRateModel = interestRateModel;
     _steps             = steps;
     _bondEngine        = new BondEngine();
 }
Exemple #4
0
 public BondEngineCn(IBondYieldPricer bondYieldPricer = null)
 {
     _bondYieldPricer = bondYieldPricer ?? new BondYieldPricer();
     _bondEngine      = new BondEngine(_bondYieldPricer);
 }