Beispiel #1
0
 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)
Beispiel #2
0
 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)
Beispiel #6
0
    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)
Beispiel #7
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 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)
Beispiel #9
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)
Beispiel #10
0
 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))
Beispiel #12
0
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)