예제 #1
0
def test_add_const():
    X = pd.DataFrame(np.arange(5), columns=["X"])
    Y = pd.Series(np.arange(0, 10, 2) + 1)
    rr = ols.OLS(y=Y, x=X, has_const=False, use_const=True)
    assert rr.x.ndim == 2
    assert rr.y.ndim == 1
    assert ols._confirm_constant(rr.x)
예제 #2
0
    def CAPM(self, benchmark, has_const=False, use_const=True):
        """Interface to OLS regression against `benchmark`.

        `self.alpha()`, `self.beta()` and several other methods
        stem from here.  For the full method set, see
        `pyfinance.ols.OLS`.

        Parameters
        ----------
        benchmark : {pd.Series, TSeries, pd.DataFrame, np.ndarray}
            The benchmark securitie(s) to which `self` is compared.
        has_const : bool, default False
            Specifies whether `benchmark` includes a user-supplied constant
            (a column vector).  If False, it is added at instantiation.
        use_const : bool, default True
            Whether to include an intercept term in the model output.  Note the
            difference between `has_const` and `use_const`: the former
            specifies whether a column vector of 1s is included in the
            input; the latter specifies whether the model itself
            should include a constant (intercept) term.  Exogenous
            data that is ~N(0,1) would have a constant equal to zero;
            specify use_const=False in this situation.

        Returns
        -------
        pyfinance.ols.OLS
        """

        return ols.OLS(y=self,
                       x=benchmark,
                       has_const=has_const,
                       use_const=use_const)
예제 #3
0
def factor_loadings(r,
                    factors=None,
                    scale=False,
                    pickle_from=None,
                    pickle_to=None):
    """Security factor exposures generated through OLS regression.

    Incorporates a handful of well-known factors models.

    Parameters
    ==========
    r : Series or DataFrame
        The left-hand-side variable(s).  If `r` is nx1 shape (a Series or
        single-column DataFrame), the result will be a DataFrame.  If `r` is
        an nxm DataFrame, the result will be a dictionary of DataFrames.
    factors : DataFrame or None, default None
        Factor returns (right-hand-side variables).  If None, factor returns
        are loaded from `pyfinance.datasets.load_factors`
    scale : bool, default False
        If True, cale up/down the volatilities of all factors besides MKT & RF,
        to the vol of MKT.  Both means and the standard deviations are
        multiplied by the scale factor (ratio of MKT.std() to other stdevs)
    pickle_from : str or None, default None
        Passed to `pyfinance.datasets.load_factors` if factors is not None
    pickle_to : str or None, default None
        Passed to `pyfinance.datasets.load_factors` if factors is not None

    Example
    =======
    # TODO
    """

    # TODO:
    # - Might be appropriate for `returns`, will require higher dimensionality
    # - Option to subtract or not subtract RF (Jensen alpha)
    # - Annualized alpha
    # - Add variance inflation factor to output (method of `ols.OLS`)
    # - Add 'missing=drop' functionality (see statsmodels.OLS)
    # - Take all combinations of factors; which has highest explanatory power
    #       or lowest SSE/MSE?

    if factors is None:
        factors = datasets.load_factors(pickle_from=pickle_from,
                                        pickle_to=pickle_to)

    r, factors = utils.constrain(r, factors)

    if isinstance(r, Series):
        n = 1
        r = r.subtract(factors['RF'])
    elif isinstance(r, DataFrame):
        n = r.shape[1]
        r = r.subtract(np.tile(factors['RF'], (n, 1)).T)
        # r = r.subtract(factors['RF'].values.reshape(-1,1))
    else:
        raise ValueError('`r` must be one of (Series, DataFrame)')

    if scale:
        # Scale up the volatilities of all factors besides MKT & RF, to the
        # vol of MKT.  Both means and the standard deviations are multiplied
        # by the scale factor (ratio of MKT.std() to other stdevs)
        tgtvol = factors['MKT'].std()
        diff = factors.columns.difference(['MKT', 'RF'])  # don't scale these
        vols = factors[diff].std()
        factors.loc[:, diff] = factors[diff] * tgtvol / vols

    # Right-hand-side dict of models
    rhs = OrderedDict([
        ('Capital Asset Pricing Model (CAPM)', ['MKT']),
        ('Fama-French 3-Factor Model', ['MKT', 'SMB', 'HML']),
        ('Carhart 4-Factor Model', ['MKT', 'SMB', 'HMLD', 'UMD']),
        ('Fama-French 5-Factor Model', ['MKT', 'SMB', 'HMLD', 'RMW', 'CMA']),
        ('AQR 6-Factor Model', ['MKT', 'SMB', 'HMLD', 'RMW', 'CMA', 'UMD']),
        ('Price-Signal Model', ['MKT', 'UMD', 'STR', 'LTR'
                                ])('Fung-Hsieh Trend-Following Model',
                                   ['BDLB', 'FXLB', 'CMLB', 'STLB', 'SILB'])
    ])

    # Get union of keys and sort them according to `factors.columns`' order;
    # used later as columns in result
    cols = set(itertools.chain(*rhs.values()))
    cols = [o for o in factors.columns if o in cols] + ['alpha', 'rsq_adj']

    # Empty DataFrame to be populated with each regression's attributes
    stats = ['coef', 'tstat']
    idx = pd.MultiIndex.from_product([rhs.keys(), stats])
    res = DataFrame(columns=cols, index=idx)

    # Regression calls
    if n > 1:
        # Dict of DataFrames
        d = {}
        for col in r:
            for k, v in rhs.items():
                res = res.copy()
                model = ols.OLS(y=r[col], x=factors[v], hasconst=False)
                res.loc[(k, 'coef'), factors[v].columns] = model.beta()
                res.loc[(k, 'tstat'), factors[v].columns] = model.tstat_beta()
                res.loc[(k, 'coef'), 'alpha'] = model.alpha()
                res.loc[(k, 'tstat'), 'alpha'] = model.tstat_alpha()
                res.loc[(k, 'coef'), 'rsq_adj'] = model.rsq_adj()
            d[col] = res
        res = d

    else:
        # Single DataFrame
        for k, v in rhs.items():
            model = ols.OLS(y=r, x=factors[v], hasconst=False)
            res.loc[(k, 'coef'), factors[v].columns] = model.beta()
            res.loc[(k, 'tstat'), factors[v].columns] = model.tstat_beta()
            res.loc[(k, 'coef'), 'alpha'] = model.alpha()
            res.loc[(k, 'tstat'), 'alpha'] = model.tstat_alpha()
            res.loc[(k, 'coef'), 'rsq_adj'] = model.rsq_adj()

    return res
예제 #4
0
    call_strike = []
    put_strike = []
    for par in call_par_list:
        call_strike.append(fsolve(lambda x: call_delta(x, par[1], 3 / 12, 100, 0) - par[0], x0=100)[0])
    for par in put_par_list:
        put_strike.append(fsolve(lambda x: put_delta(x, par[1], 3 / 12, 100, 0) - par[0], x0=100)[0])
    strike_3m = put_strike + call_strike
    sigma_3m = [i[1] for i in put_par_list + call_par_list]

    K = {'1M': strike_1m, '3M': strike_3m}
    strike = pd.DataFrame(K, index=['10DP', '25DP', '40DP', '50D', '40DC', '25DC', '10DC'])

    #1.b
    df = {'sigma1M': sigma_1m, 'strike1M': strike_1m}
    df = pd.DataFrame(df)
    model = ols.OLS(y=df.sigma1M, x=df.strike1M)
    alpha1m = model.alpha
    beta1m = model.beta

    df = {'sigma3M': sigma_3m, 'strike3M': strike_3m}
    df = pd.DataFrame(df)
    model = ols.OLS(y=df.sigma3M, x=df.strike3M)
    alpha3m = model.alpha
    beta3m = model.beta

    #1.c
    K_list = np.linspace(80, 110, 301)
    vol_1M = alpha1m + beta1m * K_list
    vol_3M = alpha3m + beta3m * K_list
    c_1M = call_price(K_list, vol_1M, 1 / 12)
    c_3M = call_price(K_list, vol_3M, 3 / 12)