def security_market_line(self, portfolio: Portfolio, date: datetime = None, regression_window: int = 36, benchmark: pd.Series = None): """ :param portfolio: :param date: :param regression_window: :param benchmark: :return: """ # ''' # The Security Market Line (SML) graphically represents the relationship between the asset's return (on y-axis) and systematic risk (or beta, on x-axis). # With E(R_i) = R_f + B_i * (E(R_m) - R_f), the y-intercept of the SML is equal to the risk-free interest rate, while the slope is equal to the market risk premium # Plotting the SML for a market index (i.e. DJIA), individual assets that are correctly priced are plotted on the SML (in the ideal 'Efficient Market Hypothesis' world). # In real market scenarios, we are able to use the SML graph to determine if an asset being considered for a portfolio offers a reasonable expected return for the risk. # - If an asset is priced at a point above the SML, it is undervalued, since for a given amount of risk, it yields a higher return. # - Conversely, an asset priced below the SML is overvalued, since for a given amount of risk, it yields a lower return. # ''' frequency = self.factors_timedf.df_frequency portfolio_copy = portfolio.set_frequency(frequency, inplace=False) \ .slice_dataframe(to_date=date, from_date=regression_window, inplace=False) betas = [ self.regress_factor_loadings(portfolio=portfolio.df_returns[ticker], benchmark_returns=benchmark, date=date, regression_window=regression_window).params[1] for ticker in portfolio_copy.df_returns] mean_asset_returns = portfolio_copy.get_mean_returns() date = portfolio_copy.df_returns.index[-1] if date is None else date risk_free_rate = risk_free_rates(lookback=regression_window, to_date=date, frequency=frequency).mean() \ * freq_to_yearly[frequency[0]] risk_premium = market_premiums(lookback=regression_window, to_date=date, frequency=frequency).mean() \ * portfolio.freq_to_yearly[frequency[0]] x = np.linspace(0, max(betas) + 0.1, 100) y = float(risk_free_rate) + x * float(risk_premium) fig, ax = plt.subplots(figsize=(10, 10)) plt.plot(x, y) ax.set_xlabel('Betas', fontsize=14) ax.set_ylabel('Expected Returns', fontsize=14) ax.set_title('Security Market Line', fontsize=18) for i, txt in enumerate(portfolio.df_returns): ax.annotate(txt, (betas[i], mean_asset_returns[i]), xytext=(10, 10), textcoords='offset points') plt.scatter(betas[i], mean_asset_returns[i], marker='x', color='red') plt.show()
class NestedClusteredOptimization(PortfolioAllocationModel): def __init__(self, portfolio: Portfolio): super().__init__(portfolio) def solve_weights(self, risk_metric=None, objective=None, leverage=0, long_short_exposure=0): pass if __name__ == '__main__': from matilda.data_pipeline.db_crud import companies_in_classification from matilda import config assets = companies_in_classification(class_=config.MarketIndices.DOW_JONES) portfolio = Portfolio(assets=assets) portfolio.set_frequency(frequency='M', inplace=True) portfolio.slice_dataframe(from_date=datetime(2016, 1, 1), to_date=datetime(2020, 1, 1), inplace=True) print(portfolio.df_returns.tail(10)) MPT = ModernPortfolioTheory(portfolio) weights = MPT.solve_weights(use_sharpe=True) print(weights) market_portfolio = Portfolio(assets='^DJI') market_portfolio.set_frequency(frequency='M', inplace=True) market_portfolio.slice_dataframe(from_date=datetime(2016, 1, 1), to_date=datetime(2020, 1, 1), inplace=True) stats = MPT.markowitz_efficient_frontier(market_portfolio=market_portfolio, plot_assets=True, plot_cal=True) pd.set_option('display.max_columns', None) print(stats.head())