Пример #1
0
 public HoldingPeriodEngine()
 {
     _bondEngine      = new BondEngineCn(new BondYieldPricerCn());
     _roundCleanPrice = true;
 }
Пример #2
0
        public override IPricingResult Calculate(BondFutures bondFuture, IMarketCondition market, PricingRequest request)
        {
            var beginValuation = DateTime.Now;
            var pricingRequest = CheckParameterCondition(bondFuture, market, request);

            //if (result.IsRequested(PricingRequest.Dv01))
            //{
            //	result.Dv01 = CalcDv01(bondFuture, market);
            //}

            var result = new PricingResult(market.ValuationDate, pricingRequest);

            //if (result.IsRequested(PricingRequest.Pv))
            //{
            //    result.Pv = CalcPv(bondFuture, market);
            //}

            if (result.IsRequested(PricingRequest.DirtyPrice))
            {
                result.DirtyPrice = market.MktQuote.Value.Where(x => x.Key == bondFuture.Id).Select(x => x.Value.Item2).First() * bondFuture.Notional / 100;
            }

            if (result.IsRequested(PricingRequest.ConvertFactors))
            {
                result.ConvertFactors = CalcConvertFactors(bondFuture, market);
            }

            if (result.IsRequested(PricingRequest.Irr) || result.IsRequested(PricingRequest.Pv01) ||
                result.IsRequested(PricingRequest.KeyRateDv01) ||
                result.IsRequested(PricingRequest.ZeroSpread) || result.IsRequested(PricingRequest.ZeroSpreadDelta) ||
                result.IsRequested(PricingRequest.UnderlyingPv) || result.IsRequested(PricingRequest.Basis) ||
                result.IsRequested(PricingRequest.Convexity) || result.IsRequested(PricingRequest.Ytm) ||
                result.IsRequested(PricingRequest.CheapestToDeliver) ||
                result.IsRequested(PricingRequest.ModifiedDuration) || result.IsRequested(PricingRequest.MacDuration)
                )
            {
                //TODO:  wierd update logic, why bother?
                var mktQuote     = market.MktQuote.Value.Keys.Where(quoteKey => !quoteKey.Contains(bondFuture.Id + "_")).ToDictionary(quoteKey => quoteKey, quoteKey => market.MktQuote.Value[quoteKey]);
                var updateMarket = market.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, mktQuote));
                var yieldPricer  = new BondFuturesYieldPricer(bondFuture, updateMarket);

                //calculate convert factors
                if (!result.ConvertFactors.Any())
                {
                    result.ConvertFactors = CalcConvertFactors(bondFuture, market);
                }
                var convertFactors = result.ConvertFactors;

                //calculate IRR
                result.ProductSpecific = yieldPricer.CalcEquation("FromFuturesPriceAndBondPrice");

                //calculate pv01
                var maxIrr    = result.ProductSpecific["Irr"].Values.Select(x => x.Rate).Max();
                var ctdBondId = result.ProductSpecific["Irr"].First(x => x.Value.Rate == maxIrr).Key;
                var ctdBond   = bondFuture.Deliverables.First(x => x.Id == ctdBondId);
                var cf        = convertFactors[ctdBondId];
                var scaling   = bondFuture.Notional / (100.0 * cf);

                var engine = new BondEngineCn();

                result.CheapestToDeliver = ctdBondId;

                //two risks here are CTD risk, not bond futures risk
                var resultCTD = engine.Calculate(ctdBond, market, PricingRequest.All);
                result.ZeroSpread   = resultCTD.ZeroSpread;
                result.UnderlyingPv = resultCTD.Pv * scaling;
                result.Basis        = yieldPricer.CalcFutureCtdBasis(ctdBond, cf);
                result.Ytm          = resultCTD.Ytm;
                result.MacDuration  = resultCTD.MacDuration;

                result.ModifiedDuration       = resultCTD.ModifiedDuration;
                result.Convexity              = resultCTD.Convexity;
                result.DollarConvexity        = resultCTD.DollarConvexity * scaling;        // 1% price impact
                result.DollarModifiedDuration = resultCTD.DollarModifiedDuration * scaling; // same order of magnitutude of CTD dollar modifiedDuration, good for pnl attribution

                //convert to bond futures risk
                result.Pv01 = resultCTD.Pv01 * scaling;   // underlying pv01 is
                foreach (var kvp in resultCTD.KeyRateDv01)
                {
                    foreach (var risk in kvp.Value)
                    {
                        risk.Risk *= scaling;
                    }
                }
                result.KeyRateDv01     = resultCTD.KeyRateDv01;
                result.ZeroSpreadDelta = resultCTD.ZeroSpreadDelta * scaling;
            }
            if (result.IsRequested(PricingRequest.FairQuote))
            {
                var mktQuote     = market.MktQuote.Value.Keys.Where(quoteKey => !quoteKey.Equals(bondFuture.Id)).ToDictionary(quoteKey => quoteKey, quoteKey => market.MktQuote.Value[quoteKey]);
                var updateMarket = market.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, mktQuote));
                var yieldPricer  = new BondFuturesYieldPricer(bondFuture, updateMarket);
                result.ProductSpecific = yieldPricer.CalcEquation("FromBondPriceAndIrr");
            }
            if (result.IsRequested(PricingRequest.MktQuote))
            {
                result.ProductSpecific = CalcMktFuturePrice(bondFuture, market);
            }
            if (result.IsRequested(PricingRequest.UnderlyingFairQuote))
            {
                var mktQuote     = market.MktQuote.Value.Keys.Where(quoteKey => quoteKey.Contains(bondFuture.Id)).ToDictionary(quoteKey => quoteKey, quoteKey => market.MktQuote.Value[quoteKey]);
                var updateMarket = market.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, Tuple <PriceQuoteType, double> > >(x => x.MktQuote, mktQuote));
                var yieldPricer  = new BondFuturesYieldPricer(bondFuture, updateMarket);
                result.ProductSpecific = yieldPricer.CalcEquation("FromFuturesPriceAndIrr");
            }


            var endValuation = DateTime.Now;

            result.CalcTimeInMilliSecond = (endValuation - beginValuation).TotalMilliseconds;
            return(result);
        }