Ejemplo n.º 1
0
        public void UpdateVersionTest()
        {
            BondEngine bondEngine = new BondEngine();

            float defaultCurrentVersion;

            defaultCurrentVersion = bondEngine.CurrentVersion;

            bondEngine.UpdateVersion(2.1f);
            float updatedEngineVersion;

            updatedEngineVersion = bondEngine.CurrentVersion;

            bondEngine.UpdateVersion(-2);
            float downgradeEngineVersion;

            downgradeEngineVersion = bondEngine.CurrentVersion;

            bondEngine.UpdateVersion(.5f);
            float upgradeEngineVersion;

            upgradeEngineVersion = bondEngine.CurrentVersion;

            Assert.AreEqual(defaultCurrentVersion, 2.0f);
            Assert.AreEqual(updatedEngineVersion, 2.0f);
            Assert.AreEqual(downgradeEngineVersion, 2.0f);
            Assert.AreEqual(upgradeEngineVersion, 2.5f);
        }
Ejemplo n.º 2
0
        private void DoTestPureBond(Bond bond, Double expected, String date = "2017-10-20", Double precision = 1e-4)
        {
            var bondengine = new BondEngine();
            var market     = TestMarket_Jin(date, spot: 6.07, CBprice: 97.5);
            var res        = bondengine.Calculate(bond, market, PricingRequest.Pv | PricingRequest.ZeroSpread | PricingRequest.ZeroSpreadDelta | PricingRequest.Ytm);
            var pv         = res.Pv;

            Assert.AreEqual(expected, pv, precision);
        }
Ejemplo n.º 3
0
        public void TestQbTfDeliverableBondYield()
        {
            var files = new[] { "QbTF1606CfTest.txt", "QbTF1609CfTest.txt", "QbTF1612CfTest.txt" };

            for (var k = 0; k < files.Length; ++k)
            {
                var bondPrices = new Dictionary <string, Tuple <PriceQuoteType, double> >();
                var targetYtm  = new List <double>();
                var targetAi   = new List <double>();
                var bonds      = File.ReadAllLines(@"./Data/BondFuture/" + files[k])
                                 .Select(x =>
                {
                    var splits       = x.Split(',');
                    var startDate    = new Date(DateTime.Parse(splits[3]));
                    var maturityDate = new Date(DateTime.Parse(splits[4]));
                    var rate         = Convert.ToDouble(splits[1]);
                    var frequency    = splits[2] == "Annual" ? Frequency.Annual : Frequency.SemiAnnual;

                    targetYtm.Add(Convert.ToDouble(splits[8]));
                    targetAi.Add(Convert.ToDouble(splits[6]) - Convert.ToDouble(splits[7]));
                    bondPrices[splits[0]] = Tuple.Create(PriceQuoteType.Dirty, Convert.ToDouble(splits[6]));

                    return(new Bond(
                               splits[0],
                               startDate,
                               maturityDate,
                               100.0,
                               CurrencyCode.CNY,
                               new FixedCoupon(rate),
                               CalendarImpl.Get("chn_ib"),
                               frequency,
                               Stub.LongEnd,
                               new ActActIsma(),
                               new ActActIsma(),
                               BusinessDayConvention.None,
                               BusinessDayConvention.None,
                               null,
                               TradingMarket.ChinaInterBank));
                }).ToArray();

                var market = new BondFutureTests().TestMarket("2016-04-06", bondPrices);
                var engine = new BondEngine();

                for (var i = 0; i < bonds.Length; ++i)
                {
                    var result = engine.Calculate(bonds[i], market, PricingRequest.Ytm | PricingRequest.Ai);
                    Assert.AreEqual(Math.Round(result.Ai, 4), targetAi[i], 1e-5);
                    Assert.AreEqual(Math.Round(result.Ytm, 6), targetYtm[i], 1e-7);
                }
            }
        }
Ejemplo n.º 4
0
        public void PureBondPnLTest()
        {
            var bond       = GeliBondPart();
            var t          = "2017-10-25";
            var t1         = "2017-10-26";
            var bondengine = new BondEngine();

            var tClose  = 97.5;
            var t1Close = 96.5;

            var tMarket         = TestMarket_Jin(t, spot: 6.07, CBprice: tClose, yield: 0.05); //actually bond price
            var tMarketRollToT1 = TestMarket_Jin(t1, spot: 6.07, CBprice: tClose, yield: 0.05);
            var t1Market        = TestMarket_Jin(t1, spot: 6.07, CBprice: t1Close, yield: 0.055);

            var actualPnl = t1Close - tClose;

            var pricingRequests     = PricingRequest.Pv | PricingRequest.ZeroSpread | PricingRequest.ZeroSpreadDelta | PricingRequest.Ytm | PricingRequest.AiEod | PricingRequest.KeyRateDv01 | PricingRequest.Convexity;
            var tResult             = bondengine.Calculate(bond, tMarket, pricingRequests);
            var t1Result            = bondengine.Calculate(bond, t1Market, pricingRequests);
            var tResultRecalibrated = bondengine.Calculate(bond, tMarketRollToT1, PricingRequest.Pv);

            //1.
            var timePnL = tResultRecalibrated.Pv - tResult.Pv;

            var curveMove = (0.055 - 0.05) * 1e4;
            var pv01      = tResult.KeyRateDv01.First();
            var pv01PnL   = pv01.Value.Select(x => new CurveRisk(x.Tenor, 1.0 * x.Risk * curveMove));
            var curvePnL  = pv01PnL.Sum(x => x.Risk);

            var zspreadPnL = (t1Result.ZeroSpread - tResult.ZeroSpread) * tResult.ZeroSpreadDelta * 1e4;

            var carryPnL  = t1Result.Ai - tResult.Ai;
            var rolllDown = timePnL - carryPnL;

            var pnlConverixy = 0.5 * Math.Pow(t1Result.Ytm - tResult.Ytm, 2.0) * tResult.Convexity * tClose;  //originally without

            var estimatedPL = timePnL + curvePnL + zspreadPnL + pnlConverixy;

            Assert.AreEqual(true, Math.Abs((estimatedPL - actualPnl) / actualPnl) < 0.01);
        }
Ejemplo n.º 5
0
        public void ConstructorTest()
        {
            BondEngine bondEngine = new BondEngine();

            PhysicsEngineState defaultPhysicsEngineState;

            defaultPhysicsEngineState = bondEngine.PhysicsEngine.Simulating;

            float defaultEngineVersion;

            defaultEngineVersion = bondEngine.CurrentVersion;

            string defaultProgrammingLang;

            defaultProgrammingLang = bondEngine.ProgrammingLanguage;

            string infoBondEngine = bondEngine.Info();

            Assert.AreEqual(defaultPhysicsEngineState, PhysicsEngineState.THREE_D);
            Assert.AreEqual(defaultEngineVersion, 2.0);
            Assert.AreEqual(defaultProgrammingLang, "C++");
            Assert.AreEqual(infoBondEngine, string.Format("This engine is currently running with {0} based physics, is running current version {1}, " +
                                                          "and uses {2} programming language", PhysicsEngineState.THREE_D, 2.0, "C++"));
        }
Ejemplo n.º 6
0
        public void BondForwardTest()
        {
            var bond = new Bond(
                "010000",
                new Date(2013, 2, 25),
                new Date(2015, 2, 25),
                100,
                CurrencyCode.CNY,
                new FixedCoupon(0.0375),
                CalendarImpl.Get("chn_ib"),
                Frequency.SemiAnnual,
                Stub.LongEnd,
                new ActActIsma(),
                new Act365(),
                BusinessDayConvention.None,
                BusinessDayConvention.None,
                null,
                TradingMarket.ChinaInterBank
                );
            var bondForward = new Forward <Bond>(
                new Date(2013, 5, 28),
                new Date(2013, 8, 28),
                100.0,
                98.57947065,
                bond,
                CurrencyCode.CNY
                );

            var referenceDate = new Date(2013, 8, 23);
            var yieldCurve    = new YieldCurve(
                "中债国债收收益率曲线",
                referenceDate,
                new[]
            {
                Tuple.Create((ITerm) new Term("1D"), 0.035),
                Tuple.Create((ITerm) new Term("1Y"), 0.035)
            },
                BusinessDayConvention.ModifiedFollowing,
                new Act365(),
                CalendarImpl.Get("chn_ib"),
                CurrencyCode.CNY,
                Compound.Simple,
                Interpolation.CubicHermiteMonotic,
                YieldCurveTrait.SpotCurve
                );

            var market = new MarketCondition
                         (
                x => x.ValuationDate.Value = referenceDate,
                x => x.MktQuote.Value      = new Dictionary <string, Tuple <PriceQuoteType, double> > {
                { "010000", Tuple.Create(PriceQuoteType.Dirty, 99.71798177) }
            },
                x => x.DiscountCurve.Value           = yieldCurve,
                x => x.FixingCurve.Value             = yieldCurve,
                x => x.RiskfreeCurve.Value           = yieldCurve,
                x => x.UnderlyingDiscountCurve.Value = yieldCurve,
                x => x.HistoricalIndexRates.Value    = new Dictionary <IndexType, SortedDictionary <Date, double> >()
                         );

            var bondengine = new BondEngine();
            var zeroSpread = bondengine.Calculate(bond, market, PricingRequest.ZeroSpread).ZeroSpread;
            var engine     = new ForwardEngine <Bond>();
            var result     = engine.Calculate(bondForward, market, PricingRequest.Pv);

            Assert.AreEqual(-0.68888788, result.Pv, 1e-8);
        }
Ejemplo n.º 7
0
        public double ModelValue(IMarketCondition market, MktInstrumentCalibMethod calibMethod = MktInstrumentCalibMethod.Default)
        {
            var engine = new BondEngine();

            return(engine.CalcPv(this, market));
        }
Ejemplo n.º 8
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));
        }