public static Greeks GetOptionOnFutureGreeks(double underlyingPrice, double strike, double riskFreeRate, DateTime expirationDate, DateTime calculationDate, string optionType, string exerciseType, double optionPrice = double.NaN, double impliedVol = 0.15, string engineName = "baw") { QLNet.Date ExpirationDateObj = new QLNet.Date(expirationDate.Day, expirationDate.Month, expirationDate.Year); QLNet.Date CalculationDateObj = new QLNet.Date(calculationDate.Day, calculationDate.Month, calculationDate.Year); QLNet.DayCounter DayCountObj = new QLNet.Actual365Fixed(); QLNet.Calendar CalendarObj = new QLNet.UnitedStates(); Greeks GreeksOutput = new Greeks(); QLNet.Option.Type OptionTypeObj; QLNet.Exercise ExerciseObj; double ImpliedVol; double OptionPrice; int CalDte = DayCountObj.dayCount(CalculationDateObj, ExpirationDateObj); GreeksOutput.CalDte = CalDte; if (!double.IsNaN(optionPrice)) { if (optionType.ToUpper() == "C") { if (optionPrice + strike - underlyingPrice <= 1.0e-12) { GreeksOutput.Delta = 1; return(GreeksOutput); } } else if (optionType.ToUpper() == "P") { if (optionPrice - strike + underlyingPrice <= 1.0e-12) { GreeksOutput.Delta = -1; return(GreeksOutput); } } } if (CalDte == 0) { if (optionType.ToUpper() == "C") { if (strike <= underlyingPrice) { GreeksOutput.Delta = 1; } else { GreeksOutput.Delta = 0; } } else if (optionType.ToUpper() == "P") { if (strike >= underlyingPrice) { GreeksOutput.Delta = -1; } else { GreeksOutput.Delta = 0; } } return(GreeksOutput); } if (optionType.ToUpper() == "C") { OptionTypeObj = QLNet.Option.Type.Call; } else if (optionType.ToUpper() == "P") { OptionTypeObj = QLNet.Option.Type.Put; } else { return(GreeksOutput); } if (exerciseType.ToUpper() == "E") { ExerciseObj = new QLNet.EuropeanExercise(ExpirationDateObj); } else if (exerciseType.ToUpper() == "A") { ExerciseObj = new QLNet.AmericanExercise(CalculationDateObj, ExpirationDateObj); } else { return(GreeksOutput); } QLNet.Settings.setEvaluationDate(CalculationDateObj); QLNet.Handle <Quote> UnderlyingObj = new QLNet.Handle <Quote>(new QLNet.SimpleQuote(underlyingPrice)); QLNet.Handle <YieldTermStructure> FlatRateObj = new QLNet.Handle <YieldTermStructure>(new QLNet.FlatForward(CalculationDateObj, riskFreeRate, DayCountObj)); QLNet.Handle <BlackVolTermStructure> FlatVolTsObj = new QLNet.Handle <BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, impliedVol, DayCountObj)); QLNet.BlackProcess BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj); QLNet.PlainVanillaPayoff PayoffObj = new QLNet.PlainVanillaPayoff(OptionTypeObj, strike); QLNet.VanillaOption OptionObj = new QLNet.VanillaOption(PayoffObj, ExerciseObj); if (engineName == "baw") { OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc)); } else if (engineName == "fda") { OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100)); } else { return(GreeksOutput); } if (!double.IsNaN(optionPrice)) { try { ImpliedVol = OptionObj.impliedVolatility(targetValue: optionPrice, process: BlackProc, accuracy: 1e-5); } catch { return(GreeksOutput); } FlatVolTsObj = new QLNet.Handle <BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, ImpliedVol, DayCountObj)); BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj); if (engineName == "baw") { OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc)); } else if (engineName == "fda") { OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100)); } OptionPrice = optionPrice; } else { OptionPrice = OptionObj.NPV(); ImpliedVol = impliedVol; } OptionObj = new QLNet.VanillaOption(PayoffObj, new QLNet.EuropeanExercise(ExpirationDateObj)); OptionObj.setPricingEngine(new QLNet.AnalyticEuropeanEngine(BlackProc)); GreeksOutput.Delta = OptionObj.delta(); GreeksOutput.Vega = OptionObj.vega(); GreeksOutput.Theta = OptionObj.thetaPerDay(); GreeksOutput.Gamma = OptionObj.gamma(); GreeksOutput.OptionPrice = OptionPrice; GreeksOutput.ImpliedVol = ImpliedVol; return(GreeksOutput); }
public void testUSNewYorkStockExchange() { List<Date> expectedHol = new List<Date>(); expectedHol.Add(new Date(1, Month.January, 2004)); expectedHol.Add(new Date(19, Month.January, 2004)); expectedHol.Add(new Date(16, Month.February, 2004)); expectedHol.Add(new Date(9, Month.April, 2004)); expectedHol.Add(new Date(31, Month.May, 2004)); expectedHol.Add(new Date(11, Month.June, 2004)); expectedHol.Add(new Date(5, Month.July, 2004)); expectedHol.Add(new Date(6, Month.September, 2004)); expectedHol.Add(new Date(25, Month.November, 2004)); expectedHol.Add(new Date(24, Month.December, 2004)); expectedHol.Add(new Date(17, Month.January, 2005)); expectedHol.Add(new Date(21, Month.February, 2005)); expectedHol.Add(new Date(25, Month.March, 2005)); expectedHol.Add(new Date(30, Month.May, 2005)); expectedHol.Add(new Date(4, Month.July, 2005)); expectedHol.Add(new Date(5, Month.September, 2005)); expectedHol.Add(new Date(24, Month.November, 2005)); expectedHol.Add(new Date(26, Month.December, 2005)); expectedHol.Add(new Date(2, Month.January, 2006)); expectedHol.Add(new Date(16, Month.January, 2006)); expectedHol.Add(new Date(20, Month.February, 2006)); expectedHol.Add(new Date(14, Month.April, 2006)); expectedHol.Add(new Date(29, Month.May, 2006)); expectedHol.Add(new Date(4, Month.July, 2006)); expectedHol.Add(new Date(4, Month.September, 2006)); expectedHol.Add(new Date(23, Month.November, 2006)); expectedHol.Add(new Date(25, Month.December, 2006)); Calendar c = new UnitedStates(UnitedStates.Market.NYSE); List<Date> hol = Calendar.holidayList(c, new Date(1, Month.January, 2004), new Date(31, Month.December, 2006)); int i; for (i = 0; i < Math.Min(hol.Count, expectedHol.Count); i++) { if (hol[i] != expectedHol[i]) Assert.Fail("expected holiday was " + expectedHol[i] + " while calculated holiday is " + hol[i]); } if (hol.Count != expectedHol.Count) Assert.Fail("there were " + expectedHol.Count + " expected holidays, while there are " + hol.Count + " calculated holidays"); List<Date> histClose = new List<Date>(); histClose.Add(new Date(11, Month.June, 2004)); // Reagan's funeral histClose.Add(new Date(14, Month.September, 2001));// September 11, 2001 histClose.Add(new Date(13, Month.September, 2001));// September 11, 2001 histClose.Add(new Date(12, Month.September, 2001));// September 11, 2001 histClose.Add(new Date(11, Month.September, 2001));// September 11, 2001 histClose.Add(new Date(14, Month.July, 1977)); // 1977 Blackout histClose.Add(new Date(25, Month.January, 1973)); // Johnson's funeral. histClose.Add(new Date(28, Month.December, 1972)); // Truman's funeral histClose.Add(new Date(21, Month.July, 1969)); // Lunar exploration nat. day histClose.Add(new Date(31, Month.March, 1969)); // Eisenhower's funeral histClose.Add(new Date(10, Month.February, 1969)); // heavy snow histClose.Add(new Date(5, Month.July, 1968)); // Day after Independence Day // June 12-Dec. 31, 1968 // Four day week (closed on Wednesdays) - Paperwork Crisis histClose.Add(new Date(12, Month.Jun, 1968)); histClose.Add(new Date(19, Month.Jun, 1968)); histClose.Add(new Date(26, Month.Jun, 1968)); histClose.Add(new Date(3, Month.Jul, 1968)); histClose.Add(new Date(10, Month.Jul, 1968)); histClose.Add(new Date(17, Month.Jul, 1968)); histClose.Add(new Date(20, Month.Nov, 1968)); histClose.Add(new Date(27, Month.Nov, 1968)); histClose.Add(new Date(4, Month.Dec, 1968)); histClose.Add(new Date(11, Month.Dec, 1968)); histClose.Add(new Date(18, Month.Dec, 1968)); // Presidential election days histClose.Add(new Date(4, Month.Nov, 1980)); histClose.Add(new Date(2, Month.Nov, 1976)); histClose.Add(new Date(7, Month.Nov, 1972)); histClose.Add(new Date(5, Month.Nov, 1968)); histClose.Add(new Date(3, Month.Nov, 1964)); for (i = 0; i < histClose.Count; i++) { if (!c.isHoliday(histClose[i])) Assert.Fail(histClose[i] + " should be holiday (historical close)"); } }
public void testUSGovernmentBondMarket() { List<Date> expectedHol = new List<Date>(); expectedHol.Add(new Date(1, Month.January, 2004)); expectedHol.Add(new Date(19, Month.January, 2004)); expectedHol.Add(new Date(16, Month.February, 2004)); expectedHol.Add(new Date(9, Month.April, 2004)); expectedHol.Add(new Date(31, Month.May, 2004)); expectedHol.Add(new Date(5, Month.July, 2004)); expectedHol.Add(new Date(6, Month.September, 2004)); expectedHol.Add(new Date(11, Month.October, 2004)); expectedHol.Add(new Date(11, Month.November, 2004)); expectedHol.Add(new Date(25, Month.November, 2004)); expectedHol.Add(new Date(24, Month.December, 2004)); Calendar c = new UnitedStates(UnitedStates.Market.GovernmentBond); List<Date> hol = Calendar.holidayList(c, new Date(1, Month.January, 2004), new Date(31, Month.December, 2004)); for (int i = 0; i < Math.Min(hol.Count, expectedHol.Count); i++) { if (hol[i] != expectedHol[i]) Assert.Fail("expected holiday was " + expectedHol[i] + " while calculated holiday is " + hol[i]); } if (hol.Count != expectedHol.Count) Assert.Fail("there were " + expectedHol.Count + " expected holidays, while there are " + hol.Count + " calculated holidays"); }
public void testModifiedCalendars() { Calendar c1 = new TARGET(); Calendar c2 = new UnitedStates(UnitedStates.Market.NYSE); Date d1 = new Date(1, Month.May, 2004); // holiday for both calendars Date d2 = new Date(26, Month.April, 2004); // business day Assert.IsTrue(c1.isHoliday(d1), "wrong assumption---correct the test"); Assert.IsTrue(c1.isBusinessDay(d2), "wrong assumption---correct the test"); Assert.IsTrue(c2.isHoliday(d1), "wrong assumption---correct the test"); Assert.IsTrue(c2.isBusinessDay(d2), "wrong assumption---correct the test"); // modify the TARGET calendar c1.removeHoliday(d1); c1.addHoliday(d2); // test Assert.IsFalse(c1.isHoliday(d1), d1 + " still a holiday for original TARGET instance"); Assert.IsFalse(c1.isBusinessDay(d2), d2 + " still a business day for original TARGET instance"); // any instance of TARGET should be modified... Calendar c3 = new TARGET(); Assert.IsFalse(c3.isHoliday(d1), d1 + " still a holiday for generic TARGET instance"); Assert.IsFalse(c3.isBusinessDay(d2), d2 + " still a business day for generic TARGET instance"); // ...but not other calendars Assert.IsFalse(c2.isBusinessDay(d1), d1 + " business day for New York"); Assert.IsFalse(c2.isHoliday(d2), d2 + " holiday for New York"); // restore original holiday set---test the other way around c3.addHoliday(d1); c3.removeHoliday(d2); Assert.IsFalse(c1.isBusinessDay(d1), d1 + " still a business day"); Assert.IsFalse(c1.isHoliday(d2), d2 + " still a holiday"); }
public void testJointCalendars() { Calendar c1 = new TARGET(), c2 = new UnitedKingdom(), c3 = new UnitedStates(UnitedStates.Market.NYSE), c4 = new Japan(); Calendar c12h = new JointCalendar(c1, c2, JointCalendar.JointCalendarRule.JoinHolidays), c12b = new JointCalendar(c1,c2,JointCalendar.JointCalendarRule.JoinBusinessDays), c123h = new JointCalendar(c1,c2,c3,JointCalendar.JointCalendarRule.JoinHolidays), c123b = new JointCalendar(c1,c2,c3,JointCalendar.JointCalendarRule.JoinBusinessDays), c1234h = new JointCalendar(c1,c2,c3,c4,JointCalendar.JointCalendarRule.JoinHolidays), c1234b = new JointCalendar(c1,c2,c3,c4,JointCalendar.JointCalendarRule.JoinBusinessDays); // test one year, starting today Date firstDate = Date.Today, endDate = firstDate + new Period(1, TimeUnit.Years); for (Date d = firstDate; d < endDate; d++) { bool b1 = c1.isBusinessDay(d), b2 = c2.isBusinessDay(d), b3 = c3.isBusinessDay(d), b4 = c4.isBusinessDay(d); if ((b1 && b2) != c12h.isBusinessDay(d)) Assert.Fail("At date " + d + ":\n" + " inconsistency between joint calendar " + c12h.name() + " (joining holidays)\n" + " and its components"); if ((b1 || b2) != c12b.isBusinessDay(d)) Assert.Fail("At date " + d + ":\n" + " inconsistency between joint calendar " + c12b.name() + " (joining business days)\n" + " and its components"); if ((b1 && b2 && b3) != c123h.isBusinessDay(d)) Assert.Fail("At date " + d + ":\n" + " inconsistency between joint calendar " + c123h.name() + " (joining holidays)\n" + " and its components"); if ((b1 || b2 || b3) != c123b.isBusinessDay(d)) Assert.Fail("At date " + d + ":\n" + " inconsistency between joint calendar " + c123b.name() + " (joining business days)\n" + " and its components"); if ((b1 && b2 && b3 && b4) != c1234h.isBusinessDay(d)) Assert.Fail("At date " + d + ":\n" + " inconsistency between joint calendar " + c1234h.name() + " (joining holidays)\n" + " and its components"); if ((b1 || b2 || b3 || b4) != c1234b.isBusinessDay(d)) Assert.Fail("At date " + d + ":\n" + " inconsistency between joint calendar " + c1234b.name() + " (joining business days)\n" + " and its components"); } }
public void testUSSettlement() { Debug.Print("Testing US settlement holiday list..."); List<Date> expectedHol = new List<Date>(); expectedHol.Add(new Date(1, Month.January, 2004)); expectedHol.Add(new Date(19, Month.January, 2004)); expectedHol.Add(new Date(16, Month.February, 2004)); expectedHol.Add(new Date(31, Month.May, 2004)); expectedHol.Add(new Date(5, Month.July, 2004)); expectedHol.Add(new Date(6, Month.September, 2004)); expectedHol.Add(new Date(11, Month.October, 2004)); expectedHol.Add(new Date(11, Month.November, 2004)); expectedHol.Add(new Date(25, Month.November, 2004)); expectedHol.Add(new Date(24, Month.December, 2004)); expectedHol.Add(new Date(31, Month.December, 2004)); expectedHol.Add(new Date(17, Month.January, 2005)); expectedHol.Add(new Date(21, Month.February, 2005)); expectedHol.Add(new Date(30, Month.May, 2005)); expectedHol.Add(new Date(4, Month.July, 2005)); expectedHol.Add(new Date(5, Month.September, 2005)); expectedHol.Add(new Date(10, Month.October, 2005)); expectedHol.Add(new Date(11, Month.November, 2005)); expectedHol.Add(new Date(24, Month.November, 2005)); expectedHol.Add(new Date(26, Month.December, 2005)); Calendar c = new UnitedStates(UnitedStates.Market.Settlement); List<Date> hol = Calendar.holidayList(c, new Date(1, Month.January, 2004), new Date(31, Month.December, 2005)); for (int i = 0; i < Math.Min(hol.Count, expectedHol.Count); i++) { if (hol[i] != expectedHol[i]) Assert.Fail("expected holiday was " + expectedHol[i] + " while calculated holiday is " + hol[i]); } if (hol.Count != expectedHol.Count) Assert.Fail("there were " + expectedHol.Count + " expected holidays, while there are " + hol.Count + " calculated holidays"); }
public void testCachedMarketValue() { // Testing credit-default swap against cached market values... SavedSettings backup = new SavedSettings(); Settings.setEvaluationDate(new Date(9,Month.June,2006)); Date evalDate = Settings.evaluationDate(); Calendar calendar = new UnitedStates(); List<Date> discountDates = new List<Date>(); discountDates.Add(evalDate); discountDates.Add(calendar.advance(evalDate, 1, TimeUnit.Weeks, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 1, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 2, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 3, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 6, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate,12, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 2, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 3, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 4, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 5, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 6, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 7, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 8, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate, 9, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate,10, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); discountDates.Add(calendar.advance(evalDate,15, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); List<double> dfs = new List<double>(); dfs.Add(1.0); dfs.Add(0.9990151375768731); dfs.Add(0.99570502636871183); dfs.Add(0.99118260474528685); dfs.Add(0.98661167950906203); dfs.Add(0.9732592953359388 ); dfs.Add(0.94724424481038083); dfs.Add(0.89844996737120875 ); dfs.Add(0.85216647839921411 ); dfs.Add(0.80775477692556874 ); dfs.Add(0.76517289234200347 ); dfs.Add(0.72401019553182933 ); dfs.Add(0.68503909569219212 ); dfs.Add(0.64797499814013748 ); dfs.Add(0.61263171936255534 ); dfs.Add(0.5791942350748791 ); dfs.Add(0.43518868769953606 ); DayCounter curveDayCounter = new Actual360(); RelinkableHandle<YieldTermStructure> discountCurve = new RelinkableHandle<YieldTermStructure>(); discountCurve.linkTo( new InterpolatedDiscountCurve<LogLinear>( discountDates, dfs, curveDayCounter,null,null,null,new LogLinear() ) ); DayCounter dayCounter = new Thirty360(); List<Date> dates = new List<Date>(); dates.Add(evalDate); dates.Add(calendar.advance(evalDate, 6, TimeUnit.Months, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate, 1, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate, 2, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate, 3, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate, 4, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate, 5, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate, 7, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); dates.Add(calendar.advance(evalDate,10, TimeUnit.Years, BusinessDayConvention.ModifiedFollowing)); List<double> defaultProbabilities = new List<double>(); defaultProbabilities.Add(0.0000); defaultProbabilities.Add(0.0047); defaultProbabilities.Add(0.0093); defaultProbabilities.Add(0.0286); defaultProbabilities.Add(0.0619); defaultProbabilities.Add(0.0953); defaultProbabilities.Add(0.1508); defaultProbabilities.Add(0.2288); defaultProbabilities.Add(0.3666); List<double> hazardRates = new List<double>(); hazardRates.Add(0.0); for (int i=1; i<dates.Count; ++i) { double t1 = dayCounter.yearFraction(dates[0], dates[i-1]); double t2 = dayCounter.yearFraction(dates[0], dates[i]); double S1 = 1.0 - defaultProbabilities[i-1]; double S2 = 1.0 - defaultProbabilities[i]; hazardRates.Add(Math.Log(S1/S2)/(t2-t1)); } RelinkableHandle<DefaultProbabilityTermStructure> piecewiseFlatHazardRate = new RelinkableHandle<DefaultProbabilityTermStructure>(); piecewiseFlatHazardRate.linkTo(new InterpolatedHazardRateCurve<BackwardFlat>(dates,hazardRates,new Thirty360())); // Testing credit default swap // Build the schedule Date issueDate = new Date(20, Month.March, 2006); Date maturity = new Date(20, Month.June, 2013); Frequency cdsFrequency = Frequency.Semiannual; BusinessDayConvention cdsConvention = BusinessDayConvention.ModifiedFollowing; Schedule schedule = new Schedule(issueDate, maturity, new Period(cdsFrequency), calendar, cdsConvention, cdsConvention, DateGeneration.Rule.Forward, false); // Build the CDS double recoveryRate = 0.25; double fixedRate=0.0224; DayCounter dayCount= new Actual360(); double cdsNotional=100.0; CreditDefaultSwap cds = new CreditDefaultSwap(Protection.Side.Seller, cdsNotional, fixedRate, schedule, cdsConvention, dayCount, true, true); cds.setPricingEngine(new MidPointCdsEngine(piecewiseFlatHazardRate, recoveryRate,discountCurve)); double calculatedNpv = cds.NPV(); double calculatedFairRate = cds.fairSpread(); double npv = -1.364048777; // from Bloomberg we have 98.15598868 - 100.00; double fairRate = 0.0248429452; // from Bloomberg we have 0.0258378; double tolerance = 1e-9; if (Math.Abs(npv - calculatedNpv) > tolerance) Assert.Fail( "Failed to reproduce the npv for the given credit-default swap\n" + " computed NPV: " + calculatedNpv + "\n" + " Given NPV: " + npv); if ( Math.Abs( fairRate - calculatedFairRate ) > tolerance ) Assert.Fail( "Failed to reproduce the fair rate for the given credit-default swap\n" + " computed fair rate: " + calculatedFairRate + "\n" + " Given fair rate: " + fairRate ); }
public static Greeks GetOptionOnFutureGreeks(double underlyingPrice,double strike,double riskFreeRate, DateTime expirationDate, DateTime calculationDate, string optionType, string exerciseType, double optionPrice=double.NaN,double impliedVol=0.15,string engineName="baw") { QLNet.Date ExpirationDateObj = new QLNet.Date(expirationDate.Day, expirationDate.Month, expirationDate.Year); QLNet.Date CalculationDateObj = new QLNet.Date(calculationDate.Day, calculationDate.Month, calculationDate.Year); QLNet.DayCounter DayCountObj = new QLNet.Actual365Fixed(); QLNet.Calendar CalendarObj = new QLNet.UnitedStates(); Greeks GreeksOutput = new Greeks(); QLNet.Option.Type OptionTypeObj; QLNet.Exercise ExerciseObj; double ImpliedVol; double OptionPrice; int CalDte = DayCountObj.dayCount(CalculationDateObj, ExpirationDateObj); GreeksOutput.CalDte = CalDte; if (!double.IsNaN(optionPrice)) { if (optionType.ToUpper() == "C") { if (optionPrice + strike - underlyingPrice <= 1.0e-12) { GreeksOutput.Delta = 1; return GreeksOutput; } } else if (optionType.ToUpper() == "P") { if (optionPrice - strike + underlyingPrice <= 1.0e-12) { GreeksOutput.Delta = -1; return GreeksOutput; } } } if (CalDte == 0) { if (optionType.ToUpper() == "C") { if (strike <= underlyingPrice) { GreeksOutput.Delta = 1; } else { GreeksOutput.Delta = 0; } } else if (optionType.ToUpper() == "P") { if (strike >= underlyingPrice) { GreeksOutput.Delta = -1; } else { GreeksOutput.Delta = 0; } } return GreeksOutput; } if (optionType.ToUpper() == "C") { OptionTypeObj = QLNet.Option.Type.Call; } else if (optionType.ToUpper() == "P") { OptionTypeObj = QLNet.Option.Type.Put; } else { return GreeksOutput; } if (exerciseType.ToUpper() == "E") { ExerciseObj = new QLNet.EuropeanExercise(ExpirationDateObj); } else if (exerciseType.ToUpper() == "A") { ExerciseObj = new QLNet.AmericanExercise(CalculationDateObj, ExpirationDateObj); } else { return GreeksOutput; } QLNet.Settings.setEvaluationDate(CalculationDateObj); QLNet.Handle<Quote> UnderlyingObj = new QLNet.Handle<Quote>(new QLNet.SimpleQuote(underlyingPrice)); QLNet.Handle<YieldTermStructure> FlatRateObj = new QLNet.Handle<YieldTermStructure>(new QLNet.FlatForward(CalculationDateObj, riskFreeRate, DayCountObj)); QLNet.Handle<BlackVolTermStructure> FlatVolTsObj = new QLNet.Handle<BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, impliedVol, DayCountObj)); QLNet.BlackProcess BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj); QLNet.PlainVanillaPayoff PayoffObj = new QLNet.PlainVanillaPayoff(OptionTypeObj, strike); QLNet.VanillaOption OptionObj = new QLNet.VanillaOption(PayoffObj, ExerciseObj); if (engineName == "baw") { OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc)); } else if (engineName == "fda") { OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100)); } else { return GreeksOutput; } if (!double.IsNaN(optionPrice)) { try { ImpliedVol = OptionObj.impliedVolatility(targetValue:optionPrice, process:BlackProc,accuracy:1e-5); } catch { return GreeksOutput; } FlatVolTsObj = new QLNet.Handle<BlackVolTermStructure>(new QLNet.BlackConstantVol(CalculationDateObj, CalendarObj, ImpliedVol, DayCountObj)); BlackProc = new QLNet.BlackProcess(UnderlyingObj, FlatRateObj, FlatVolTsObj); if (engineName == "baw") { OptionObj.setPricingEngine(new QLNet.BaroneAdesiWhaleyApproximationEngine(BlackProc)); } else if (engineName == "fda") { OptionObj.setPricingEngine(new QLNet.FDAmericanEngine(BlackProc, 100, 100)); } OptionPrice = optionPrice; } else { OptionPrice = OptionObj.NPV(); ImpliedVol = impliedVol; } OptionObj = new QLNet.VanillaOption(PayoffObj, new QLNet.EuropeanExercise(ExpirationDateObj)); OptionObj.setPricingEngine(new QLNet.AnalyticEuropeanEngine(BlackProc)); GreeksOutput.Delta = OptionObj.delta(); GreeksOutput.Vega = OptionObj.vega(); GreeksOutput.Theta = OptionObj.thetaPerDay(); GreeksOutput.Gamma = OptionObj.gamma(); GreeksOutput.OptionPrice = OptionPrice; GreeksOutput.ImpliedVol = ImpliedVol; return GreeksOutput; }
static void Main(string[] args) { // boost::timer timer; Date today = new Date(16,Month.October,2007); Settings.setEvaluationDate(today); Console.WriteLine(); Console.WriteLine("Pricing a callable fixed rate bond using"); Console.WriteLine("Hull White model w/ reversion parameter = 0.03"); Console.WriteLine("BAC4.65 09/15/12 ISIN: US06060WBJ36"); Console.WriteLine("roughly five year tenor, "); Console.WriteLine("quarterly coupon and call dates"); Console.WriteLine("reference date is : " + today ); /* Bloomberg OAS1: "N" model (Hull White) varying volatility parameter The curve entered into Bloomberg OAS1 is a flat curve, at constant yield = 5.5%, semiannual compounding. Assume here OAS1 curve uses an ACT/ACT day counter, as documented in PFC1 as a "default" in the latter case. */ // set up a flat curve corresponding to Bloomberg flat curve double bbCurveRate = 0.055; DayCounter bbDayCounter = new ActualActual(ActualActual.Convention.Bond); InterestRate bbIR = new InterestRate(bbCurveRate,bbDayCounter,Compounding.Compounded ,Frequency.Semiannual); Handle<YieldTermStructure> termStructure = new Handle<YieldTermStructure>(flatRate( today, bbIR.rate(), bbIR.dayCounter(), bbIR.compounding(), bbIR.frequency())); // set up the call schedule CallabilitySchedule callSchedule = new CallabilitySchedule(); double callPrice = 100.0; int numberOfCallDates = 24; Date callDate = new Date(15,Month.September,2006); for (int i=0; i< numberOfCallDates; i++) { Calendar nullCalendar = new NullCalendar(); Callability.Price myPrice = new Callability.Price(callPrice, Callability.Price.Type.Clean); callSchedule.Add( new Callability(myPrice,Callability.Type.Call, callDate )); callDate = nullCalendar.advance(callDate, 3, TimeUnit.Months); } // set up the callable bond Date dated = new Date(16,Month.September,2004); Date issue = dated; Date maturity = new Date(15,Month.September,2012); int settlementDays = 3; // Bloomberg OAS1 settle is Oct 19, 2007 Calendar bondCalendar = new UnitedStates(UnitedStates.Market.GovernmentBond); double coupon = .0465; Frequency frequency = Frequency.Quarterly; double redemption = 100.0; double faceAmount = 100.0; /* The 30/360 day counter Bloomberg uses for this bond cannot reproduce the US Bond/ISMA (constant) cashflows used in PFC1. Therefore use ActAct(Bond) */ DayCounter bondDayCounter = new ActualActual(ActualActual.Convention.Bond); // PFC1 shows no indication dates are being adjusted // for weekends/holidays for vanilla bonds BusinessDayConvention accrualConvention = BusinessDayConvention.Unadjusted; BusinessDayConvention paymentConvention = BusinessDayConvention.Unadjusted; Schedule sch = new Schedule( dated, maturity, new Period(frequency), bondCalendar, accrualConvention, accrualConvention, DateGeneration.Rule.Backward, false); int maxIterations = 1000; double accuracy = 1e-8; int gridIntervals = 40; double reversionParameter = .03; // output price/yield results for varying volatility parameter double sigma = Const.QL_Epsilon; // core dumps if zero on Cygwin ShortRateModel hw0 = new HullWhite(termStructure,reversionParameter,sigma); IPricingEngine engine0 = new TreeCallableFixedRateBondEngine(hw0, gridIntervals, termStructure); CallableFixedRateBond callableBond = new CallableFixedRateBond( settlementDays, faceAmount, sch, new InitializedList<double>(1, coupon), bondDayCounter, paymentConvention, redemption, issue, callSchedule); callableBond.setPricingEngine(engine0); Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma)); Console.WriteLine("QuantLib price/yld (%) "); Console.WriteLine( "{0:0.00} / {1:0.00} ", callableBond.cleanPrice() , 100.0 * callableBond.yield(bondDayCounter, Compounding.Compounded, frequency, accuracy, maxIterations)); Console.WriteLine("Bloomberg price/yld (%) "); Console.WriteLine("96.50 / 5.47"); // sigma = .01; Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma)); ShortRateModel hw1 = new HullWhite(termStructure,reversionParameter,sigma); IPricingEngine engine1 = new TreeCallableFixedRateBondEngine(hw1,gridIntervals,termStructure); callableBond.setPricingEngine(engine1); Console.WriteLine("QuantLib price/yld (%) "); Console.WriteLine( "{0:0.00} / {1:0.00} ", callableBond.cleanPrice() , 100.0 * callableBond.yield(bondDayCounter, Compounding.Compounded, frequency, accuracy, maxIterations)); Console.WriteLine("Bloomberg price/yld (%) "); Console.WriteLine("95.68 / 5.66"); // sigma = .03; Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma)); ShortRateModel hw2 = new HullWhite(termStructure, reversionParameter, sigma); IPricingEngine engine2 = new TreeCallableFixedRateBondEngine(hw2, gridIntervals, termStructure); callableBond.setPricingEngine(engine2); Console.WriteLine("QuantLib price/yld (%) "); Console.WriteLine("{0:0.00} / {1:0.00} ", callableBond.cleanPrice(), 100.0 * callableBond.yield(bondDayCounter, Compounding.Compounded, frequency, accuracy, maxIterations)); Console.WriteLine("Bloomberg price/yld (%) "); Console.WriteLine("92.34 / 6.49"); // sigma = .06; Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma)); ShortRateModel hw3 = new HullWhite(termStructure, reversionParameter, sigma); IPricingEngine engine3 = new TreeCallableFixedRateBondEngine(hw3, gridIntervals, termStructure); callableBond.setPricingEngine(engine3); Console.WriteLine("QuantLib price/yld (%) "); Console.WriteLine("{0:0.00} / {1:0.00} ", callableBond.cleanPrice(), 100.0 * callableBond.yield(bondDayCounter, Compounding.Compounded, frequency, accuracy, maxIterations)); Console.WriteLine("Bloomberg price/yld (%) "); Console.WriteLine("87.16 / 7.83"); // sigma = .12; Console.WriteLine("sigma/vol (%) = {0:0.00}", (100.0 * sigma)); ShortRateModel hw4 = new HullWhite(termStructure, reversionParameter, sigma); IPricingEngine engine4 = new TreeCallableFixedRateBondEngine(hw4, gridIntervals, termStructure); callableBond.setPricingEngine(engine4); Console.WriteLine("QuantLib price/yld (%) "); Console.WriteLine("{0:0.00} / {1:0.00} ", callableBond.cleanPrice(), 100.0 * callableBond.yield(bondDayCounter, Compounding.Compounded, frequency, accuracy, maxIterations)); Console.WriteLine("Bloomberg price/yld (%) "); Console.WriteLine("77.31 / 10.65"); }
public DateTime ExpirationDate(int year, int month, string calendarType = "US") { DateTime referenceDay = new DateTime(year, month, 1); referenceDay = referenceDay.AddMonths((int)Rule.ReferenceRelativeMonth); Calendar calendar = new UnitedStates(UnitedStates.Market.NYSE); //todo add functionality to allow changing this to other countries int day; if (Rule.ReferenceDayIsLastBusinessDayOfMonth) { var tmpDay = referenceDay.AddMonths(1); tmpDay = tmpDay.AddDays(-1); while (!calendar.isBusinessDay(tmpDay)) { tmpDay = tmpDay.AddDays(-1); } day = tmpDay.Day; } else if (Rule.ReferenceUsesDays) //we use a fixed number of days from the start of the month { day = Rule.ReferenceDays; } else //we use a number of weeks and then a weekday of that week { if (Rule.ReferenceWeekDayCount == WeekDayCount.Last) //the last week of the month { var tmpDay = referenceDay.AddMonths(1); tmpDay = tmpDay.AddDays(-1); while (tmpDay.DayOfWeek.ToInt() != (int)Rule.ReferenceWeekDay) { tmpDay = tmpDay.AddDays(-1); } day = tmpDay.Day; } else //1st to 4th week of the month, just loop until we find the right day { int weekCount = 0; while (weekCount < (int)Rule.ReferenceWeekDayCount + 1) { if (referenceDay.DayOfWeek.ToInt() == (int)Rule.ReferenceWeekDay) weekCount++; referenceDay = referenceDay.AddDays(1); } day = referenceDay.Day - 1; } } referenceDay = new DateTime(year, month, day); referenceDay = referenceDay.AddMonths((int)Rule.ReferenceRelativeMonth); if (Rule.DayType == DayType.BusinessDay) { int daysLeft = Rule.DaysBefore; int daysBack = 0; while (daysLeft > 0) { daysBack++; if (calendar.isBusinessDay(referenceDay.AddDays(-daysBack))) //todo fix here... daysLeft--; } return referenceDay.AddDays(-daysBack); } else if (Rule.DayType == DayType.CalendarDay) { return referenceDay.AddDays(-Rule.DaysBefore); } return referenceDay; }