def test_custom_lower_bound():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(0.02, 1)
    )
    ef.max_sharpe()
    assert ef.weights.min() >= 0.02
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
Exemple #2
0
def getMinVolatilityPortfolio(data):
    mu, Sigma = getMuSigma(data)
    ef = EfficientFrontier(mu, Sigma)
    raw_weights = ef.min_volatility()
    weights = ef.clean_weights()
    performance = ef.portfolio_performance()
    return weights, performance
Exemple #3
0
def test_lp_portfolio_allocation_different_params():
    df = get_data()
    mu = mean_historical_return(df)
    S = sample_cov(df)
    ef = EfficientFrontier(mu, S)
    w = ef.max_sharpe()

    latest_prices = get_latest_prices(df)
    da = DiscreteAllocation(w,
                            latest_prices,
                            total_portfolio_value=80000,
                            short_ratio=0.4)
    allocation, leftover = da.lp_portfolio()

    # assert allocation == {
    #     "GOOG": 3,
    #     "AAPL": 32,
    #     "FB": 99,
    #     "BABA": 34,
    #     "AMZN": 2,
    #     "BBY": 15,
    #     "MA": 164,
    #     "PFE": 438,
    #     "SBUX": 15,
    # }

    total = 0
    for ticker, num in allocation.items():
        total += num * latest_prices[ticker]
    np.testing.assert_almost_equal(total + leftover, 80000, decimal=4)
def test_lp_portfolio_allocation_different_params():
    df = get_data()
    mu = mean_historical_return(df)
    S = sample_cov(df)
    ef = EfficientFrontier(mu, S)
    w = ef.max_sharpe()

    latest_prices = get_latest_prices(df)
    da = DiscreteAllocation(
        w,
        latest_prices,
        min_allocation=0.002,
        total_portfolio_value=80000,
        short_ratio=0.4,
    )
    allocation, leftover = da.lp_portfolio()

    assert da.allocation == {
        "GOOG": 1,
        "AAPL": 43,
        "FB": 95,
        "BABA": 44,
        "AMZN": 4,
        "BBY": 69,
        "MA": 114,
        "PFE": 412,
        "SBUX": 51,
    }
    total = 0
    for ticker, num in allocation.items():
        total += num * latest_prices[ticker]
    np.testing.assert_almost_equal(total + leftover, 80000)
            def get_momentum_stocks(df, date, portfolio_size, cash):
                # Filter the df to get the top 10 momentum stocks for the latest day
                df_top_m = df.loc[df['date'] == pd.to_datetime(date)]
                df_top_m = df_top_m.sort_values(
                    by='momentum', ascending=False).head(portfolio_size)

                # Set the universe to the top momentum stocks for the period
                universe = df_top_m['symbol'].tolist()

                # Create a df with just the stocks from the universe
                df_u = df.loc[df['symbol'].isin(universe)]

                # Create the portfolio
                # Pivot to format for the optimization library
                df_u = df_u.pivot_table(index='date',
                                        columns='symbol',
                                        values='close',
                                        aggfunc='sum')

                # Calculate expected returns and sample covariance
                mu = expected_returns.mean_historical_return(df_u)
                S = risk_models.sample_cov(df_u)

                # Optimise the portfolio for maximal Sharpe ratio
                ef = EfficientFrontier(mu, S,
                                       gamma=1)  # Use regularization (gamma=1)
                weights = ef.max_sharpe()
                cleaned_weights = ef.clean_weights()

                # Allocate
                latest_prices = get_latest_prices(df_u)

                da = DiscreteAllocation(cleaned_weights,
                                        latest_prices,
                                        total_portfolio_value=cash)

                allocation = da.lp_portfolio()[0]

                # Put the stocks and the number of shares from the portfolio into a df
                symbol_list = []
                num_shares_list = []

                for symbol, num_shares in allocation.items():
                    symbol_list.append(symbol)
                    num_shares_list.append(num_shares)

                # Now that we have the stocks we want to buy we filter the df for those ones
                df_buy = df.loc[df['symbol'].isin(symbol_list)]

                # Filter for the period to get the closing price
                df_buy = df_buy.loc[df_buy['date'] == date].sort_values(
                    by='symbol')

                # Add in the qty that was allocated to each stock
                df_buy['qty'] = num_shares_list

                # Calculate the amount we own for each stock
                df_buy['amount_held'] = df_buy['close'] * df_buy['qty']
                df_buy = df_buy.loc[df_buy['qty'] != 0]
                return df_buy
Exemple #6
0
def get_mean_variance_share_allocation():
    dates, ticker_to_closing_prices = get_ticker_to_closing_prices(
        START_DATE, TEST_START_DATE - timedelta(days=1))

    tickers = ticker_to_closing_prices.keys()
    prices = list(
        zip(*[ticker_to_closing_prices[ticker] for ticker in tickers]))
    df = pd.DataFrame(
        prices,
        index=dates,
        columns=tickers,
    )

    mu = mean_historical_return(df)
    S = CovarianceShrinkage(df).ledoit_wolf()

    ef = EfficientFrontier(mu, S)
    weights = ef.max_sharpe()

    _, ticker_to_closing_prices_at_test_start = get_ticker_to_closing_prices(
        TEST_START_DATE, TEST_END_DATE)
    prices_at_test_start = pd.Series([
        float(ticker_to_closing_prices_at_test_start[ticker][0])
        for ticker in tickers
    ],
                                     index=tickers)
    da = DiscreteAllocation(weights,
                            prices_at_test_start,
                            total_portfolio_value=INITIAL_PORTFOLIO_VAL)
    allocation, leftover = da.lp_portfolio()
    for ticker in tickers:
        if ticker not in allocation:
            allocation[ticker] = 0

    return allocation
def test_allocation_errors():
    df = get_data()
    mu = mean_historical_return(df)
    S = sample_cov(df)
    ef = EfficientFrontier(mu, S)
    w = ef.max_sharpe()
    latest_prices = get_latest_prices(df)

    assert DiscreteAllocation(w, latest_prices)
    with pytest.raises(TypeError):
        DiscreteAllocation(ef.weights, latest_prices)
    with pytest.raises(TypeError):
        DiscreteAllocation(w, latest_prices.values.tolist())
    with pytest.raises(ValueError):
        DiscreteAllocation(w, latest_prices, total_portfolio_value=0)
    with pytest.raises(ValueError):
        DiscreteAllocation(w, latest_prices, short_ratio=-0.4)
    with pytest.raises(NameError):
        da = DiscreteAllocation(w, latest_prices)
        da.lp_portfolio(solver="ABCDEF")
    w2 = w.copy()
    w2["AAPL"] = np.nan
    with pytest.raises(ValueError):
        DiscreteAllocation(w2, latest_prices)
    latest_prices.iloc[0] = np.nan
    with pytest.raises(TypeError):
        DiscreteAllocation(w, latest_prices)
def get_sorted_weights(prices):
    '''
    prices: dataframe of the following shape. Column as symbols, Date as indices
                      AAL       AAPL    GOOGL
      Date
      2014-02-14  32.439728   17.411098  0.00
      2014-02-15  32.439728   17.411098  0.00
    '''
    # calculate parameters
    mu = expected_returns.mean_historical_return(prices)
    S = risk_models.sample_cov(prices)

    # remove infinite values
    symbols = prices.columns
    for symbol in symbols:
        # if value is infinite
        mu_value = mu[symbol]
        if not np.isfinite(mu_value) or mu_value == 0:
            # delete from means
            del mu[symbol]

            # delete from sample covariance
            S.drop(symbol, axis=1, inplace=True)
            S.drop(symbol, axis=0, inplace=True)

    # calculate efficient frontier
    ef = EfficientFrontier(mu, S)
    weights = ef.max_sharpe()
    cleaned_weights = ef.clean_weights()
    sorted_weights = sorted(cleaned_weights.items(), key=lambda x: -x[1])
    return sorted_weights
    def expected_r(tickers, start_date):
        today = pd.datetime.today()
        if start_date == '1y':
            delta = today - pd.DateOffset(years=1)
            delta = delta.date()
            delta = delta.strftime('%Y-%m-%d')
        elif start_date == '3y':
            delta = today - pd.DateOffset(years=3)
            delta = delta.date()
            delta = delta.strftime('%Y-%m-%d')
        elif start_date == '5y':
            delta = today - pd.DateOffset(years=5)
            delta = delta.date()
            delta = delta.strftime('%Y-%m-%d')
        elif start_date == '10y':
            delta = today - pd.DateOffset(years=10)
            delta = delta.date()
            delta = delta.strftime('%Y-%m-%d')
        elif start_date == 'max':
            delta = today - pd.DateOffset(years=30)
            delta = delta.date()
            delta = delta.strftime('%Y-%m-%d')

        prices = ffn.get(tickers, start=delta)
        mu = expected_returns.mean_historical_return(prices)
        S = risk_models.sample_cov(prices)
        ef = EfficientFrontier(mu, S)
        raw_weights = ef.max_sharpe()
        cleaned_weights = ef.clean_weights()
        st.write(cleaned_weights)
        metrics = ef.portfolio_performance(verbose=True)
        st.write('Expected Return: {:.2f}'.format(metrics[0]))
        st.write('Annual Volatility: {:.2f}'.format(metrics[1]))
        st.write('Sharpe Ratio {:.2f}'.format(metrics[2]))
    def __min_vol(mu: pd.Series, cov_matrix: pd.DataFrame) -> pd.DataFrame:
        # Setup
        ef = EfficientFrontier(mu, cov_matrix)

        # Optimizes for minimum volatility
        min_ptf = ef.min_volatility()
        return pd.DataFrame.from_dict(data=min_ptf, orient='index').T
def test_greedy_portfolio_allocation():
    df = get_data()
    mu = mean_historical_return(df)
    S = sample_cov(df)
    ef = EfficientFrontier(mu, S)
    w = ef.max_sharpe()

    latest_prices = get_latest_prices(df)
    da = DiscreteAllocation(w, latest_prices)
    allocation, leftover = da.greedy_portfolio()

    assert da.allocation == {
        "MA": 14,
        "FB": 12,
        "PFE": 51,
        "BABA": 5,
        "AAPL": 5,
        "AMZN": 0,
        "BBY": 9,
        "SBUX": 6,
        "GOOG": 1,
    }
    total = 0
    for ticker, num in allocation.items():
        total += num * latest_prices[ticker]
    np.testing.assert_almost_equal(total + leftover, 10000)
Exemple #12
0
def getMaxSharpePortfolio(data):
    mu, Sigma = getMuSigma(data)
    ef = EfficientFrontier(mu, Sigma)
    raw_weights = ef.max_sharpe()
    weights = ef.clean_weights()
    performance = ef.portfolio_performance()
    return weights, performance
Exemple #13
0
def test_custom_bounds_same():
    ef = EfficientFrontier(*setup_efficient_frontier(data_only=True),
                           weight_bounds=(0.03, 0.13))
    ef.max_sharpe()
    assert ef.weights.min() >= 0.03
    assert ef.weights.max() <= 0.13
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
Exemple #14
0
def opt_data(ticker, start, end, amt):
    weight = np.array([1 / len(ticker)] * len(ticker))

    hist_data = get_data(ticker, start, end)

    daily_returns = hist_data.pct_change()
    cov_annual_mat = daily_returns.cov() * 255

    port_variance = np.dot(weight.T, np.dot(cov_annual_mat, weight))
    port_volatility = np.sqrt(port_variance).round(4)
    port_simple_annual_return = np.sum(daily_returns.mean() * weight) * 255

    mu = expected_returns.mean_historical_return(hist_data)
    S = risk_models.sample_cov(hist_data)
    ef = EfficientFrontier(mu, S)
    w = ef.max_sharpe()
    cw = ef.clean_weights()

    e = ef.portfolio_performance(verbose=False)
    latest_prices = get_latest_prices(hist_data)
    da = DiscreteAllocation(cw, latest_prices, total_portfolio_value=amt)

    allocation, leftover = da.lp_portfolio()

    return {
        "orignal_port_volatility": str(round(port_volatility, 3) * 100) + "%",
        "orignal_annual_return":
        str(round(port_simple_annual_return, 3) * 100) + "%",
        "new_port_volatility": str(round(e[1], 3) * 100) + "%",
        "new_annual_return": str(round(e[0], 3) * 100) + "%",
        "Allocation": cw,
        "AllocationNo": allocation,
        "Left_Amount": str(round(leftover, 2))
    }
def run_allocation(date, duration):
    df = pd.DataFrame(columns=symbols)
    for symbol in symbols:
        try:
            data = get_all_binance(symbol, date, duration, save=False)
            df[symbol] = data["close"]

        except BinanceAPIException:
            print("Symbol was : " + symbol)

    df = df.apply(pd.to_numeric)
    df.fillna(0)
    print(df)
    mu = mean_historical_return(df)
    S = CovarianceShrinkage(df).ledoit_wolf()

    ef = EfficientFrontier(mu, S)

    weights = ef.max_sharpe()

    #aws, graphql, table'a ekle

    cleaned_weights = ef.clean_weights()
    print(ef.portfolio_performance(verbose=True))
    lists = sorted(weights.items())  # sorted by key, return a list of tuples
    lists = {x: y for x, y in lists if y > 0}

    f = open("Coin" + duration + ".txt", "w")
    f.write(str(lists))
    f.close()
    print(weights)
    s3 = boto3.client('s3')
    with open("Coin" + duration + ".txt", "rb") as f:
        s3.upload_fileobj(f, "model-predictions", "Coin" + duration + ".txt")
def test_greedy_portfolio_allocation():
    df = get_data()
    mu = mean_historical_return(df)
    S = sample_cov(df)
    ef = EfficientFrontier(mu, S)
    w = ef.max_sharpe()

    latest_prices = get_latest_prices(df)
    da = DiscreteAllocation(w, latest_prices, short_ratio=0.3)
    allocation, leftover = da.greedy_portfolio()

    assert allocation == {
        "MA": 20,
        "FB": 12,
        "PFE": 54,
        "BABA": 4,
        "AAPL": 4,
        "BBY": 2,
        "SBUX": 1,
        "GOOG": 1,
    }

    total = 0
    for ticker, num in allocation.items():
        total += num * latest_prices[ticker]
    np.testing.assert_almost_equal(total + leftover, 10000, decimal=4)

    # Cover the verbose parameter,
    allocation_verbose, leftover_verbose = da.greedy_portfolio(verbose=True)
    assert allocation_verbose == allocation
    assert leftover_verbose == leftover
 def asset_allocation(tickers, start_date):
     today = pd.datetime.today()
     if start_date == '1y':
         delta = today - pd.DateOffset(years=1)
         delta = delta.date()
         delta = delta.strftime('%Y-%m-%d')
     elif start_date == '3y':
         delta = today - pd.DateOffset(years=3)
         delta = delta.date()
         delta = delta.strftime('%Y-%m-%d')
     elif start_date == '5y':
         delta = today - pd.DateOffset(years=5)
         delta = delta.date()
         delta = delta.strftime('%Y-%m-%d')
     elif start_date == '10y':
         delta = today - pd.DateOffset(years=10)
         delta = delta.date()
         delta = delta.strftime('%Y-%m-%d')
     elif start_date == 'max':
         delta = today - pd.DateOffset(years=30)
         delta = delta.date()
         delta = delta.strftime('%Y-%m-%d')
     prices = ffn.get(tickers, start=delta)
     mu = expected_returns.mean_historical_return(prices)
     S = risk_models.sample_cov(prices)
     ef = EfficientFrontier(mu, S)
     raw_weights = ef.max_sharpe()
     cleaned_weights = ef.clean_weights()
     latest_prices = discrete_allocation.get_latest_prices(prices)
     da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value=amount)
     allocation, leftover = da.lp_portfolio()
     st.subheader('Asset Allocation breakdown: ')
     st.write(allocation)
     st.write("Funds remaining: ${:.2f}".format(leftover))
Exemple #18
0
def ef_risk_strategy(returns=None, cov_matrix=None, target_volatility=5.0):
    assert returns is not None
    assert cov_matrix is not None
    ef = EfficientFrontier(returns, cov_matrix)
    ef.add_objective(objective_functions.L2_reg, gamma=0.1)
    weights = ef.efficient_risk(target_volatility=target_volatility)
    return weights, portfolio_performance(ef), ef
Exemple #19
0
def ef_sharpe_strategy(returns=None, cov_matrix=None):
    assert returns is not None
    ef = EfficientFrontier(returns, cov_matrix)
    ef.add_objective(objective_functions.L2_reg,
                     gamma=0.1)  # eliminate minor weights
    weights = ef.max_sharpe()
    return weights, portfolio_performance(ef), ef
Exemple #20
0
def max_sharpe_multi(ticker_list, time='1d', cash=10000000):
    data = yf.download(ticker_list, period='10y', interval=time)
    if len(ticker_list) > 1:
        data = yf.download(ticker_list,
                           period='10y',
                           interval=time,
                           group_by='ticker')
    new_data = []
    df = pd.DataFrame()
    weight = 1 / len(ticker_list)
    for i in ticker_list:
        stock_normal_ret = data['Close'] / data.iloc[0]['Close']
        df[i] = data['Close']
        if len(ticker_list) > 1:
            stock_normal_ret = data[i]['Close'] / data[i].iloc[0]['Close']
            df[i] = data[i]['Close']
        alloc = stock_normal_ret * weight
        balance = alloc * cash
        new_data.append(balance)

    mu = expected_returns.mean_historical_return(df)
    s = risk_models.sample_cov(df)
    ef = EfficientFrontier(mu, s)
    weights = ef.max_sharpe()
    cleaned_weights = ef.clean_weights()
    x = ef.portfolio_performance(verbose=True)
    return cleaned_weights, round(2.5 * x[2] / 15, 3)  # sharpe adjusted weight
def test_custom_lower_bound():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(0.02, 1)
    )
    ef.max_sharpe()
    assert ef.weights.min() >= 0.02
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
Exemple #22
0
def get_momentum_stocks(df, date, portfolio_size, cash):
    # Convert dates and filter all momentum scores to include only top `portfolio_size` movers
    df_top_movers = df.loc[df['date'] == pd.to_datetime(date)]
    df_top_movers = df_top_movers.sort_values(by='momentum', ascending=False).head(portfolio_size)

    # Create a universe of top momentum stocks
    universe = df_top_movers['symbol'].tolist()

    # Create universe as DF for these stocks
    df_universe_top_movers = df.loc[df['symbol'].isin(universe)]

    # Create pre-optimzed portfolio
    df_universe_top_movers = df_universe_top_movers.pivot_table(
        index='date', 
        columns='symbol',
        values='close',
        aggfunc='sum')

    # Calculate expected returns and sample covariance
    mu = expected_returns.mean_historical_return(df_universe_top_movers)
    S = risk_models.sample_cov(df_universe_top_movers)

    # Optimize by Sharpe Ratio
    ef = EfficientFrontier(mu, S, gamma=1) # Use regularization (gamma=1)
    weights = ef.max_sharpe()
    cleaned_weights = ef.clean_weights()

    # Allocate
    latest_prices = get_latest_prices(df_universe_top_movers)

    allocated = DiscreteAllocation(
        cleaned_weights,
        latest_prices,
        total_portfolio_value=cash)

    allocation = allocated.lp_portfolio()[0]

    # Put the stocks and the number of shares from the portfolio into a df
    symbols = []
    num_shares = []

    for sym, shares in allocation.items():
        symbols.append(sym)
        num_shares.append(shares)

    # Create the to-buy dataframe
    df_buy = df.loc[df['symbol'].isin(symbols)]

    # Filter out irrelevant dates
    df_buy = df_buy.loc[df_buy['date'] == date].sort_values(by='symbol')

    # Add quantity allocations into dataframe
    df_buy['qty'] = num_shares # has thrown -> ValueError

    # Calculate the new/desired equity for each stock
    df_buy['equity'] = df_buy['close'] * df_buy['qty']
    df_buy = df_buy.loc[df_buy['qty'] != 0]

    return df_buy
def test_custom_upper_bound():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(0, 0.10)
    )
    ef.max_sharpe()
    ef.portfolio_performance()
    assert ef.weights.max() <= 0.1
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
Exemple #24
0
 def new_w(self, new_pred, date):
     new_ret = self.train_ret.append(new_pred)
     new_vcv = new_ret.cov()
     new_mu = new_ret.mean()
     eff = EfficientFrontier(expected_returns=new_mu,
                             cov_matrix=new_vcv,
                             weight_bounds=self.w_bounds)
     return pd.DataFrame(eff.max_sharpe(risk_free_rate=0), index=[date])
Exemple #25
0
def markowitz(tickers, start=None, end=None, regularize=False):
    prices = load_prices(tickers, start, end)
    mu = expected_returns.mean_historical_return(prices, frequency=12)
    S = risk_models.sample_cov(prices, frequency=12)
    ef = EfficientFrontier(mu, S)
    if regularize:
        ef.gamma = 1
    return ef
Exemple #26
0
 def calculate(self, date, universe):
     prices = universe.pricing['price'].unstack()[self.assets].iloc[-self.window:]
     mu = mean_historical_return(prices)
     S = CovarianceShrinkage(prices).ledoit_wolf()
     ef = EfficientFrontier(mu, S)
     weights = ef.min_volatility()
     weights = pd.Series(weights, index=self.assets)
     return weights
def test_efficient_frontier_init_errors():
    df = get_data()
    mean_returns = df.pct_change().dropna(how="all").mean()
    with pytest.raises(TypeError):
        EfficientFrontier("test", "string")

    with pytest.raises(TypeError):
        EfficientFrontier(mean_returns, mean_returns)
Exemple #28
0
    def min_CVaR(self):
        prices = self.prices
        returns = self.returns
        cov = self.covariance

        ef = EfficientFrontier(None, cov)
        optimal_weights = ef.custom_objective(negative_cvar, returns)
        return optimal_weights, None
Exemple #29
0
def ef_sharpe_strategy(ld: LazyDictionary, **kwargs) -> None:
    ef = EfficientFrontier(
        expected_returns=kwargs.get("returns"),
        cov_matrix=kwargs.get("cov_matrix", None),
    )
    ef.add_objective(objective_functions.L2_reg,
                     gamma=0.1)  # eliminate minor weights
    ld["optimizer"] = ef
    ld["raw_weights"] = lambda ld: ld["optimizer"].max_sharpe()
Exemple #30
0
 def __init__(self, dfs, on='date', rf=0.02):
     df = reduce(lambda left, right: pd.merge(left, right, on=on), dfs)
     df_pct = df.pct_change()
     self.prices = df
     self.mu = expected_returns.mean_historical_return(df)
     self.rf = rf
     self.S = risk_models.sample_cov(df)
     self.ef = EfficientFrontier(self.mu, self.S)
     self.ef.max_sharpe(risk_free_rate=rf)
Exemple #31
0
def test_bounds_errors():
    with pytest.raises(ValueError):
        EfficientFrontier(*setup_efficient_frontier(data_only=True),
                          weight_bounds=(0.06, 1))
    assert EfficientFrontier(*setup_efficient_frontier(data_only=True),
                             weight_bounds=(0, 1))

    with pytest.raises(ValueError):
        EfficientFrontier(*setup_efficient_frontier(data_only=True),
                          weight_bounds=(0.06, 1, 3))
Exemple #32
0
    def __init__(self, dataframe):

        self.dataframe = dataframe
        # Calculate expected returns and sample covariance
        self.mu = expected_returns.mean_historical_return(self.dataframe)
        self.S = risk_models.sample_cov(self.dataframe)
        # Optimise for maximal Sharpe ratio
        self.ef = EfficientFrontier(self.mu, self.S)
        self.weights = self.ef.max_sharpe()
        self.ef.portfolio_performance(verbose=True)
def test_clean_weights_short():
    ef = setup_efficient_frontier()
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)
    )
    ef.max_sharpe()
    # In practice we would never use such a high cutoff
    number_tiny_weights = sum(np.abs(ef.weights) < 0.05)
    cleaned = ef.clean_weights(cutoff=0.05)
    cleaned_weights = cleaned.values()
    clean_number_tiny_weights = sum(abs(i) < 0.05 for i in cleaned_weights)
    assert clean_number_tiny_weights == number_tiny_weights
def test_max_sharpe_input_errors():
    with pytest.raises(ValueError):
        ef = EfficientFrontier(
            *setup_efficient_frontier(data_only=True), gamma="2"
        )

    with warnings.catch_warnings(record=True) as w:
        ef = EfficientFrontier(
            *setup_efficient_frontier(data_only=True), gamma=-1)
        assert len(w) == 1
        assert issubclass(w[0].category, UserWarning)
        assert (
            str(w[0].message)
            == "in most cases, gamma should be positive"
        )

    with pytest.raises(ValueError):
        ef.max_sharpe(risk_free_rate="0.2")
def test_efficient_return_short():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
    )
    w = ef.efficient_return(0.25)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(), (0.25, 0.168264744226909, 1.3640929002973508)
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_portfolio_allocation_errors():
    df = get_data()
    e_ret = mean_historical_return(df)
    cov = sample_cov(df)
    ef = EfficientFrontier(e_ret, cov)
    w = ef.max_sharpe()
    latest_prices = discrete_allocation.get_latest_prices(df)

    with pytest.raises(TypeError):
        discrete_allocation.portfolio(ef.weights, latest_prices)

    with pytest.raises(TypeError):
        discrete_allocation.portfolio(w, latest_prices.values.tolist())

    with pytest.raises(ValueError):
        discrete_allocation.portfolio(w, latest_prices, min_allocation=0.5)

    with pytest.raises(ValueError):
        discrete_allocation.portfolio(w, latest_prices, total_portfolio_value=0)
def test_max_sharpe_short():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
    )
    w = ef.max_sharpe()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.40723757138191374, 0.24823079451957306, 1.5524922427959371),
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.max_sharpe()
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_efficient_return_market_neutral():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)
    )
    w = ef.efficient_return(0.25, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_almost_equal(
        ef.portfolio_performance(),
        (0.25, 0.20567621957041887, 1.1087335497769277)
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]
    assert long_only_sharpe > sharpe
def test_efficient_risk_market_neutral():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1)
    )
    w = ef.efficient_risk(0.19, market_neutral=True)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 0)
    assert (ef.weights < 1).all() and (ef.weights > -1).all()
    np.testing.assert_almost_equal(
        ef.portfolio_performance(),
        (0.2309497469661495, 0.19000021138101422, 1.1021245569881066)
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]
    assert long_only_sharpe > sharpe
def test_min_volatility_short():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
    )
    w = ef.min_volatility()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.1719799158957379, 0.15559547854162945, 0.9734986722620801),
    )

    # Shorting should reduce volatility
    volatility = ef.portfolio_performance()[1]
    ef_long_only = setup_efficient_frontier()
    ef_long_only.min_volatility()
    long_only_volatility = ef_long_only.portfolio_performance()[1]
    assert volatility < long_only_volatility
def test_max_sharpe_L2_reg_with_shorts():
    ef_no_reg = setup_efficient_frontier()
    ef_no_reg.max_sharpe()
    initial_number = sum(ef_no_reg.weights > 0.01)

    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
    )
    ef.gamma = 1
    w = ef.max_sharpe()
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.3236047844566581, 0.20241509723550233, 1.4969817524033966),
    )
    new_number = sum(ef.weights > 0.01)
    assert new_number >= initial_number
def test_efficient_risk_short():
    ef = EfficientFrontier(
        *setup_efficient_frontier(data_only=True), weight_bounds=(None, None)
    )
    w = ef.efficient_risk(0.19)
    assert isinstance(w, dict)
    assert set(w.keys()) == set(ef.tickers)
    assert set(w.keys()) == set(ef.expected_returns.index)
    np.testing.assert_almost_equal(ef.weights.sum(), 1)
    np.testing.assert_allclose(
        ef.portfolio_performance(),
        (0.30468522897560224, 0.19, 1.4947624032507056),
        atol=1e6,
    )
    sharpe = ef.portfolio_performance()[2]

    ef_long_only = setup_efficient_frontier()
    ef_long_only.efficient_return(0.25)
    long_only_sharpe = ef_long_only.portfolio_performance()[2]

    assert sharpe > long_only_sharpe
def test_portfolio_allocation():
    df = get_data()
    e_ret = mean_historical_return(df)
    cov = sample_cov(df)
    ef = EfficientFrontier(e_ret, cov)
    w = ef.max_sharpe()

    latest_prices = discrete_allocation.get_latest_prices(df)
    allocation, leftover = discrete_allocation.portfolio(w, latest_prices)
    assert allocation == {
        "MA": 14,
        "FB": 12,
        "PFE": 51,
        "BABA": 5,
        "AAPL": 5,
        "AMZN": 0,
        "BBY": 9,
        "SBUX": 6,
        "GOOG": 1,
    }
    total = 0
    for ticker, num in allocation.items():
        total += num * latest_prices[ticker]
    np.testing.assert_almost_equal(total + leftover, 10000)
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
from pypfopt.hierarchical_risk_parity import hrp_portfolio
from pypfopt.value_at_risk import CVAROpt
from pypfopt import discrete_allocation


# Reading in the data; preparing expected returns and a risk model
df = pd.read_csv("tests/stock_prices.csv", parse_dates=True, index_col="date")
returns = df.pct_change().dropna(how="all")
mu = expected_returns.mean_historical_return(df)
S = risk_models.sample_cov(df)

# Long-only Maximum Sharpe portfolio, with discretised weights
ef = EfficientFrontier(mu, S)
weights = ef.max_sharpe()
ef.portfolio_performance(verbose=True)
latest_prices = discrete_allocation.get_latest_prices(df)
allocation, leftover = discrete_allocation.portfolio(weights, latest_prices)
print("Discrete allocation:", allocation)
print("Funds remaining: ${:.2f}".format(leftover))

"""
Expected annual return: 33.0%
Annual volatility: 21.7%
Sharpe Ratio: 1.43

Discrete allocation: {'MA': 14, 'FB': 12, 'PFE': 51, 'BABA': 5, 'AAPL': 5,
                      'AMZN': 0, 'BBY': 9, 'SBUX': 6, 'GOOG': 1}
Funds remaining: $12.15