Esempio n. 1
0
    def test_pandas(self):
        """Test with pandas input."""
        count = int(1e3)
        maturity = 30 / 365
        call = True
        sigma = np.random.uniform(.05, .8, count)
        moneyness = np.random.uniform(-.1, .1, count)
        premium = blackscholes_norm(moneyness, maturity, sigma, call)
        table = pd.DataFrame({'premium': premium, 'moneyness': moneyness})
        table['maturity'] = maturity
        table['call'] = call
        table['imp_vol'] = impvol_table(table)

        self.assertIsInstance(table, pd.DataFrame)
        np.testing.assert_array_almost_equal(table['imp_vol'].values, sigma, 3)

        dct = {
            'premium': premium,
            'moneyness': moneyness,
            'maturity': maturity,
            'call': call
        }
        dct['imp_vol'] = impvol_table(dct)
        self.assertIsInstance(dct, dict)
        np.testing.assert_array_almost_equal(dct['imp_vol'], sigma, 3)
    def test_gbm(self):
        """Test GBM model."""

        price, strike = 100, 110
        riskfree, maturity = .01, 30/365
        call = True
        put = np.logical_not(call)
        moneyness = lfmoneyness(price, strike, riskfree, maturity)

        sigma = .15

        model = GBM(GBMParam(sigma=sigma), riskfree, maturity)
        premium = cosmethod(model, moneyness=moneyness, call=call)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, call)
        impvol_model = impvol_bisection(moneyness, maturity, premium, call)

        self.assertEqual(premium.shape, (1,))
        np.testing.assert_array_almost_equal(premium, premium_true, 3)
        np.testing.assert_array_almost_equal(impvol_model, sigma, 2)

        moneyness = np.linspace(0, .1, 10)
        premium = cosmethod(model, moneyness=moneyness, call=call)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, call)
        impvol_model = impvol_bisection(moneyness, maturity, premium, call)
        impvol_true = np.ones_like(impvol_model) * sigma

        self.assertEqual(premium.shape, moneyness.shape)
        np.testing.assert_array_almost_equal(premium, premium_true, 2)
        np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2)

        riskfree = np.zeros_like(moneyness)
        premium = cosmethod(model, moneyness=moneyness, call=call)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, call)
        impvol_model = impvol_bisection(moneyness, maturity, premium, call)

        self.assertEqual(premium.shape, moneyness.shape)
        np.testing.assert_array_almost_equal(premium, premium_true, 3)
        np.testing.assert_array_almost_equal(impvol_model, sigma, 2)

        moneyness = np.linspace(-.1, 0, 10)
        premium = cosmethod(model, moneyness=moneyness, call=put)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, put)
        impvol_model = impvol_bisection(moneyness, maturity, premium, put)

        np.testing.assert_array_almost_equal(premium, premium_true, 2)
        np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2)
Esempio n. 3
0
    def test_gbm(self):
        """Test GBM model."""

        price, strike = 100, 110
        riskfree, maturity = .01, 30 / 365
        call = True
        put = np.logical_not(call)
        moneyness = lfmoneyness(price, strike, riskfree, maturity)

        sigma = .15

        model = GBM(GBMParam(sigma=sigma), riskfree, maturity)
        premium = cosmethod(model, moneyness=moneyness, call=call)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, call)
        impvol_model = impvol_bisection(moneyness, maturity, premium, call)

        self.assertEqual(premium.shape, (1, ))
        np.testing.assert_array_almost_equal(premium, premium_true, 3)
        np.testing.assert_array_almost_equal(impvol_model, sigma, 2)

        moneyness = np.linspace(0, .1, 10)
        premium = cosmethod(model, moneyness=moneyness, call=call)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, call)
        impvol_model = impvol_bisection(moneyness, maturity, premium, call)
        impvol_true = np.ones_like(impvol_model) * sigma

        self.assertEqual(premium.shape, moneyness.shape)
        np.testing.assert_array_almost_equal(premium, premium_true, 2)
        np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2)

        riskfree = np.zeros_like(moneyness)
        premium = cosmethod(model, moneyness=moneyness, call=call)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, call)
        impvol_model = impvol_bisection(moneyness, maturity, premium, call)

        self.assertEqual(premium.shape, moneyness.shape)
        np.testing.assert_array_almost_equal(premium, premium_true, 3)
        np.testing.assert_array_almost_equal(impvol_model, sigma, 2)

        moneyness = np.linspace(-.1, 0, 10)
        premium = cosmethod(model, moneyness=moneyness, call=put)
        premium_true = blackscholes_norm(moneyness, maturity, sigma, put)
        impvol_model = impvol_bisection(moneyness, maturity, premium, put)

        np.testing.assert_array_almost_equal(premium, premium_true, 2)
        np.testing.assert_array_almost_equal(impvol_model, impvol_true, 2)
def impvol_bisection(moneyness, maturity, premium, call, tol=1e-5, fcount=1e3):
    """Function to find BS Implied Vol using Bisection Method.

    Parameters
    ----------
    moneyness : float
        Log-forward moneyness
    maturity : float
        Fraction of the year
    premium : float
        Option premium normalized by current asset price
    call : bool
        Call/put flag. True for call, False for put

    Returns
    -------
    float
        Implied volatilities.
        Shape of the array is according to broadcasting rules.

    """

    sig, sig_u, sig_d = .2, 1, 1e-3
    count = 0
    err = blackscholes_norm(moneyness, maturity, sig, call) - premium

    # repeat until error is sufficiently small
    # or counter hits fcount
    while abs(err) > tol and count < fcount:
        if err < 0:
            sig_d = sig
            sig = (sig_u + sig)/2
        else:
            sig_u = sig
            sig = (sig_d + sig)/2

        err = blackscholes_norm(moneyness, maturity, sig, call) - premium
        count += 1

    # return NA if counter hit 1000
    if count == fcount:
        return -1
    else:
        return sig
Esempio n. 5
0
def impvol_bisection(moneyness, maturity, premium, call, tol=1e-5, fcount=1e3):
    """Function to find BS Implied Vol using Bisection Method.

    Parameters
    ----------
    moneyness : float
        Log-forward moneyness
    maturity : float
        Fraction of the year
    premium : float
        Option premium normalized by current asset price
    call : bool
        Call/put flag. True for call, False for put

    Returns
    -------
    float
        Implied volatilities.
        Shape of the array is according to broadcasting rules.

    """

    sig, sig_u, sig_d = .2, 1, 1e-3
    count = 0
    err = blackscholes_norm(moneyness, maturity, sig, call) - premium

    # repeat until error is sufficiently small
    # or counter hits fcount
    while abs(err) > tol and count < fcount:
        if err < 0:
            sig_d = sig
            sig = (sig_u + sig) / 2
        else:
            sig_u = sig
            sig = (sig_d + sig) / 2

        err = blackscholes_norm(moneyness, maturity, sig, call) - premium
        count += 1

    # return NA if counter hit 1000
    if count == fcount:
        return -1
    else:
        return sig
Esempio n. 6
0
    def test_bs_prices(self):
        """Test accuracy of back and forth BS conversion."""
        count = int(1e3)
        maturity = 30/365
        call = True
        sigma = np.random.uniform(.05, .8, count)
        moneyness = np.random.uniform(-.1, .1, count)
        premium = blackscholes_norm(moneyness, maturity, sigma, call)
        vol = impvol_bisection(moneyness, maturity, premium, call)

        np.testing.assert_array_almost_equal(vol, sigma, 3)
Esempio n. 7
0
    def test_bs_prices(self):
        """Test accuracy of back and forth BS conversion."""
        count = int(1e3)
        maturity = 30 / 365
        call = True
        sigma = np.random.uniform(.05, .8, count)
        moneyness = np.random.uniform(-.1, .1, count)
        premium = blackscholes_norm(moneyness, maturity, sigma, call)
        vol = impvol_bisection(moneyness, maturity, premium, call)

        np.testing.assert_array_almost_equal(vol, sigma, 3)
Esempio n. 8
0
    def premium(self):
        """Get price given implied volatility.

        Returns
        -------
        float array
            Option premium normalized by current underlying price

        """

        return blackscholes_norm(self.data['moneyness'], self.data['maturity'],
                                 self.impvol(), self.data['call'])
Esempio n. 9
0
    def premium(self):
        """Get price given implied volatility.

        Returns
        -------
        float array
            Option premium normalized by current underlying price

        """

        return blackscholes_norm(self.data['moneyness'],
                                 self.data['maturity'],
                                 self.impvol(), self.data['call'])
Esempio n. 10
0
    def premium(self):
        """Black-Scholes option price formula.

        Parameters
        ----------
        moneyness : float array
            Log-forward moneyness
        call : bool array
            Call/put flag. True for call, False for put

        Returns
        -------
        float array
            Option premium normalized by current underlying price

        """
        return blackscholes_norm(self.data['moneyness'], self.data['maturity'],
                                 self.sigma, self.data['call'])
Esempio n. 11
0
    def premium(self):
        """Black-Scholes option price formula.

        Parameters
        ----------
        moneyness : float array
            Log-forward moneyness
        call : bool array
            Call/put flag. True for call, False for put

        Returns
        -------
        float array
            Option premium normalized by current underlying price

        """
        return blackscholes_norm(self.data['moneyness'], self.data['maturity'],
                                 self.sigma, self.data['call'])
Esempio n. 12
0
    def test_pandas(self):
        """Test with pandas input."""
        count = int(1e3)
        maturity = 30/365
        call = True
        sigma = np.random.uniform(.05, .8, count)
        moneyness = np.random.uniform(-.1, .1, count)
        premium = blackscholes_norm(moneyness, maturity, sigma, call)
        table = pd.DataFrame({'premium': premium, 'moneyness': moneyness})
        table['maturity'] = maturity
        table['call'] = call
        table['imp_vol'] = impvol_table(table)

        self.assertIsInstance(table, pd.DataFrame)
        np.testing.assert_array_almost_equal(table['imp_vol'].values, sigma, 3)

        dct = {'premium': premium, 'moneyness': moneyness,
               'maturity': maturity, 'call': call}
        dct['imp_vol'] = impvol_table(dct)
        self.assertIsInstance(dct, dict)
        np.testing.assert_array_almost_equal(dct['imp_vol'], sigma, 3)
Esempio n. 13
0
    def premium(self):
        """Mixture of log-normals option price formula.

        Parameters
        ----------
        moneyness : float array
            Log-forward moneyness
        call : bool array
            Call/put flag. True for call, False for put

        Returns
        -------
        float array
            Option premium normalized by current underlying price

        """
        premium = 0
        for weight, mean, std in zip(self.weights, self.means, self.stds):
            shift = (self.data['riskfree'] - mean) * self.data['maturity']
            moneyness = np.array(self.data['moneyness']) + shift
            premium += weight * blackscholes_norm(
                moneyness, self.data['maturity'], std, self.data['call'])
        return premium
Esempio n. 14
0
    def premium(self):
        """Mixture of log-normals option price formula.

        Parameters
        ----------
        moneyness : float array
            Log-forward moneyness
        call : bool array
            Call/put flag. True for call, False for put

        Returns
        -------
        float array
            Option premium normalized by current underlying price

        """
        premium = 0
        for weight, mean, std in zip(self.weights, self.means, self.stds):
            shift = (self.data['riskfree'] - mean) * self.data['maturity']
            moneyness = np.array(self.data['moneyness']) + shift
            premium += weight * blackscholes_norm(moneyness,
                                                  self.data['maturity'],
                                                  std, self.data['call'])
        return premium
Esempio n. 15
0
if __name__ == '__main__':

    price = 1
    strike = 1
    riskfree = .02
    maturity = 30/365
    premium = .057
    call = True
    moneyness = lfmoneyness(price, strike, riskfree, maturity)
    vol = impvol_bisection(moneyness, maturity, premium, call)

    count = int(1e2)
    sigma = np.random.uniform(.05, .8, count)
    moneyness = np.random.uniform(-.1, .1, count)
    premium = blackscholes_norm(moneyness, maturity, sigma, call)

    text = 'Time elapsed: %.2f seconds'

    time_start = time.time()
    # Based on SciPy root method
    vol = imp_vol(moneyness, maturity, premium, call)
    print(np.allclose(sigma, vol))
    print(text % (time.time() - time_start))

    time_start = time.time()
    # Based on bisection method
    vol = impvol_bisection(moneyness, maturity, premium, call)
    print('Relative difference (percent) = ', ((sigma/vol-1).max()*100))
    print(np.allclose(vol, sigma, rtol=1e-3))
    print(text % (time.time() - time_start))
Esempio n. 16
0
if __name__ == '__main__':

    price = 1
    strike = 1
    riskfree = .02
    maturity = 30 / 365
    premium = .057
    call = True
    moneyness = lfmoneyness(price, strike, riskfree, maturity)
    vol = impvol_bisection(moneyness, maturity, premium, call)

    count = int(1e2)
    sigma = np.random.uniform(.05, .8, count)
    moneyness = np.random.uniform(-.1, .1, count)
    premium = blackscholes_norm(moneyness, maturity, sigma, call)

    text = 'Time elapsed: %.2f seconds'

    time_start = time.time()
    # Based on SciPy root method
    vol = imp_vol(moneyness, maturity, premium, call)
    print(np.allclose(sigma, vol))
    print(text % (time.time() - time_start))

    time_start = time.time()
    # Based on bisection method
    vol = impvol_bisection(moneyness, maturity, premium, call)
    print('Relative difference (percent) = ', ((sigma / vol - 1).max() * 100))
    print(np.allclose(vol, sigma, rtol=1e-3))
    print(text % (time.time() - time_start))