public void PVFacts() { var t = 1.0; var t2 = 2.0; var k = 0; var f = 100; var vol = 0.32; var rf = 0.05; var cp = OptionType.P; //expired is worthless var PV = TurnbullWakeman.PV(f, 0, vol, 0, t, 0, rf, OptionType.P); Assert.Equal(0, PV, 10); PV = TurnbullWakeman.PV(f, 0, vol, 0, t, 0, rf, OptionType.C); Assert.Equal(0, PV, 10); //zero strike put is worthless PV = TurnbullWakeman.PV(f, 0, vol, 0, t, t2, rf, cp); Assert.Equal(0, PV, 10); PV = TurnbullWakeman.PV(f, 50, vol, 0, -0.1, t2, rf, cp); Assert.Equal(0, PV, 10); //zero strike call is worth discounted fwd cp = OptionType.C; PV = TurnbullWakeman.PV(f, 0, vol, 0, t, t2, rf, cp); Assert.Equal(System.Math.Exp(-rf * t2) * f, PV, 2); //OTM option with zero vol is worthless vol = 0.0; k = f + 1; PV = TurnbullWakeman.PV(f, k, vol, 0, t, t2, rf, cp); Assert.Equal(0, PV, 10); //put-call parity at f==k k = f; vol = 0.32; var PVcall = TurnbullWakeman.PV(f, 0, vol, k, t, t2, rf, OptionType.C); var PVput = TurnbullWakeman.PV(f, 0, vol, k, t, t2, rf, OptionType.P); Assert.Equal(PVcall, PVput, 2); //independent fwds version var valDate = new DateTime(2019, 10, 24); var fixingStartDate = new DateTime(2019, 10, 01); var fixingEndDate = new DateTime(2019, 10, 25); var fixingDates = DateExtensions.BusinessDaysInPeriod(fixingStartDate, fixingEndDate, TestProviderHelper.CalendarProvider.Collection["NYC"]).ToArray(); var fwds = fixingDates.Select(x => 100.0).ToArray(); var sigmas = fixingDates.Select(x => 0.32).ToArray(); PV = TurnbullWakeman.PV(fwds, fixingDates, valDate, fixingEndDate, sigmas, 1, 0.0, OptionType.C, true); var blackPV = BlackFunctions.BlackPV(100.0, 1, 0.0, 1 / 365.0, 0.32, OptionType.C); Assert.Equal(blackPV, PV, 4); }