def test_BKExampleOne(): testCases.banner("=== HULL INITIAL EXAMPLE SECTION 28.7 ED 6 PG 668 ====") times = [0.0, 0.5000, 1.00000, 1.50000, 2.00000, 2.500000, 3.00000] zeros = [0.03, 0.0343, 0.03824, 0.04183, 0.04512, 0.048512, 0.05086] times = np.array(times) zeros = np.array(zeros) dfs = np.exp(-zeros * times) startDate = FinDate(1, 12, 2019) endDate = FinDate(1, 6, 2021) sigma = 0.25 a = 0.22 numTimeSteps = 3 tmat = (endDate - startDate) / gDaysInYear model = FinModelRatesBK(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) # Agrees with Figure 28.10 - Not exact as we have dt not exactly 0.50 if numTimeSteps < 5: testCases.header("LABEL", "VALUE") testCases.print("QTREE", model._Q) testCases.print("RTREE", model._rt) printTree(model._rt) testCases.print("PU AT LAST TIME", model._pu) testCases.print("PDM AT LAST TIME", model._pm) testCases.print("PD AT LAST TIME", model._pd)
def test_FinBondOptionAmericanConvergenceONE(): # Build discount curve settlementDate = FinDate(1, 12, 2019) discountCurve = FinDiscountCurveFlat(settlementDate, 0.05) # Bond details maturityDate = FinDate(1, 9, 2025) issueDate = FinDate(1, 9, 2016) coupon = 0.05 freqType = FinFrequencyTypes.SEMI_ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, freqType, accrualType) # Option Details expiryDate = FinDate(1, 12, 2020) strikePrice = 100.0 face = 100.0 testCases.header("TIME", "N", "PUT_AMER", "PUT_EUR", "CALL_AME", "CALL_EUR") timeSteps = range(30, 100, 10) for numTimeSteps in timeSteps: sigma = 0.20 a = 0.1 start = time.time() optionType = FinOptionTypes.AMERICAN_PUT bondOption1 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model1 = FinModelRatesBK(sigma, a, numTimeSteps) v1put = bondOption1.value(settlementDate, discountCurve, model1) optionType = FinOptionTypes.EUROPEAN_PUT bondOption2 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model2 = FinModelRatesBK(sigma, a, numTimeSteps) v2put = bondOption2.value(settlementDate, discountCurve, model2) optionType = FinOptionTypes.AMERICAN_CALL bondOption1 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model1 = FinModelRatesBK(sigma, a, numTimeSteps) v1call = bondOption1.value(settlementDate, discountCurve, model1) optionType = FinOptionTypes.EUROPEAN_CALL bondOption2 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model2 = FinModelRatesBK(sigma, a, numTimeSteps) v2call = bondOption2.value(settlementDate, discountCurve, model2) end = time.time() period = end - start testCases.print(period, numTimeSteps, v1put, v2put, v1call, v2call)
def test_FinBondEmbeddedOptionMATLAB(): # https://fr.mathworks.com/help/fininst/optembndbybk.html # I FIND THAT THE PRICE CONVERGES TO 102.365 WHICH IS CLOSE TO 102.382 # FOUND BY MATLAB ALTHOUGH THEY DO NOT EXAMINE THE ASYMPTOTIC PRICE # WHICH MIGHT BE A BETTER MATCH - ALSO THEY DO NOT USE A REALISTIC VOL settlementDate = FinDate(1, 1, 2007) ########################################################################### swapType = FinSwapTypes.PAYER dcType = FinDayCountTypes.THIRTY_E_360 fixedFreq = FinFrequencyTypes.ANNUAL swap1 = FinIborSwap(settlementDate, "1Y", swapType, 0.0350, fixedFreq, dcType) swap2 = FinIborSwap(settlementDate, "2Y", swapType, 0.0400, fixedFreq, dcType) swap3 = FinIborSwap(settlementDate, "3Y", swapType, 0.0450, fixedFreq, dcType) swaps = [swap1, swap2, swap3] discountCurve = FinIborCurve(settlementDate, [], [], swaps) ########################################################################### issueDate = FinDate(1, 1, 2005) maturityDate = FinDate(1, 1, 2010) coupon = 0.0525 frequencyType = FinFrequencyTypes.ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType) callDates = [] callPrices = [] putDates = [] putPrices = [] putDate = FinDate(1, 1, 2008) for _ in range(0, 24): putDates.append(putDate) putPrices.append(100) putDate = putDate.addMonths(1) testCases.header("BOND PRICE", "PRICE") v = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve) testCases.print("Bond Pure Price:", v) sigma = 0.01 # This volatility is very small for a BK process a = 0.1 puttableBond = FinBondEmbeddedOption(issueDate, maturityDate, coupon, frequencyType, accrualType, callDates, callPrices, putDates, putPrices) testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure") timeSteps = range(100, 200, 10) # 1000, 10) values = [] for numTimeSteps in timeSteps: model = FinModelRatesBK(sigma, a, numTimeSteps) start = time.time() v = puttableBond.value(settlementDate, discountCurve, model) end = time.time() period = end - start testCases.print(period, numTimeSteps, v['bondwithoption'], v['bondpure']) values.append(v['bondwithoption']) if plotGraphs: plt.figure() plt.plot(timeSteps, values)
def test_FinBondEmbeddedOptionQUANTLIB(): # Based on example at the nice blog on Quantlib at # http://gouthamanbalaraman.com/blog/callable-bond-quantlib-python.html # I get a price of 68.97 for 1000 time steps which is higher than the # 68.38 found in blog article. But this is for 40 grid points. # Note also that a basis point vol of 0.120 is 12% which is VERY HIGH! valueDate = FinDate(16, 8, 2016) settlementDate = valueDate.addWeekDays(3) ########################################################################### discountCurve = FinDiscountCurveFlat(valueDate, 0.035, FinFrequencyTypes.SEMI_ANNUAL) ########################################################################### issueDate = FinDate(15, 9, 2010) maturityDate = FinDate(15, 9, 2022) coupon = 0.025 frequencyType = FinFrequencyTypes.QUARTERLY accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType) ########################################################################### # Set up the call and put times and prices ########################################################################### nextCallDate = FinDate(15, 9, 2016) callDates = [nextCallDate] callPrices = [100.0] for _ in range(1, 24): nextCallDate = nextCallDate.addMonths(3) callDates.append(nextCallDate) callPrices.append(100.0) putDates = [] putPrices = [] # the value used in blog of 12% bp vol is unrealistic sigma = 0.12 / 0.035 # basis point volatility a = 0.03 puttableBond = FinBondEmbeddedOption(issueDate, maturityDate, coupon, frequencyType, accrualType, callDates, callPrices, putDates, putPrices) testCases.header("BOND PRICE", "PRICE") v = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve) testCases.print("Bond Pure Price:", v) testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure") timeSteps = range(100, 200, 20) # 1000, 10) values = [] for numTimeSteps in timeSteps: model = FinModelRatesBK(sigma, a, numTimeSteps) start = time.time() v = puttableBond.value(settlementDate, discountCurve, model) end = time.time() period = end - start testCases.print(period, numTimeSteps, v['bondwithoption'], v['bondpure']) values.append(v['bondwithoption']) if plotGraphs: plt.figure() plt.title("Puttable Bond Price Convergence") plt.plot(timeSteps, values)
def test_BKExampleTwo(): # Valuation of a European option on a coupon bearing bond # This follows example in Fig 28.11 of John Hull's book but does not # have the exact same dt so there are some differences settlementDate = FinDate(1, 12, 2019) issueDate = FinDate(1, 12, 2018) expiryDate = settlementDate.addTenor("18m") maturityDate = settlementDate.addTenor("10Y") coupon = 0.05 frequencyType = FinFrequencyTypes.SEMI_ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType) couponTimes = [] couponFlows = [] cpn = bond._coupon / bond._frequency numFlows = len(bond._flowDates) for i in range(1, numFlows): pcd = bond._flowDates[i - 1] ncd = bond._flowDates[i] if pcd < settlementDate and ncd > settlementDate: flowTime = (pcd - settlementDate) / gDaysInYear couponTimes.append(flowTime) couponFlows.append(cpn) for flowDate in bond._flowDates: if flowDate > settlementDate: flowTime = (flowDate - settlementDate) / gDaysInYear couponTimes.append(flowTime) couponFlows.append(cpn) couponTimes = np.array(couponTimes) couponFlows = np.array(couponFlows) strikePrice = 105.0 face = 100.0 tmat = (maturityDate - settlementDate) / gDaysInYear texp = (expiryDate - settlementDate) / gDaysInYear times = np.linspace(0, tmat, 11) dates = settlementDate.addYears(times) dfs = np.exp(-0.05 * times) curve = FinDiscountCurve(settlementDate, dates, dfs) price = bond.cleanPriceFromDiscountCurve(settlementDate, curve) testCases.header("LABEL", "VALUE") testCases.print("Fixed Income Price:", price) sigma = 0.20 a = 0.05 numTimeSteps = 26 model = FinModelRatesBK(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) exerciseType = FinOptionExerciseTypes.AMERICAN v = model.bondOption(texp, strikePrice, face, couponTimes, couponFlows, exerciseType) # Test convergence numStepsList = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000] exerciseType = FinOptionExerciseTypes.AMERICAN testCases.header("TIMESTEPS", "VALUE", "TIME") treeVector = [] for numTimeSteps in numStepsList: start = time.time() model = FinModelRatesBK(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) v = model.bondOption(texp, strikePrice, face, couponTimes, couponFlows, exerciseType) end = time.time() period = end - start treeVector.append(v) testCases.print(numTimeSteps, v, period) # plt.plot(numStepsList, treeVector) # Value in Hill converges to 0.699 with 100 time steps while I get 0.700 if 1 == 0: print("RT") printTree(model._rt, 5) print("Q") printTree(model._Q, 5)
def test_FinIborBermudanSwaptionBKModel(): ''' Replicate examples in paper by Leif Andersen which can be found at file:///C:/Users/Dominic/Downloads/SSRN-id155208.pdf ''' valuationDate = FinDate(1, 1, 2011) settlementDate = valuationDate exerciseDate = settlementDate.addYears(1) swapMaturityDate = settlementDate.addYears(4) swapFixedCoupon = 0.060 swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL swapFixedDayCountType = FinDayCountTypes.ACT_365F liborCurve = FinDiscountCurveFlat(valuationDate, 0.0625, FinFrequencyTypes.SEMI_ANNUAL) fwdPAYSwap = FinIborSwap(exerciseDate, swapMaturityDate, FinSwapTypes.PAY, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fwdSwapValue = fwdPAYSwap.value(settlementDate, liborCurve, liborCurve) testCases.header("LABEL", "VALUE") testCases.print("FWD SWAP VALUE", fwdSwapValue) # fwdPAYSwap.printFixedLegPV() # Now we create the European swaptions fixedLegType = FinSwapTypes.PAY europeanSwaptionPay = FinIborSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE europeanSwaptionRec = FinIborSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) ########################################################################### ########################################################################### ########################################################################### # BLACK'S MODEL ########################################################################### ########################################################################### ########################################################################### testCases.banner("======= ZERO VOLATILITY ========") model = FinModelBlack(0.0000001) testCases.print("Black Model", model._volatility) valuePay = europeanSwaptionPay.value(settlementDate, liborCurve, model) testCases.print("EUROPEAN BLACK PAY VALUE ZERO VOL:", valuePay) valueRec = europeanSwaptionRec.value(settlementDate, liborCurve, model) testCases.print("EUROPEAN BLACK REC VALUE ZERO VOL:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 20%% BLACK VOLATILITY ========") model = FinModelBlack(0.20) testCases.print("Black Model", model._volatility) valuePay = europeanSwaptionPay.value(settlementDate, liborCurve, model) testCases.print("EUROPEAN BLACK PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(settlementDate, liborCurve, model) testCases.print("EUROPEAN BLACK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### ########################################################################### ########################################################################### # BK MODEL ########################################################################### ########################################################################### ########################################################################### testCases.banner("=======================================================") testCases.banner("=======================================================") testCases.banner("==================== BK MODEL =========================") testCases.banner("=======================================================") testCases.banner("=======================================================") testCases.banner("======= 0% VOLATILITY EUROPEAN SWAPTION BK MODEL ======") # Used BK with constant short-rate volatility sigma = 0.00001 a = 0.01 numTimeSteps = 200 model = FinModelRatesBK(sigma, a, numTimeSteps) valuePay = europeanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BK PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 20% VOLATILITY EUROPEAN SWAPTION BK MODEL ========") # Used BK with constant short-rate volatility sigma = 0.20 a = 0.01 model = FinModelRatesBK(sigma, a, numTimeSteps) testCases.banner("BK MODEL SWAPTION CLASS EUROPEAN EXERCISE") valuePay = europeanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BK PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### # Now we create the Bermudan swaptions but only allow European exercise fixedLegType = FinSwapTypes.PAY exerciseType = FinExerciseTypes.EUROPEAN bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE exerciseType = FinExerciseTypes.EUROPEAN bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) testCases.banner("======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BK MODEL ========") # Used BK with constant short-rate volatility sigma = 0.000001 a = 0.01 model = FinModelRatesBK(sigma, a, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 20% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BK MODEL ========") # Used BK with constant short-rate volatility sigma = 0.2 a = 0.01 model = FinModelRatesBK(sigma, a, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### # Now we create the Bermudan swaptions but allow Bermudan exercise ########################################################################### fixedLegType = FinSwapTypes.PAY exerciseType = FinExerciseTypes.BERMUDAN bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE exerciseType = FinExerciseTypes.BERMUDAN bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) testCases.banner("======= ZERO VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BK MODEL ========") # Used BK with constant short-rate volatility sigma = 0.000001 a = 0.01 model = FinModelRatesBK(sigma, a, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 20% VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BK MODEL ========") # Used BK with constant short-rate volatility sigma = 0.20 a = 0.01 model = FinModelRatesBK(sigma, a, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BK REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### ########################################################################### ########################################################################### # BDT MODEL ########################################################################### ########################################################################### ########################################################################### testCases.banner("=======================================================") testCases.banner("=======================================================") testCases.banner("======================= BDT MODEL =====================") testCases.banner("=======================================================") testCases.banner("=======================================================") testCases.banner("====== 0% VOLATILITY EUROPEAN SWAPTION BDT MODEL ======") # Used BK with constant short-rate volatility sigma = 0.00001 numTimeSteps = 200 model = FinModelRatesBDT(sigma, numTimeSteps) valuePay = europeanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BDT PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("===== 20% VOLATILITY EUROPEAN SWAPTION BDT MODEL ======") # Used BK with constant short-rate volatility sigma = 0.20 a = 0.01 model = FinModelRatesBDT(sigma, numTimeSteps) testCases.banner("BDT MODEL SWAPTION CLASS EUROPEAN EXERCISE") valuePay = europeanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BDT PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### # Now we create the Bermudan swaptions but only allow European exercise fixedLegType = FinSwapTypes.PAY exerciseType = FinExerciseTypes.EUROPEAN bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) testCases.banner("======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BDT MODEL ========") # Used BK with constant short-rate volatility sigma = 0.000001 model = FinModelRatesBDT(sigma, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 20% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE BDT MODEL ========") # Used BK with constant short-rate volatility sigma = 0.2 model = FinModelRatesBDT(sigma, numTimeSteps) testCases.banner("BDT MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### # Now we create the Bermudan swaptions but allow Bermudan exercise ########################################################################### fixedLegType = FinSwapTypes.PAY exerciseType = FinExerciseTypes.BERMUDAN bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) testCases.banner("======= ZERO VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BDT MODEL ========") # Used BK with constant short-rate volatility sigma = 0.000001 a = 0.01 model = FinModelRatesBDT(sigma, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 20% VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE BDT MODEL ========") # Used BK with constant short-rate volatility sigma = 0.20 a = 0.01 model = FinModelRatesBDT(sigma, numTimeSteps) # print("BDT MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### ########################################################################### ########################################################################### # BDT MODEL ########################################################################### ########################################################################### ########################################################################### testCases.banner("=======================================================") testCases.banner("=======================================================") testCases.banner("======================= HW MODEL ======================") testCases.banner("=======================================================") testCases.banner("=======================================================") testCases.banner("====== 0% VOLATILITY EUROPEAN SWAPTION HW MODEL ======") sigma = 0.0000001 a = 0.1 numTimeSteps = 200 model = FinModelRatesHW(sigma, a, numTimeSteps) valuePay = europeanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN HW PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN HW REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("===== 20% VOLATILITY EUROPEAN SWAPTION BDT MODEL ======") # Used BK with constant short-rate volatility sigma = 0.01 a = 0.01 model = FinModelRatesHW(sigma, a, numTimeSteps) testCases.banner("HW MODEL SWAPTION CLASS EUROPEAN EXERCISE") valuePay = europeanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN HW PAY VALUE:", valuePay) valueRec = europeanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("EUROPEAN HW REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### # Now we create the Bermudan swaptions but only allow European exercise fixedLegType = FinSwapTypes.PAY exerciseType = FinExerciseTypes.EUROPEAN bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) testCases.banner("======= 0% VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE HW MODEL ========") sigma = 0.000001 model = FinModelRatesHW(sigma, a, numTimeSteps) testCases.banner("BK MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 100bp VOLATILITY BERMUDAN SWAPTION EUROPEAN EXERCISE HW MODEL ========") # Used BK with constant short-rate volatility sigma = 0.01 model = FinModelRatesHW(sigma, a, numTimeSteps) testCases.banner("BDT MODEL BERMUDAN SWAPTION CLASS EUROPEAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN BDT REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) ########################################################################### # Now we create the Bermudan swaptions but allow Bermudan exercise ########################################################################### fixedLegType = FinSwapTypes.PAY exerciseType = FinExerciseTypes.BERMUDAN bermudanSwaptionPay = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) fixedLegType = FinSwapTypes.RECEIVE bermudanSwaptionRec = FinIborBermudanSwaption(settlementDate, exerciseDate, swapMaturityDate, fixedLegType, exerciseType, swapFixedCoupon, swapFixedFrequencyType, swapFixedDayCountType) testCases.banner("======= ZERO VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE HW MODEL ========") # Used BK with constant short-rate volatility sigma = 0.000001 a = 0.01 model = FinModelRatesHW(sigma, a, numTimeSteps) testCases.banner("HW MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN HW PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN HW REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec) testCases.banner("======= 100bps VOLATILITY BERMUDAN SWAPTION BERMUDAN EXERCISE HW MODEL ========") # Used BK with constant short-rate volatility sigma = 0.01 a = 0.01 model = FinModelRatesHW(sigma, a, numTimeSteps) testCases.banner("HW MODEL BERMUDAN SWAPTION CLASS BERMUDAN EXERCISE") valuePay = bermudanSwaptionPay.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN HW PAY VALUE:", valuePay) valueRec = bermudanSwaptionRec.value(valuationDate, liborCurve, model) testCases.print("BERMUDAN HW REC VALUE:", valueRec) payRec = valuePay - valueRec testCases.print("PAY MINUS RECEIVER :", payRec)
def testFinLiborSwaptionModels(): ########################################################################## # COMPARISON OF MODELS ########################################################################## valuationDate = FinDate(2011, 1, 1) liborCurve = test_FinLiborDepositsAndSwaps(valuationDate) exerciseDate = FinDate(2012, 1, 1) swapMaturityDate = FinDate(2017, 1, 1) swapFixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL swapFixedDayCountType = FinDayCountTypes.ACT_365F strikes = np.linspace(0.02, 0.08, 10) testCases.header("LAB", "STRIKE", "BLK", "BLK_SHFT", "SABR", "SABR_SHFT", "HW", "BK") model1 = FinModelBlack(0.00001) model2 = FinModelBlackShifted(0.00001, 0.0) model3 = FinModelSABR(0.013, 0.5, 0.5, 0.5) model4 = FinModelSABRShifted(0.013, 0.5, 0.5, 0.5, -0.008) model5 = FinModelRatesHW(0.00001, 0.00001) model6 = FinModelRatesBK(0.01, 0.01) settlementDate = valuationDate.addWorkDays(2) for k in strikes: swaptionType = FinLiborSwapTypes.PAYER swaption = FinLiborSwaption(settlementDate, exerciseDate, swapMaturityDate, swaptionType, k, swapFixedFrequencyType, swapFixedDayCountType) swap1 = swaption.value(valuationDate, liborCurve, model1) swap2 = swaption.value(valuationDate, liborCurve, model2) swap3 = swaption.value(valuationDate, liborCurve, model3) swap4 = swaption.value(valuationDate, liborCurve, model4) swap5 = swaption.value(valuationDate, liborCurve, model5) swap6 = swaption.value(valuationDate, liborCurve, model6) testCases.print("PAY", k, swap1, swap2, swap3, swap4, swap5, swap6) testCases.header("LABEL", "STRIKE", "BLK", "BLK_SHFTD", "SABR", "SABR_SHFTD", "HW", "BK") for k in strikes: swaptionType = FinLiborSwapTypes.RECEIVER swaption = FinLiborSwaption(settlementDate, exerciseDate, swapMaturityDate, swaptionType, k, swapFixedFrequencyType, swapFixedDayCountType) swap1 = swaption.value(valuationDate, liborCurve, model1) swap2 = swaption.value(valuationDate, liborCurve, model2) swap3 = swaption.value(valuationDate, liborCurve, model3) swap4 = swaption.value(valuationDate, liborCurve, model4) swap5 = swaption.value(valuationDate, liborCurve, model5) swap6 = swaption.value(valuationDate, liborCurve, model6) testCases.print("REC", k, swap1, swap2, swap3, swap4, swap5, swap6)
def testFinLiborSwaptionMatlabExamples(): # We value a European swaption using Black's model and try to replicate a # ML example at https://fr.mathworks.com/help/fininst/swaptionbyblk.html testCases.header("=======================================") testCases.header("MATLAB EXAMPLE WITH FLAT TERM STRUCTURE") testCases.header("=======================================") valuationDate = FinDate(1, 1, 2010) liborCurve = FinDiscountCurveFlat(valuationDate, 0.06, FinFrequencyTypes.CONTINUOUS, FinDayCountTypes.THIRTY_E_360) settlementDate = FinDate(1, 1, 2011) exerciseDate = FinDate(1, 1, 2016) maturityDate = FinDate(1, 1, 2019) fixedCoupon = 0.062 fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA notional = 100.0 # Pricing a PAYER swaptionType = FinLiborSwapTypes.PAYER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional) model = FinModelBlack(0.20) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 2.071 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab) ############################################################################### testCases.header("===================================") testCases.header("MATLAB EXAMPLE WITH TERM STRUCTURE") testCases.header("===================================") valuationDate = FinDate(1, 1, 2010) dates = [ FinDate(1, 1, 2011), FinDate(1, 1, 2012), FinDate(1, 1, 2013), FinDate(1, 1, 2014), FinDate(1, 1, 2015) ] zeroRates = [0.03, 0.034, 0.037, 0.039, 0.040] contFreq = FinFrequencyTypes.CONTINUOUS interpType = FinInterpTypes.LINEAR_ZERO_RATES dayCountType = FinDayCountTypes.THIRTY_E_360 liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates, contFreq, dayCountType, interpType) settlementDate = FinDate(1, 1, 2011) exerciseDate = FinDate(1, 1, 2012) maturityDate = FinDate(1, 1, 2017) fixedCoupon = 0.03 fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL fixedDayCountType = FinDayCountTypes.THIRTY_E_360 floatFrequencyType = FinFrequencyTypes.SEMI_ANNUAL floatDayCountType = FinDayCountTypes.THIRTY_E_360 notional = 1000.0 # Pricing a put swaptionType = FinLiborSwapTypes.RECEIVER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional, floatFrequencyType, floatDayCountType) model = FinModelBlack(0.21) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 0.5771 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab) ############################################################################### testCases.header("===================================") testCases.header("MATLAB EXAMPLE WITH SHIFTED BLACK") testCases.header("===================================") valuationDate = FinDate(1, 1, 2016) dates = [ FinDate(1, 1, 2017), FinDate(1, 1, 2018), FinDate(1, 1, 2019), FinDate(1, 1, 2020), FinDate(1, 1, 2021) ] zeroRates = np.array([-0.02, 0.024, 0.047, 0.090, 0.12]) / 100.0 contFreq = FinFrequencyTypes.ANNUAL interpType = FinInterpTypes.LINEAR_ZERO_RATES dayCountType = FinDayCountTypes.THIRTY_E_360 liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates, contFreq, dayCountType, interpType) settlementDate = FinDate(1, 1, 2016) exerciseDate = FinDate(1, 1, 2017) maturityDate = FinDate(1, 1, 2020) fixedCoupon = -0.003 fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA floatFrequencyType = FinFrequencyTypes.SEMI_ANNUAL floatDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA notional = 1000.0 # Pricing a PAYER swaptionType = FinLiborSwapTypes.PAYER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional, floatFrequencyType, floatDayCountType) model = FinModelBlackShifted(0.31, 0.008) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 12.8301 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab) ############################################################################### testCases.header("===================================") testCases.header("MATLAB EXAMPLE WITH HULL WHITE") testCases.header("===================================") # https://fr.mathworks.com/help/fininst/swaptionbyhw.html valuationDate = FinDate(1, 1, 2007) dates = [ FinDate(1, 1, 2007), FinDate(1, 7, 2007), FinDate(1, 1, 2008), FinDate(1, 7, 2008), FinDate(1, 1, 2009), FinDate(1, 7, 2009), FinDate(1, 1, 2010), FinDate(1, 7, 2010), FinDate(1, 1, 2011), FinDate(1, 7, 2011), FinDate(1, 1, 2012) ] zeroRates = np.array([0.075] * 11) interpType = FinInterpTypes.FLAT_FORWARDS dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA contFreq = FinFrequencyTypes.SEMI_ANNUAL liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates, contFreq, dayCountType, interpType) settlementDate = valuationDate exerciseDate = FinDate(1, 1, 2010) maturityDate = FinDate(1, 1, 2012) fixedCoupon = 0.04 fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA notional = 100.0 swaptionType = FinLiborSwapTypes.RECEIVER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional) model = FinModelRatesHW(0.05, 0.01) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 2.9201 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab) ############################################################################### testCases.header("====================================") testCases.header("MATLAB EXAMPLE WITH BLACK KARASINSKI") testCases.header("====================================") # https://fr.mathworks.com/help/fininst/swaptionbybk.html valuationDate = FinDate(1, 1, 2007) dates = [ FinDate(1, 1, 2007), FinDate(1, 7, 2007), FinDate(1, 1, 2008), FinDate(1, 7, 2008), FinDate(1, 1, 2009), FinDate(1, 7, 2009), FinDate(1, 1, 2010), FinDate(1, 7, 2010), FinDate(1, 1, 2011), FinDate(1, 7, 2011), FinDate(1, 1, 2012) ] zeroRates = np.array([0.07] * 11) interpType = FinInterpTypes.FLAT_FORWARDS dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA contFreq = FinFrequencyTypes.SEMI_ANNUAL liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates, contFreq, dayCountType, interpType) settlementDate = valuationDate exerciseDate = FinDate(1, 1, 2011) maturityDate = FinDate(1, 1, 2012) fixedFrequencyType = FinFrequencyTypes.SEMI_ANNUAL fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA notional = 100.0 model = FinModelRatesBK(0.1, 0.05, 200) fixedCoupon = 0.07 swaptionType = FinLiborSwapTypes.PAYER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 0.3634 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab) fixedCoupon = 0.0725 swaptionType = FinLiborSwapTypes.RECEIVER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 0.4798 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab) ############################################################################### testCases.header("====================================") testCases.header("MATLAB EXAMPLE WITH BLACK-DERMAN-TOY") testCases.header("====================================") # https://fr.mathworks.com/help/fininst/swaptionbybdt.html valuationDate = FinDate(1, 1, 2007) dates = [ FinDate(1, 1, 2007), FinDate(1, 7, 2007), FinDate(1, 1, 2008), FinDate(1, 7, 2008), FinDate(1, 1, 2009), FinDate(1, 7, 2009), FinDate(1, 1, 2010), FinDate(1, 7, 2010), FinDate(1, 1, 2011), FinDate(1, 7, 2011), FinDate(1, 1, 2012) ] zeroRates = np.array([0.06] * 11) interpType = FinInterpTypes.FLAT_FORWARDS dayCountType = FinDayCountTypes.THIRTY_E_360_ISDA contFreq = FinFrequencyTypes.ANNUAL liborCurve = FinDiscountCurveZeros(valuationDate, dates, zeroRates, contFreq, dayCountType, interpType) settlementDate = valuationDate exerciseDate = FinDate(1, 1, 2012) maturityDate = FinDate(1, 1, 2015) fixedFrequencyType = FinFrequencyTypes.ANNUAL fixedDayCountType = FinDayCountTypes.THIRTY_E_360_ISDA notional = 100.0 fixedCoupon = 0.062 swaptionType = FinLiborSwapTypes.PAYER swaption = FinLiborSwaption(settlementDate, exerciseDate, maturityDate, swaptionType, fixedCoupon, fixedFrequencyType, fixedDayCountType, notional) model = FinModelRatesBDT(0.20, 200) v_finpy = swaption.value(valuationDate, liborCurve, model) v_matlab = 2.0592 testCases.header("LABEL", "VALUE") testCases.print("FP Price:", v_finpy) testCases.print("MATLAB Prix:", v_matlab) testCases.print("DIFF:", v_finpy - v_matlab)
def test_FinBondOptionZEROVOLConvergence(): # Build discount curve settlementDate = FinDate(1, 9, 2019) rate = 0.05 discountCurve = FinDiscountCurveFlat(settlementDate, rate, FinFrequencyTypes.ANNUAL) # Bond details issueDate = FinDate(1, 9, 2014) maturityDate = FinDate(1, 9, 2025) coupon = 0.06 frequencyType = FinFrequencyTypes.ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType) # Option Details expiryDate = FinDate(1, 12, 2021) face = 100.0 dfExpiry = discountCurve.df(expiryDate) fwdCleanValue = bond.cleanPriceFromDiscountCurve(expiryDate, discountCurve) fwdFullValue = bond.fullPriceFromDiscountCurve(expiryDate, discountCurve) print("BOND FwdCleanBondPx", fwdCleanValue) print("BOND FwdFullBondPx", fwdFullValue) print("BOND Accrued:", bond._accruedInterest) spotCleanValue = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve) testCases.header("STRIKE", "STEPS", "CALL_INT", "CALL_INT_PV", "CALL_EUR", "CALL_AMER", "PUT_INT", "PUT_INT_PV", "PUT_EUR", "PUT_AMER") numTimeSteps = range(50, 1000, 50) strikePrices = [90, 100, 110, 120] for strikePrice in strikePrices: callIntrinsic = max(spotCleanValue - strikePrice, 0) putIntrinsic = max(strikePrice - spotCleanValue, 0) callIntrinsicPV = max(fwdCleanValue - strikePrice, 0) * dfExpiry putIntrinsicPV = max(strikePrice - fwdCleanValue, 0) * dfExpiry for numSteps in numTimeSteps: sigma = 0.0000001 a = 0.1 model = FinModelRatesBK(sigma, a, numSteps) optionType = FinOptionTypes.EUROPEAN_CALL bondOption1 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) v1 = bondOption1.value(settlementDate, discountCurve, model) optionType = FinOptionTypes.AMERICAN_CALL bondOption2 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) v2 = bondOption2.value(settlementDate, discountCurve, model) optionType = FinOptionTypes.EUROPEAN_PUT bondOption3 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) v3 = bondOption3.value(settlementDate, discountCurve, model) optionType = FinOptionTypes.AMERICAN_PUT bondOption4 = FinBondOption(bond, expiryDate, strikePrice, face, optionType) v4 = bondOption4.value(settlementDate, discountCurve, model) testCases.print(strikePrice, numSteps, callIntrinsic, callIntrinsicPV, v1, v2, putIntrinsic, putIntrinsicPV, v3, v4)
def test_FinBondOption(): settlementDate = FinDate(1, 12, 2019) issueDate = FinDate(1, 12, 2018) maturityDate = settlementDate.addTenor("10Y") coupon = 0.05 frequencyType = FinFrequencyTypes.SEMI_ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType) tmat = (maturityDate - settlementDate) / gDaysInYear times = np.linspace(0, tmat, 20) dates = settlementDate.addYears(times) dfs = np.exp(-0.05*times) discountCurve = FinDiscountCurve(settlementDate, dates, dfs) expiryDate = settlementDate.addTenor("18m") strikePrice = 105.0 face = 100.0 ########################################################################### strikes = [80, 85, 90, 95, 100, 105, 110, 115, 120] optionType = FinOptionTypes.EUROPEAN_CALL testCases.header("LABEL", "VALUE") price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve) testCases.print("Fixed Income Price:", price) numTimeSteps = 20 testCases.header("OPTION TYPE AND MODEL", "STRIKE", "VALUE") for strikePrice in strikes: sigma = 0.20 a = 0.1 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a, numTimeSteps) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("EUROPEAN CALL - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 a = 0.05 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a, numTimeSteps) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("EUROPEAN CALL - BK", strikePrice, v) ########################################################################### optionType = FinOptionTypes.AMERICAN_CALL price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve) testCases.header("LABEL", "VALUE") testCases.print("Fixed Income Price:", price) testCases.header("OPTION TYPE AND MODEL", "STRIKE", "VALUE") for strikePrice in strikes: sigma = 0.01 a = 0.1 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("AMERICAN CALL - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 a = 0.05 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("AMERICAN CALL - BK", strikePrice, v) ########################################################################### optionType = FinOptionTypes.EUROPEAN_PUT price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve) for strikePrice in strikes: sigma = 0.01 a = 0.1 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("EUROPEAN PUT - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 a = 0.05 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("EUROPEAN PUT - BK", strikePrice, v) ########################################################################### optionType = FinOptionTypes.AMERICAN_PUT price = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve) for strikePrice in strikes: sigma = 0.02 a = 0.1 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("AMERICAN PUT - BK", strikePrice, v) for strikePrice in strikes: sigma = 0.20 a = 0.05 bondOption = FinBondOption(bond, expiryDate, strikePrice, face, optionType) model = FinModelRatesBK(sigma, a) v = bondOption.value(settlementDate, discountCurve, model) testCases.print("AMERICAN PUT - BK", strikePrice, v)
def test_FinBondOptionAmericanConvergenceTWO(): # Build discount curve settlementDate = FinDate(1, 12, 2019) discountCurve = FinDiscountCurveFlat(settlementDate, 0.05, FinFrequencyTypes.CONTINUOUS) # Bond details issueDate = FinDate(1, 9, 2014) maturityDate = FinDate(1, 9, 2025) coupon = 0.05 frequencyType = FinFrequencyTypes.ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, frequencyType, accrualType) expiryDate = settlementDate.addTenor("18m") face = 100.0 spotValue = bond.fullPriceFromDiscountCurve(settlementDate, discountCurve) testCases.header("LABEL", "VALUE") testCases.print("BOND PRICE", spotValue) testCases.header("PERIOD", "N", "EUR_CALL", "AMER_CALL", "EUR_PUT", "AMER_PUT") sigma = 0.2 a = 0.1 bkModel = FinModelRatesBK(sigma, a) K = 101.0 vec_ec = [] vec_ac = [] vec_ep = [] vec_ap = [] if 1 == 1: K = 100.0 bkModel = FinModelRatesBK(sigma, a, 100) europeanCallBondOption = FinBondOption(bond, expiryDate, K, face, FinOptionTypes.EUROPEAN_CALL) v_ec = europeanCallBondOption.value(settlementDate, discountCurve, bkModel) testCases.header("LABEL", "VALUE") testCases.print("OPTION", v_ec) numStepsVector = range(100, 100, 1) # should be 100-400 for numSteps in numStepsVector: bkModel = FinModelRatesBK(sigma, a, numSteps) start = time.time() europeanCallBondOption = FinBondOption(bond, expiryDate, K, face, FinOptionTypes.EUROPEAN_CALL) v_ec = europeanCallBondOption.value(settlementDate, discountCurve, bkModel) americanCallBondOption = FinBondOption(bond, expiryDate, K, face, FinOptionTypes.AMERICAN_CALL) v_ac = americanCallBondOption.value(settlementDate, discountCurve, bkModel) europeanPutBondOption = FinBondOption(bond, expiryDate, K, face, FinOptionTypes.EUROPEAN_PUT) v_ep = europeanPutBondOption.value(settlementDate, discountCurve, bkModel) americanPutBondOption = FinBondOption(bond, expiryDate, K, face, FinOptionTypes.AMERICAN_PUT) v_ap = americanPutBondOption.value(settlementDate, discountCurve, bkModel) end = time.time() period = end - start testCases.print(period, numSteps, v_ec, v_ac, v_ep, v_ap) vec_ec.append(v_ec) vec_ac.append(v_ac) vec_ep.append(v_ep) vec_ap.append(v_ap) if plotGraphs: plt.figure() plt.plot(numStepsVector, vec_ec, label="European Call") plt.legend() plt.figure() plt.plot(numStepsVector, vec_ac, label="American Call") plt.legend() plt.figure() plt.plot(numStepsVector, vec_ep, label="European Put") plt.legend() plt.figure() plt.plot(numStepsVector, vec_ap, label="American Put") plt.legend()