def test_FinEquityForward(): valueDate = FinDate(13, 2, 2018) expiryDate = valueDate.addMonths(12) stockPrice = 130.0 forwardPrice = 125.0 # Locked discountRate = 0.05 dividendRate = 0.02 ########################################################################### expiryDate = valueDate.addMonths(12) notional = 100.0 discountCurve = FinDiscountCurveFlat(valueDate, discountRate) dividendCurve = FinDiscountCurveFlat(valueDate, dividendRate) equityForward = FinEquityForward(expiryDate, forwardPrice, notional, FinLongShort.LONG) testCases.header("SPOT FX", "FX FWD", "VALUE_BS") fwdPrice = equityForward.forward(valueDate, stockPrice, discountCurve, dividendCurve) fwdValue = equityForward.value(valueDate, stockPrice, discountCurve, dividendCurve) print(stockPrice, fwdPrice, fwdValue) testCases.print(stockPrice, fwdPrice, fwdValue)
def test_FinCDSCurve(): curveDate = FinDate(2018, 12, 20) swaps = [] depos = [] fras = [] fixedDCC = FinDayCountTypes.ACT_365_ISDA fixedFreq = FinFrequencyTypes.SEMI_ANNUAL fixedCoupon = 0.05 for i in range(1, 11): maturityDate = curveDate.addMonths(12 * i) swap = FinLiborSwap( curveDate, maturityDate, fixedCoupon, fixedFreq, fixedDCC) swaps.append(swap) libor_curve = FinLiborCurve("USD_LIBOR", curveDate, depos, fras, swaps) cdsContracts = [] for i in range(1, 11): maturityDate = curveDate.addMonths(12 * i) cds = FinCDS(curveDate, maturityDate, 0.005 + 0.001 * (i - 1)) cdsContracts.append(cds) issuerCurve = FinCDSCurve(curveDate, cdsContracts, libor_curve, recoveryRate=0.40, useCache=False) testCases.header("T", "Q") n = len(issuerCurve._times) for i in range(0, n): testCases.print(issuerCurve._times[i], issuerCurve._values[i]) testCases.header("CONTRACT", "VALUE") for i in range(1, 11): maturityDate = curveDate.addMonths(12 * i) cds = FinCDS(curveDate, maturityDate, 0.005 + 0.001 * (i - 1)) v = cds.value(curveDate, issuerCurve) testCases.print(i, v)
def test_OIS(): startDate = FinDate(2018, 11, 30) endDate = FinDate(2028, 6, 20) endDate = startDate.addMonths(60) oisRate = 0.04 isPayer = True fixedFreq = FinFrequencyTypes.ANNUAL fixedDayCount = FinDayCountTypes.ACT_ACT_ISDA floatFreq = FinFrequencyTypes.ANNUAL floatDayCount = FinDayCountTypes.ACT_ACT_ISDA notional = ONE_MILLION ois = FinOIS(startDate, endDate, oisRate, fixedFreq, fixedDayCount, floatFreq, floatDayCount, isPayer, notional) valueDate = FinDate(2018, 11, 30) marketRate = 0.05 indexCurve = FinDiscountCurveFlat(valueDate, marketRate, FinFrequencyTypes.ANNUAL) v = ois.value(startDate, indexCurve) testCases.header("LABEL", "VALUE") testCases.print("SWAP_VALUE", v)
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_OIS(): # Here I follow the example in # https://blog.deriscope.com/index.php/en/excel-quantlib-overnight-index-swap startDate = FinDate(30, 11, 2018) endDate = FinDate(30, 11, 2023) endDate = startDate.addMonths(60) oisRate = 0.04 swapType = FinSwapTypes.PAYER fixedFreq = FinFrequencyTypes.ANNUAL fixedDayCount = FinDayCountTypes.ACT_360 floatFreq = FinFrequencyTypes.ANNUAL floatDayCount = FinDayCountTypes.ACT_360 notional = ONE_MILLION ois = FinOIRSwap(startDate, endDate, swapType, oisRate, fixedFreq, fixedDayCount, floatFreq, floatDayCount, notional) valueDate = FinDate(2018, 11, 30) marketRate = 0.05 indexCurve = FinDiscountCurveFlat(valueDate, marketRate, FinFrequencyTypes.ANNUAL) v = ois.value(startDate, [], [], indexCurve, indexCurve) testCases.header("LABEL", "VALUE") testCases.print("SWAP_VALUE", v) print(v)
def test_FinFXForward(): # https://stackoverflow.com/questions/48778712 # /fx-vanilla-call-price-in-quantlib-doesnt-match-bloomberg valueDate = FinDate(13, 2, 2018) expiryDate = valueDate.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 settlementDate = valueDate.addWorkDays(spotDays) maturityDate = settlementDate.addMonths(12) notional = 100.0 calendarType = FinCalendarTypes.TARGET depos = [] fras = [] swaps = [] depositRate = ccy1InterestRate depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, FinDayCountTypes.ACT_360, notional, calendarType) depos.append(depo) forDiscountCurve = FinLiborCurve(settlementDate, depos, fras, swaps) depos = [] fras = [] swaps = [] depositRate = ccy2InterestRate depo = FinLiborDeposit(settlementDate, maturityDate, depositRate, FinDayCountTypes.ACT_360, notional, calendarType) depos.append(depo) domDiscountCurve = FinLiborCurve(settlementDate, depos, fras, swaps) notional = 100.0 notionalCurrency = forName fxForward = FinFXForward(expiryDate, strikeFXRate, currencyPair, notional, notionalCurrency) testCases.header("SPOT FX", "FX FWD", "VALUE_BS") fwdValue = fxForward.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve) fwdFXRate = fxForward.forward(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve) testCases.print(spotFXRate, fwdFXRate, fwdValue)
def test_FinDateAddMonths(): startDate = FinDate(1, 1, 2010) testCases.header("Months", "Dates") months = [1, 3, 6, 9, 12, 24, 36, 48, 60] dates = startDate.addMonths(months) testCases.header("DATES", "DATE") for dt in dates: testCases.print("DATE", dt)
def test_IssuerCurveBuild(): ''' Test issuer curve build with simple libor curve to isolate cds curve building time cost. ''' valuationDate = FinDate(20, 6, 2018) times = np.linspace(0.0, 10.0, 11) r = 0.05 discountFactors = np.power((1.0 + r), -times) dates = valuationDate.addYears(times) liborCurve = FinDiscountCurve(valuationDate, dates, discountFactors, FinInterpTypes.FLAT_FWD_RATES) recoveryRate = 0.40 cdsContracts = [] cdsCoupon = 0.005 # 50 bps maturityDate = valuationDate.addMonths(12) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0055 maturityDate = valuationDate.addMonths(24) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0060 maturityDate = valuationDate.addMonths(36) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0065 maturityDate = valuationDate.addMonths(60) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0070 maturityDate = valuationDate.addMonths(84) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0073 maturityDate = valuationDate.addMonths(120) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) issuerCurve = FinCDSCurve(valuationDate, cdsContracts, liborCurve, recoveryRate) return cdsContracts, issuerCurve
def test_FinEquityVarianceSwap(): startDate = FinDate(20, 3, 2018) tenor = "3M" strike = 0.3 * 0.3 volSwap = FinEquityVarianceSwap(startDate, tenor, strike) valuationDate = FinDate(20, 3, 2018) stockPrice = 100.0 dividendYield = 0.0 dividendCurve = FinDiscountCurveFlat(valuationDate, dividendYield) maturityDate = startDate.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(valuationDate, maturityDate, strikes, vols) strikeSpacing = 5.0 numCallOptions = 10 numPutOptions = 10 r = 0.05 discountCurve = FinDiscountCurveFlat(valuationDate, r) useForward = False testCases.header("LABEL", "VALUE") k1 = volSwap.fairStrike(valuationDate, stockPrice, dividendCurve, volCurve, numCallOptions, numPutOptions, strikeSpacing, discountCurve, useForward) testCases.print("REPLICATION VARIANCE:", k1) k2 = volSwap.fairStrikeApprox(valuationDate, stockPrice, strikes, vols) testCases.print("DERMAN SKEW APPROX for K:", k2)
def test_CurveBuild(): valuationDate = FinDate(2018, 6, 20) times = np.linspace(0.0, 10.0, 10) r = 0.05 discountFactors = np.power((1.0 + r), -times) liborCurve = FinDiscountCurve(valuationDate, times, discountFactors, FinInterpMethods.FLAT_FORWARDS) recoveryRate = 0.40 cdsContracts = [] cdsCoupon = 0.005 # 50 bps maturityDate = valuationDate.addMonths(12) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0055 maturityDate = valuationDate.addMonths(24) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0060 maturityDate = valuationDate.addMonths(36) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0065 maturityDate = valuationDate.addMonths(60) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0070 maturityDate = valuationDate.addMonths(84) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) cdsCoupon = 0.0073 maturityDate = valuationDate.addMonths(120) cds = FinCDS(valuationDate, maturityDate, cdsCoupon) cdsContracts.append(cds) issuerCurve = FinCDSCurve(valuationDate, cdsContracts, liborCurve, recoveryRate) return cdsContracts, issuerCurve
def test_FinFixedOIS(): # Here I follow the example in # https://blog.deriscope.com/index.php/en/excel-quantlib-overnight-index-swap effectiveDate = FinDate(30, 11, 2018) endDate = FinDate(30, 11, 2023) endDate = effectiveDate.addMonths(60) oisRate = 0.04 fixedLegType = FinSwapTypes.PAY fixedFreqType = FinFrequencyTypes.ANNUAL fixedDayCount = FinDayCountTypes.ACT_360 floatFreqType = FinFrequencyTypes.ANNUAL floatDayCount = FinDayCountTypes.ACT_360 floatSpread = 0.0 notional = ONE_MILLION paymentLag = 1 ois = FinOIS(effectiveDate, endDate, fixedLegType, oisRate, fixedFreqType, fixedDayCount, notional, paymentLag, floatSpread, floatFreqType, floatDayCount) # print(ois) valueDate = effectiveDate marketRate = 0.05 oisCurve = FinDiscountCurveFlat(valueDate, marketRate, FinFrequencyTypes.ANNUAL) v = ois.value(effectiveDate, oisCurve) # print(v) # ois._fixedLeg.printValuation() # ois._floatLeg.printValuation() testCases.header("LABEL", "VALUE") testCases.print("SWAP_VALUE", v)
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("=============================") settlementDate = FinDate(23, 8, 2019) issueDate = FinDate(25, 9, 2013) maturityDate = FinDate(22, 3, 2068) coupon = 0.00125 freqType = FinFrequencyTypes.SEMI_ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA face = 100.0 baseCPIValue = 249.70 ########################################################################### # Discount curve discountCurve = FinDiscountCurveFlat(settlementDate, 0.01033692, FinFrequencyTypes.ANNUAL, FinDayCountTypes.ACT_ACT_ISDA) lag = 3 fixingCPI = 244.65884 fixingDate = settlementDate.addMonths(-lag) ########################################################################### # Create Index Curve months = range(0, 12, 1) fixingDates = FinDate(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 = [(FinDate(31,7,2020), 3.1500000000137085), (FinDate(31,7,2021), 3.547500000013759), (FinDate(31,7,2022), 3.675000000013573), (FinDate(31,7,2023), 3.7250000000134342), (FinDate(31,7,2024), 3.750000000013265), (FinDate(31,7,2025), 3.7430000000129526), (FinDate(31,7,2026), 3.741200000012679), (FinDate(31,7,2027), 3.7337000000123632), (FinDate(31,7,2028), 3.725000000011902), (FinDate(31,7,2029), 3.720000000011603), (FinDate(31,7,2030), 3.712517289063011), (FinDate(31,7,2031), 3.7013000000108764), (FinDate(31,7,2032), 3.686986039205209), (FinDate(31,7,2033), 3.671102614032895), (FinDate(31,7,2034), 3.655000000009778), (FinDate(31,7,2035), 3.6394715951305834), (FinDate(31,7,2036), 3.624362044800966), (FinDate(31,7,2037), 3.6093619727979087), (FinDate(31,7,2038), 3.59421438364369), (FinDate(31,7,2039), 3.5787000000081948), (FinDate(31,7,2040), 3.5626192748395624), (FinDate(31,7,2041), 3.545765016376823), (FinDate(31,7,2042), 3.527943521613608), (FinDate(31,7,2043), 3.508977137925462), (FinDate(31,7,2044), 3.48870000000685), (FinDate(31,7,2045), 3.467083068721011), (FinDate(31,7,2046), 3.4445738220594935), (FinDate(31,7,2047), 3.4216470902302065), (FinDate(31,7,2048), 3.3986861494999188), (FinDate(31,7,2049), 3.376000000005752), (FinDate(31,7,2050), 3.3538412080641233), (FinDate(31,7,2051), 3.3324275806807746), (FinDate(31,7,2052), 3.311938788306623), (FinDate(31,7,2053), 3.2925208131865835), (FinDate(31,7,2054), 3.274293040759302), (FinDate(31,7,2055), 3.2573541974782794), (FinDate(31,7,2056), 3.241787355503245), (FinDate(31,7,2057), 3.227664186159851), (FinDate(31,7,2058), 3.2150486140060774), (FinDate(31,7,2059), 3.204000000004159), (FinDate(31,7,2060), 3.1945334946674064), (FinDate(31,7,2061), 3.1865047145143377), (FinDate(31,7,2062), 3.179753073456304), (FinDate(31,7,2063), 3.1741427790361154), (FinDate(31,7,2064), 3.1695593261025223), (FinDate(31,7,2065), 3.1659065919088736), (FinDate(31,7,2066), 3.163104428386987), (FinDate(31,7,2067), 3.1610866681252903), (FinDate(31,7,2068), 3.1597994770515836), (FinDate(31,7,2069), 3.159200000003204), (FinDate(31,7,2070), 3.159242349440139), (FinDate(31,7,2071), 3.1598400898057433), (FinDate(31,7,2072), 3.16090721831932), (FinDate(31,7,2073), 3.162369676612098), (FinDate(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 = FinDiscountCurveZeros(settlementDate, zcDates, zcRates, FinFrequencyTypes.ANNUAL, FinDayCountTypes.ACT_ACT_ISDA) print(inflationZeroCurve) ########################################################################### bond = FinInflationBond(issueDate, maturityDate, coupon, freqType, accrualType, face, baseCPIValue) testCases.header("FIELD", "VALUE") cleanPrice = 104.03502 yld = bond.currentYield(cleanPrice) testCases.print("Current Yield = ", yld) ########################################################################### # Inherited functions that just calculate real yield without CPI adjustments ########################################################################### ytm = bond.yieldToMaturity(settlementDate, cleanPrice, FinYTMCalcType.UK_DMO) testCases.print("UK DMO REAL Yield To Maturity = ", ytm) ytm = bond.yieldToMaturity(settlementDate, cleanPrice, FinYTMCalcType.US_STREET) testCases.print("US STREET REAL Yield To Maturity = ", ytm) ytm = bond.yieldToMaturity(settlementDate, cleanPrice, FinYTMCalcType.US_TREASURY) testCases.print("US TREASURY REAL Yield To Maturity = ", ytm) fullPrice = bond.fullPriceFromYTM(settlementDate, ytm) testCases.print("Full Price from REAL YTM = ", fullPrice) cleanPrice = bond.cleanPriceFromYTM(settlementDate, ytm) testCases.print("Clean Price from Real YTM = ", cleanPrice) accddays = bond._accruedDays testCases.print("Accrued Days = ", accddays) accd = bond._accruedInterest testCases.print("REAL Accrued Interest = ", accd) ########################################################################### # Inflation functions that calculate nominal yield with CPI adjustment ########################################################################### ########################################################################### cleanPrice = bond.cleanPriceFromYTM(settlementDate, ytm) testCases.print("Clean Price from Real YTM = ", cleanPrice) inflationAccd = bond.calcInflationAccruedInterest(settlementDate, refCPIValue) testCases.print("Inflation Accrued = ", inflationAccd) lastCpnCPIValue = 244.61839 cleanPrice = bond.flatPriceFromYieldToMaturity(settlementDate, ytm, lastCpnCPIValue, FinYTMCalcType.US_TREASURY) testCases.print("Flat Price from Real YTM = ", cleanPrice) principal = bond.inflationPrincipal(settlementDate, ytm, refCPIValue, FinYTMCalcType.US_TREASURY) testCases.print("Inflation Principal = ", principal) ########################################################################### duration = bond.dollarDuration(settlementDate, ytm) testCases.print("Dollar Duration = ", duration) modifiedDuration = bond.modifiedDuration(settlementDate, ytm) testCases.print("Modified Duration = ", modifiedDuration) macauleyDuration = bond.macauleyDuration(settlementDate, ytm) testCases.print("Macauley Duration = ", macauleyDuration) conv = bond.convexityFromYTM(settlementDate, ytm) testCases.print("Convexity = ", conv)
def test_FinCDSCurve(): curveDate = FinDate(2018, 12, 20) swaps = [] depos = [] fras = [] fixedDCC = FinDayCountTypes.ACT_365F fixedFreq = FinFrequencyTypes.SEMI_ANNUAL fixedCoupon = 0.05 for i in range(1, 11): maturityDate = curveDate.addMonths(12 * i) swap = FinIborSwap(curveDate, maturityDate, FinSwapTypes.PAYER, fixedCoupon, fixedFreq, fixedDCC) swaps.append(swap) libor_curve = FinIborCurve(curveDate, depos, fras, swaps) cdsContracts = [] for i in range(1, 11): maturityDate = curveDate.addMonths(12 * i) cds = FinCDS(curveDate, maturityDate, 0.005 + 0.001 * (i - 1)) cdsContracts.append(cds) issuerCurve = FinCDSCurve(curveDate, cdsContracts, libor_curve, recoveryRate=0.40, useCache=False) testCases.header("T", "Q") n = len(issuerCurve._times) for i in range(0, n): testCases.print(issuerCurve._times[i], issuerCurve._values[i]) testCases.header("CONTRACT", "VALUE") for i in range(1, 11): maturityDate = curveDate.addMonths(12 * i) cds = FinCDS(curveDate, maturityDate, 0.005 + 0.001 * (i - 1)) v = cds.value(curveDate, issuerCurve) testCases.print(i, v) if 1 == 0: x = [0.0, 1.2, 1.6, 1.7, 10.0] qs = issuerCurve.survProb(x) print("===>", qs) x = [0.3, 1.2, 1.6, 1.7, 10.0] xx = np.array(x) qs = issuerCurve.survProb(xx) print("===>", qs) x = [0.3, 1.2, 1.6, 1.7, 10.0] dfs = issuerCurve.df(x) print("===>", dfs) x = [0.3, 1.2, 1.6, 1.7, 10.0] xx = np.array(x) dfs = issuerCurve.df(xx) print("===>", dfs)
print("ADD CALENDAR DAYS") dt2 = dt1.addDays(2) print(dt2) # dt has not changed, we just created a new date # To add business days we do the following - note this does not know # about regional or religious holidays - just weekends print("ADD WORKDAYS") print(dt1, dt1.addWorkDays(2)) # The weekend has now been skipped # To add a month do print("ADD MONTHS") print(dt1, dt1.addMonths(2)) # An invalid date will throw an error # dt5 = FinDate(2019, 1, 31) # print(dt5) # You can use tenors - a number and a 'd', 'm' or 'y' in upper or lower case print("TENORS") print(dt1.addTenor("1d")) print(dt1.addTenor("2D")) print(dt1.addTenor("3M")) print(dt1.addTenor("4m")) print(dt1.addTenor("5Y")) print(dt1.addTenor("6y")) # You can subtract dates
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! valuationDate = FinDate(16, 8, 2016) settlementDate = valuationDate.addWeekDays(3) ########################################################################### discountCurve = FinDiscountCurveFlat(valuationDate, 0.035, FinFrequencyTypes.SEMI_ANNUAL) ########################################################################### issueDate = FinDate(15, 9, 2010) maturityDate = FinDate(15, 9, 2022) coupon = 0.025 freqType = FinFrequencyTypes.QUARTERLY accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, freqType, accrualType) ########################################################################### # Set up the call and put times and prices ########################################################################### nextCallDate = FinDate(15, 9, 2016) callDates = [nextCallDate] callPrices = [100.0] for i 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 # basis point volatility a = 0.03 puttableBond = FinBondEmbeddedOption(issueDate, maturityDate, coupon, freqType, 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, 1000, 100) values = [] for numTimeSteps in timeSteps: model = FinModelRatesHW(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_FinFXVanillaOptionHullExample(): # Example from Hull 4th edition page 284 valueDate = FinDate(2015, 1, 1) expiryDate = valueDate.addMonths(4) spotFXRate = 1.60 volatility = 0.1411 domInterestRate = 0.08 forInterestRate = 0.11 model = FinFXModelBlackScholes(volatility) domDiscountCurve = FinDiscountCurveFlat(valueDate, domInterestRate) forDiscountCurve = FinDiscountCurveFlat(valueDate, forInterestRate) numPathsList = [10000, 20000, 40000, 80000, 160000, 320000] testCases.header("NUMPATHS", "VALUE_BS", "VALUE_MC", "TIME") strikeFXRate = 1.60 for numPaths in numPathsList: callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) start = time.time() valueMC = callOption.valueMC(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model, numPaths) end = time.time() duration = end - start testCases.print(numPaths, value, valueMC, duration) ########################################################################## spotFXRates = np.arange(100, 200, 10) spotFXRates = spotFXRates / 100.0 numPaths = 100000 testCases.header("NUMPATHS", "CALL_VALUE_BS", "CALL_VALUE_MC", "TIME") for spotFXRate in spotFXRates: callOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) start = time.time() valueMC = callOption.valueMC(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model, numPaths) end = time.time() duration = end - start testCases.print(numPaths, value, valueMC, duration) ########################################################################## spotFXRates = np.arange(100, 200, 10) / 100.0 numPaths = 100000 testCases.header("SPOT FX RATE", "PUT_VALUE_BS", "PUT_VALUE_MC", "TIME") for spotFXRate in spotFXRates: putOption = FinFXVanillaOption(expiryDate, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_PUT, 1000000, "USD") value = putOption.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) start = time.time() valueMC = putOption.valueMC(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model, numPaths) 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(expiryDate, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) delta = callOption.delta(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) vega = callOption.vega(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) theta = callOption.theta(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) # callOption.rho(valueDate,stockPrice, 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(expiryDate, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_PUT, 1000000, "USD") value = putOption.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) delta = putOption.delta(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) vega = putOption.vega(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) theta = putOption.theta(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model) # putOption.rho(valueDate,stockPrice, 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(expiryDate, strikeFXRate, "EURUSD", FinOptionTypes.EUROPEAN_CALL, 1000000, "USD") value = callOption.value(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, model)['v'] impliedVol = callOption.impliedVolatility(valueDate, spotFXRate, domDiscountCurve, forDiscountCurve, value) testCases.print(spotFXRate, value, volatility, impliedVol)
def test_FinLiborCapFloor(): import time todayDate = FinDate(2019, 6, 20) # Need to check this how it aligns with curve startDate = FinDate(2019, 6, 24) valuationDate = startDate maturityDate = startDate.addMonths(60) strikeRate = 0.050 liborCurve = test_FinLiborDepositsAndSwaps(todayDate) # The capfloor has begun #lastFixing = 0.028 ########################################################################## ############################ BLACK ###################################### ########################################################################## start = time.time() testCases.header("LABEL", "VALUE") testCases.banner("==================== BLACK =======================") model = FinLiborModelBlack(0.25) capFloorType = FinLiborCapFloorType.CAP capfloor = FinLiborCapFloor(startDate, maturityDate, capFloorType, strikeRate) value = capfloor.value(valuationDate, liborCurve, model) # capfloor.print() testCases.print("CAP Value:", value) capFloorType = FinLiborCapFloorType.FLOOR capfloor = FinLiborCapFloor(startDate, maturityDate, capFloorType, strikeRate) value = capfloor.value(valuationDate, liborCurve, model) # capfloor.print() testCases.print("FLOOR Value:", value) end = time.time() testCases.header("TIME") testCases.print(end - start) ########################################################################## ####################### SHIFTED BLACK ################################## ########################################################################## testCases.banner("============== SHIFTED BLACK ==================") testCases.header("LABEL", "VALUE") start = time.time() model = FinLiborModelShiftedBlack(0.25, -0.01) capFloorType = FinLiborCapFloorType.CAP capfloor = FinLiborCapFloor(startDate, maturityDate, capFloorType, strikeRate) value = capfloor.value(valuationDate, liborCurve, model) # capfloor.print() testCases.print("CAP Value:", value) capFloorType = FinLiborCapFloorType.FLOOR capfloor = FinLiborCapFloor(startDate, maturityDate, capFloorType, strikeRate) value = capfloor.value(valuationDate, liborCurve, model) # capfloor.print() testCases.print("FLOOR Value:", value) end = time.time() testCases.header("TIME") testCases.print(end - start) ########################################################################## ################################ SABR ################################### ########################################################################## testCases.header("LABEL", "VALUE") start = time.time() testCases.banner("============== SABR ==================") model = FinLiborModelSABR(0.28, 1.0, -0.09, 0.21) capFloorType = FinLiborCapFloorType.CAP capfloor = FinLiborCapFloor(startDate, maturityDate, capFloorType, strikeRate) value = capfloor.value(valuationDate, liborCurve, model) # capfloor.print() testCases.print("CAP Value:", value) capFloorType = FinLiborCapFloorType.FLOOR capfloor = FinLiborCapFloor(startDate, maturityDate, capFloorType, strikeRate) value = capfloor.value(valuationDate, liborCurve, model) # capfloor.print() testCases.print("FLOOR Value:", value) end = time.time() testCases.header("TIME") testCases.print(end - start)
def test_FinBondEmbeddedOptionMATLAB(): # https://fr.mathworks.com/help/fininst/optembndbyhw.html # I FIND THAT THE PRICE CONVERGES TO 102.88 WHICH IS CLOSE TO 102.9127 # FOUND BY MATLAB ALTHOUGH THEY DO NOT EXAMINE THE ASYMPTOTIC PRICE # WHICH MIGHT BE A BETTER MATCH settlementDate = FinDate(1, 1, 2007) valuationDate = settlementDate ########################################################################### dcType = FinDayCountTypes.THIRTY_E_360 fixedFreq = FinFrequencyTypes.ANNUAL fixedLegType = FinSwapTypes.PAY swap1 = FinIborSwap(settlementDate, "1Y", fixedLegType, 0.0350, fixedFreq, dcType) swap2 = FinIborSwap(settlementDate, "2Y", fixedLegType, 0.0400, fixedFreq, dcType) swap3 = FinIborSwap(settlementDate, "3Y", fixedLegType, 0.0450, fixedFreq, dcType) swaps = [swap1, swap2, swap3] discountCurve = FinIborSingleCurve(valuationDate, [], [], swaps) ########################################################################### issueDate = FinDate(1, 1, 2004) maturityDate = FinDate(1, 1, 2010) coupon = 0.0525 freqType = FinFrequencyTypes.ANNUAL accrualType = FinDayCountTypes.ACT_ACT_ICMA bond = FinBond(issueDate, maturityDate, coupon, freqType, accrualType) callDates = [] callPrices = [] putDates = [] putPrices = [] putDate = FinDate(1, 1, 2008) for i 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 # basis point volatility a = 0.1 puttableBond = FinBondEmbeddedOption(issueDate, maturityDate, coupon, freqType, accrualType, callDates, callPrices, putDates, putPrices) testCases.header("TIME", "NumTimeSteps", "BondWithOption", "BondPure") timeSteps = range(50, 1000, 10) values = [] for numTimeSteps in timeSteps: model = FinModelRatesHW(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 buildFullIssuerCurve2(mktSpreadBump, irBump): # https://www.markit.com/markit.jsp?jsppage=pv.jsp # YIELD CURVE 20 August 2020 SNAP AT 1600 m = 1.0 settlementDate = FinDate(24, 8, 2020) dcType = FinDayCountTypes.ACT_360 depos = [] maturityDate = settlementDate.addMonths(1) depo1 = FinLiborDeposit(settlementDate, maturityDate, m * 0.001709, dcType) maturityDate = settlementDate.addMonths(2) depo2 = FinLiborDeposit(settlementDate, maturityDate, m * 0.002123, dcType) maturityDate = settlementDate.addMonths(3) depo3 = FinLiborDeposit(settlementDate, maturityDate, m * 0.002469, dcType) maturityDate = settlementDate.addMonths(6) depo4 = FinLiborDeposit(settlementDate, maturityDate, m * 0.003045, dcType) maturityDate = settlementDate.addMonths(12) depo5 = FinLiborDeposit(settlementDate, maturityDate, m * 0.004449, dcType) depos.append(depo1) depos.append(depo2) depos.append(depo3) depos.append(depo4) depos.append(depo5) swaps = [] dcType = FinDayCountTypes.THIRTY_E_360_ISDA fixedFreq = FinFrequencyTypes.SEMI_ANNUAL maturityDate = settlementDate.addMonths(24) swap1 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER, m * 0.002155 + irBump, fixedFreq, dcType) swaps.append(swap1) maturityDate = settlementDate.addMonths(36) swap2 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER, m * 0.002305 + irBump, fixedFreq, dcType) swaps.append(swap2) maturityDate = settlementDate.addMonths(48) swap3 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER, m * 0.002665 + irBump, fixedFreq, dcType) swaps.append(swap3) maturityDate = settlementDate.addMonths(60) swap4 = FinLiborSwap(settlementDate, maturityDate, FinSwapTypes.PAYER, m * 0.003290 + irBump, fixedFreq, dcType) swaps.append(swap4) liborCurve = FinLiborCurve(settlementDate, depos, [], swaps) cdsCoupon = 0.01 + mktSpreadBump cdsMarketContracts = [] effectiveDate = FinDate(21, 8, 2020) cds = FinCDS(effectiveDate, "6M", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "1Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "2Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "3Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "4Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "5Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "7Y", cdsCoupon) cdsMarketContracts.append(cds) cds = FinCDS(effectiveDate, "10Y", cdsCoupon) cdsMarketContracts.append(cds) recoveryRate = 0.40 issuerCurve = FinCDSCurve(settlementDate, cdsMarketContracts, liborCurve, recoveryRate) testCases.header("DATE", "DISCOUNT_FACTOR", "SURV_PROB") years = np.linspace(0.0, 10.0, 20) dates = settlementDate.addYears(years) for dt in dates: df = liborCurve.df(dt) q = issuerCurve.survProb(dt) testCases.print("%16s" % dt, "%12.8f" % df, "%12.8f" % q) return liborCurve, issuerCurve