def setUp(self): domAlias = 'EUR' domModel = HWModel(0.01, 0.0050, 0.03) forAliases = ['USD', 'GBP', 'JPY'] spotS0 = [1.0, 1.0, 1.0] spotVol = [0.3, 0.3, 0.3] rates = [0.01, 0.01, 0.01] ratesVols = [0.006, 0.007, 0.008] mean = [0.01, 0.01, 0.01] # forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0, spotVol) ] forRatesModels = [ HWModel(r, v, m) for r, v, m in zip(rates, ratesVols, mean) ] # corr = np.identity(2 * len(forAliases) + 1) corr[1, 2] = 0.6 # USD quanto corr[2, 1] = 0.6 corr[3, 4] = 0.8 # GBP quanto corr[4, 3] = 0.8 corr[5, 6] = -0.7 # JPY quanto corr[6, 5] = -0.7 # self.model = HybridModel(domAlias, domModel, forAliases, forAssetModels, forRatesModels, corr)
def test_CreditHybridModel(self): # Rates-FX eurRates = HullWhiteModel(YieldCurve(0.015),0.03,np.array([10.0]),np.array([0.0050])) usdRates = HullWhiteModel(YieldCurve(0.015),0.03,np.array([10.0]),np.array([0.0050])) usdFx = AssetModel(1.25,0.15) hybModel = HybridModel('EUR',eurRates,['USD'],[usdFx],[usdRates],np.eye(3)) # Credit spreadLevel = 0.05 spreadCurve = YieldCurve(spreadLevel) # use 5% instantanous default probablility mean = 0.0001 # 1bp sigma = 0.0100 # 100bp skew = 0.5*sigma/spreadLevel # spreadModel = QuasiGaussianModel(spreadCurve,1,np.array([10.0]),np.array([[sigma]]), np.array([[skew]]),np.array([[-skew]]),np.array([0.01]),np.array([mean]),np.identity(1)) corr = np.eye(4) corr[1,3] = -0.85 # credit-FX corr[3,1] = -0.85 creditModel = CreditModel(hybModel,['CP'],[spreadModel],corr) # print(creditModel.factorAliases()) # obsTimes = np.linspace(0.0,10.0,3) nPaths = 2 seed = 314159265359 mcSim = McSimulation(creditModel,obsTimes,nPaths,seed,True,False)
def test_FxSwap(self): today = ql.Settings.instance().getEvaluationDate() startDate = ql.WeekendsOnly().advance(today,ql.Period('5d')) endDate = ql.WeekendsOnly().advance(today,ql.Period('1y')) eurLeg = ql.Leg([ ql.SimpleCashFlow(1.0,startDate), ql.SimpleCashFlow(-1.0,endDate) ]) usdLeg = ql.Leg([ ql.SimpleCashFlow(1.25,startDate), ql.SimpleCashFlow(-1.25,endDate) ]) swap = Swap([eurLeg,usdLeg],[1.0,-1.0],discYtsHs=None,currencyAliases=['EUR','USD']) obsTimes = np.array([0.0, 0.5, 1.1]) timeLine = swap.timeLine(obsTimes) # print('') for t in timeLine: print('ObsTime: %.2f' % t) for p in timeLine[t]: print(p) # # we set up a very simplistic hybrid model eurModel = HWModel() usdModel = HWModel() fxModel = AssetModel(1.25,0.15) hybModel = HybridModel('EUR',eurModel,['USD'],[fxModel],[usdModel],np.eye(3)) mcSim = McSimulation(hybModel,obsTimes,2,123,True) V = swap.scenarios(obsTimes,mcSim) print(V)
def test_HybridModelWithDeterministicRates(self): curve0 = YieldCurve(0.03) dcfModel0 = DcfModel(curve0) # times = np.array([0.0, 1.0]) nPaths = 1 seed = 314159265359 # hybrid adjuster hybAdjTimes = np.array([0.0, 1.0, 2.0]) # simulate deterministic model only mcSim = McSimulation(dcfModel0,times,nPaths,seed,False) self.assertEqual(mcSim.path(0).zeroBond(1.0,10.0,None),curve0.discount(10.0)/curve0.discount(1.0)) # simulate deterministic domestic model hwModel = HWModel(0.01,0.0050,0.03) asModel = AssetModel(1.0,0.30) corr = np.identity(2) model = HybridModel('EUR',dcfModel0,['USD'],[asModel],[hwModel],corr) model.recalculateHybridVolAdjuster(hybAdjTimes) mcSim = McSimulation(model,times,nPaths,seed,False) dcfModel0.domAlias = 'EUR' p = mcSim.path(0) self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),curve0.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),model.forRatesModels[0].yieldCurve.discount(5.0)) # simulate deterministic foreign model model = HybridModel('EUR',hwModel,['USD'],[asModel],[dcfModel0],corr) model.recalculateHybridVolAdjuster(hybAdjTimes) mcSim = McSimulation(model,times,nPaths,seed,False) dcfModel0.domAlias = 'USD' p = mcSim.path(0) self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),model.domRatesModel.yieldCurve.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),curve0.discount(5.0)) # simulate deterministic domestic and foreign curve curve1 = YieldCurve(0.05) dcfModel1 = DcfModel(curve1) corr = np.identity(1) model = HybridModel('EUR',dcfModel0,['USD'],[asModel],[dcfModel1],corr) model.recalculateHybridVolAdjuster(hybAdjTimes) mcSim = McSimulation(model,times,nPaths,seed,False) dcfModel0.domAlias = 'EUR' dcfModel1.domAlias = 'USD' p = mcSim.path(0) self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),curve0.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),curve1.discount(5.0))
class TestHybridModel(unittest.TestCase): # set up the stage for testing the models def setUp(self): domAlias = 'EUR' domModel = HWModel(0.01, 0.0050, 0.03) forAliases = [ 'USD', 'GBP', 'JPY' ] spotS0 = [ 1.0, 1.0, 1.0 ] spotVol = [ 0.3, 0.3, 0.3 ] rates = [ 0.01, 0.01, 0.01 ] ratesVols = [ 0.006, 0.007, 0.008 ] mean = [ 0.01, 0.01, 0.01 ] # forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0,spotVol) ] forRatesModels = [ HWModel(r,v,m) for r,v,m in zip(rates,ratesVols,mean) ] # corr = np.identity(2 * len(forAliases) + 1) corr[1,2] = 0.6 # USD quanto corr[2,1] = 0.6 corr[3,4] = 0.8 # GBP quanto corr[4,3] = 0.8 corr[5,6] = -0.7 # JPY quanto corr[6,5] = -0.7 # self.model = HybridModel(domAlias,domModel,forAliases,forAssetModels,forRatesModels,corr) def test_HybridModelSetup(self): # we check against known values self.assertListEqual(self.model.modelsStartIdx, [2, 3, 5, 6, 8, 9]) self.assertDictEqual(self.model.index, {'USD': 0, 'GBP': 1, 'JPY': 2}) self.assertEqual(self.model.size(), len(self.model.stateAliases())) self.assertEqual(self.model.factors(), len(self.model.factorAliases())) self.assertListEqual(self.model.stateAliases(), \ [ 'EUR_x', 'EUR_s', 'USD_logS', 'USD_x', 'USD_s', 'GBP_logS', 'GBP_x', 'GBP_s', 'JPY_logS', 'JPY_x', 'JPY_s' ]) self.assertListEqual(self.model.factorAliases(), \ ['EUR_x', 'USD_logS', 'USD_x', 'GBP_logS', 'GBP_x', 'JPY_logS', 'JPY_x']) # check correlation C = self.model.L.dot(self.model.L.transpose()) C = np.abs(C - self.model.correlations) self.assertLess(np.max(C), 1.0e-15) def test_HybridModelEvolution(self): times = np.array([0.0]) nPaths = 1 seed = 314159265359 # risk-neutral simulation mcSim = McSimulation(self.model,times,nPaths,seed,False) p = mcSim.path(0) # self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.asset(0.0,'GBP'),self.model.forAssetModels[1].X0) self.assertEqual(p.asset(0.0,'JPY'),self.model.forAssetModels[2].X0) # self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),self.model.domRatesModel.yieldCurve.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),self.model.forRatesModels[0].yieldCurve.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'GBP'),self.model.forRatesModels[1].yieldCurve.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'JPY'),self.model.forRatesModels[2].yieldCurve.discount(5.0)) def test_HybridModelWithDeterministicRates(self): curve0 = YieldCurve(0.03) dcfModel0 = DcfModel(curve0) # times = np.array([0.0, 1.0]) nPaths = 1 seed = 314159265359 # hybrid adjuster hybAdjTimes = np.array([0.0, 1.0, 2.0]) # simulate deterministic model only mcSim = McSimulation(dcfModel0,times,nPaths,seed,False) self.assertEqual(mcSim.path(0).zeroBond(1.0,10.0,None),curve0.discount(10.0)/curve0.discount(1.0)) # simulate deterministic domestic model hwModel = HWModel(0.01,0.0050,0.03) asModel = AssetModel(1.0,0.30) corr = np.identity(2) model = HybridModel('EUR',dcfModel0,['USD'],[asModel],[hwModel],corr) model.recalculateHybridVolAdjuster(hybAdjTimes) mcSim = McSimulation(model,times,nPaths,seed,False) dcfModel0.domAlias = 'EUR' p = mcSim.path(0) self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),curve0.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),model.forRatesModels[0].yieldCurve.discount(5.0)) # simulate deterministic foreign model model = HybridModel('EUR',hwModel,['USD'],[asModel],[dcfModel0],corr) model.recalculateHybridVolAdjuster(hybAdjTimes) mcSim = McSimulation(model,times,nPaths,seed,False) dcfModel0.domAlias = 'USD' p = mcSim.path(0) self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),model.domRatesModel.yieldCurve.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),curve0.discount(5.0)) # simulate deterministic domestic and foreign curve curve1 = YieldCurve(0.05) dcfModel1 = DcfModel(curve1) corr = np.identity(1) model = HybridModel('EUR',dcfModel0,['USD'],[asModel],[dcfModel1],corr) model.recalculateHybridVolAdjuster(hybAdjTimes) mcSim = McSimulation(model,times,nPaths,seed,False) dcfModel0.domAlias = 'EUR' dcfModel1.domAlias = 'USD' p = mcSim.path(0) self.assertEqual(p.asset(0.0,'USD'),self.model.forAssetModels[0].X0) self.assertEqual(p.zeroBond(0.0,5.0,'EUR'),curve0.discount(5.0)) self.assertEqual(p.zeroBond(0.0,5.0,'USD'),curve1.discount(5.0))
def setUp(self): ### full smile/skew model # domestic rates domAlias = 'EUR' eurCurve = YieldCurve(0.03) d = 2 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0040]]) slope = np.array([[0.10], [0.15]]) curve = np.array([[0.05], [0.10]]) delta = np.array([1.0, 10.0]) chi = np.array([0.01, 0.15]) Gamma = np.array([[1.0, 0.6], [0.6, 1.0]]) eurRatesModel = QuasiGaussianModel(eurCurve, d, times, sigma, slope, curve, delta, chi, Gamma) # assets forAliases = ['USD', 'GBP'] spotS0 = [1.0, 2.0] spotVol = [0.3, 0.2] forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0, spotVol) ] # USD rates usdCurve = YieldCurve(0.02) d = 3 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0050], [0.0040]]) slope = np.array([[0.10], [0.20], [0.30]]) curve = np.array([[0.05], [0.10], [0.20]]) delta = np.array([1.0, 5.0, 20.0]) chi = np.array([0.01, 0.05, 0.15]) Gamma = np.array([[1.0, 0.8, 0.6], [0.8, 1.0, 0.8], [0.6, 0.8, 1.0]]) usdRatesModel = QuasiGaussianModel(usdCurve, d, times, sigma, slope, curve, delta, chi, Gamma) # gbpRatesModel = HWModel() # # 'EUR_x_0', 'EUR_x_1', 'USD_logS', 'USD_x_0', 'USD_x_1', 'USD_x_2', 'GBP_logS', 'GBP_x' corr = np.array([ [1.0, 0.0, 0.5, -0.5, 0.0, 0.0, -0.5, -0.5], # EUR_x_0 [0.0, 1.0, 0.0, 0.0, -0.5, 0.0, -0.5, 0.0], # EUR_x_1 [0.5, 0.0, 1.0, -0.5, -0.5, -0.5, 0.0, 0.0], # USD_logS [-0.5, 0.0, -0.5, 1.0, 0.0, 0.0, 0.0, 0.0], # USD_x_0 [0.0, -0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0], # USD_x_1 [0.0, 0.0, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0], # USD_x_2 [-0.5, -0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.5], # GBP_logS [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1.0], # GBP_x ]) # # corr = np.identity(2 + 1 + 3 + 1 + 1 ) # overwrite # self.model = HybridModel(domAlias, eurRatesModel, forAliases, forAssetModels, [usdRatesModel, gbpRatesModel], corr) ### Gaussian model # domestic rates domAlias = 'EUR' eurCurve = YieldCurve(0.03) d = 2 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0040]]) slope = np.array([[0.00], [0.00]]) curve = np.array([[0.00], [0.00]]) delta = np.array([1.0, 10.0]) chi = np.array([0.01, 0.15]) Gamma = np.array([[1.0, 0.6], [0.6, 1.0]]) eurRatesModel = QuasiGaussianModel(eurCurve, d, times, sigma, slope, curve, delta, chi, Gamma) # assets forAliases = ['USD', 'GBP'] spotS0 = [1.0, 2.0] spotVol = [0.3, 0.2] forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0, spotVol) ] # USD rates usdCurve = YieldCurve(0.02) d = 3 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0050], [0.0040]]) slope = np.array([[0.10], [0.20], [0.30]]) curve = np.array([[0.05], [0.10], [0.20]]) delta = np.array([1.0, 5.0, 20.0]) chi = np.array([0.01, 0.05, 0.15]) Gamma = np.array([[1.0, 0.8, 0.6], [0.8, 1.0, 0.8], [0.6, 0.8, 1.0]]) self.gaussianModel = HybridModel(domAlias, eurRatesModel, forAliases, forAssetModels, [usdRatesModel, gbpRatesModel], corr)
class TestHybridQuasiGaussian(unittest.TestCase): # set up the stage for testing the models def setUp(self): ### full smile/skew model # domestic rates domAlias = 'EUR' eurCurve = YieldCurve(0.03) d = 2 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0040]]) slope = np.array([[0.10], [0.15]]) curve = np.array([[0.05], [0.10]]) delta = np.array([1.0, 10.0]) chi = np.array([0.01, 0.15]) Gamma = np.array([[1.0, 0.6], [0.6, 1.0]]) eurRatesModel = QuasiGaussianModel(eurCurve, d, times, sigma, slope, curve, delta, chi, Gamma) # assets forAliases = ['USD', 'GBP'] spotS0 = [1.0, 2.0] spotVol = [0.3, 0.2] forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0, spotVol) ] # USD rates usdCurve = YieldCurve(0.02) d = 3 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0050], [0.0040]]) slope = np.array([[0.10], [0.20], [0.30]]) curve = np.array([[0.05], [0.10], [0.20]]) delta = np.array([1.0, 5.0, 20.0]) chi = np.array([0.01, 0.05, 0.15]) Gamma = np.array([[1.0, 0.8, 0.6], [0.8, 1.0, 0.8], [0.6, 0.8, 1.0]]) usdRatesModel = QuasiGaussianModel(usdCurve, d, times, sigma, slope, curve, delta, chi, Gamma) # gbpRatesModel = HWModel() # # 'EUR_x_0', 'EUR_x_1', 'USD_logS', 'USD_x_0', 'USD_x_1', 'USD_x_2', 'GBP_logS', 'GBP_x' corr = np.array([ [1.0, 0.0, 0.5, -0.5, 0.0, 0.0, -0.5, -0.5], # EUR_x_0 [0.0, 1.0, 0.0, 0.0, -0.5, 0.0, -0.5, 0.0], # EUR_x_1 [0.5, 0.0, 1.0, -0.5, -0.5, -0.5, 0.0, 0.0], # USD_logS [-0.5, 0.0, -0.5, 1.0, 0.0, 0.0, 0.0, 0.0], # USD_x_0 [0.0, -0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0], # USD_x_1 [0.0, 0.0, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0], # USD_x_2 [-0.5, -0.5, 0.0, 0.0, 0.0, 0.0, 1.0, 0.5], # GBP_logS [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1.0], # GBP_x ]) # # corr = np.identity(2 + 1 + 3 + 1 + 1 ) # overwrite # self.model = HybridModel(domAlias, eurRatesModel, forAliases, forAssetModels, [usdRatesModel, gbpRatesModel], corr) ### Gaussian model # domestic rates domAlias = 'EUR' eurCurve = YieldCurve(0.03) d = 2 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0040]]) slope = np.array([[0.00], [0.00]]) curve = np.array([[0.00], [0.00]]) delta = np.array([1.0, 10.0]) chi = np.array([0.01, 0.15]) Gamma = np.array([[1.0, 0.6], [0.6, 1.0]]) eurRatesModel = QuasiGaussianModel(eurCurve, d, times, sigma, slope, curve, delta, chi, Gamma) # assets forAliases = ['USD', 'GBP'] spotS0 = [1.0, 2.0] spotVol = [0.3, 0.2] forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0, spotVol) ] # USD rates usdCurve = YieldCurve(0.02) d = 3 times = np.array([10.0]) sigma = np.array([[0.0060], [0.0050], [0.0040]]) slope = np.array([[0.10], [0.20], [0.30]]) curve = np.array([[0.05], [0.10], [0.20]]) delta = np.array([1.0, 5.0, 20.0]) chi = np.array([0.01, 0.05, 0.15]) Gamma = np.array([[1.0, 0.8, 0.6], [0.8, 1.0, 0.8], [0.6, 0.8, 1.0]]) self.gaussianModel = HybridModel(domAlias, eurRatesModel, forAliases, forAssetModels, [usdRatesModel, gbpRatesModel], corr) def test_ModelSetup(self): self.assertListEqual(self.model.stateAliases(), [ 'EUR_x_0', 'EUR_x_1', 'EUR_y_0_0', 'EUR_y_0_1', 'EUR_y_1_0', 'EUR_y_1_1', 'EUR_s', 'USD_logS', 'USD_x_0', 'USD_x_1', 'USD_x_2', 'USD_y_0_0', 'USD_y_0_1', 'USD_y_0_2', 'USD_y_1_0', 'USD_y_1_1', 'USD_y_1_2', 'USD_y_2_0', 'USD_y_2_1', 'USD_y_2_2', 'USD_s', 'GBP_logS', 'GBP_x', 'GBP_s' ]) self.assertListEqual(self.model.factorAliases(), [ 'EUR_x_0', 'EUR_x_1', 'USD_logS', 'USD_x_0', 'USD_x_1', 'USD_x_2', 'GBP_logS', 'GBP_x' ]) # @unittest.skip('Too time consuming') def test_HybridSimulation(self): times = np.concatenate([np.linspace(0.0, 10.0, 11), [10.5]]) nPaths = 2**13 seed = 314159265359 # risk-neutral simulation print('') mcSim = McSimulation(self.model, times, nPaths, seed, False) # T = 10.0 P = Pay(Fixed(1.0), T) fw, err = fwd(mcSim, P) # domestic numeraire print('1.0 @ %4.1lfy %8.6lf - mc_err = %8.6lf' % (T, fw, err)) # foreign assets for k, alias in enumerate(self.model.forAliases): p = Asset(T, alias) xT = self.model.forAssetModels[k].X0 * \ self.model.forRatesModels[k].yieldCurve.discount(T) / \ self.model.domRatesModel.yieldCurve.discount(T) fw, err = fwd(mcSim, p) print(alias + ' @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (T, fw, xT, err)) # domestic Libor rate Tstart = 10.0 Tend = 10.5 L = Pay(LiborRate(T, Tstart, Tend, alias='EUR'), Tend) fw, err = fwd(mcSim, L) Lref = (mcSim.model.domRatesModel.yieldCurve.discount(Tstart) / \ mcSim.model.domRatesModel.yieldCurve.discount(Tend) - 1) / \ (Tend - Tstart) print('L_EUR @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (T, fw, Lref, err)) # foreign Lbor rates for k, alias in enumerate(self.model.forAliases): L = Pay( LiborRate(T, Tstart, Tend, alias=alias) * Asset(Tend, alias), Tend) fw, err = fwd(mcSim, L) fw *= mcSim.model.domRatesModel.yieldCurve.discount(Tend) / \ mcSim.model.forRatesModels[k].yieldCurve.discount(Tend) / \ mcSim.model.forAssetModels[k].X0 err *= mcSim.model.domRatesModel.yieldCurve.discount(Tend) / \ mcSim.model.forRatesModels[k].yieldCurve.discount(Tend) / \ mcSim.model.forAssetModels[k].X0 Lref = (mcSim.model.forRatesModels[k].yieldCurve.discount(Tstart) / \ mcSim.model.forRatesModels[k].yieldCurve.discount(Tend) - 1) / \ (Tend - Tstart) print('L_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, fw, Lref, err)) def test_HybridVolAdjusterCalculation(self): model = copy.deepcopy(self.model) # model = copy.deepcopy(self.gaussianModel) hybVolAdjTimes = np.linspace(0.0, 20.0, 21) model.recalculateHybridVolAdjuster(hybVolAdjTimes) plt.plot(model.hybAdjTimes, model.hybVolAdj[0], 'r*', label='USD') plt.plot(model.hybAdjTimes, model.hybVolAdj[1], 'b*', label='GBP') plt.legend() # times = np.linspace(0.0, 20.0, 101) plt.plot(times, [model.hybridVolAdjuster(0, t) for t in times], 'r-') plt.plot(times, [model.hybridVolAdjuster(1, t) for t in times], 'b-') plt.show() # # return times = np.linspace(0.0, 10.0, 11) nPaths = 2**13 seed = 314159265359 # risk-neutral simulation print('') mcSim = McSimulation(model, times, nPaths, seed, False) # T = 10.0 for k, alias in enumerate(model.forAliases): # ATM forward xT = model.forAssetModels[k].X0 * \ model.forRatesModels[k].yieldCurve.discount(T) / \ model.domRatesModel.yieldCurve.discount(T) K = Fixed(xT) Z = Fixed(0.0) C = Pay(Max(Asset(T, alias) - K, Z), T) fw, err = fwd(mcSim, C) vol = BlackImpliedVol(fw, xT, xT, T, 1.0) vega = BlackVega(xT, xT, vol, T) err /= vega volRef = model.forAssetModels[k].sigma print('C_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, vol, volRef, err)) P = Pay(Max(K - Asset(T, alias), Z), T) fw, err = fwd(mcSim, P) vol = BlackImpliedVol(fw, xT, xT, T, -1.0) vega = BlackVega(xT, xT, vol, T) err /= vega volRef = model.forAssetModels[k].sigma print('P_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, vol, volRef, err))
class TestHybridModel(unittest.TestCase): # set up the stage for testing the models def setUp(self): domAlias = 'EUR' domModel = HWModel(0.01, 0.0050, 0.03) forAliases = ['USD', 'GBP', 'JPY'] spotS0 = [1.0, 1.0, 1.0] spotVol = [0.3, 0.3, 0.3] rates = [0.01, 0.01, 0.01] ratesVols = [0.006, 0.007, 0.008] mean = [0.01, 0.01, 0.01] # forAssetModels = [ AssetModel(S0, vol) for S0, vol in zip(spotS0, spotVol) ] forRatesModels = [ HWModel(r, v, m) for r, v, m in zip(rates, ratesVols, mean) ] # corr = np.identity(2 * len(forAliases) + 1) corr[1, 2] = 0.6 # USD quanto corr[2, 1] = 0.6 corr[3, 4] = 0.8 # GBP quanto corr[4, 3] = 0.8 corr[5, 6] = -0.7 # JPY quanto corr[6, 5] = -0.7 # self.model = HybridModel(domAlias, domModel, forAliases, forAssetModels, forRatesModels, corr) def test_HybridModelSetup(self): # we check against known values self.assertListEqual(self.model.modelsStartIdx, [2, 3, 5, 6, 8, 9]) self.assertDictEqual(self.model.index, {'USD': 0, 'GBP': 1, 'JPY': 2}) self.assertEqual(self.model.size(), len(self.model.stateAliases())) self.assertEqual(self.model.factors(), len(self.model.factorAliases())) self.assertListEqual(self.model.stateAliases(), \ [ 'EUR_x', 'EUR_s', 'USD_logS', 'USD_x', 'USD_s', 'GBP_logS', 'GBP_x', 'GBP_s', 'JPY_logS', 'JPY_x', 'JPY_s' ]) self.assertListEqual(self.model.factorAliases(), \ ['EUR_x', 'USD_logS', 'USD_x', 'GBP_logS', 'GBP_x', 'JPY_logS', 'JPY_x']) # check correlation C = self.model.L.dot(self.model.L.transpose()) C = np.abs(C - self.model.correlations) self.assertLess(np.max(C), 1.0e-15) def test_HybridSimulation(self): times = np.concatenate([np.linspace(0.0, 10.0, 11), [10.5]]) nPaths = 2**13 seed = 314159265359 # risk-neutral simulation print('') mcSim = McSimulation(self.model, times, nPaths, seed, False) # T = 10.0 P = Pay(Fixed(1.0), T) fw, err = fwd(mcSim, P) # domestic numeraire print('1.0 @ %4.1lfy %8.6lf - mc_err = %8.6lf' % (T, fw, err)) # foreign assets for k, alias in enumerate(self.model.forAliases): p = Asset(T, alias) xT = self.model.forAssetModels[k].X0 * \ self.model.forRatesModels[k].yieldCurve.discount(T) / \ self.model.domRatesModel.yieldCurve.discount(T) fw, err = fwd(mcSim, p) print(alias + ' @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (T, fw, xT, err)) # domestic Libor rate Tstart = 10.0 Tend = 10.5 L = Pay(LiborRate(T, Tstart, Tend, alias='EUR'), Tend) fw, err = fwd(mcSim, L) Lref = (mcSim.model.domRatesModel.yieldCurve.discount(Tstart) / \ mcSim.model.domRatesModel.yieldCurve.discount(Tend) - 1) / \ (Tend - Tstart) print('L_EUR @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (T, fw, Lref, err)) # foreign Lbor rates for k, alias in enumerate(self.model.forAliases): L = Pay( LiborRate(T, Tstart, Tend, alias=alias) * Asset(Tend, alias), Tend) fw, err = fwd(mcSim, L) fw *= mcSim.model.domRatesModel.yieldCurve.discount(Tend) / \ mcSim.model.forRatesModels[k].yieldCurve.discount(Tend) / \ mcSim.model.forAssetModels[k].X0 err *= mcSim.model.domRatesModel.yieldCurve.discount(Tend) / \ mcSim.model.forRatesModels[k].yieldCurve.discount(Tend) / \ mcSim.model.forAssetModels[k].X0 Lref = (mcSim.model.forRatesModels[k].yieldCurve.discount(Tstart) / \ mcSim.model.forRatesModels[k].yieldCurve.discount(Tend) - 1) / \ (Tend - Tstart) print('L_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, fw, Lref, err)) def test_HybridVolAdjusterCalculation(self): # we set up a hybrid model consistent to QuantLib domAlias = 'EUR' domModel = HWModel(0.01, 0.0050, 0.01) forAliases = ['USD', 'GBP'] forAssetModels = [AssetModel(1.0, 0.30), AssetModel(2.0, 0.15)] forRatesModels = [ HWModel(0.02, 0.0060, 0.02), HWModel(0.02, 0.0070, 0.03) ] corr = np.identity(2 * len(forAliases) + 1) # [ EUR, USD-EUR, USD, GBP-EUR, GBP ] # 0 1 2 3 4 # USD-EUR - EUR corr[0, 1] = 0.5 corr[1, 0] = 0.5 # USD-EUR - USD corr[1, 2] = -0.5 corr[2, 1] = -0.5 # EUR - USD corr[0, 2] = -0.5 corr[2, 0] = -0.5 # GBP-EUR - EUR corr[0, 3] = -0.5 corr[3, 0] = -0.5 # GBP-EUR - GBP corr[3, 4] = 0.5 corr[4, 3] = 0.5 # EUR - GBP corr[0, 4] = -0.8 corr[4, 0] = -0.8 # USD - GBP corr[2, 4] = 0.0 corr[4, 2] = 0.0 # overwrtite # corr = np.identity(2 * len(forAliases) + 1) # print(corr-corr.transpose()) model = HybridModel(domAlias, domModel, forAliases, forAssetModels, forRatesModels, corr) hybVolAdjTimes = np.linspace(0.0, 20.0, 21) model.recalculateHybridVolAdjuster(hybVolAdjTimes) #plt.plot(model.hybAdjTimes,model.hybVolAdj[0], 'r*') #plt.plot(model.hybAdjTimes,model.hybVolAdj[1], 'b*') # #times = np.linspace(0.0,20.0,101) #plt.plot(times,[ model.hybridVolAdjuster(0,t) for t in times ] , 'r-') #plt.plot(times,[ model.hybridVolAdjuster(1,t) for t in times ] , 'b-') # plt.show() # times = np.linspace(0.0, 10.0, 11) nPaths = 2**13 seed = 314159265359 # risk-neutral simulation print('') mcSim = McSimulation(model, times, nPaths, seed, False) # T = 10.0 for k, alias in enumerate(model.forAliases): # ATM forward xT = model.forAssetModels[k].X0 * \ model.forRatesModels[k].yieldCurve.discount(T) / \ model.domRatesModel.yieldCurve.discount(T) K = Fixed(xT) Z = Fixed(0.0) C = Pay(Max(Asset(T, alias) - K, Z), T) fw, err = fwd(mcSim, C) vol = BlackImpliedVol(fw, xT, xT, T, 1.0) vega = BlackVega(xT, xT, vol, T) err /= vega volRef = model.forAssetModels[k].sigma print('C_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, vol, volRef, err)) P = Pay(Max(K - Asset(T, alias), Z), T) fw, err = fwd(mcSim, P) vol = BlackImpliedVol(fw, xT, xT, T, -1.0) vega = BlackVega(xT, xT, vol, T) err /= vega volRef = model.forAssetModels[k].sigma print('P_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, vol, volRef, err))
def test_HybridVolAdjusterCalculation(self): # we set up a hybrid model consistent to QuantLib domAlias = 'EUR' domModel = HWModel(0.01, 0.0050, 0.01) forAliases = ['USD', 'GBP'] forAssetModels = [AssetModel(1.0, 0.30), AssetModel(2.0, 0.15)] forRatesModels = [ HWModel(0.02, 0.0060, 0.02), HWModel(0.02, 0.0070, 0.03) ] corr = np.identity(2 * len(forAliases) + 1) # [ EUR, USD-EUR, USD, GBP-EUR, GBP ] # 0 1 2 3 4 # USD-EUR - EUR corr[0, 1] = 0.5 corr[1, 0] = 0.5 # USD-EUR - USD corr[1, 2] = -0.5 corr[2, 1] = -0.5 # EUR - USD corr[0, 2] = -0.5 corr[2, 0] = -0.5 # GBP-EUR - EUR corr[0, 3] = -0.5 corr[3, 0] = -0.5 # GBP-EUR - GBP corr[3, 4] = 0.5 corr[4, 3] = 0.5 # EUR - GBP corr[0, 4] = -0.8 corr[4, 0] = -0.8 # USD - GBP corr[2, 4] = 0.0 corr[4, 2] = 0.0 # overwrtite # corr = np.identity(2 * len(forAliases) + 1) # print(corr-corr.transpose()) model = HybridModel(domAlias, domModel, forAliases, forAssetModels, forRatesModels, corr) hybVolAdjTimes = np.linspace(0.0, 20.0, 21) model.recalculateHybridVolAdjuster(hybVolAdjTimes) #plt.plot(model.hybAdjTimes,model.hybVolAdj[0], 'r*') #plt.plot(model.hybAdjTimes,model.hybVolAdj[1], 'b*') # #times = np.linspace(0.0,20.0,101) #plt.plot(times,[ model.hybridVolAdjuster(0,t) for t in times ] , 'r-') #plt.plot(times,[ model.hybridVolAdjuster(1,t) for t in times ] , 'b-') # plt.show() # times = np.linspace(0.0, 10.0, 11) nPaths = 2**13 seed = 314159265359 # risk-neutral simulation print('') mcSim = McSimulation(model, times, nPaths, seed, False) # T = 10.0 for k, alias in enumerate(model.forAliases): # ATM forward xT = model.forAssetModels[k].X0 * \ model.forRatesModels[k].yieldCurve.discount(T) / \ model.domRatesModel.yieldCurve.discount(T) K = Fixed(xT) Z = Fixed(0.0) C = Pay(Max(Asset(T, alias) - K, Z), T) fw, err = fwd(mcSim, C) vol = BlackImpliedVol(fw, xT, xT, T, 1.0) vega = BlackVega(xT, xT, vol, T) err /= vega volRef = model.forAssetModels[k].sigma print('C_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, vol, volRef, err)) P = Pay(Max(K - Asset(T, alias), Z), T) fw, err = fwd(mcSim, P) vol = BlackImpliedVol(fw, xT, xT, T, -1.0) vega = BlackVega(xT, xT, vol, T) err /= vega volRef = model.forAssetModels[k].sigma print('P_%s @ %4.1lfy %8.6lf vs %8.6lf (curve) - mc_err = %8.6lf' % (alias, T, vol, volRef, err))