public void TestBondPriceConversions3() { var bond = new FixedRateBondInfo("bond1") { StartDate = "2010-10-28", MaturityDate = "2020-10-28", Notional = 100.0, Currency = "CNY", FixedCoupon = 0.0367, Calendar = "chn", PaymentFreq = "SemiAnnual", PaymentStub = "ShortStart", AccrualDC = "Act365NoLeap", DayCount = "ModifiedAfb", AccrualBD = "None", PaymentBD = "None", TradingMarket = "ChinaExShg", Settlement = "+0BD", ValuationParamters = new SimpleCfValuationParameters("Fr007", null, "Fr007") }; var bondVf = new BondVf(bond); var market = TestMarket("2016-08-04", new BondMktData(bond.TradeId, "Dirty", 100.995424657531)); var result = bondVf.ValueTrade(market, PricingRequest.Ytm); Assert.AreEqual(Math.Round(result.Ytm, 15), 0.036663932289318, 1e-13); }
public void TestConvertibleBondWhenCallOnMaturity() { var bond = new FixedRateBondInfo("110030.SH") { StartDate = "2014-12-25", MaturityDate = "2019-12-25", Notional = 100.0, Currency = "CNY", FixedCoupon = 0.006, Calendar = "chn", PaymentFreq = "Annual", PaymentStub = "ShortStart", AccrualDC = "Act365NoLeap", DayCount = "ModifiedAfb", AccrualBD = "None", PaymentBD = "None", TradingMarket = "ChinaExShg", Settlement = "+0BD", CompensationRate = new Dictionary <int, double>() { { 2, 0.002 }, { 3, 0.002 }, { 4, 0.005 }, { 5, 0.005 } }, ValuationParamters = new SimpleCfValuationParameters("Fr007", null, "Fr007"), RedemptionRate = 1.06, RedemptionIncludeLastCoupon = true }; var bondVf = new BondVf(bond); var market = TestMarket("2017-10-20", new BondMktData(bond.TradeId, "Dirty", 95.90891)); //var result = bondVf.ValueTrade(market, PricingRequest.Ytm); XlManager.AddTrades(new TradeInfoBase[] { bond }); var ytm = XlUdf.xl_YieldFromPrice("110030.SH", "2017-10-20", 95.90891); }
public void TestStepWiseCompensationRate() { //为什么没输入tradedate?应该有tradedate为交易属性 var bond = new FixedRateBondInfo("bond1") { StartDate = "2016-10-28", MaturityDate = "2020-10-28", Notional = 100.0, //trade Currency = "CNY", FixedCoupon = 0.0367, Calendar = "chn", PaymentFreq = "Annual", //付息频率 PaymentStub = "ShortStart", //instrument AccrualDC = "ActActIsma", // 日期规则,应计利息 DayCount = "ModifiedAfb", // 收益率的日期规则 AccrualBD = "None", //应计利息 日期调整规则 instrument PaymentBD = "None", //支付利息 日期调整规则 TradingMarket = "ChinaExShg", //交易市场 Settlement = "+0BD", //BD工作日, 后可以拿到交易的东西 instrument CompensationRate = new Dictionary <int, double> // : //补偿利率的意思是有些债券会根据年限的变化增长利息 //2,0.01是指第二年开始利率增加0.01 { { 2, 0.01 }, { 3, 0.015 } }, ValuationParamters = new SimpleCfValuationParameters("Fr007", null, "Fr007") }; var bondVf = new BondVf(bond); var market = TestMarket("2016-08-04", new BondMktData(bond.TradeId, "Dirty", 100.995424657531)); var result = bondVf.ValueTrade(market, PricingRequest.Cashflow); var nettedCfs = result.Cashflows.GroupBy(cf => cf.PaymentDate) .Select(item => new Cashflow(item.Min(x => x.AccrualStartDate), item.Max(x => x.AccrualEndDate), item.Key, item.Sum(entry => entry.PaymentAmount), item.First().PaymentCurrency, CashflowType.Coupon, item.Aggregate(true, (current, v) => current && v.IsFixed), double.NaN, item.Min(x => x.CalculationDetails), item.Min(x => x.RefStartDate), item.Max(x => x.RefEndDate), item.Max(entry => entry.StartPrincipal), item.Sum(entry => entry.CouponRate))) .OrderBy(cf => cf.PaymentDate) .ToArray(); Assert.AreEqual(nettedCfs[0].PaymentAmount, 3.67, 1e-3); Assert.AreEqual(nettedCfs[1].PaymentAmount, 4.67, 1e-3); Assert.AreEqual(nettedCfs[2].PaymentAmount, 6.17, 1e-3); Assert.AreEqual(nettedCfs[3].PaymentAmount, 106.17, 1e-3); //Date tradedate = new Date(2016, 11, 28); //Date startdate = new Date(2016, 10, 28); //Date maturitydate = new Date(2020, 10, 28); //var bond_v2 = new V2.FixedRateBondInfo("bond1",tradedate, startdate,maturitydate, V2.TradeType.Buy, 100, 1000); //var bond2s = CreateBonds(); //var singlebond = bond2s[0]; //var marketV2 = CreateTestMarket("2016-11-28", singlebond); //IPricingResult ipResult = bond_v2.CalculateRisks(marketV2, PricingRequest.Cashflow); //var nettedCfs2 = ipResult.Cashflows.GroupBy(cf => cf.PaymentDate) // .Select(item => new Cashflow(item.Min(x => x.AccrualStartDate), item.Max(x => x.AccrualEndDate), item.Key, item.Sum(entry => entry.PaymentAmount), item.First().PaymentCurrency, CashflowType.Coupon, item.Aggregate(true, (current, v) => current && v.IsFixed), double.NaN, item.Min(x => x.CalculationDetails), item.Min(x => x.RefStartDate), item.Max(x => x.RefEndDate), item.Max(entry => entry.StartPrincipal), item.Sum(entry => entry.CouponRate))) // .OrderBy(cf => cf.PaymentDate) // .ToArray(); //string results = "0:" + nettedCfs2[0].PaymentAmount + "1:" + nettedCfs2[1].PaymentAmount +"2:" + nettedCfs2[2].PaymentAmount +"3:" + nettedCfs2[3].PaymentAmount; ; //System.Diagnostics.Debugger.Log(2, "results", results); }
public static object BondEngineCalc(string bondId, string calcDate, PriceQuoteType priceQuote, double quote, PricingRequest request, FixedRateBondInfo fixedBond = null) { var bond = fixedBond ?? XlManager.GetTrade(bondId); if (bond == null) { return(string.Format("Cannot find bond {0}.", bondId)); } var vf = new BondVf((BondInfoBase)bond); var bondInstrument = vf.GenerateInstrument(); var valueDate = calcDate.ToDate(); var fixingCurve = new YieldCurve( "中债国债收收益率曲线", valueDate, new[] { new Tuple <Date, double>(valueDate, 0.0), new Tuple <Date, double>(new Term("10Y").Next(valueDate), 0.0) }, BusinessDayConvention.ModifiedFollowing, new Act365(), CalendarImpl.Get("Chn_ib"), CurrencyCode.CNY, Compound.Continuous, Interpolation.ForwardFlat, YieldCurveTrait.ForwardCurve ); var market = new MarketCondition( x => x.ValuationDate.Value = valueDate, x => x.FixingCurve.Value = fixingCurve, x => x.MktQuote.Value = new Dictionary <string, Tuple <PriceQuoteType, double> > { { bondId, Tuple.Create(priceQuote, quote) } }, x => x.HistoricalIndexRates.Value = HistoricalIndexRates ); if (bond is FloatingRateBondInfo) { var fixingTuple = bondInstrument.Coupon.GetPrimeCoupon(HistoricalIndexRates, fixingCurve, valueDate); var keyTenors = new string[fixingCurve.GetKeyTenors().Length]; fixingCurve.GetKeyTenors().CopyTo(keyTenors, 0); for (var i = 0; i < keyTenors.Length; ++i) { market = (MarketCondition)market.UpdateCondition(new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, market.FixingCurve.Value.BumpKeyRate(i, fixingTuple.Item2))); } if (request.Equals(PricingRequest.None)) { return(fixingTuple); } } var engine = vf.GenerateEngine(); var result = engine.Calculate(bondInstrument, market, request); if (!result.Succeeded) { return(string.Format("Failed to Calculate bond {0}:{1}", bondId, result.ErrorMessage)); } return(result); }
/// <summary> /// Return QDP bond qdp object. /// </summary> /// <param name="tradeId"></param> /// <param name="startDate"></param> /// <param name="maturityDate"></param> /// <param name="notional"></param> /// <param name="calendar"></param> /// <param name="currency"></param> /// <param name="accrualDayCount"></param> /// <param name="accrualBusinessDayConvention"></param> /// <param name="paymentDayCount"></param> /// <param name="paymentFrequency"></param> /// <param name="paymentStub"></param> /// <param name="paymentBusinessDayConvention"></param> /// <param name="settlement"></param> /// <param name="settlementCoupon"></param> /// <param name="issuePrice"></param> /// <param name="firstPaymentDate"></param> /// <param name="issueRate"></param> /// <param name="amoritzationInIndex"></param> /// <param name="renormalizeAfterAmoritzation"></param> /// <param name="compensationRate"></param> /// <param name="optionToCall"></param> /// <param name="optionToPut"></param> /// <param name="optionToAssPut"></param> /// <param name="fixedCoupon"></param> /// <param name="index"></param> /// <param name="resetDayCount"></param> /// <param name="resetCompound"></param> /// <param name="resetStub"></param> /// <param name="resetBusinessDayConvention"></param> /// <param name="resetToFixingGap"></param> /// <param name="resetTerm"></param> /// <param name="resetAverageDays"></param> /// <param name="resetRateDigits"></param> /// <param name="spread"></param> /// <param name="floatingRateMultiplier"></param> /// <param name="stickToEom"></param> /// <returns></returns> private static object xl_Bond( string tradeId, string startDate = null, string maturityDate = null, double notional = 100, string calendar = "chn_ib", string currency = "CNY", string accrualDayCount = "Act365", string accrualBusinessDayConvention = "ModifiedFollowing", string paymentDayCount = "Act365", string paymentFrequency = "SemiAnnual", string paymentStub = "ShortStart", string paymentBusinessDayConvention = "ModifiedFollowing", string settlement = "+0D", double settlementCoupon = double.NaN, double issuePrice = double.NaN, string firstPaymentDate = null, double issueRate = double.NaN, Dictionary <int, double> amoritzationInIndex = null, bool renormalizeAfterAmoritzation = false, Dictionary <int, double> compensationRate = null, Dictionary <string, double> optionToCall = null, Dictionary <string, double> optionToPut = null, Dictionary <string, double> optionToAssPut = null, double fixedCoupon = double.NaN, string index = null, string resetDayCount = null, string resetCompound = null, string resetStub = null, string resetBusinessDayConvention = null, string resetToFixingGap = null, string resetTerm = null, int resetAverageDays = 1, int resetRateDigits = 12, double spread = double.NaN, double floatingRateMultiplier = double.NaN, bool stickToEom = false) { var tradeInfo = XlManager.GetTrade(tradeId); if (!(tradeInfo is BondInfoBase)) { startDate = startDate ?? DateTime.Now.ToString("yyyy-MM-dd"); maturityDate = maturityDate ?? new Term("1Y").Next(startDate.ToDate()).ToString(); BondInfoBase bondInfo = null; if (string.IsNullOrWhiteSpace(index)) { bondInfo = new FixedRateBondInfo(tradeId) { FixedCoupon = double.IsNaN(fixedCoupon) ? 0.03 : fixedCoupon }; } else { bondInfo = new FloatingRateBondInfo(tradeId) { Index = index ?? "Shibor3M", ResetDC = resetDayCount ?? "Act365", ResetCompound = resetCompound ?? "Simple", ResetStub = resetStub ?? "ShortStart", ResetBD = resetBusinessDayConvention ?? "ModifiedFollowing", ResetToFixingGap = resetToFixingGap ?? "-1BD", ResetTerm = resetTerm ?? "3M", Spread = double.IsNaN(spread) ? 0.0 : spread, ResetAverageDays = resetAverageDays, ResetRateDigits = resetRateDigits, FloatingRateMultiplier = double.IsNaN(floatingRateMultiplier) ? 1.0 : floatingRateMultiplier, FloatingCalc = "ZzFrn", CapRate = 100, FloorRate = -100 }; } bondInfo.StartDate = startDate; bondInfo.MaturityDate = maturityDate; bondInfo.Calendar = calendar; bondInfo.PaymentFreq = paymentFrequency; bondInfo.StickToEom = stickToEom; bondInfo.PaymentStub = paymentStub; bondInfo.Notional = notional; bondInfo.Currency = currency; bondInfo.AccrualDC = accrualDayCount; bondInfo.DayCount = paymentDayCount; bondInfo.AccrualBD = accrualBusinessDayConvention; bondInfo.PaymentBD = paymentBusinessDayConvention; bondInfo.Settlement = settlement; bondInfo.SettlementCoupon = settlementCoupon; bondInfo.TradingMarket = calendar == "chn_ib" ? TradingMarket.ChinaInterBank.ToString() : TradingMarket.ChinaExShe.ToString(); bondInfo.IsZeroCouponBond = !double.IsNaN(issuePrice); bondInfo.IssuePrice = issuePrice; bondInfo.FirstPaymentDate = firstPaymentDate; bondInfo.AmortizationType = "None"; bondInfo.AmoritzationInIndex = amoritzationInIndex; bondInfo.RenormAmortization = renormalizeAfterAmoritzation; bondInfo.CompensationRate = compensationRate; bondInfo.IssueRate = issueRate; bondInfo.OptionToCall = optionToCall; bondInfo.OptionToPut = optionToPut; bondInfo.OptionToAssPut = optionToAssPut; bondInfo.ValuationParamters = new SimpleCfValuationParameters("中债国债收益率曲线", "", "中债国债收益率曲线"); XlManager.AddTrades(new[] { bondInfo }); tradeInfo = bondInfo; } return(tradeInfo.ToTradeInfoInLabelData(null)); }