def test_portfolio_performance():
    """
    Cover logic in base_optimizer.portfolio_performance not covered elsewhere.
    """
    ef = setup_efficient_frontier()
    ef.min_volatility()
    expected = ef.portfolio_performance()

    # Cover verbose logic
    assert (portfolio_performance(ef.weights, ef.expected_returns,
                                  ef.cov_matrix, True) == expected)

    # Internal ticker creations when weights param is a dict and ...
    w_dict = dict(zip(ef.tickers, ef.weights))
    # ... expected_returns is a Series
    er = pd.Series(ef.expected_returns, index=ef.tickers)
    assert portfolio_performance(w_dict, er, ef.cov_matrix) == expected
    # ... cov_matrix is a DataFrame
    cov = pd.DataFrame(data=ef.cov_matrix,
                       index=ef.tickers,
                       columns=ef.tickers)
    assert portfolio_performance(w_dict, ef.expected_returns, cov) == expected

    # Will only support 'tickers' as dict keys that are ints starting from zero.
    w_dict = dict(zip(range(len(ef.weights)), ef.weights))
    assert portfolio_performance(w_dict, ef.expected_returns,
                                 ef.cov_matrix) == expected

    # Weights must not sum to zero.
    w_dict = dict(zip(range(len(ef.weights)), np.zeros(len(ef.weights))))
    with pytest.raises(ValueError):
        portfolio_performance(w_dict, ef.expected_returns, ef.cov_matrix)
def get_allocation_MPT(tickers,
                       objective,
                       history=500,
                       get_mpt_adjustment=None,
                       date=None,
                       **kwargs):

    _, df_prices = get_ticker_prices(tickers, history=history, date=date)
    if objective == "hrp":
        weights = hrp_portfolio(df_prices)
    else:
        returns_model = kwargs.get('returns_model', 'mean_historical_return')
        risk_model = kwargs.get('risk_model', 'ledoit_wolf')
        frequency = kwargs.get('frequency', 252)
        timezone = kwargs.get('timezone', 'US/Mountain')

        tz = pytz.timezone(timezone)
        t_end = datetime.now(tz) if date is None else date

        mu, S = get_mu_sigma(df_prices, returns_model, risk_model, frequency)

        if (get_mpt_adjustment is None):
            weights, _, _ = optimal_portfolio(mu,
                                              S,
                                              objective,
                                              get_entire_frontier=False,
                                              **kwargs)
        else:
            w_max_sharpe, opt_ret, opt_risk = optimal_portfolio(
                mu, S, objective, get_entire_frontier=True)
            r, v, _ = portfolio_performance(mu, S, w_max_sharpe)

            ga_model = kwargs.get('ga_model', 'SMPT_GA_MAX_RET_p200_g5_s2020')
            with open(f"../../../backend/data/ga/{ga_model}.pickle",
                      "rb+") as f:
                top10_max_ret = pickle.load(f)
            kwargs['weights'] = top10_max_ret[0]

            v_adjusted = get_mpt_adjustment(t_end, v, **kwargs)
            weights, _, _ = optimal_portfolio(
                mu,
                S,
                "efficient_risk",
                get_entire_frontier=False,
                **{"target_volatility": v_adjusted})

    weights = {k: Decimal(v) for k, v in weights.items()}
    return weights
Beispiel #3
0
    def get_weights(self, context, prices):

        if self.objective == "hrp":
            # Hierarchical Risk Parity
            weights = hrp_portfolio(prices)
        else:
            # Modern Portfolio Theory
            mu, S = get_mu_sigma(prices, self.returns_model, self.risk_model, self.frequency)

            if (self.get_mpt_adjustment is None):
                weights, _, _ = optimal_portfolio(mu, S, self.objective, get_entire_frontier=False, **self.kwargs)
            else:
                w_max_sharpe, opt_ret, opt_risk = optimal_portfolio(mu, S, self.objective, get_entire_frontier=True)
                r, v, _ = portfolio_performance(mu, S, w_max_sharpe)

                v_adjusted = self.get_mpt_adjustment(context.datetime, v, **self.kwargs)
                weights, _, _ = optimal_portfolio(mu, S, "efficient_risk", get_entire_frontier=False, **{"target_volatility": v_adjusted})

        if type(weights) == dict: weights = list(weights.values())
        return weights
Beispiel #4
0
def generate_markowitz_bullet(prices, returns_model='mean_historical_return', risk_model='ledoit_wolf',
                              frequency=252, span=500, objective='max_sharpe', num_random=20000,
                              ax=None, plot_individual=True, verbose=True, visualise=True):
    """Plot the markowitz bullet taking reference for plotting style from
        https://towardsdatascience.com/efficient-frontier-portfolio-optimisation-in-python-e7844051e7f

    Arguments:
        prices (pd.DataFrame) – adjusted closing prices of the asset, each row is a date and each column is a ticker/id.
        returns_model (string, optional) - Model for estimating expected returns of assets,
            either 'mean_historical_return' or 'ema_historical_return' (default: mean_historical_return)
        risk_model (string, optional) - Risk model to quantify risk: sample_cov, ledoit_wolf,
            defaults to ledoit_wolf, as recommended by Quantopian in their lecture series on quantitative finance.
        frequency (int, optional) – number of time periods in a year, defaults to 252 (the number of trading days in a year)
        span (int, optional) – Applicable only for 'ema_historical_return' expected returns.
            The time-span for the EMA, defaults to 500-day EMA)
        objective (string, optional) - Optimise for either 'max_sharpe', or 'min_volatility', defaults to 'max_sharpe'
        num_random (int, optional) - Number of random portfolios to generate for Markowitz Bullet. Set to 0 if not required
        plot_individual (boolean, optional) - If True, plots individual stocks on chart as well
        verbose (boolean, optional) - If True, prints out optimum portfolio allocations
        visualise (boolean, optional) - If True, plots Markowitz bullet

    Returns:
        r_volatility, r_returns, opt_volatility, opt_returns
        where
            r_volatility - array containing expected annual volatility values for generated random portfolios
            r_returns - array containg expected annual returns values for generated random portfolios
            opt_volatility - array containing expected annual volatility values along the efficient frontier
            opt_returns - array containing expected annual returns values along the efficient frontier

    """

    mu, S = get_mu_sigma(prices, returns_model, risk_model, frequency, span)
    opt_weights, opt_returns, opt_volatility = optimal_portfolio(mu, S, None, True)

    if (verbose): print("-"*80 + "\nMaximum Sharpe Ratio Portfolio Allocation\n")
    max_sharpe_returns, max_sharpe_volatility, max_sharpe_ratio = portfolio_performance(mu, S, opt_weights[0], verbose)
    if (verbose): print("-"*80 + "\nMinimum Volatility Portfolio Allocation\n")
    min_vol_returns, min_vol_volatility, min_vol_ratio = portfolio_performance(mu, S, opt_weights[1], verbose)

    if (visualise):
        plt.style.use('fivethirtyeight')

        if (ax is None): fig, ax = plt.subplots(figsize=(12, 8))

        # Plot Efficient Frontier (Annualised returns vs annualised volatility)
        ax.plot(opt_volatility, opt_returns, linestyle='-.', linewidth=1, color='black', label='Efficient frontier')

        # Plot optimum portfolios
        ax.plot(max_sharpe_volatility, max_sharpe_returns, 'r*', label='Max Sharpe', markersize=20)
        ax.plot(min_vol_volatility, min_vol_returns, 'g*', label='Min Volatility', markersize=20)

        # Plot individual stocks in 'prices' pandas dataframe
        if plot_individual:
            stock_names = list(prices.columns)
            s_returns = []
            s_volatility = []
            for i in range(len(stock_names)):
                w = [0] * len(stock_names)
                w[i] = 1
                s_returns, s_volatility, _ = portfolio_performance(mu, S, w)
                ax.plot(s_volatility, s_returns, 'o', markersize=10)
                ax.annotate(stock_names[i], (s_volatility, s_returns), xytext=(10, 0), textcoords='offset points')

        # Generate random portfolios
        if (num_random > 0):
            r_returns, r_volatility, r_sharpe = tuple(zip(*[portfolio_performance(mu, S, rand_weights(len(mu))) for _ in range(num_random)]))
            ax.scatter(r_volatility, r_returns, c=r_sharpe, cmap='YlGnBu', marker='o', s=10, alpha=0.3)  # random portfolios, colormap based on sharpe ratio

        # Set graph's axes
        ax.set_title('Markowitz Bullet')
        ax.set_xlabel('annualised volatility')
        ax.set_ylabel('annualised returns')
        ax.legend()

        plt.style.use('default')

    return r_volatility, r_returns, opt_volatility, opt_returns