public override IPricingResult Calculate(ConvertibleBond convertibleBond, IMarketCondition market, PricingRequest request)
        {
            var result = new PricingResult(market.ValuationDate, request);

            if (convertibleBond.ConversionOption == null)
            {
                result.Pv = market.MktQuote.Value[convertibleBond.Bond.Id].Item2;
            }
            else
            {
                var optionParts = _optionEngine.Calculate(convertibleBond.ConversionOption,
                                                          market.UpdateCondition(
                                                              new UpdateMktConditionPack <IYieldCurve>(x => x.DiscountCurve, market.RiskfreeCurve.Value)),
                                                          PricingRequest.All);

                //TODO:  refactor calculation here
                //(jira: http://139.196.190.223:8888/browse/QDP-255)
                result.Pv = market.MktQuote.Value[convertibleBond.Bond.Id].Item2 -
                            optionParts.Pv * convertibleBond.ConversionRatio;
                result.Delta = optionParts.Delta * convertibleBond.ConversionRatio;
                result.Gamma = optionParts.Gamma * convertibleBond.ConversionRatio;
                result.Vega  = optionParts.Vega * convertibleBond.ConversionRatio;
                result.Rho   = optionParts.Rho * convertibleBond.ConversionRatio;
            }
            //(jira: http://139.196.190.223:8888/browse/QDP-251)
            //Disable unnecessary and offending calc below
            //This will fail  14宝钢-E pricing and many other pricing when spot is high

            //var newMarket = market.UpdateCondition(new UpdateMktConditionPack<Dictionary<string, Tuple<PriceQuoteType, double>>>(x => x.MktQuote, market.MktQuote.Value.UpdateKey(convertibleBond.Bond.Id, Tuple.Create(PriceQuoteType.Dirty, result.Pv))));
            //var zeroSpread = BondPricingFunctions.ZeroSpread(convertibleBond.Bond, newMarket);
            //var bondMarket =
            //	market.UpdateCondition(new UpdateMktConditionPack<IYieldCurve>(x => x.DiscountCurve,
            //		market.DiscountCurve.Value.GetSpreadedCurve(new ZeroSpread(zeroSpread))));
            //var bondEngine = new BondEngine();
            //var bondResults = bondEngine.Calculate(convertibleBond.Bond, bondMarket, PricingRequest.All);

            return(result);
        }
Пример #2
0
        public void C7_11_2_ReverseConvertibleBondOnEquityBasket()
        {
            var cb = new ConvertibleBond(OptionType.Put, 5, 100, 0, 0, 0.2);

            cb.Basket.Add(new Equity()
            {
                Price = 100, Volatility = 0.2
            }, 0.5);
            cb.Basket.Add(new Equity()
            {
                Price = 100, Volatility = 0.2
            }, 0.5);

            var correlations = new Matrix <double>(2, 2);

            correlations[1, 1] = 0.8;
            correlations[1, 2] = 1;
            correlations[2, 1] = 1;
            correlations[2, 1] = 0.8;

            var price = cb.Price(100, correlations);

            Console.WriteLine(price);
        }
Пример #3
0
        private static ConvertibleBondAnalytics computeAnalytics(IMarketCondition market, ConvertibleBond cb, double putRedemptionPrice)
        {
            //analytics part
            var cbSpot              = market.MktQuote.Value[cb.Bond.Id].Item2;
            var stockPrice          = market.SpotPrices.Value.Values.First();
            var conversionValue     = stockPrice * cb.ConversionRatio;
            var premiumToShareInPct = (cbSpot / conversionValue - 1) * 100; // in Pct
            var arbitragePL         = conversionValue - cbSpot;             //buy cb, sell stock
            var timeToMaturity      = (cb.UnderlyingMaturityDate - market.ValuationDate) / 365.0;

            //bond analytics
            var    bondengine         = new BondEngine();
            var    yieldToMaturity    = bondengine.Calculate(cb.Bond, market, PricingRequest.Ytm).Ytm * 100.0;
            var    bondFloor          = bondengine.Calculate(cb.Bond, market, PricingRequest.Pv).Pv;
            double premiumToBondInPct = (cbSpot / bondFloor - 1) * 100;  //in Pct

            //parity vs bond floor premium
            var parityFloorPremiumInPct = (conversionValue / bondFloor - 1) * 100.0;


            //option analytics
            var impliedOptionValue       = cbSpot - bondFloor;
            var impliedUnitOptionPremium = impliedOptionValue / cb.ConversionRatio;

            var option     = createOption(strike: cb.ConversionOption.Strike, expiry: cb.ConversionOption.UnderlyingMaturityDate, firstConversionDate: cb.ConversionOption.StartDate, American: false);
            var engine     = new AnalyticalVanillaEuropeanOptionEngine();
            var impliedVol = engine.ImpliedVol(option, market, impliedUnitOptionPremium);


            //Note: assume simple calc here:  putPrice 103, current price 109.69, then if we can put the bond now, returnOnPut = (103 - 109.69)/109.69
            var returnOnPut = (putRedemptionPrice / cbSpot - 1.0) * 100;

            //cb style based on  parity/ bond floor relationship
            //if parity is worth 20% more than bond floor, then stock like
            //if parity is worth -20% less than bond floor, then bond like
            //otherwise,  cb is in balance mode
            var cbStatus = ConvertibleBondStatus.Balance;

            if (parityFloorPremiumInPct > 20)
            {
                cbStatus = ConvertibleBondStatus.StockLike;
            }
            else if (parityFloorPremiumInPct < -20)
            {
                cbStatus = ConvertibleBondStatus.BondLike;
            }

            return(new ConvertibleBondAnalytics(
                       conversionValue: conversionValue,
                       premiumToShareInPct: premiumToShareInPct,
                       arbitragePL: arbitragePL,
                       timeToMaturity: timeToMaturity,
                       yieldToMaturity: yieldToMaturity,
                       bondFloor: bondFloor,
                       premiumToBondInPct: premiumToBondInPct,
                       parityFloorPremiumInPct: parityFloorPremiumInPct,
                       optionValue: impliedOptionValue,
                       impliedVol: impliedVol,
                       returnOnPut: returnOnPut,
                       cbStatus: cbStatus));
        }