Exemplo n.º 1
0
def test_FinCapVolCurve():

    # Reproduces example in Table 32.1 of Hull Book
    valuationDate = FinDate(1, 1, 2020)

    capVolDates = []
    capletVolTenor = "1Y"
    numPeriods = 10
    capletDt = valuationDate

    capVolDates.append(valuationDate)

    for i in range(0, numPeriods):
        capletDt = capletDt.addTenor(capletVolTenor)
        capVolDates.append(capletDt)

    capVolatilities = [
        0.0, 15.50, 18.25, 17.91, 17.74, 17.27, 16.79, 16.30, 16.01, 15.76,
        15.54
    ]
    capVolatilities = np.array(capVolatilities) / 100.0

    dayCountType = FinDayCountTypes.ACT_ACT_ISDA
    volCurve = FinLiborCapVolCurve(valuationDate, capVolDates, capVolatilities,
                                   dayCountType)

    testCases.header("DATE", "CAPVOL", "CAPLETVOL")
    for dt in capVolDates:
        capFloorVol = volCurve.capVol(dt)
        capFloorLetVol = volCurve.capletVol(dt)
        testCases.print("%s" % dt, "%7.3f" % (capFloorVol * 100.0),
                        "%7.2f" % (capFloorLetVol * 100.0))
Exemplo n.º 2
0
    def simulateNF(self,
                   discountCurve,
                   volCurve: FinLiborCapVolCurve,
                   correlationMatrix: np.ndarray,
                   modelType: FinRateModelLMMModelTypes,
                   numPaths: int = 1000,
                   numeraireIndex: int = 0,
                   useSobol: bool = True,
                   seed: int = 42):
        ''' Run the simulation to generate and store all of the Libor forward
        rate paths using a full factor reduction of the fwd-fwd correlation
        matrix using Cholesky decomposition.'''

        checkArgumentTypes(self.__init__, locals())

        if numPaths < 2 or numPaths > 1000000:
            raise FinError("NumPaths must be between 2 and 1 million")

        if isinstance(modelType, FinRateModelLMMModelTypes) is False:
            raise FinError("Model type must be type FinRateModelLMMModelTypes")

        if discountCurve.curveDate != self._startDate:
            raise FinError("Curve anchor date not the same as LMM start date.")

        self._numPaths = numPaths
        self._volCurves = volCurve
        self._correlationMatrix = correlationMatrix
        self._modelType = modelType
        self._numeraireIndex = numeraireIndex
        self._useSobol = useSobol

        numGridPoints = len(self._gridTimes)

        self._numForwards = numGridPoints - 1
        self._forwardCurve = []

        for i in range(1, numGridPoints):
            startDate = self._gridDates[i-1]
            endDate = self._gridDates[i]
            fwdRate = discountCurve.forwardRate(startDate,
                                                endDate,
                                                self._floatDayCountType)
            self._forwardCurve.append(fwdRate)

        self._forwardCurve = np.array(self._forwardCurve)

        zetas = np.zeros(numGridPoints)
        for ix in range(1, numGridPoints):
            dt = self._gridDates[ix]
            zetas[ix] = volCurve.capletVol(dt)

        # This function does not use Sobol - TODO
        self._fwds = LMMSimulateFwdsNF(self._numForwards,
                                       numPaths,
                                       self._forwardCurve,
                                       zetas,
                                       correlationMatrix,
                                       self._accrualFactors,
                                       seed)
Exemplo n.º 3
0
    def simulate1F(self,
                   discountCurve,
                   volCurve: FinLiborCapVolCurve,
                   numPaths: int = 1000,
                   numeraireIndex: int = 0,
                   useSobol: bool = True,
                   seed: int = 42):
        ''' Run the one-factor simulation of the evolution of the forward
        Libors to generate and store all of the Libor forward rate paths. '''

        if numPaths < 2 or numPaths > 1000000:
            raise FinError("NumPaths must be between 2 and 1 million")

        if discountCurve._valuationDate != self._startDate:
            raise FinError("Curve anchor date not the same as LMM start date.")

        self._numPaths = numPaths
        self._numeraireIndex = numeraireIndex
        self._useSobol = useSobol

        numGridPoints = len(self._gridDates)

        self._numForwards = numGridPoints
        self._forwardCurve = []

        for i in range(1, numGridPoints):
            startDate = self._gridDates[i-1]
            endDate = self._gridDates[i]
            fwdRate = discountCurve.fwdRate(startDate,
                                            endDate,
                                            self._floatDayCountType)
            self._forwardCurve.append(fwdRate)

        self._forwardCurve = np.array(self._forwardCurve)

        gammas = np.zeros(numGridPoints)
        for ix in range(1, numGridPoints):
            dt = self._gridDates[ix]
            gammas[ix] = volCurve.capletVol(dt)

        self._fwds = LMMSimulateFwds1F(self._numForwards,
                                       numPaths,
                                       numeraireIndex,
                                       self._forwardCurve,
                                       gammas,
                                       self._accrualFactors,
                                       useSobol,
                                       seed)
Exemplo n.º 4
0
def test_FinLiborCapFloorVolCurve():
    ''' Aim here is to price cap and caplets using cap and caplet vols and to
    demonstrate they are the same - NOT SURE THAT HULLS BOOKS FORMULA WORKS FOR
    OPTIONS. '''

    todayDate = FinDate(20, 6, 2019)
    valuationDate = todayDate
    maturityDate = valuationDate.addTenor("3Y")
    dayCountType = FinDayCountTypes.THIRTY_E_360
    frequency = FinFrequencyTypes.ANNUAL

    k = 0.04
    capFloorType = FinLiborCapFloorTypes.CAP
    capFloor = FinLiborCapFloor(valuationDate, maturityDate, capFloorType, k,
                                None, frequency, dayCountType)

    capVolDates = FinSchedule(valuationDate, valuationDate.addTenor("10Y"),
                              frequency)._generate()

    flatRate = 0.04
    liborCurve = FinDiscountCurveFlat(valuationDate, flatRate, frequency,
                                      dayCountType)

    flat = False
    if flat is True:
        capVolatilities = [20.0] * 11
        capVolatilities[0] = 0.0
    else:
        capVolatilities = [
            0.00, 15.50, 18.25, 17.91, 17.74, 17.27, 16.79, 16.30, 16.01,
            15.76, 15.54
        ]

    capVolatilities = np.array(capVolatilities) / 100.0
    capVolatilities[0] = 0.0

    volCurve = FinLiborCapVolCurve(valuationDate, capVolDates, capVolatilities,
                                   dayCountType)

    print(volCurve._capletGammas)

    # Value cap using a single flat cap volatility
    tcap = (maturityDate - valuationDate) / gDaysInYear
    vol = volCurve.capVol(maturityDate)
    model = FinModelBlack(vol)
    valueCap = capFloor.value(valuationDate, liborCurve, model)
    print("CAP T", tcap, "VOL:", vol, "VALUE OF CAP:", valueCap)

    # Value cap by breaking it down into caplets using caplet vols
    vCaplets = 0.0
    capletStartDate = capFloor._capFloorLetDates[1]
    testCases.header("START", "END", "VOL", "VALUE")

    for capletEndDate in capFloor._capFloorLetDates[2:]:
        vol = volCurve.capletVol(capletEndDate)
        modelCaplet = FinModelBlack(vol)
        vCaplet = capFloor.valueCapletFloorLet(valuationDate, capletStartDate,
                                               capletEndDate, liborCurve,
                                               modelCaplet)

        vCaplets += vCaplet
        testCases.print("%12s" % capletStartDate, "%s" % capletEndDate,
                        "%9.5f" % (vol * 100.0), "%9.5f" % vCaplet)

        capletStartDate = capletEndDate

    testCases.header("LABEL", "VALUE")
    testCases.print("CAPLETS->CAP: ", vCaplets)