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_CirSimulation(self): r0 = 0.02 chi_ = 0.07 theta_ = 0.05 sigma_ = 0.10 modelFT = CoxIngersollRossModel(r0,chi_,theta_,sigma_,fullTruncation) modelLN = CoxIngersollRossModel(r0,chi_,theta_,sigma_,lognormalApproximation) modelQE = CoxIngersollRossModel(r0,chi_,theta_,sigma_,quadraticExponential(1.5)) # dT = 5.0 times = np.linspace(0.0, 10.0, 11) zcbs = np.array([ modelFT.zeroBondPrice(0.0,T + dT,r0) for T in times ]) # nPaths = 2**13 seed = 314159265359 # risk-neutral simulation simFT = McSimulation(modelFT,times,nPaths,seed,showProgress=True) simLN = McSimulation(modelLN,times,nPaths,seed,showProgress=True) simQE = McSimulation(modelQE,times,nPaths,seed,showProgress=True) # zcbFT = np.mean(np.array([ [ modelFT.zeroBond(times[t],times[t]+dT,simFT.X[p,t,:],None) / modelFT.numeraire(times[t],simFT.X[p,t,:]) for t in range(len(times)) ] for p in range(nPaths) ]), axis=0) zcbLN = np.mean(np.array([ [ modelLN.zeroBond(times[t],times[t]+dT,simLN.X[p,t,:],None) / modelLN.numeraire(times[t],simLN.X[p,t,:]) for t in range(len(times)) ] for p in range(nPaths) ]), axis=0) zcbQE = np.mean(np.array([ [ modelQE.zeroBond(times[t],times[t]+dT,simQE.X[p,t,:],None) / modelQE.numeraire(times[t],simQE.X[p,t,:]) for t in range(len(times)) ] for p in range(nPaths) ]), axis=0) # results = pd.DataFrame([ times, zcbs, zcbFT, zcbLN, zcbQE ]).T results.columns = ['times', 'zcbs', 'zcbFT', 'zcbLN', 'zcbQE'] print(results)
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 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_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_MartingalePropertyTimeDependentParameters(self): d = 2 times = np.array([2.0, 4.0]) sigmaT = np.zeros([2, 2, 2]) sigmaT[0, :, :] = np.array([[0.10, 0.15], [0.20, 0.25]]) sigmaT[1, :, :] = np.array([[0.15, 0.20], [0.25, 0.30]]) chi = np.array([0.1, 0.2]) # model0 = MarkovFutureModel(None, d, times, sigmaT, chi) # times = np.linspace(0.0, 5.0, 6) nPaths = 2**10 seed = 314159265359 sim = McSimulation(model0, times, nPaths, seed, False, showProgress=False) dT = np.linspace(0.0, 5.0, 3) for k, t_ in enumerate(times): for dT_ in dT: F = np.array([ model0.futurePrice(t_, t_ + dT_, X, None) for X in sim.X[:, k, :] ]) #print(np.abs(np.mean(F) - 1.0)) self.assertLess(np.abs(np.mean(F) - 1.0), 0.07)
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_KnownSimulationValues(self): d = 2 times = np.array([2.0, 4.0]) sigmaT = np.zeros([2, 2, 2]) sigmaT[0, :, :] = np.array([[0.10, 0.15], [0.20, 0.25]]).T sigmaT[1, :, :] = np.array([[0.15, 0.20], [0.25, 0.30]]).T chi = np.array([0.1, 0.2]) # model0 = MarkovFutureModel(None, d, times, sigmaT, chi) # times = np.linspace(0.0, 5.0, 6) nPaths = 2**3 seed = 314159265359 sim = McSimulation(model0, times, nPaths, seed, False, showProgress=False) # np.set_printoptions(precision=16) # print(sim.X[:,-1,:]) Xref = np.array([[-0.6000110699011598, -0.6431768273428073], [0.138146279288649, 0.1270588210285978], [-0.2615455421299724, -0.3054110432018231], [-1.1042559026028758, -1.0151899131194109], [-0.934746072227638, -1.1542393979975838], [-0.0771484387711384, -0.1328561062878627], [-0.5411246272833143, -0.4660671538747663], [0.6805897799894314, 0.7389950985079005]]) #print(np.max(np.abs(sim.X[:,-1,:]-Xref))) self.assertLess(np.max(np.abs(sim.X[:, -1, :] - Xref)), 1.2e-16)
def test_AmcSwapSimulation(self): model = HWModel() obsTimes = np.linspace(0.0,10.0,121) nPaths = 2**7 print('') # calibration seed0 = 314159265359 mcSim0 = McSimulation(model,obsTimes,nPaths,seed0,True) # simulation seed0 = 141592653593 mcSim1 = McSimulation(model,obsTimes,nPaths,seed0,True) swap = AmcSwap(self.legs,self.pors,mcSim0,2,self.discYtsH) scen = swap.scenarios(obsTimes,mcSim1) epe = np.average(np.maximum(scen,0.0),axis=0) plt.plot(obsTimes,epe) plt.show()
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_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_QuantLibPayoff(self): model = self.sim.model simTimes = self.sim.times nPaths = 2**7 seed = 3141592 timeInterpolation = True sim = McSimulation(model,simTimes,nPaths,seed,timeInterpolation,False) qSim = QuantLibSimulation(sim) # payoffs = self.timeline[0.0] scens = np.array([ [ payoff.discountedAt(path) for path in sim.paths() ] for payoff in payoffs ]) # qPayoffs = QuantLibPayoffs(payoffs) qScens = QuantLibDiscountedAt(qSim,qPayoffs) # self.assertAlmostEqual(np.mean(qScens),np.mean(scens),places=16) # that's trivial at t=0
def test_SwapSimulation(self): model = HWModel() obsTimes = np.linspace(0.0,10.0,121) nPaths = 2**7 seed = 314159265359 print('') mcSim = McSimulation(model,obsTimes,nPaths,seed,True) swap = Swap(self.legs,self.pors,self.discYtsH) scen = swap.scenarios(obsTimes,mcSim) epe = np.average(np.maximum(scen,0.0),axis=0) plt.plot(obsTimes,epe) plt.show()
def test_SpreadSimulation(self): times = np.linspace(0.0, 10.0, 11) nPaths = 2**10 seed = 1234 # risk-neutral simulation print('') mcSim = McSimulation(self.model,times,nPaths,seed,False) # T = 10.0 P = Pay(Fixed(1.0),T) pv, err = fwd(mcSim,P) # domestic numeraire print('1.0 @ %4.1lfy %8.6lf - mc_err = %8.6lf' % (T,pv,err))
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_CompareWithMarkovModel(self): kappa = 1.35 sigma_0 = 0.50 sigma_infty = 0.17 rho_infty = 0.50 model0 = AndersenFutureModel(None,kappa,sigma_0,sigma_infty,rho_infty) # def sigmaT(sigma_0, sigma_infty, rho_infty): h1 = -sigma_infty + rho_infty * sigma_0 h2 = sigma_0 * np.sqrt(1.0 - rho_infty**2) hi = sigma_infty return np.array([ [h1, h2], [hi, 0.0] ]) # def chi(kappa): return np.array([ kappa, 0.0 ]) # sigmaT_ = sigmaT(sigma_0,sigma_infty,rho_infty) chi_ = chi(kappa) # d = 2 times = np.array([0.0]) model1 = MarkovFutureModel(None,d,times,np.array([ sigmaT_ ]),chi_) # times = np.linspace(0.0, 5.0, 3) nPaths = 2**3 seed = 14159265359 # sim0 = McSimulation(model0,times,nPaths,seed,False,showProgress=False) sim1 = McSimulation(model1,times,nPaths,seed,False,showProgress=False) # for idx in range(1,times.shape[0]): t = times[idx] for dT in [ 0.0, 1.0, 2.0, 5.0, 10.0]: T = t + dT F0 = np.array([ model0.futurePrice(t,T,X,None) for X in sim0.X[:,idx,:] ]) F1 = np.array([ model1.futurePrice(t,T,X,None) for X in sim1.X[:,idx,:] ]) # print(F0-F1) self.assertLess(np.max(np.abs(F0-F1)),3.0e-16)
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_AmcSwapSetup(self): model = HWModel() obsTimes = np.array([0.0]) nPaths = 1 seed = 1 print('') mcSim = McSimulation(model,obsTimes,nPaths,seed,True) swap = AmcSwap(self.legs,self.pors,mcSim,2,self.discYtsH) #swap.cashFlows(8.1) timeLine = swap.timeLine([1.0, 2.0, 3.0]) # for t in timeLine: print('ObsTime: %.2f' % t) for p in timeLine[t]: print(p)
def test_QuantLibSimulation(self): model = self.sim.model simTimes = self.sim.times nPaths = 2**7 seed = 314159 timeInterpolation = True sim = McSimulation(model,simTimes,nPaths,seed,timeInterpolation,False) # qSim = QuantLibSimulation(sim) # just copy # simTimes = np.array([0.0, 1.0, 2.0]) nPaths = 2 seed = 112 timeInterpolation = False qSim = QuantLibSimulation(sim,nPaths=nPaths,times=simTimes,seed=seed,timeInterpolation=timeInterpolation) # adjust simulation details self.assertEqual(qSim.nPaths(),nPaths) self.assertEqual(np.max(np.abs(qSim.simTimes() - simTimes)), 0.0)
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_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))
def test_ModelEvolution(self): model = self.model # times = np.linspace(0.0, 10.0, 11) nPaths = 2**3 seed = 314159265359 # risk-neutral simulation mcSim = McSimulation(model, times, nPaths, seed, showProgress=False) # T = 10 P10 = np.array( [1.0 / model.numeraire(T, x) for x in mcSim.X[:, -1, :]]) #print(np.mean(P10)) #print(model.zeroBondPrice(0.0,10.0,model.r0)) self.assertAlmostEqual(np.mean(P10), 0.6480670673701923, 12) self.assertAlmostEqual(model.zeroBondPrice(0.0, 10.0, model.r0), 0.5997174951900259, 12)
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_MartingaleProperty(self): kappa = 1.35 sigma_0 = 0.50 sigma_infty = 0.17 rho_infty = 0.50 model = AndersenFutureModel(None,kappa,sigma_0,sigma_infty,rho_infty) # times = np.linspace(0.0, 5.0, 3) nPaths = 2**13 seed = 14159265359 sim = McSimulation(model,times,nPaths,seed,False,showProgress=False) # for idx in range(1,times.shape[0]): t = times[idx] for dT in [ 0.0, 1.0, 2.0, 5.0, 10.0]: T = t + dT F = np.array([ model.futurePrice(t,T,X,None) for X in sim.X[:,idx,:] ]) Fav = np.mean(F) sigma = np.std(F) / np.sqrt(t) # print('t: %6.2f, T: %6.2f, F: %6.4f, sigma: %6.4f' % (t,T,Fav,sigma) ) # print(np.abs(Fav - 1.0)) self.assertLess(np.abs(Fav - 1.0),0.0026)
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_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))