コード例 #1
0
ファイル: volutil.py プロジェクト: bhatiavishal/deriv
def fivepointtostrikevol(fwd, atm, rr25, fly25, rr10, fly10, mat):
    ''' create volslice with atm vol
    transform strikes with a quadratic
    '''
    strikevol = fivepointsmile(fwd, atm, rr25, fly25, rr10, fly10, mat)
    strikevolbase = fivepointsmile(fwd, atm, 0, 0, 0, 0, mat)

    strikevolmap = interpolate.interp1d(np.log(strikevolbase[:, 0]),
                                        np.log(strikevol[:, 0]),
                                        fill_value="extrapolate",
                                        kind=2)

    lbound = BS.blackstrikefordelta(atm, strikevol[0, 0], mat, -1, 0.01)
    ubound = BS.blackstrikefordelta(atm, strikevol[-1, 0], mat, 1, 0.01)
    stvol = np.ones([1000, 2])
    stvol[:, 0] = np.linspace(lbound, ubound, 1000)
    stvol[:, 1] = atm
    vol = logvolslice(stvol, fwd, mat)
    baseprob = vol.cumdf.strikeprob
    prob = baseprob.copy()
    prob[:,
         0] = [np.exp(strikevolmap(np.log(stri))) for stri in baseprob[:, 0]]
    prob[:, 1] = baseprob[:, 1]
    plt.plot(prob[:, 0], prob[:, 1], label="smile")
    plt.plot(baseprob[:, 0], baseprob[:, 1], label="nonsmile")
    plt.title("smile")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

    plt.show()

    strikevol = cdf(prob).getstrikevol(prob[:, 0], mat)
    return strikevol
コード例 #2
0
ファイル: volutil.py プロジェクト: bhatiavishal/deriv
    def __init__(self, strikevol, fwd, mat):
        """ strike vol : 2d np array ascending order strike, vol
        """
        self.strikevol = strikevol
        self.fwd = fwd
        self.mat = mat
        self.strikevolinter = interpolate.interp1d(strikevol[:, 0],
                                                   strikevol[:, 1],
                                                   kind=2,
                                                   fill_value="extrapolate")
        nofstrikes = self.strikevol.shape[0]
        strprob = np.ones((nofstrikes - 1, 2)) * 0.5
        for i in range(0, nofstrikes - 1):
            v0 = self.strikevol[i][1]
            v1 = self.strikevol[i + 1][1]
            k0 = self.strikevol[i][0]
            k1 = self.strikevol[i + 1][0]
            #cp = -1 if k0 < self.fwd else 1
            cp = 1 if fwd < k0 else -1

            d0 = BS.black(v0, self.fwd, k0, self.mat, cp)
            d1 = BS.black(v1, self.fwd, k1, self.mat, cp)
            strprob[i, 0] = (k1 + k0) / 2
            strprob[i, 1] = (cp + 1) / 2 + (d1 - d0) / (k1 - k0)
        self.cumdf = cdf(strprob)
コード例 #3
0
ファイル: Stochvol.py プロジェクト: bhatiavishal/deriv
            def calibslice(lvol):
                lvolf = np.maximum(0, lvol)
                interped = intp.interp1d(calibki,
                                         lvolf,
                                         kind=1,
                                         fill_value="extrapolate")
                lvolj = interped(R[i - 1])
                volj = volji * lvolj
                #print(lvol)
                R[i] = R[i - 1] * dffor[i - 1] / dfdom[i - 1] * np.exp(
                    -volj * volj * t / 2 + paths[i - 1] * volj * math.sqrt(t))
                driftadj = np.mean(R[i]) / fwd
                R[i] = R[i] / driftadj
                volsim = [
                    BS.volfromsim(R[i], fwd, strk, i * t) for strk in calibki
                ]
                #err =  np.linalg.norm(np.log(volsim) - np.log(volcalibi))

                err = np.linalg.norm(volsim - volcalibi)
                #if i == 1 :
                #   print(err, volsim, volcalibi)
                return err
                cdf0 = vu.cdf(BS.mccdf(R[i]))
                err = np.linalg.norm(
                    np.log(cdf0.probinterpinv(cumppt)) -
                    np.log(cdf1.probinterpinv(cumppt)))
                print(err)
                return err * err
コード例 #4
0
ファイル: volutil.py プロジェクト: bhatiavishal/deriv
 def getstrikevol(self, strikes, mat):
     simul = self.getsimulation(500000)
     fwd = simul.mean()
     print("Fwd", fwd)
     fwd = 15.0
     strikevol = np.zeros((strikes.shape[0], 2))
     strikevol[:, 0] = strikes
     strikevol[:, 1] = np.array(
         [BS.volfromsim(simul, fwd, stri, mat) for stri in strikes])
     return strikevol
コード例 #5
0
ファイル: volutil.py プロジェクト: bhatiavishal/deriv
def testquadsmile():
    fwd = 15.0
    T = 10
    a = 0.5
    b = 0.0001
    c = 1.05
    stvol = np.ones([1000, 2])
    stvol[:, 0] = np.exp(np.linspace(np.log(0.5), np.log(100), 1000))
    stvol[:, 1] = 0.2
    stvol[:, 1] = 0.2 * du.quad(np.log(stvol[:, 0] / fwd) / 0.2 / T, a, b, c)

    vol = logvolslice(stvol, fwd, T)
    cdfvol = vol.cumdf.strikeprob
    plt.plot(cdfvol[:, 0], cdfvol[:, 1])
    plt.title("cdf")
    plt.show()

    pdfvol = vol.cumdf.getpdf()
    plt.plot(pdfvol[:, 0], pdfvol[:, 1])
    plt.title("pdf")
    plt.show()
    strvol = vol.cumdf.getstrikevol(stvol[:, 0], vol.mat)
    plt.plot(stvol[:, 0], stvol[:, 1], label="input quadvoL")
    plt.plot(strvol[:, 0], strvol[:, 1], label="vol from cdf")
    plt.title("vol from cdf")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    plt.show()

    xran = np.random.normal(size=10000)
    vols = 0.2
    sim = fwd * np.exp(-vols * vols * T / 2 + vols * xran * math.sqrt(T))

    lbound = vol.cumdf.getstrike(0.01)
    ubound = vol.cumdf.getstrike(0.99)
    print(lbound, ubound)
    x = np.linspace(ubound, lbound, 30)
    y = [BS.volfromsim(sim, sim.mean(), stri, T) for stri in x]
    plt.plot(x, y)
    plt.title("vol from cdf")
    plt.show()

    print(vol.deltastrike(0.25, 1), vol.deltastrike(0.25, -1))
    print(vol.getrr(0.25), vol.getfly(0.25))
    print(vol.deltastrike(0.1, 1), vol.deltastrike(0.1, -1))

    print(vol.getrr(0.1), vol.getfly(0.1))

    strikevolsmile = fivepointtostrikevol(15, 0.20, -0.06, 0.01, -0.12, 0.03,
                                          5)
    plt.plot(strikevolsmile[:, 0], strikevolsmile[:, 1])
    plt.title("interpolated smile")
    plt.show()

    return vol
コード例 #6
0
ファイル: volutil.py プロジェクト: bhatiavishal/deriv
def fivepointsmile(fwd, atm, rr25, fly25, rr10, fly10, mat):
    c25 = 0.5 * (rr25 + 2 * fly25 + 2 * atm)
    p25 = c25 - rr25
    c10 = 0.5 * (rr10 + 2 * fly10 + 2 * atm)
    p10 = c10 - rr10
    kc25 = BS.blackstrikefordelta(c25, fwd, mat, 1, 0.25)
    kc10 = BS.blackstrikefordelta(c10, fwd, mat, 1, 0.1)
    kp25 = BS.blackstrikefordelta(p25, fwd, mat, -1, 0.25)
    kp10 = BS.blackstrikefordelta(p10, fwd, mat, -1, 0.1)

    strikevol = np.ones((5, 2))
    strikevol[0, 0] = kp10
    strikevol[0, 1] = p10
    strikevol[1, 0] = kp25
    strikevol[1, 1] = p25
    strikevol[2, 0] = fwd
    strikevol[2, 1] = atm
    strikevol[3, 0] = kc25
    strikevol[3, 1] = c25
    strikevol[4, 0] = kc10
    strikevol[4, 1] = c10

    return strikevol
コード例 #7
0
ファイル: volutil.py プロジェクト: bhatiavishal/deriv
 def bounddelta(strike):
     f = self.fwd
     v = self.getvolforstrike(strike)
     mat = self.mat
     err = (BS.blackdelta(v, f, strike, mat, cp) - delta)
     return err * err
コード例 #8
0
ファイル: Stochvol.py プロジェクト: bhatiavishal/deriv
    def __init__(self,
                 spot,
                 sigma,
                 paths,
                 time,
                 rdom=None,
                 rfor=None,
                 volcalib=None,
                 marginadjust=False):
        self.sigma = sigma
        self.numpaths = paths.shape[1]
        self.timeslices = paths.shape[0]
        self.sigma = sigma
        self.time = time
        R = np.zeros([self.timeslices + 1, self.numpaths])
        dti = self.time[1:] - self.time[:-1]
        if rdom is None:
            rdom = np.ones((self.timeslices, self.numpaths)) * 0.05
            rfor = np.ones((self.timeslices, self.numpaths)) * 0.05
        dffor = 1.0 / (1 + rfor[:-1] * dti.reshape((-1, 1)))
        dfdom = 1.0 / (1 + rdom[:-1] * dti.reshape((-1, 1)))
        R[0, :] = spot
        cumppt = np.linspace(0.1, 0.9, 5)
        bounds = [(0, None), (0, None), (0, None), (0, None), (0, None)]
        for i in range(1, self.timeslices + 1):
            print("calib timeslice", i)
            t = dti[i - 1]
            dfr = (1 + t * np.mean(rfor[i - 1])) / (1 +
                                                    t * np.mean(rdom[i - 1]))
            fwd = np.mean(R[i - 1]) / dfr
            volji = np.maximum(0, sigma[i - 1])
            cdf1 = volcalib[i - 1].cumdf
            calibki = cdf1.getstrike(cumppt) * dfr
            volcalibi = volcalib[i - 1].getvolforstrike(calibki)

            def calibslice(lvol):
                lvolf = np.maximum(0, lvol)
                interped = intp.interp1d(calibki,
                                         lvolf,
                                         kind=1,
                                         fill_value="extrapolate")
                lvolj = interped(R[i - 1])
                volj = volji * lvolj
                #print(lvol)
                R[i] = R[i - 1] * dffor[i - 1] / dfdom[i - 1] * np.exp(
                    -volj * volj * t / 2 + paths[i - 1] * volj * math.sqrt(t))
                driftadj = np.mean(R[i]) / fwd
                R[i] = R[i] / driftadj
                volsim = [
                    BS.volfromsim(R[i], fwd, strk, i * t) for strk in calibki
                ]
                #err =  np.linalg.norm(np.log(volsim) - np.log(volcalibi))

                err = np.linalg.norm(volsim - volcalibi)
                #if i == 1 :
                #   print(err, volsim, volcalibi)
                return err
                cdf0 = vu.cdf(BS.mccdf(R[i]))
                err = np.linalg.norm(
                    np.log(cdf0.probinterpinv(cumppt)) -
                    np.log(cdf1.probinterpinv(cumppt)))
                print(err)
                return err * err

            # do drift adjustment
            #res = opt.minimize(calibslice,np.ones(cumppt.shape[0]), method="Nelder-Mead",options={"maxiter":100})
            #res = opt.minimize(calibslice,np.ones(cumppt.shape[0]), method="Nelder-Mead",tol=1e-2)
            #res = opt.minimize(calibslice,np.ones(cumppt.shape[0]), bounds = bounds)
            #print(res.x)
            #print(res.message, res.x)
            #calibslice(res.x)
            #driftadj = np.mean(R[i])/fwd
            #R[i] = R[i]/driftadj
            if volcalib is not None:
                res = opt.minimize(calibslice,
                                   np.ones(cumppt.shape[0]),
                                   bounds=bounds)
                print(res.x)
                #print(res.message, res.x)
                calibslice(res.x)

                x = np.linspace(0.05, 0.95, 20)
                cdf0 = vu.cdf(BS.mccdf(R[i]))
                p = cdf0.getcumprob(R[i])
                adjRi = cdf1.getstrike(p)
                if i == 1 or marginadjust:
                    R[i] = adjRi
                    pass
                cdf2 = vu.cdf(BS.mccdf(R[i]))
                #plt.plot(cdf0.getstrike(x),x, label = "original")
                plt.plot(cdf1.getstrike(x), x, label="target")
                plt.plot(cdf2.getstrike(x), x, label="adjusted")

                plt.title("generated cdf vs target")
                plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

                plt.show()

            else:
                calibslice(np.ones(cumppt.shape[0]))

            driftadj = np.mean(R[i]) / fwd
            R[i] = R[i] / driftadj

        self.paths = R
コード例 #9
0
ファイル: Stochvol.py プロジェクト: bhatiavishal/deriv
def main():

    #np.random.seed(100910)
    numpaths = 20000
    N = 5
    rho = 0.75
    T = 5.0
    t = T / N
    spot = 18.95
    TI = np.linspace(0, T, N + 1)

    # 0 :fx, 1:fxvol, 2:dom, 3:for
    rho01 = 0
    rho02 = 0.002
    rho03 = -0.27
    rho12 = 0
    rho13 = 0
    rho23 = 0.16

    cov = np.array([[1, rho01, rho02, rho03], [rho01, 1, rho12, rho13],
                    [rho02, rho12, 1, rho23], [rho03, rho13, rho23, 1]])

    paths = corpath.getpaths(cov, numpaths, N)

    #dom
    domts = np.ones(N + 1) * 0.001
    meanrev = np.ones([N]) * 0.01
    sigma = np.ones([N]) * 0.005 * 20
    rdom = irprocess.OrUhl(domts, meanrev, sigma, paths[2], TI)

    #for
    forts = du.funa(0.205, 0.15, 0.25, N + 1)
    meanrev = np.ones([N]) * 0.05
    sigma = np.ones([N]) * 0.020
    rfor = irprocess.OrUhl(forts, meanrev, sigma, paths[3], TI)

    atm = intp.interp1d([0.25, 5], [0.208, 0.28])
    rr25 = intp.interp1d([0.25, 5], [-0.06, -0.1025])
    rr10 = intp.interp1d([0.25, 5], [-0.12, -0.2])
    fly25 = intp.interp1d([0.25, 5], [0.009, 0.0154])
    fly10 = intp.interp1d([0.25, 5], [0.045, 0.075])
    fwd = spot
    volcalib = []
    for i in range(0, N):
        ti = (i + 1) * t
        fwd = fwd * (1 + domts[i] * t) / (1 + forts[i] * t)
        #print( fwd,atm(ti),rr25(ti),fly25(ti),rr10(ti),fly10(ti),ti)
        voluninterp = vu.fivepointsmile(fwd, atm(ti), rr25(ti), fly25(ti),
                                        rr10(ti), fly10(ti), ti)
        volinterp = vu.strikevolinterp(voluninterp)
        volcalib.append(vu.logvolslice(volinterp, fwd, ti))

    #Stoch vol process
    meanrev = np.ones([N]) * 0.2
    vvol = np.ones([N]) * 0.05
    basevol = np.ones([N + 1]) * 0.135
    vol = volprocess.Logoruhl(basevol, meanrev, vvol, paths[1], TI)
    sigma = vol.paths
    asset = Stochvol(spot, sigma, paths[0], TI, rdom.paths, rfor.paths,
                     volcalib)
    #plot 10 random sample paths
    R = asset.paths

    a = np.random.permutation(R.shape[1])
    for i in range(0, 50):
        plt.plot(TI, rdom.paths[:, a[i]])
    plt.title("Dom Rate Process")
    plt.show()

    for i in range(0, 50):
        plt.plot(TI, rfor.paths[:, a[i]])
    plt.title("For Rate Process")
    plt.show()

    for i in range(0, 50):
        plt.plot(TI, vol.paths[:, a[i]])
    plt.title("Vol Process")
    plt.show()

    for i in range(0, 50):
        plt.plot(TI, R[:, a[i]])
    plt.title("Fx Process")
    plt.show()

    fxfwds = np.ones([N + 1]) * spot
    fxfwdspaths = np.ones([N + 1]) * spot
    fxvolpaths = np.ones([N + 1]) * basevol[0]

    for i in range(1, N + 1):
        fxfwds[i] = fxfwds[i - 1] * (1 + t * np.mean(rdom.paths[i - 1])) / (
            1 + t * np.mean(rfor.paths[i - 1]))
        fxfwdspaths[i] = np.mean(R[i])
        fxvolpaths[i] = BS.blackimply(fxfwdspaths[i], fxfwdspaths[i], t * i, 1,
                                      asset.optprice(fxfwdspaths[i], 1, i))

    plt.plot(TI, fxfwds)
    plt.plot(TI, fxfwdspaths)
    plt.title("Fxfwds: fwds and on paths")
    plt.show()

    plt.plot(TI, fxvolpaths)
    plt.title("Vol evolving with time")
    plt.show()

    fwd = fxfwds[-1]
    std = fxvolpaths[-1] * fwd
    x = np.linspace(fwd - 3 * std, fwd + 3 * std, 15)
    y = [
        BS.blackimply(fwd, stri, T, -1, asset.optprice(stri, -1)) for stri in x
    ]
    plt.plot(x, y, label="from mc")
    y1 = volcalib[-1].strikevolinter(x)
    plt.plot(x, y1, label="original")
    plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
    plt.title("Terminal Smile")
    plt.show()
    print(BS.blackimply(fwd, fwd + std, T, 1, (asset.optprice(fwd + std, 1))))
    print(BS.blackimply(fwd, fwd, T, 1, (asset.optprice(fwd, 1))))
    print(BS.blackimply(fwd, fwd - std, T, -1,
                        (asset.optprice(fwd - std, -1))))
    return asset, vol, rdom, rfor, volcalib, paths