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)
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)
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
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)