# Post-processing weights¶

After optimal weights have been generated, it is often necessary to do some post-processing before they can be used practically. In particular, you are likely using portfolio optimisation techniques to generate a portfolio allocation – a list of tickers and corresponding integer quantities that you could go and purchase at a broker.

However, it is not trivial to convert the continuous weights (output by any of our optimisation methods) into an actionable allocation. For example, let us say that we have $10,000 that we would like to allocate. If we multiply the weights by this total portfolio value, the result will be dollar amounts of each asset. So if the optimal weight for Apple is 0.15, we need$1500 worth of Apple stock. However, Apple shares come in discrete units ($190 at the time of writing), so we will not be able to buy exactly$1500 of stock. The best we can do is to buy the number of shares that gets us closest to the desired dollar value.

PyPortfolioOpt offers two ways of solving this problem: one using a simple greedy algorithm, the other using integer programming.

## Usage¶

The discrete_allocation module contains the DiscreteAllocation class, which offers multile methods to generate a discrete portfolio allocation from continuous weights.

class pypfopt.discrete_allocation.DiscreteAllocation(weights, latest_prices, min_allocation=0.01, total_portfolio_value=10000, short_ratio=0.3)

Generate a discrete portfolio allocation from continuous weights

Instance variables:

• Inputs:

• weights
• latest_prices
• min_allocation
• total_portfolio_value
• short_ratio
• Output: allocation

Public methods:

• greedy_portfolio()
• lp_portfolio()
__init__(weights, latest_prices, min_allocation=0.01, total_portfolio_value=10000, short_ratio=0.3)
Parameters: weights (dict) – continuous weights generated from the efficient_frontier module latest_prices (pd.Series or dict) – the most recent price for each asset min_allocation (float, optional) – any weights less than this number are considered negligible, defaults to 0.01 total_portfolio_value (int/float, optional) – the desired total value of the portfolio, defaults to 10000 short_ratio (float) – the short ratio, e.g 0.3 corresponds to 130/30 TypeError – if weights is not a dict TypeError – if latest_prices isn’t a series ValueError – if not 0 < min_allocation < 0.3 ValueError – if short_ratio < 0
_allocation_rmse_error(verbose=True)

Utility function to calculate and print RMSE error between discretised weights and continuous weights. RMSE was usen instead of MAE because we want to penalise large variations.

Parameters: verbose (bool) – print weight discrepancies? rmse error float
greedy_portfolio(verbose=False)

Convert continuous weights into a discrete portfolio allocation using a greedy iterative approach.

Parameters: verbose (bool) – print error analysis? the number of shares of each ticker that should be purchased, along with the amount of funds leftover. (dict, float)
lp_portfolio(verbose=False)

Convert continuous weights into a discrete portfolio allocation using integer programming.

Parameters: verbose (bool) – print error analysis? the number of shares of each ticker that should be purchased, along with the amount of funds leftover. (dict, float)