Esempio n. 1
0
def test_FinSobol():

    numPoints = 1000
    dimensions = 3

    points = getUniformSobol(numPoints, dimensions)

    for d in range(dimensions):
        av = 0.0
        var = 0.0

        for point in points[:, d]:
            av += point
            var += point**2

        av /= numPoints
        var /= numPoints

        avError = abs(av - (1 / 2))
        varError = abs(var - (1 / 3))
        assert (avError < 0.002)
        assert (varError < 0.002)

    numRepeats = 100
    numDimensions = 10

    testCases.header("LABEL", "TIME")
    start = time.time()
    for _ in range(numRepeats):
        getUniformSobol(1000, numDimensions)
    end = time.time()
    testCases.print("Average time taken", (end - start) / numRepeats)

    start = time.time()
    for _ in range(numRepeats):
        getGaussianSobol(1000, numDimensions)
    end = time.time()
    testCases.print("Average time taken", (end - start) / numRepeats)
Esempio n. 2
0
def test_FinSobolCache():
    return getUniformSobol(2, 2)
Esempio n. 3
0
def LMMSimulateFwdsMF(numForwards, numFactors, numPaths, numeraireIndex, fwd0,
                      lambdas, taus, useSobol, seed):
    ''' Multi-Factor Arbitrage-free simulation of forward Ibor curves in the
    spot measure following Hull Page 768. Given an initial forward curve,
    volatility factor term structure. The 3D matrix of forward rates by path,
    time and forward point is returned. '''

    np.random.seed(seed)

    if len(lambdas) != numFactors:
        raise FinError("Lambda does not have the right number of factors")

    if len(lambdas[0]) != numForwards:
        raise FinError("Lambda does not have the right number of forwards")

    # Even number of paths for antithetics
    numPaths = 2 * int(numPaths/2)
    halfNumPaths = int(numPaths/2)
    fwd = np.empty((numPaths, numForwards, numForwards))
    fwdB = np.zeros(numForwards)

    numTimes = numForwards

    if useSobol == 1:
        numDimensions = numTimes * numFactors
        rands = getUniformSobol(halfNumPaths, numDimensions)
        gMatrix = np.empty((numPaths, numTimes, numFactors))
        for iPath in range(0, halfNumPaths):
            for j in range(0, numTimes):
                for q in range(0, numFactors):
                    col = j*numFactors + q
                    u = rands[iPath, col]
                    g = norminvcdf(u)
                    gMatrix[iPath, j, q] = g
                    gMatrix[iPath + halfNumPaths, j, q] = -g
    elif useSobol == 0:
        gMatrix = np.empty((numPaths, numTimes, numFactors))
        for iPath in range(0, halfNumPaths):
            for j in range(0, numTimes):
                for q in range(0, numFactors):
                    g = np.random.normal()
                    gMatrix[iPath, j, q] = g
                    gMatrix[iPath + halfNumPaths, j, q] = -g
    else:
        raise FinError("Use Sobol must be 0 or 1.")

    for iPath in range(0, numPaths):
        # Initial value of forward curve at time 0
        for iFwd in range(0, numForwards):
            fwd[iPath, 0, iFwd] = fwd0[iFwd]

        for j in range(0, numForwards-1):  # TIME LOOP
            dtj = taus[j]
            sqrtdtj = np.sqrt(dtj)

            for k in range(j, numForwards):  # FORWARDS LOOP

                muA = 0.0
                for i in range(j+1, k+1):
                    fi = fwd[iPath, j, i]
                    ti = taus[i]
                    zz = 0.0
                    for q in range(0, numFactors):
                        zij = lambdas[q][i-j]
                        zkj = lambdas[q][k-j]
                        zz += zij * zkj
                    muA += fi * ti * zz / (1.0 + fi * ti)

                itoTerm = 0.0
                for q in range(0, numFactors):
                    itoTerm += lambdas[q][k-j] * lambdas[q][k-j]

                randomTerm = 0.0
                for q in range(0, numFactors):
                    wq = gMatrix[iPath, j, q]
                    randomTerm += lambdas[q][k-j] * wq
                randomTerm *= sqrtdtj

                x = np.exp(muA * dtj - 0.5 * itoTerm * dtj + randomTerm)
                fwdB[k] = fwd[iPath, j, k] * x

                muB = 0.0
                for i in range(j+1, k+1):
                    fi = fwdB[k]
                    ti = taus[i]
                    zz = 0.0
                    for q in range(0, numFactors):
                        zij = lambdas[q][i-j]
                        zkj = lambdas[q][k-j]
                        zz += zij * zkj
                    muB += fi * ti * zz / (1.0 + fi * ti)

                muC = 0.5 * (muA + muB)

                x = np.exp(muC * dtj - 0.5 * itoTerm * dtj + randomTerm)
                fwd[iPath, j+1, k] = fwd[iPath, j, k] * x

    return fwd
Esempio n. 4
0
def LMMSimulateFwds1F(numForwards, numPaths, numeraireIndex, fwd0, gammas,
                      taus, useSobol, seed):
    ''' One factor Arbitrage-free simulation of forward Ibor curves in the
    spot measure following Hull Page 768. Given an initial forward curve,
    volatility term structure. The 3D matrix of forward rates by path, time
    and forward point is returned. This function is kept mainly for its
    simplicity and speed.

    NB: The Gamma volatility has an initial entry of zero. This differs from
    Hull's indexing by one and so is why I do not subtract 1 from the index as
    Hull does in his equation 32.14.

    The Number of Forwards is the number of points on the initial curve to the
    trade maturity date.

    But be careful: a cap that matures in 10 years with quarterly caplets has
    40 forwards BUT the last forward to reset occurs at 9.75 years. You should
    not simulate beyond this time. If you give the model 10 years as in the
    Hull examples, you need to simulate 41 (or in this case 11) forwards as the
    final cap or ratchet has its reset in 10 years. '''

    if len(gammas) != numForwards:
        raise FinError("Gamma vector does not have right number of forwards")

    if len(fwd0) != numForwards:
        raise FinError("The length of fwd0 is not equal to numForwards")

    if len(taus) != numForwards:
        raise FinError("The length of Taus is not equal to numForwards")

    np.random.seed(seed)
    # Even number of paths for antithetics
    numPaths = 2 * int(numPaths/2)
    halfNumPaths = int(numPaths/2)
    fwd = np.empty((numPaths, numForwards, numForwards))
    fwdB = np.zeros(numForwards)

    numTimes = numForwards

    if useSobol == 1:
        numDimensions = numTimes
        rands = getUniformSobol(halfNumPaths, numDimensions)
        gMatrix = np.empty((numPaths, numTimes))
        for iPath in range(0, halfNumPaths):
            for j in range(0, numTimes):
                u = rands[iPath, j]
                g = norminvcdf(u)
                gMatrix[iPath, j] = g
                gMatrix[iPath + halfNumPaths, j] = -g
    elif useSobol == 0:
        gMatrix = np.empty((numPaths, numTimes))
        for iPath in range(0, halfNumPaths):
            for j in range(0, numTimes):
                g = np.random.normal()
                gMatrix[iPath, j] = g
                gMatrix[iPath + halfNumPaths, j] = -g
    else:
        raise FinError("Use Sobol must be 0 or 1")

    for iPath in range(0, numPaths): # changed from prange
        # Initial value of forward curve at time 0
        for iFwd in range(0, numForwards):
            fwd[iPath, 0, iFwd] = fwd0[iFwd]

        for j in range(0, numForwards-1):  # TIME LOOP
            dtj = taus[j]
            sqrtdtj = np.sqrt(dtj)
            w = gMatrix[iPath, j]

            for k in range(j, numForwards):  # FORWARDS LOOP
                zkj = gammas[k-j]
                muA = 0.0

                for i in range(j+1, k+1):
                    fi = fwd[iPath, j, i]
                    zij = gammas[i-j]
                    ti = taus[i]
                    muA += zkj * fi * ti * zij / (1.0 + fi * ti)

                # predictor corrector
                x = np.exp(muA * dtj - 0.5*(zkj**2) * dtj + zkj * w * sqrtdtj)
                fwdB[k] = fwd[iPath, j, k] * x

                muB = 0.0
                for i in range(j+1, k+1):
                    fi = fwdB[k]
                    zij = gammas[i-j]
                    ti = taus[i]
                    muB += zkj * fi * ti * zij / (1.0 + fi * ti)

                muC = 0.5*(muA+muB)

                x = np.exp(muC*dtj - 0.5 * (zkj**2) * dtj + zkj * w * sqrtdtj)
                fwd[iPath, j+1, k] = fwd[iPath, j, k] * x

    return fwd