class amplpyfinance.DiscreteAllocation(weights, latest_prices, total_portfolio_value=10000, short_ratio=None)[source]

Generate a discrete portfolio allocation from continuous weights.

AMPL version of pypfopt.DiscreteAllocation with similar interface. This class is also available under the alias amplpyfinance.DiscreteAllocationWithAMPL in order to distinguish from pypfopt.DiscreteAllocation if used together.

Instance variables:

  • Inputs:

    • weights - dict

    • latest_prices - pd.Series or dict

    • total_portfolio_value - int/float

    • short_ratio- float

  • Output: allocation - dict

Public methods:

  • greedy_portfolio() - uses a greedy algorithm

  • lp_portfolio() - uses linear programming

__init__(weights, latest_prices, total_portfolio_value=10000, short_ratio=None)[source]
  • weights (dict) – continuous weights generated from the efficient_frontier module

  • latest_prices (pd.Series) – the most recent price for each asset

  • total_portfolio_value (int/float, optional) – the desired total value of the portfolio, defaults to 10000

  • short_ratio (float, defaults to None.) – the short ratio, e.g 0.3 corresponds to 130/30. If None, defaults to the input weights.

  • TypeError – if weights is not a dict

  • TypeError – if latest_prices isn’t a series

  • ValueError – if short_ratio < 0

lp_portfolio(reinvest=False, verbose=False, solver='gurobi', solver_options=None)[source]

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

Model from pypfopt:

  • \(T \in \mathbb{R}\) is the total dollar value to be allocated

  • \(p \in \mathbb{R}^n\) is the array of latest prices

  • \(w \in \mathbb{R}^n\) is the set of target weights

  • \(x \in \mathbb{Z}^n\) is the integer allocation (i.e the result)

  • \(r \in \mathbb{R}\) is the remaining unallocated value, i.e \(r = T - x \cdot p\).

The optimization problem is then given by:

\[\begin{split}\begin{equation*} \begin{aligned} & \underset{x \in \mathbb{Z}^n}{\text{minimize}} & & r + \lVert wT - x \odot p \rVert_1 \\ & \text{subject to} & & r + x \cdot p = T\\ \end{aligned} \end{equation*}\end{split}\]

Corresponding AMPL code:

param n;
param p{1..n};
param w{1..n};
param total_portfolio_value;

var x{1..n} >= 0 integer;
var u{1..n} >= 0;
var r >= 0;

minimize objective:
    r + sum{i in 1..n} u[i];

s.t. norm1{i in 1..n}:
    u[i] >= w[i] * total_portfolio_value - x[i] * p[i];
s.t. norm2{i in 1..n}:
    -u[i] <= w[i] * total_portfolio_value - x[i] * p[i];
s.t. total_value:
    r + sum{i in 1..n} x[i] * p[i] = total_portfolio_value;
ampl.param["n"] = len(latest_prices)
ampl.param["p"] = latest_prices
ampl.param["w"] = weights
ampl.param["total_portfolio_value"] = total_portfolio_value

AMPL version of pypfopt.DiscreteAllocation.lp_portfolio() with similar interface:

  • reinvest (bool, defaults to False) – whether or not to reinvest cash gained from shorting

  • verbose (bool) – print error analysis?

  • solver (str) – name of the AMPL solver to use.

  • solver_options (str) – options for the given solver


the number of shares of each ticker that should be purchased, along with the amount of funds leftover.

Return type

(dict, float)

__module__ = 'amplpyfinance.discrete_allocation'