def portfolio_byvalue(<EOL>weights, steps, min_values, max_values=<NUM_LIT>, total_portfolio_value=<NUM_LIT><EOL>):
import pulp<EOL>if not isinstance(weights, dict):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if total_portfolio_value <= <NUM_LIT:0>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>if isinstance(steps, numbers.Real):<EOL><INDENT>steps = {k: steps for k in weights}<EOL><DEDENT>if isinstance(min_values, numbers.Real):<EOL><INDENT>min_values = {k: min_values for k in weights}<EOL><DEDENT>if isinstance(max_values, numbers.Real):<EOL><INDENT>max_values = {k: max_values for k in weights}<EOL><DEDENT>m = pulp.LpProblem("<STR_LIT>", pulp.LpMinimize)<EOL>vals = {}<EOL>realvals = {}<EOL>usevals = {}<EOL>etas = {}<EOL>abss = {}<EOL>remaining = pulp.LpVariable("<STR_LIT>", <NUM_LIT:0>)<EOL>for k, w in weights.items():<EOL><INDENT>if steps.get(k):<EOL><INDENT>vals[k] = pulp.LpVariable("<STR_LIT>" % k, <NUM_LIT:0>, cat="<STR_LIT>")<EOL>realvals[k] = steps[k] * vals[k]<EOL>etas[k] = w * total_portfolio_value - realvals[k]<EOL><DEDENT>else:<EOL><INDENT>realvals[k] = vals[k] = pulp.LpVariable("<STR_LIT>" % k, <NUM_LIT:0>)<EOL>etas[k] = w * total_portfolio_value - vals[k]<EOL><DEDENT>abss[k] = pulp.LpVariable("<STR_LIT>" % k, <NUM_LIT:0>)<EOL>usevals[k] = pulp.LpVariable("<STR_LIT>" % k, cat="<STR_LIT>")<EOL>m += etas[k] <= abss[k]<EOL>m += -etas[k] <= abss[k]<EOL>m += realvals[k] >= usevals[k] * min_values.get(k, steps.get(k, <NUM_LIT:0>))<EOL>m += realvals[k] <= usevals[k] * max_values.get(k, <NUM_LIT>)<EOL><DEDENT>m += remaining == total_portfolio_value - pulp.lpSum(realvals.values())<EOL>m += pulp.lpSum(abss.values()) + remaining<EOL>m.solve()<EOL>results = {k: pulp.value(val) for k, val in realvals.items()}<EOL>return results, remaining.varValue<EOL>
For a long only portfolio, convert the continuous weights to a discrete
allocation using Mixed Integer Linear Programming. This function assumes
that we buy some asset based on value instead of shares, and there is a
limit of minimum value and increasing step.

:param weights: continuous weights generated from the ``efficient_frontier`` module
:type weights: dict
:param min_values: the minimum value for each asset
:type min_values: int/float or dict
:param max_values: the maximum value for each asset
:type max_values: int/float or dict
:param steps: the minimum value increase for each asset
:type steps: int/float or dict
:param total_portfolio_value: the desired total value of the portfolio, defaults to 10000
:type total_portfolio_value: int/float, optional
:raises TypeError: if ``weights`` is not a dict
:return: the number of value of each ticker that should be purchased,
along with the amount of funds leftover.
:rtype: (dict, float)