def test_FinFlatCurve(): curveDate = FinDate(1, 1, 2019) months = range(1, 60, 3) dates = curveDate.addMonths(months) testCases.header("COMPOUNDING", "DFS") compounding = FinFrequencyTypes.CONTINUOUS flatCurve = FinDiscountCurveFlat(curveDate, 0.05, compounding) dfs = flatCurve.df(dates) testCases.print(compounding, dfs) compounding = FinFrequencyTypes.ANNUAL flatCurve = FinDiscountCurveFlat(curveDate, 0.05, compounding) dfs = flatCurve.df(dates) testCases.print(compounding, dfs) compounding = FinFrequencyTypes.SEMI_ANNUAL flatCurve = FinDiscountCurveFlat(curveDate, 0.05, compounding) dfs = flatCurve.df(dates) testCases.print(compounding, dfs) compounding = FinFrequencyTypes.QUARTERLY flatCurve = FinDiscountCurveFlat(curveDate, 0.05, compounding) dfs = flatCurve.df(dates) testCases.print(compounding, dfs) compounding = FinFrequencyTypes.MONTHLY flatCurve = FinDiscountCurveFlat(curveDate, 0.05, compounding) dfs = flatCurve.df(dates) testCases.print(compounding, dfs)
def test_FinBondOptionZEROVOLConvergence(): # Build discount curve settlementDate = FinDate(1, 12, 2019) # CHANGED rate = 0.05 discountCurve = FinDiscountCurveFlat(settlementDate, rate, FinFrequencyTypes.ANNUAL) # Bond details issueDate = FinDate(1, 9, 2015) maturityDate = FinDate(1, 9, 2025) coupon = 0.06 freqType = FinFrequencyTypes.ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, freqType, accrualType) # Option Details expiryDate = settlementDate.addTenor("18m") # FinDate(1, 12, 2021) # print("EXPIRY:", expiryDate) face = 100.0 dfExpiry = discountCurve.df(expiryDate) spotCleanValue = bond.cleanPriceFromDiscountCurve(settlementDate, discountCurve) fwdCleanValue = bond.cleanPriceFromDiscountCurve(expiryDate, discountCurve) # print("BOND SpotCleanBondPx", spotCleanValue) # print("BOND FwdCleanBondPx", fwdCleanValue) # 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(100, 1000, 200) 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 model = FinModelRatesBDT(sigma, 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_HullWhiteCallableBond(): # Valuation of a European option on a coupon bearing bond 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) couponTimes = [] couponFlows = [] cpn = bond._coupon / bond._frequency for flowDate in bond._flowDates[1:]: if flowDate > settlementDate: flowTime = (flowDate - settlementDate) / gDaysInYear couponTimes.append(flowTime) couponFlows.append(cpn) couponTimes = np.array(couponTimes) couponFlows = np.array(couponFlows) ########################################################################### # Set up the call and put times and prices ########################################################################### callDates = [] callPrices = [] callPx = 120.0 callDates.append(settlementDate.addTenor("2Y")) callPrices.append(callPx) callDates.append(settlementDate.addTenor("3Y")) callPrices.append(callPx) callDates.append(settlementDate.addTenor("4Y")) callPrices.append(callPx) callDates.append(settlementDate.addTenor("5Y")) callPrices.append(callPx) callDates.append(settlementDate.addTenor("6Y")) callPrices.append(callPx) callDates.append(settlementDate.addTenor("7Y")) callPrices.append(callPx) callDates.append(settlementDate.addTenor("8Y")) callPrices.append(callPx) callTimes = [] for dt in callDates: t = (dt - settlementDate) / gDaysInYear callTimes.append(t) putDates = [] putPrices = [] putPx = 98.0 putDates.append(settlementDate.addTenor("2Y")) putPrices.append(putPx) putDates.append(settlementDate.addTenor("3Y")) putPrices.append(putPx) putDates.append(settlementDate.addTenor("4Y")) putPrices.append(putPx) putDates.append(settlementDate.addTenor("5Y")) putPrices.append(putPx) putDates.append(settlementDate.addTenor("6Y")) putPrices.append(putPx) putDates.append(settlementDate.addTenor("7Y")) putPrices.append(putPx) putDates.append(settlementDate.addTenor("8Y")) putPrices.append(putPx) putTimes = [] for dt in putDates: t = (dt - settlementDate) / gDaysInYear putTimes.append(t) ########################################################################### tmat = (maturityDate - settlementDate) / gDaysInYear curve = FinDiscountCurveFlat(settlementDate, 0.05, FinFrequencyTypes.CONTINUOUS) dfs = [] times = [] for dt in bond._flowDates: if dt > settlementDate: t = (dt - settlementDate) / gDaysInYear df = curve.df(dt) times.append(t) dfs.append(df) dfs = np.array(dfs) times = np.array(times) ########################################################################### v1 = bond.cleanPriceFromDiscountCurve(settlementDate, curve) sigma = 0.02 # basis point volatility a = 0.01 # Test convergence numStepsList = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000] tmat = (maturityDate - settlementDate) / gDaysInYear testCases.header("NUMSTEPS", "BOND_ONLY", "CALLABLE_BOND", "TIME") for numTimeSteps in numStepsList: start = time.time() model = FinModelRatesHW(sigma, a, numTimeSteps) model.buildTree(tmat, times, dfs) v2 = model.callablePuttableBond_Tree(couponTimes, couponFlows, callTimes, callPrices, putTimes, putPrices, 100.0) end = time.time() period = end - start testCases.print(numTimeSteps, v1, v2, period)