def setUp(self): self.curve = YieldCurve(0.03) mean = 0.03 times = np.array([ 1.0, 2.0, 5.0, 10.0 ]) vols = np.array([ 0.0060, 0.0070, 0.0080, 0.0100 ]) self.modelRiskNeutral = HullWhiteModel(self.curve, mean, times, vols) self.modelDiscreteFwd = HullWhiteModelWithDiscreteNumeraire(self.curve, mean, times, vols)
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_ZeroBond(self): yts = YieldCurve(0.03) 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] ]) model = QuasiGaussianModel(yts,d,times,sigma,slope,curve,delta,chi,Gamma) # x = np.random.uniform(0.0,0.05,d) y = np.random.uniform(0.0,0.05,[d,d]) y = y @ y.T t = 5.0 T = 10.0 # X = np.append(x,y.reshape((d*d,))) X = np.append(X,[0.0]) zcb = model.zeroBond(t,T,X,None) # G = (1.0 - np.exp(-chi*(T-t)))/chi zcbRef = yts.discount(T) / yts.discount(t) * np.exp(-G.dot(x) - 0.5 * G.dot(y).dot(G) ) self.assertAlmostEqual(zcb,zcbRef,14)
def test_ModelCurve(self): # CIR parameters r0 = 0.02 chi_ = 0.07 theta_ = 0.05 sigma_ = 0.10 CirModel = CoxIngersollRossModel(r0, chi_, theta_, sigma_) model = CirModel T = np.linspace(0.0, 10.0, 11) dt = 1.0 / 365.0 f = np.array([ np.log( \ model.zeroBondPrice(0.0,T_,model.r0) / model.zeroBondPrice(0.0,T_+dt,model.r0)) / dt \ for T_ in T ]) # plt.plot(T,f,label='CIR') # curve = YieldCurve(0.03) model = ShiftedRatesModel(curve, CirModel) X0 = model.initialValues() f = np.array([ np.log( \ model.zeroBond(0.0,T_,X0,None) / model.zeroBond(0.0,T_+dt,X0,None)) / dt \ for T_ in T ]) # plt.plot(T,f,label='Shifted') # plt.legend() # plt.show() # print(f - 0.03) self.assertLess(np.max(np.abs(f - 0.03)), 7.e-14)
def test_Evolve(self): # we set up a test case via QuantLib zeroRate = 0.03 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] ]) # try QuantLib try: import QuantLib as ql ytsH = ql.YieldTermStructureHandle(ql.FlatForward(0,ql.NullCalendar(),zeroRate,ql.Actual365Fixed())) qg = ql.QuasiGaussianModel(ytsH,d,times,sigma,slope,curve,[ 0.0 ],delta,chi,Gamma,0.1) mc = ql.RealMCSimulation(qg,[0.0, 5.0, 10.0],[0.0, 5.0, 10.0],1,1234,False,False,True) mc.simulate() dW = np.array(mc.brownian(0)) dW = dW[:,:3] #print(dW) X = np.array(mc.observedPath(0)) Xref = np.delete(X,12,1) #print(Xref) qlzcb = ql.RealMCZeroBond(5.0,10.0,'') zcbRef = ql.RealMCPayoffPricer_at(qlzcb,mc)[0] # atol = 1.0e-14 equalPlaces = 15 except: # we save QL results in case we don't have QL available ytsH = YieldCurve(zeroRate) dW = np.array([ [-0.8723107, -0.00585635, 0.31102388], [-0.15673275, 0.28482762, 0.79041947]]) Xref = np.array([ [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [-0.02182255, 0.0397456 , -0.01717905, 0.0006412 , -0.00116167, 0.00059747, -0.00116167, 0.00259077, -0.00141925, 0.00059747, -0.00141925, 0.00088815, 0.00185998], [-0.02476015, 0.04705765, -0.0083194 , 0.00127306, -0.00232704, 0.00102049, -0.00232704, 0.00518216, -0.00243878, 0.00102049, -0.00243878, 0.00133699, 0.03866521]]) # zcbRef = 0.851676232405887 # atol = 1.0e-8 equalPlaces = 9 # model = QuasiGaussianModel(ytsH,d,times,sigma,slope,curve,delta,chi,Gamma) X = np.zeros([3,13]) model.evolve(0.0,X[0],5.0,dW[0],X[1]) model.evolve(5.0,X[1],5.0,dW[1],X[2]) self.assertTrue(np.allclose(X,Xref,rtol=0.0,atol=atol)) zcb = model.zeroBond(5.0,10.0,X[1],None) self.assertAlmostEqual(zcb,zcbRef,equalPlaces)
def test_AuxilliaryStateVsQuasiGaussian(self): curve = YieldCurve(0.03) d = 3 times = np.array([1.0, 2.0, 5.0, 10.0]) sigma = np.array([[0.0060, 0.0070, 0.0080, 0.0100], [0.0030, 0.0035, 0.0040, 0.0050], [0.0025, 0.0025, 0.0025, 0.0025]]) slope = np.zeros([3, 4]) curve = np.zeros([3, 4]) 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]]) qGmodel = QuasiGaussianModel(curve, d, times, sigma, slope, curve, delta, chi, Gamma) X0 = qGmodel.initialValues() #T = np.linspace(-1.0, 11.0, 121) #vols = np.array([ qGmodel.sigma_xT(t,X0) for t in T ]) #plt.plot(T,vols[:,0,0],label='sigma[0,0]') vols = np.array([qGmodel.sigma_xT(t, X0) for t in times]) #plt.plot(times,vols[:,0,0],'*',label='sigma[0,0]') #plt.show() # mVmodel = MarkovFutureModel(None, d, times, vols, chi) # we need to evolve the Quasi Gaussian model to obtain y(t) times = np.linspace(0.0, 11.0, 111) sim = McSimulation(qGmodel, times, 1, 1, showProgress=False) Y0 = sim.X[0, :, d:d + d * d] Y0.shape = [111, 3, 3] Y1 = np.array([mVmodel.y(t) for t in times]) # print(np.max(np.abs(Y1[1:]/Y0[1:] - 1.0))) self.assertLess(np.max(np.abs(Y1[1:] / Y0[1:] - 1.0)), 6.2e-14)
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 test_liborPayoff(self): # Libor Rate payoff liborTimes = np.linspace(0.0, 10.0, 11) dT0 = 2.0 / 365 dT1 = 0.5 cfs = [ Pay(LiborRate(t, t + dT0, t + dT0 + dT1), t + dT0 + dT1) for t in liborTimes ] curve = YieldCurve(0.03) path = DcfModel(curve).path() cfPVs = np.array([p.discountedAt(path) for p in cfs]) discounts0 = np.array([curve.discount(t + dT0) for t in liborTimes]) discounts1 = np.array( [curve.discount(t + dT0 + dT1) for t in liborTimes]) liborsCv = (discounts0 / discounts1 - 1.0) / dT1 liborsMC = cfPVs / discounts1 print('') print(' T LiborRate ModelLibor') for k, t in enumerate(liborTimes): print(' %4.1f %6.4lf %6.4lf' % (t, liborsCv[k], liborsMC[k])) self.assertAlmostEqual(liborsCv[k], liborsMC[k], 2)
def setUp(self): today = ql.Date(5,ql.October,2020) ql.Settings.instance().evaluationDate = today # discYtsH = ql.YieldTermStructureHandle( ql.FlatForward(today,0.015,ql.Actual365Fixed())) projYtsH = ql.YieldTermStructureHandle( ql.FlatForward(today,0.020,ql.Actual365Fixed())) index = ql.Euribor6M(projYtsH) startDate = ql.Date(12,ql.October,2020) endDate = ql.Date(12,ql.October,2030) calendar = ql.TARGET() fixedTenor = ql.Period('1y') floatTenor = ql.Period('6m') fixedSchedule = ql.MakeSchedule(startDate,endDate,tenor=fixedTenor,calendar=calendar) floatSchedule = ql.MakeSchedule(startDate,endDate,tenor=floatTenor,calendar=calendar) couponDayCount = ql.Thirty360() notional = 1.0 fixedRate = 0.02 fixedLeg = ql.FixedRateLeg(fixedSchedule,couponDayCount,[notional],[fixedRate]) floatingLeg = ql.IborLeg([notional],floatSchedule,index) # swap = Swap([fixedLeg,floatingLeg],[1.0,-1.0],discYtsH) # observationTimes = np.linspace(0.0,10.0,11) self.timeline = swap.timeLine(observationTimes) # yc = YieldCurve(0.02) d = 2 times = np.array( [ 1.0, 5.0, 10.0 ]) sigma = np.array([ [ 0.0050, 0.0060, 0.0070 ], [ 0.0050, 0.0060, 0.0070 ] ]) slope = np.array([ [ 0.0100, 0.0100, 0.0100 ], [ 0.0200, 0.0200, 0.0200 ] ]) curve = np.array([ [ 0.0000, 0.0000, 0.0000 ], [ 0.0000, 0.0000, 0.0000 ] ]) delta = np.array( [ 1.0, 20.0 ]) chi = np.array( [ 0.01, 0.15 ]) Gamma = np.identity(2) model = QuasiGaussianModel(yc,d,times,sigma,slope,curve,delta,chi,Gamma) # nPaths = 1 simTimes = observationTimes seed = 314159265359 timeInterpolation = True self.sim = McSimulation(model,simTimes,nPaths,seed,timeInterpolation,False)
def test_ModelSetup(self): baseModel = HWModel() name1Model = HWModel(0.03, 0.0100, 0.10) name2Model = DcfModel(YieldCurve(0.02)) name2Model.domAlias = 'Two' corr = np.identity(2) model = CreditModel(baseModel,['One', 'Two'],[name1Model,name2Model],corr) # basic tests self.assertEqual(model.size(),4) self.assertEqual(model.factors(),2) self.assertListEqual(model.stateAliases(),['x', 's', 'One_x', 'One_s']) # no state for DCF model self.assertListEqual(model.factorAliases(),['x', 'One_x']) # no state for DCF model # times = np.array([0.0, 5.0]) nPaths = 1 seed = 314159265359 # risk-neutral simulation mcSim = McSimulation(model,times,nPaths,seed,False,False) p = mcSim.path(0) # self.assertEqual(p.zeroBond(0.0, 10.0, None), baseModel.yieldCurve.discount(10.0) ) # self.assertEqual(p.hazardProcess(0.0,'One'), 1.0) self.assertAlmostEqual(p.hazardRate(0.0,'One'),0.03,13) self.assertEqual(p.survivalProb(0.0,10.0,'One'),name1Model.yieldCurve.discount(10.0)) # self.assertEqual(p.hazardProcess(5.0,'Two'), name2Model.domCurve.discount(5.0)) self.assertAlmostEqual(p.hazardRate(5.0,'Two'),0.02,13) self.assertEqual(p.survivalProb(5.0,10.0,'Two'), name2Model.domCurve.discount(10.0) / name2Model.domCurve.discount(5.0)) # evolve manually X0 = baseModel.initialValues() X1 = np.array(X0) baseModel.evolve(0.0,X0,5.0,mcSim.dW[0,0,0:1],X1) self.assertTrue(np.allclose(X1,mcSim.X[0,1,:2],rtol=0.0,atol=1.0e-14)) X0 = name1Model.initialValues() X1 = np.array(X0) name1Model.evolve(0.0,X0,5.0,mcSim.dW[0,0,1:2],X1) self.assertTrue(np.allclose(X1,mcSim.X[0,1,2:],rtol=0.0,atol=1.0e-14))
def test_Sigma_xT(self): yts = YieldCurve(0.03) 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] ]) model = QuasiGaussianModel(yts,d,times,sigma,slope,curve,delta,chi,Gamma) # x = np.array([0.00206853, 0.01093424, 0.00696041]) # np.random.uniform(0.0,0.05,d) y = np.array([[0.0298081, 0.00656372, 0.0041344 ], [0.04282753, 0.02406725, 0.0001211 ], [0.02906687, 0.01078535, 0.02328022]]) # np.random.uniform(0.0,0.05,[d,d]) y = y @ y.T t = 5.0 # X = np.append(x,y.reshape((d*d,))) X = np.append(X,[0.0]) sigma_xT = model.sigma_xT(t,X) # reference result from QuantLib sigma_xT_Ref = np.array([ [ 0.031658475910, 0.017375011335, 0.084573118461 ], [-0.007058576846, 0.021654204395, -0.134352049767 ], [-0.016417240779, -0.043917617245, 0.051199735933 ] ]) self.assertTrue(np.allclose(sigma_xT,sigma_xT_Ref,rtol=0.0,atol=1.0e-12))
class TestHullWhiteMonteCarlo(unittest.TestCase): # set up the stage for testing the models def setUp(self): self.curve = YieldCurve(0.03) mean = 0.03 times = np.array([ 1.0, 2.0, 5.0, 10.0 ]) vols = np.array([ 0.0060, 0.0070, 0.0080, 0.0100 ]) self.modelRiskNeutral = HullWhiteModel(self.curve, mean, times, vols) self.modelDiscreteFwd = HullWhiteModelWithDiscreteNumeraire(self.curve, mean, times, vols) def test_monteCarloSimulation(self): times = np.linspace(0.0, 10.0, 11) nPaths = 2**11 seed = 1234 # risk-neutral simulation mcSim = McSimulation(self.modelRiskNeutral,times,nPaths,seed,showProgress=False) discZeroBonds = np.array([ [ 1.0 / self.modelRiskNeutral.numeraire(t,x) for t,x in zip(times,path) ] for path in mcSim.X ]) mcZeroBondsRiskNeutral = np.average(discZeroBonds,axis=0) # discrete forward measure simulation mcSim = McSimulation(self.modelDiscreteFwd,times,nPaths,seed,showProgress=False) discZeroBonds = np.array([ [ 1.0 / self.modelDiscreteFwd.numeraire(t,x) for t,x in zip(times,path) ] for path in mcSim.X ]) mcZeroBondsDiscreteFwd = np.average(discZeroBonds,axis=0) # curve zeroBonds = np.array([ self.curve.discount(t) for t in times ]) print('') print(' T ZeroRate RiskNeutral DiscreteFwd') for k, t in enumerate(times[1:]): zeroRate = -np.log(zeroBonds[k+1])/t riskNeutral = -np.log(mcZeroBondsRiskNeutral[k+1])/t discreteFwd = -np.log(mcZeroBondsDiscreteFwd[k+1])/t print(' %4.1f %6.4lf %6.4lf %6.4lf' % (t, zeroRate, riskNeutral, discreteFwd) ) self.assertAlmostEqual(zeroRate,riskNeutral,3) self.assertAlmostEqual(zeroRate,discreteFwd,3) def test_simulationStates(self): times = np.array([0.0, 2.0, 5.0, 10.0]) nPaths = 2 seed = 1234 mcSim = McSimulation(self.modelRiskNeutral,times,nPaths,seed,False,showProgress=False) # test exact values for k, t in enumerate(times): self.assertListEqual(list(mcSim.state(0,t)),list(mcSim.X[0][k])) # now we allow interpolation/extrapolation mcSim.timeInterpolation = True # test extrapolation self.assertListEqual(list(mcSim.state(1,-0.5)),list(mcSim.X[1][0])) self.assertListEqual(list(mcSim.state(1,12.5)),list(mcSim.X[1][3])) # test interpolation self.assertListEqual(list(mcSim.state(1,1.0)),list(0.5*(mcSim.X[1][0] + mcSim.X[1][1]))) self.assertListEqual(list(mcSim.state(1,7.0)),list((0.6*mcSim.X[1][2] + 0.4*mcSim.X[1][3]))) def test_pathGeneration(self): times = np.array([0.0, 2.0, 5.0, 10.0]) nPaths = 2 seed = 1234 mcSim = McSimulation(self.modelRiskNeutral,times,nPaths,seed,True,showProgress=False) idx = 0 dT = 5.7 path = mcSim.path(idx) for t in np.linspace(-1.0, 11.0, 13): s = mcSim.state(idx,t) self.assertEqual(path.numeraire(t),mcSim.model.numeraire(t,s)) self.assertEqual(path.zeroBond(t,t+dT,None),mcSim.model.zeroBond(t,t+dT,s,None)) def test_liborPayoff(self): # Libor Rate payoff liborTimes = np.linspace(0.0, 10.0, 11) dT0 = 2.0 / 365 dT1 = 0.5 cfs = [ Pay(LiborRate(t,t+dT0,t+dT0+dT1),t+dT0+dT1) for t in liborTimes] times = set.union(*[ p.observationTimes() for p in cfs ]) times = np.array(sorted(list(times))) # nPaths = 2**11 seed = 1234 # risk-neutral simulation mcSim = McSimulation(self.modelRiskNeutral,times,nPaths,seed,showProgress=False) # cfPVs = np.array([ [ p.discountedAt(mcSim.path(idx)) for p in cfs ] for idx in range(nPaths) ]) cfPVs = np.average(cfPVs,axis=0) discounts0 = np.array([ mcSim.model.yieldCurve.discount(t+dT0) for t in liborTimes ]) discounts1 = np.array([ mcSim.model.yieldCurve.discount(t+dT0+dT1) for t in liborTimes ]) liborsCv = (discounts0/discounts1 - 1.0)/dT1 liborsMC = cfPVs / discounts1 print('') print(' T LiborRate MnteCarlo') for k,t in enumerate(liborTimes): print(' %4.1f %6.4lf %6.4lf' % (t, liborsCv[k], liborsMC[k]) ) self.assertAlmostEqual(liborsCv[k],liborsMC[k],2)
def HWModel(rate=0.01, vol=0.0050, mean=0.03): curve = YieldCurve(rate) times = np.array([ 10.0 ]) vols = np.array([ vol ]) return HullWhiteModel(curve, mean, times, vols)
def test_ModelSetup(self): curve = YieldCurve(0.03) d = 3 times = np.array([ 1.0, 2.0, 5.0, 10.0 ]) sigma = np.array([ [ 0.0060, 0.0070, 0.0080, 0.0100 ], [ 0.0030, 0.0035, 0.0040, 0.0050 ], [ 0.0025, 0.0025, 0.0025, 0.0025 ] ]) slope = np.array([ [ 0.10, 0.15, 0.20 , 0.25 ], [ 0.20, 0.35, 0.40 , 0.55 ], [ 0.10, 0.10, 0.10 , 0.10 ] ]) curve = np.array([ [ 0.05, 0.05, 0.05 , 0.05 ], [ 0.10, 0.10, 0.10 , 0.10 ], [ 0.20, 0.15, 0.10 , 0.00 ] ]) 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] ]) # test matricies model = QuasiGaussianModel(curve,d,times,sigma,slope,curve,delta,chi,Gamma) self.assertTrue(np.allclose(model._DfT @ model._DfT.T,Gamma)) Hf_H_inv = np.exp(np.array([ [ -chi_ * delta_ for chi_ in chi ] for delta_ in delta ])) self.assertTrue(np.allclose(Hf_H_inv @ model._HHfInv,np.eye(d))) aliases = model.stateAliases() aliasesRef = ['x_0', 'x_1', 'x_2', 'y_0_0', 'y_0_1', 'y_0_2', 'y_1_0', 'y_1_1', 'y_1_2', 'y_2_0', 'y_2_1', 'y_2_2', 's'] self.assertListEqual(aliases,aliasesRef) aliases = model.factorAliases() aliasesRef = ['x_0', 'x_1', 'x_2'] self.assertListEqual(aliases,aliasesRef) # test parameter functions times = np.linspace(0.0, 11.0, 23) # sigma = np.array([ [t] + [ model.sigma(i,t) for i in range(d) ] for t in times ]) sigmaRef = np.array([ [0.00e+00, 6.00e-03, 3.00e-03, 2.50e-03], [5.00e-01, 6.00e-03, 3.00e-03, 2.50e-03], [1.00e+00, 6.00e-03, 3.00e-03, 2.50e-03], [1.50e+00, 7.00e-03, 3.50e-03, 2.50e-03], [2.00e+00, 7.00e-03, 3.50e-03, 2.50e-03], [2.50e+00, 8.00e-03, 4.00e-03, 2.50e-03], [3.00e+00, 8.00e-03, 4.00e-03, 2.50e-03], [3.50e+00, 8.00e-03, 4.00e-03, 2.50e-03], [4.00e+00, 8.00e-03, 4.00e-03, 2.50e-03], [4.50e+00, 8.00e-03, 4.00e-03, 2.50e-03], [5.00e+00, 8.00e-03, 4.00e-03, 2.50e-03], [5.50e+00, 1.00e-02, 5.00e-03, 2.50e-03], [6.00e+00, 1.00e-02, 5.00e-03, 2.50e-03], [6.50e+00, 1.00e-02, 5.00e-03, 2.50e-03], [7.00e+00, 1.00e-02, 5.00e-03, 2.50e-03], [7.50e+00, 1.00e-02, 5.00e-03, 2.50e-03], [8.00e+00, 1.00e-02, 5.00e-03, 2.50e-03], [8.50e+00, 1.00e-02, 5.00e-03, 2.50e-03], [9.00e+00, 1.00e-02, 5.00e-03, 2.50e-03], [9.50e+00, 1.00e-02, 5.00e-03, 2.50e-03], [1.00e+01, 1.00e-02, 5.00e-03, 2.50e-03], [1.05e+01, 1.00e-02, 5.00e-03, 2.50e-03], [1.10e+01, 1.00e-02, 5.00e-03, 2.50e-03] ]) self.assertTrue(np.allclose(sigma,sigmaRef)) # slope = np.array([ [t] + [ model.slope(i,t) for i in range(d) ] for t in times ]) slopeRef = np.array([ [ 0. , 0.1 , 0.2 , 0.1 ], [ 0.5, 0.1 , 0.2 , 0.1 ], [ 1. , 0.1 , 0.2 , 0.1 ], [ 1.5, 0.15, 0.35, 0.1 ], [ 2. , 0.15, 0.35, 0.1 ], [ 2.5, 0.2 , 0.4 , 0.1 ], [ 3. , 0.2 , 0.4 , 0.1 ], [ 3.5, 0.2 , 0.4 , 0.1 ], [ 4. , 0.2 , 0.4 , 0.1 ], [ 4.5, 0.2 , 0.4 , 0.1 ], [ 5. , 0.2 , 0.4 , 0.1 ], [ 5.5, 0.25, 0.55, 0.1 ], [ 6. , 0.25, 0.55, 0.1 ], [ 6.5, 0.25, 0.55, 0.1 ], [ 7. , 0.25, 0.55, 0.1 ], [ 7.5, 0.25, 0.55, 0.1 ], [ 8. , 0.25, 0.55, 0.1 ], [ 8.5, 0.25, 0.55, 0.1 ], [ 9. , 0.25, 0.55, 0.1 ], [ 9.5, 0.25, 0.55, 0.1 ], [10. , 0.25, 0.55, 0.1 ], [10.5, 0.25, 0.55, 0.1 ], [11. , 0.25, 0.55, 0.1 ] ]) self.assertTrue(np.allclose(slope,slopeRef)) # curve = np.array([ [t] + [ model.curve(i,t) for i in range(d) ] for t in times ]) curveRef = np.array([ [ 0. , 0.05, 0.1, 0.2 ], [ 0.5, 0.05, 0.1, 0.2 ], [ 1. , 0.05, 0.1, 0.2 ], [ 1.5, 0.05, 0.1, 0.15], [ 2. , 0.05, 0.1, 0.15], [ 2.5, 0.05, 0.1, 0.1 ], [ 3. , 0.05, 0.1, 0.1 ], [ 3.5, 0.05, 0.1, 0.1 ], [ 4. , 0.05, 0.1, 0.1 ], [ 4.5, 0.05, 0.1, 0.1 ], [ 5. , 0.05, 0.1, 0.1 ], [ 5.5, 0.05, 0.1, 0. ], [ 6. , 0.05, 0.1, 0. ], [ 6.5, 0.05, 0.1, 0. ], [ 7. , 0.05, 0.1, 0. ], [ 7.5, 0.05, 0.1, 0. ], [ 8. , 0.05, 0.1, 0. ], [ 8.5, 0.05, 0.1, 0. ], [ 9. , 0.05, 0.1, 0. ], [ 9.5, 0.05, 0.1, 0. ], [10. , 0.05, 0.1, 0. ], [10.5, 0.05, 0.1, 0. ], [11. , 0.05, 0.1, 0. ] ]) self.assertTrue(np.allclose(curve,curveRef))
def setUp(self): self.curve = YieldCurve(0.03) mean = 0.03 times = np.array([1.0, 2.0, 5.0, 10.0]) vols = np.array([0.0060, 0.0070, 0.0080, 0.0100]) self.model = HullWhiteModel(self.curve, mean, times, vols)
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)