def test_FinFXForward(): # https://stackoverflow.com/questions/48778712 # /fx-vanilla-call-price-in-quantlib-doesnt-match-bloomberg valuation_date = Date(13, 2, 2018) expiry_date = valuation_date.addMonths(12) # Forward is on EURUSD which is expressed as number of USD per EUR # ccy1 = EUR and ccy2 = USD forName = "EUR" domName = "USD" currencyPair = forName + domName # Always ccy1ccy2 spotFXRate = 1.300 # USD per EUR strikeFXRate = 1.365 # USD per EUR ccy1InterestRate = 0.02 # USD Rates ccy2InterestRate = 0.05 # EUR rates ########################################################################### spotDays = 0 settlement_date = valuation_date.addWeekDays(spotDays) maturity_date = settlement_date.addMonths(12) notional = 100.0 calendar_type = CalendarTypes.TARGET depos = [] fras = [] swaps = [] deposit_rate = ccy1InterestRate depo = FinIborDeposit(settlement_date, maturity_date, deposit_rate, DayCountTypes.ACT_360, notional, calendar_type) depos.append(depo) forDiscountCurve = IborSingleCurve(valuation_date, depos, fras, swaps) depos = [] fras = [] swaps = [] deposit_rate = ccy2InterestRate depo = FinIborDeposit(settlement_date, maturity_date, deposit_rate, DayCountTypes.ACT_360, notional, calendar_type) depos.append(depo) domDiscountCurve = IborSingleCurve(valuation_date, depos, fras, swaps) notional = 100.0 notionalCurrency = forName fxForward = FinFXForward(expiry_date, strikeFXRate, currencyPair, notional, notionalCurrency) testCases.header("SPOT FX", "FX FWD", "VALUE_BS") fwdValue = fxForward.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve) fwdFXRate = fxForward.forward(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve) testCases.print(spotFXRate, fwdFXRate, fwdValue)
def test_DateAddMonths(): startDate = Date(1, 1, 2010) months = [1, 3, 6, 9, 12, 24, 36, 48, 60] dates = startDate.addMonths(months) for dt in dates: print("DATE", dt)
def test_FinDateAddMonths(): start_date = Date(1, 1, 2010) testCases.header("Months", "Dates") months = [1, 3, 6, 9, 12, 24, 36, 48, 60] dates = start_date.addMonths(months) testCases.header("DATES", "DATE") for dt in dates: testCases.print("DATE", dt)
def test_FinEquityForward(): valuation_date = Date(13, 2, 2018) expiry_date = valuation_date.addMonths(12) stock_price = 130.0 forwardPrice = 125.0 # Locked discountRate = 0.05 dividendRate = 0.02 ########################################################################### expiry_date = valuation_date.addMonths(12) notional = 100.0 discount_curve = DiscountCurveFlat(valuation_date, discountRate) dividendCurve = DiscountCurveFlat(valuation_date, dividendRate) equityForward = FinEquityForward(expiry_date, forwardPrice, notional, FinLongShort.LONG) testCases.header("SPOT FX", "FX FWD", "VALUE_BS") fwdPrice = equityForward.forward(valuation_date, stock_price, discount_curve, dividendCurve) fwdValue = equityForward.value(valuation_date, stock_price, discount_curve, dividendCurve) # print(stock_price, fwdPrice, fwdValue) testCases.print(stock_price, fwdPrice, fwdValue)
def test_IssuerCurveBuild(): """ Test issuer curve build with simple libor curve to isolate cds curve building time cost. """ valuation_date = Date(20, 6, 2018) times = np.linspace(0.0, 10.0, 11) r = 0.05 discount_factors = np.power((1.0 + r), -times) dates = valuation_date.addYears(times) libor_curve = DiscountCurve(valuation_date, dates, discount_factors, FinInterpTypes.FLAT_FWD_RATES) recovery_rate = 0.40 cds_contracts = [] cdsCoupon = 0.005 # 50 bps maturity_date = valuation_date.addMonths(12) cds = FinCDS(valuation_date, maturity_date, cdsCoupon) cds_contracts.append(cds) cdsCoupon = 0.0055 maturity_date = valuation_date.addMonths(24) cds = FinCDS(valuation_date, maturity_date, cdsCoupon) cds_contracts.append(cds) cdsCoupon = 0.0060 maturity_date = valuation_date.addMonths(36) cds = FinCDS(valuation_date, maturity_date, cdsCoupon) cds_contracts.append(cds) cdsCoupon = 0.0065 maturity_date = valuation_date.addMonths(60) cds = FinCDS(valuation_date, maturity_date, cdsCoupon) cds_contracts.append(cds) cdsCoupon = 0.0070 maturity_date = valuation_date.addMonths(84) cds = FinCDS(valuation_date, maturity_date, cdsCoupon) cds_contracts.append(cds) cdsCoupon = 0.0073 maturity_date = valuation_date.addMonths(120) cds = FinCDS(valuation_date, maturity_date, cdsCoupon) cds_contracts.append(cds) issuer_curve = FinCDSCurve(valuation_date, cds_contracts, libor_curve, recovery_rate) return cds_contracts, issuer_curve
def test_FinEquityVarianceSwap(): start_date = Date(20, 3, 2018) tenor = "3M" strike = 0.3 * 0.3 volSwap = FinEquityVarianceSwap(start_date, tenor, strike) valuation_date = Date(20, 3, 2018) stock_price = 100.0 dividendYield = 0.0 dividendCurve = DiscountCurveFlat(valuation_date, dividendYield) maturity_date = start_date.addMonths(3) atmVol = 0.20 atmK = 100.0 skew = -0.02 / 5.0 # defined as dsigma/dK strikes = np.linspace(50.0, 135.0, 18) vols = volSkew(strikes, atmVol, atmK, skew) volCurve = FinEquityVolCurve(valuation_date, maturity_date, strikes, vols) strikeSpacing = 5.0 numCallOptions = 10 numPutOptions = 10 r = 0.05 discount_curve = DiscountCurveFlat(valuation_date, r) useForward = False testCases.header("LABEL", "VALUE") k1 = volSwap.fairStrike(valuation_date, stock_price, dividendCurve, volCurve, numCallOptions, numPutOptions, strikeSpacing, discount_curve, useForward) testCases.print("REPLICATION VARIANCE:", k1) k2 = volSwap.fairStrikeApprox(valuation_date, stock_price, strikes, vols) testCases.print("DERMAN SKEW APPROX for K:", k2)
def test_FinFixedOIS(): # Here I follow the example in # https://blog.deriscope.com/index.php/en/excel-quantlib-overnight-index-swap effective_date = Date(30, 11, 2018) end_date = Date(30, 11, 2023) end_date = effective_date.addMonths(60) oisRate = 0.04 fixed_legType = FinSwapTypes.PAY fixedFreqType = FrequencyTypes.ANNUAL fixedDayCount = DayCountTypes.ACT_360 floatFreqType = FrequencyTypes.ANNUAL floatDayCount = DayCountTypes.ACT_360 floatSpread = 0.0 notional = ONE_MILLION payment_lag = 1 ois = FinOIS(effective_date, end_date, fixed_legType, oisRate, fixedFreqType, fixedDayCount, notional, payment_lag, floatSpread, floatFreqType, floatDayCount) # print(ois) valuation_date = effective_date marketRate = 0.05 oisCurve = DiscountCurveFlat(valuation_date, marketRate, FrequencyTypes.ANNUAL) v = ois.value(effective_date, oisCurve) # print(v) # ois._fixed_leg.printValuation() # ois._floatLeg.printValuation() testCases.header("LABEL", "VALUE") testCases.print("SWAP_VALUE", v)
def test_FinFXVanillaOptionHullExample(): # Example from Hull 4th edition page 284 valuation_date = Date(1, 1, 2015) expiry_date = valuation_date.addMonths(4) spotFXRate = 1.60 volatility = 0.1411 domInterestRate = 0.08 forInterestRate = 0.11 model = FinModelBlackScholes(volatility) domDiscountCurve = DiscountCurveFlat(valuation_date, domInterestRate) forDiscountCurve = DiscountCurveFlat(valuation_date, forInterestRate) num_pathsList = [10000, 20000, 40000, 80000, 160000, 320000] testCases.header("NUMPATHS", "VALUE_BS", "VALUE_MC", "TIME") strikeFXRate = 1.60 for num_paths in num_pathsList: callOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) start = time.time() valueMC = callOption.valueMC(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model, num_paths) end = time.time() duration = end - start testCases.print(num_paths, value, valueMC, duration) ########################################################################## spotFXRates = np.arange(100, 200, 10) spotFXRates = spotFXRates / 100.0 num_paths = 100000 testCases.header("NUMPATHS", "CALL_VALUE_BS", "CALL_VALUE_MC", "TIME") for spotFXRate in spotFXRates: callOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) start = time.time() valueMC = callOption.valueMC(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model, num_paths) end = time.time() duration = end - start testCases.print(num_paths, value, valueMC, duration) ########################################################################## spotFXRates = np.arange(100, 200, 10) / 100.0 num_paths = 100000 testCases.header("SPOT FX RATE", "PUT_VALUE_BS", "PUT_VALUE_MC", "TIME") for spotFXRate in spotFXRates: putOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_PUT, 1000000, "USD") value = putOption.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) start = time.time() valueMC = putOption.valueMC(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model, num_paths) end = time.time() duration = end - start testCases.print(spotFXRate, value, valueMC, duration) ########################################################################## spotFXRates = np.arange(100, 200, 10) / 100.0 testCases.header("SPOT FX RATE", "CALL_VALUE_BS", "DELTA_BS", "VEGA_BS", "THETA_BS", "RHO_BS") for spotFXRate in spotFXRates: callOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) delta = callOption.delta(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) vega = callOption.vega(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) theta = callOption.theta(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) # callOption.rho(valuation_date,stock_price, interestRate, # dividendYield, modelType, modelParams) rho = 999 testCases.print(spotFXRate, value, delta, vega, theta, rho) testCases.header("SPOT FX RATE", "PUT_VALUE_BS", "DELTA_BS", "VEGA_BS", "THETA_BS", "RHO_BS") for spotFXRate in spotFXRates: putOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_PUT, 1000000, "USD") value = putOption.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) delta = putOption.delta(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) vega = putOption.vega(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) theta = putOption.theta(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model) # putOption.rho(valuation_date,stock_price, interestRate, dividendYield, # modelType, modelParams) rho = 999 testCases.print(spotFXRate, value, delta, vega, theta, rho) ########################################################################## testCases.header("SPOT FX RATE", "VALUE_BS", "VOL_IN", "IMPLD_VOL") spotFXRates = np.arange(100, 200, 10) / 100.0 for spotFXRate in spotFXRates: callOption = FinFXVanillaOption(expiry_date, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, model)['v'] impliedVol = callOption.impliedVolatility(valuation_date, spotFXRate, domDiscountCurve, forDiscountCurve, value) testCases.print(spotFXRate, value, volatility, impliedVol)
def buildFullIssuerCurve2(mktSpreadBump, irBump): # https://www.markit.com/markit.jsp?jsppage=pv.jsp # YIELD CURVE 20 August 2020 SNAP AT 1600 m = 1.0 valuation_date = Date(24, 8, 2020) settlement_date = Date(24, 8, 2020) dcType = DayCountTypes.ACT_360 depos = [] maturity_date = settlement_date.addMonths(1) depo1 = FinIborDeposit(settlement_date, maturity_date, m * 0.001709, dcType) maturity_date = settlement_date.addMonths(2) depo2 = FinIborDeposit(settlement_date, maturity_date, m * 0.002123, dcType) maturity_date = settlement_date.addMonths(3) depo3 = FinIborDeposit(settlement_date, maturity_date, m * 0.002469, dcType) maturity_date = settlement_date.addMonths(6) depo4 = FinIborDeposit(settlement_date, maturity_date, m * 0.003045, dcType) maturity_date = settlement_date.addMonths(12) depo5 = FinIborDeposit(settlement_date, maturity_date, m * 0.004449, dcType) depos.append(depo1) depos.append(depo2) depos.append(depo3) depos.append(depo4) depos.append(depo5) swaps = [] dcType = DayCountTypes.THIRTY_E_360_ISDA fixedFreq = FrequencyTypes.SEMI_ANNUAL maturity_date = settlement_date.addMonths(24) swap1 = FinIborSwap(settlement_date, maturity_date, FinSwapTypes.PAY, m * 0.002155 + irBump, fixedFreq, dcType) swaps.append(swap1) maturity_date = settlement_date.addMonths(36) swap2 = FinIborSwap(settlement_date, maturity_date, FinSwapTypes.PAY, m * 0.002305 + irBump, fixedFreq, dcType) swaps.append(swap2) maturity_date = settlement_date.addMonths(48) swap3 = FinIborSwap(settlement_date, maturity_date, FinSwapTypes.PAY, m * 0.002665 + irBump, fixedFreq, dcType) swaps.append(swap3) maturity_date = settlement_date.addMonths(60) swap4 = FinIborSwap(settlement_date, maturity_date, FinSwapTypes.PAY, m * 0.003290 + irBump, fixedFreq, dcType) swaps.append(swap4) libor_curve = IborSingleCurve(valuation_date, depos, [], swaps) cdsCoupon = 0.01 + mktSpreadBump cdsMarketContracts = [] effective_date = Date(21, 8, 2020) cds = FinCDS(effective_date, "6M", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "1Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "2Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "3Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "4Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "5Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "7Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effective_date, "10Y", cdsCoupon) cdsMarketContracts.append(cds) recovery_rate = 0.40 issuer_curve = FinCDSCurve(settlement_date, cdsMarketContracts, libor_curve, recovery_rate) testCases.header("DATE", "DISCOUNT_FACTOR", "SURV_PROB") years = np.linspace(0.0, 10.0, 20) dates = settlement_date.addYears(years) for dt in dates: df = libor_curve.df(dt) q = issuer_curve.survProb(dt) testCases.print("%16s" % dt, "%12.8f" % df, "%12.8f" % q) return libor_curve, issuer_curve
def test_FinCDSCurve(): curveDate = Date(20, 12, 2018) swaps = [] depos = [] fras = [] fixedDCC = DayCountTypes.ACT_365F fixedFreq = FrequencyTypes.SEMI_ANNUAL fixedCoupon = 0.05 for i in range(1, 11): maturity_date = curveDate.addMonths(12 * i) swap = FinIborSwap(curveDate, maturity_date, FinSwapTypes.PAY, fixedCoupon, fixedFreq, fixedDCC) swaps.append(swap) libor_curve = IborSingleCurve(curveDate, depos, fras, swaps) cds_contracts = [] for i in range(1, 11): maturity_date = curveDate.addMonths(12 * i) cds = FinCDS(curveDate, maturity_date, 0.005 + 0.001 * (i - 1)) cds_contracts.append(cds) issuer_curve = FinCDSCurve(curveDate, cds_contracts, libor_curve, recovery_rate=0.40, useCache=False) testCases.header("T", "Q") n = len(issuer_curve._times) for i in range(0, n): testCases.print(issuer_curve._times[i], issuer_curve._values[i]) testCases.header("CONTRACT", "VALUE") for i in range(1, 11): maturity_date = curveDate.addMonths(12 * i) cds = FinCDS(curveDate, maturity_date, 0.005 + 0.001 * (i - 1)) v = cds.value(curveDate, issuer_curve) testCases.print(i, v) if 1 == 0: x = [0.0, 1.2, 1.6, 1.7, 10.0] qs = issuer_curve.survProb(x) print("===>", qs) x = [0.3, 1.2, 1.6, 1.7, 10.0] xx = np.array(x) qs = issuer_curve.survProb(xx) print("===>", qs) x = [0.3, 1.2, 1.6, 1.7, 10.0] dfs = issuer_curve.df(x) print("===>", dfs) x = [0.3, 1.2, 1.6, 1.7, 10.0] xx = np.array(x) dfs = issuer_curve.df(xx) print("===>", dfs)
def test_FinInflationBondStack(): ########################################################################## # https://stackoverflow.com/questions/57676724/failing-to-obtain-correct-accrued-interest-with-quantlib-inflation-bond-pricer-i ########################################################################## testCases.banner("=============================") testCases.banner("QUANT FINANCE US TIPS EXAMPLE") testCases.banner("=============================") settlement_date = Date(23, 8, 2019) issue_date = Date(25, 9, 2013) maturity_date = Date(22, 3, 2068) coupon = 0.00125 freq_type = FrequencyTypes.SEMI_ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA face = 100.0 baseCPIValue = 249.70 ########################################################################### # Discount curve discount_curve = DiscountCurveFlat(settlement_date, 0.01033692, FrequencyTypes.ANNUAL, DayCountTypes.ACT_ACT_ISDA) lag = 3 fixingCPI = 244.65884 fixingDate = settlement_date.addMonths(-lag) ########################################################################### # Create Index Curve months = range(0, 12, 1) fixingDates = Date(31, 8, 2018).addMonths(months) fixingRates = [ 284.2, 284.1, 284.5, 284.6, 285.6, 283.0, 285.0, 285.1, 288.2, 289.2, 289.6, 289.5 ] inflationIndex = FinInflationIndexCurve(fixingDates, fixingRates, lag) # print(inflationIndex) ########################################################################### zciisData = [(Date(31, 7, 2020), 3.1500000000137085), (Date(31, 7, 2021), 3.547500000013759), (Date(31, 7, 2022), 3.675000000013573), (Date(31, 7, 2023), 3.7250000000134342), (Date(31, 7, 2024), 3.750000000013265), (Date(31, 7, 2025), 3.7430000000129526), (Date(31, 7, 2026), 3.741200000012679), (Date(31, 7, 2027), 3.7337000000123632), (Date(31, 7, 2028), 3.725000000011902), (Date(31, 7, 2029), 3.720000000011603), (Date(31, 7, 2030), 3.712517289063011), (Date(31, 7, 2031), 3.7013000000108764), (Date(31, 7, 2032), 3.686986039205209), (Date(31, 7, 2033), 3.671102614032895), (Date(31, 7, 2034), 3.655000000009778), (Date(31, 7, 2035), 3.6394715951305834), (Date(31, 7, 2036), 3.624362044800966), (Date(31, 7, 2037), 3.6093619727979087), (Date(31, 7, 2038), 3.59421438364369), (Date(31, 7, 2039), 3.5787000000081948), (Date(31, 7, 2040), 3.5626192748395624), (Date(31, 7, 2041), 3.545765016376823), (Date(31, 7, 2042), 3.527943521613608), (Date(31, 7, 2043), 3.508977137925462), (Date(31, 7, 2044), 3.48870000000685), (Date(31, 7, 2045), 3.467083068721011), (Date(31, 7, 2046), 3.4445738220594935), (Date(31, 7, 2047), 3.4216470902302065), (Date(31, 7, 2048), 3.3986861494999188), (Date(31, 7, 2049), 3.376000000005752), (Date(31, 7, 2050), 3.3538412080641233), (Date(31, 7, 2051), 3.3324275806807746), (Date(31, 7, 2052), 3.311938788306623), (Date(31, 7, 2053), 3.2925208131865835), (Date(31, 7, 2054), 3.274293040759302), (Date(31, 7, 2055), 3.2573541974782794), (Date(31, 7, 2056), 3.241787355503245), (Date(31, 7, 2057), 3.227664186159851), (Date(31, 7, 2058), 3.2150486140060774), (Date(31, 7, 2059), 3.204000000004159), (Date(31, 7, 2060), 3.1945334946674064), (Date(31, 7, 2061), 3.1865047145143377), (Date(31, 7, 2062), 3.179753073456304), (Date(31, 7, 2063), 3.1741427790361154), (Date(31, 7, 2064), 3.1695593261025223), (Date(31, 7, 2065), 3.1659065919088736), (Date(31, 7, 2066), 3.163104428386987), (Date(31, 7, 2067), 3.1610866681252903), (Date(31, 7, 2068), 3.1597994770515836), (Date(31, 7, 2069), 3.159200000003204), (Date(31, 7, 2070), 3.159242349440139), (Date(31, 7, 2071), 3.1598400898057433), (Date(31, 7, 2072), 3.16090721831932), (Date(31, 7, 2073), 3.162369676612098), (Date(31, 7, 2074), 3.1641636543027207)] zcDates = [] zcRates = [] for i in range(0, len(zciisData)): zcDates.append(zciisData[i][0]) zcRates.append(zciisData[i][1] / 100.0) inflationZeroCurve = DiscountCurveZeros(settlement_date, zcDates, zcRates, FrequencyTypes.ANNUAL, DayCountTypes.ACT_ACT_ISDA) # print(inflationZeroCurve) ########################################################################### bond = FinInflationBond(issue_date, maturity_date, coupon, freq_type, accrual_type, face, baseCPIValue) testCases.header("FIELD", "VALUE") clean_price = 104.03502 yld = bond.current_yield(clean_price) testCases.print("Current Yield = ", yld) return ########################################################################### # Inherited functions that just calculate real yield without CPI adjustments ########################################################################### ytm = bond.yield_to_maturity(settlement_date, clean_price, FinYTMCalcType.UK_DMO) testCases.print("UK DMO REAL Yield To Maturity = ", ytm) ytm = bond.yield_to_maturity(settlement_date, clean_price, FinYTMCalcType.US_STREET) testCases.print("US STREET REAL Yield To Maturity = ", ytm) ytm = bond.yield_to_maturity(settlement_date, clean_price, FinYTMCalcType.US_TREASURY) testCases.print("US TREASURY REAL Yield To Maturity = ", ytm) full_price = bond.full_price_from_ytm(settlement_date, ytm) testCases.print("Full Price from REAL YTM = ", full_price) clean_price = bond.clean_price_from_ytm(settlement_date, ytm) testCases.print("Clean Price from Real YTM = ", clean_price) accddays = bond._accrued_days testCases.print("Accrued Days = ", accddays) accrued_interest = bond._accruedInterest testCases.print("REAL Accrued Interest = ", accrued_interest) ########################################################################### # Inflation functions that calculate nominal yield with CPI adjustment ########################################################################### ########################################################################### clean_price = bond.clean_price_from_ytm(settlement_date, ytm) testCases.print("Clean Price from Real YTM = ", clean_price) inflationAccd = bond.calcInflationAccruedInterest(settlement_date, refCPIValue) testCases.print("Inflation Accrued = ", inflationAccd) lastCpnCPIValue = 244.61839 clean_price = bond.flatPriceFromYieldToMaturity(settlement_date, ytm, lastCpnCPIValue, FinYTMCalcType.US_TREASURY) testCases.print("Flat Price from Real YTM = ", clean_price) principal = bond.inflationPrincipal(settlement_date, ytm, refCPIValue, FinYTMCalcType.US_TREASURY) testCases.print("Inflation Principal = ", principal) ########################################################################### duration = bond.dollar_duration(settlement_date, ytm) testCases.print("Dollar Duration = ", duration) modified_duration = bond.modified_duration(settlement_date, ytm) testCases.print("Modified Duration = ", modified_duration) macauley_duration = bond.macauley_duration(settlement_date, ytm) testCases.print("Macauley Duration = ", macauley_duration) conv = bond.convexity_from_ytm(settlement_date, ytm) testCases.print("Convexity = ", conv)
def test_BondEmbeddedOptionMATLAB(): # 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 valuation_date = Date(1, 1, 2007) settlement_date = valuation_date ########################################################################### fixed_legType = FinSwapTypes.PAY dcType = DayCountTypes.THIRTY_E_360 fixedFreq = FrequencyTypes.ANNUAL swap1 = FinIborSwap(settlement_date, "1Y", fixed_legType, 0.0350, fixedFreq, dcType) swap2 = FinIborSwap(settlement_date, "2Y", fixed_legType, 0.0400, fixedFreq, dcType) swap3 = FinIborSwap(settlement_date, "3Y", fixed_legType, 0.0450, fixedFreq, dcType) swaps = [swap1, swap2, swap3] discount_curve = IborSingleCurve(valuation_date, [], [], swaps) ########################################################################### issue_date = Date(1, 1, 2005) maturity_date = Date(1, 1, 2010) coupon = 0.0525 freq_type = FrequencyTypes.ANNUAL accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) call_dates = [] call_prices = [] put_dates = [] put_prices = [] putDate = Date(1, 1, 2008) for _ in range(0, 24): put_dates.append(putDate) put_prices.append(100) putDate = putDate.addMonths(1) testCases.header("BOND PRICE", "PRICE") v = bond.clean_price_from_discount_curve(settlement_date, discount_curve) testCases.print("Bond Pure Price:", v) sigma = 0.01 # This volatility is very small for a BK process a = 0.1 puttableBond = BondEmbeddedOption(issue_date, maturity_date, coupon, freq_type, accrual_type, call_dates, call_prices, put_dates, put_prices) 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(settlement_date, discount_curve, 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_BondEmbeddedOptionQUANTLIB(): # 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! valuation_date = Date(16, 8, 2016) settlement_date = valuation_date.addWeekDays(3) ########################################################################### discount_curve = DiscountCurveFlat(valuation_date, 0.035, FrequencyTypes.SEMI_ANNUAL) ########################################################################### issue_date = Date(15, 9, 2010) maturity_date = Date(15, 9, 2022) coupon = 0.025 freq_type = FrequencyTypes.QUARTERLY accrual_type = DayCountTypes.ACT_ACT_ICMA bond = Bond(issue_date, maturity_date, coupon, freq_type, accrual_type) ########################################################################### # Set up the call and put times and prices ########################################################################### nextCallDate = Date(15, 9, 2016) call_dates = [nextCallDate] call_prices = [100.0] for _ in range(1, 24): nextCallDate = nextCallDate.addMonths(3) call_dates.append(nextCallDate) call_prices.append(100.0) put_dates = [] put_prices = [] # the value used in blog of 12% bp vol is unrealistic sigma = 0.12 / 0.035 # basis point volatility a = 0.03 puttableBond = BondEmbeddedOption(issue_date, maturity_date, coupon, freq_type, accrual_type, call_dates, call_prices, put_dates, put_prices) testCases.header("BOND PRICE", "PRICE") v = bond.clean_price_from_discount_curve(settlement_date, discount_curve) 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(settlement_date, discount_curve, 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)