mirror of
https://github.com/robertmartin8/PyPortfolioOpt.git
synced 2022-11-27 18:02:41 +03:00
Make Verbose Option a Hidden API
This commit is contained in:
@@ -132,7 +132,8 @@ raw_weights = ef.max_sharpe()
|
||||
cleaned_weights = ef.clean_weights()
|
||||
ef.save_weights_to_file("weights.csv") # saves to file
|
||||
print(cleaned_weights)
|
||||
ef.portfolio_performance(verbose=True)
|
||||
ef.verbose = True
|
||||
ef.portfolio_performance()
|
||||
```
|
||||
|
||||
This outputs the following weights:
|
||||
|
||||
@@ -930,7 +930,8 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef.portfolio_performance(verbose=True);"
|
||||
"ef.verbose = True\n",
|
||||
"ef.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1255,7 +1256,8 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef.portfolio_performance(verbose=True);"
|
||||
"ef.verbose = True\n",
|
||||
"ef.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1417,7 +1419,8 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef.portfolio_performance(verbose=True);"
|
||||
"ef.verbose = True\n",
|
||||
"ef.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1491,7 +1494,8 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef.portfolio_performance(verbose=True);"
|
||||
"ef.verbose = True\n",
|
||||
"ef.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1562,4 +1566,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
}
|
||||
@@ -556,7 +556,8 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef.portfolio_performance(verbose=True);"
|
||||
"ef.verbose = True\n",
|
||||
"ef.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -685,7 +686,8 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"ef.portfolio_performance(verbose=True);"
|
||||
"ef.verbose = True\n",
|
||||
"ef.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1165,4 +1167,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,8 @@
|
||||
"returns = risk_models.returns_from_prices(df)\n",
|
||||
"hrp = HRPOpt(returns)\n",
|
||||
"weights = hrp.optimize()\n",
|
||||
"hrp.portfolio_performance(verbose=True);"
|
||||
"hrp.verbose = True\n",
|
||||
"hrp.portfolio_performance();"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -85,4 +86,4 @@
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ the main difficulty is inputting our specific problem into a solver.
|
||||
|
||||
PyPortfolioOpt aims to do the hard work for you, allowing for one-liners like ``ef.min_volatility()``
|
||||
to generate a portfolio that minimises the volatility, while at the same time allowing for more
|
||||
complex problems to be built up from modular units. This is all possible thanks to
|
||||
complex problems to be built up from modular units. This is all possible thanks to
|
||||
`cvxpy <https://www.cvxpy.org/>`_, the *fantastic* python-embedded modelling
|
||||
language for convex optimisation upon which PyPortfolioOpt's efficient frontier functionality lies.
|
||||
|
||||
@@ -47,7 +47,7 @@ the optimisation objective, and the optimisation constraints. For example, the c
|
||||
optimisation problem is to **minimise risk** subject to a **return constraint** (i.e the portfolio
|
||||
must return more than a certain amount). From an implementation perspective, however, there is
|
||||
not much difference between an objective and a constraint. Consider a similar problem, which is to
|
||||
**maximize return** subject to a **risk constraint** -- now, the role of risk and return have swapped.
|
||||
**maximize return** subject to a **risk constraint** -- now, the role of risk and return have swapped.
|
||||
|
||||
To that end, PyPortfolioOpt defines an :py:mod:`objective_functions` module that contains objective functions
|
||||
(which can also act as constraints, as we have just seen). The actual optimisation occurs in the :py:class:`efficient_frontier.EfficientFrontier` class.
|
||||
@@ -61,7 +61,7 @@ For example, adding a regularisation objective (explained below) to a minimum vo
|
||||
ef.min_volatility() # find the portfolio that minimises volatility and L2_reg
|
||||
|
||||
.. tip::
|
||||
|
||||
|
||||
If you would like to plot the efficient frontier, take a look at the :ref:`plotting` module.
|
||||
|
||||
Basic Usage
|
||||
@@ -90,7 +90,7 @@ Basic Usage
|
||||
.. caution::
|
||||
|
||||
Because ``max_sharpe()`` makes a variable substitution, additional objectives may
|
||||
not work as intended.
|
||||
not work as intended.
|
||||
|
||||
|
||||
.. automethod:: max_quadratic_utility
|
||||
@@ -116,19 +116,19 @@ Basic Usage
|
||||
.. tip::
|
||||
|
||||
If you would like to use the ``portfolio_performance`` function independently of any
|
||||
optimiser (e.g for debugging purposes), you can use::
|
||||
optimiser (e.g for debugging purposes), you can use::
|
||||
|
||||
from pypfopt import base_optimizer
|
||||
|
||||
base_optimizer.portfolio_performance(
|
||||
weights, expected_returns, cov_matrix, verbose=True, risk_free_rate=0.02
|
||||
weights, expected_returns, cov_matrix, risk_free_rate=0.02
|
||||
)
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
PyPortfolioOpt defers to cvxpy's default choice of solver. If you would like to explicitly
|
||||
choose the solver and see verbose output, simply assign ``ef.solver = "ECOS"`` prior to calling
|
||||
the actual optimisation method. You can choose from any of the `supported solvers <https://www.cvxpy.org/tutorial/advanced/index.html#choosing-a-solver>`_.
|
||||
choose the solver, simply assign ``ef.solver = "ECOS"`` prior to calling the actual optimisation
|
||||
method. You can choose from any of the `supported solvers <https://www.cvxpy.org/tutorial/advanced/index.html#choosing-a-solver>`_.
|
||||
|
||||
Adding objectives and constraints
|
||||
=================================
|
||||
@@ -213,7 +213,7 @@ different API. For examples, check out this `cookbook recipe <https://github.com
|
||||
.. class:: pypfopt.base_optimizer.BaseConvexOptimizer
|
||||
|
||||
.. automethod:: convex_objective
|
||||
|
||||
|
||||
.. automethod:: nonconvex_objective
|
||||
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ portfolio) – the set of all these optimal portfolios is referred to as the
|
||||
|
||||
.. image:: ../media/efficient_frontier.png
|
||||
:align: center
|
||||
:alt: risk-return characteristics of possible portfolios
|
||||
:alt: risk-return characteristics of possible portfolios
|
||||
|
||||
Each dot on this diagram represents a different possible portfolio, with darker blue
|
||||
corresponding to 'better' portfolios (in terms of the Sharpe Ratio). The dotted
|
||||
@@ -178,7 +178,8 @@ This prints::
|
||||
If we want to know the expected performance of the portfolio with optimal
|
||||
weights ``w``, we can use the :py:meth:`portfolio_performance` method::
|
||||
|
||||
ef.portfolio_performance(verbose=True)
|
||||
ef.verbose = True
|
||||
ef.portfolio_performance()
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ The alternative is to clone/download the project, then in the project directory
|
||||
|
||||
python setup.py install
|
||||
|
||||
Thanks to Thomas Schmelzer, PyPortfolioOpt now supports Docker (requires
|
||||
**make**, **docker**, **docker-compose**). Build your first container with
|
||||
Thanks to Thomas Schmelzer, PyPortfolioOpt now supports Docker (requires
|
||||
**make**, **docker**, **docker-compose**). Build your first container with
|
||||
``make build``; run tests with ``make test``. For more information, please read
|
||||
`this guide <https://docker-curriculum.com/#introduction>`_.
|
||||
|
||||
@@ -131,7 +131,8 @@ that's fine too::
|
||||
# Optimise for maximal Sharpe ratio
|
||||
ef = EfficientFrontier(mu, S)
|
||||
weights = ef.max_sharpe()
|
||||
ef.portfolio_performance(verbose=True)
|
||||
ef.verbose = True
|
||||
ef.portfolio_performance()
|
||||
|
||||
This outputs the following:
|
||||
|
||||
@@ -159,7 +160,7 @@ Contents
|
||||
|
||||
.. toctree::
|
||||
:caption: Other information
|
||||
|
||||
|
||||
Roadmap
|
||||
Contributing
|
||||
About
|
||||
|
||||
12
examples.py
12
examples.py
@@ -28,7 +28,8 @@ def deviation_risk_parity(w, cov_matrix):
|
||||
|
||||
ef = EfficientFrontier(mu, S)
|
||||
weights = ef.nonconvex_objective(deviation_risk_parity, ef.cov_matrix)
|
||||
ef.portfolio_performance(verbose=True)
|
||||
ef.verbose = True
|
||||
ef.portfolio_performance()
|
||||
|
||||
"""
|
||||
Expected annual return: 22.9%
|
||||
@@ -82,7 +83,8 @@ rets = bl.bl_returns()
|
||||
ef = EfficientFrontier(rets, S)
|
||||
ef.max_sharpe()
|
||||
print(ef.clean_weights())
|
||||
ef.portfolio_performance(verbose=True)
|
||||
ef.verbose = True
|
||||
ef.portfolio_performance()
|
||||
|
||||
"""
|
||||
{'GOOG': 0.2015,
|
||||
@@ -115,7 +117,8 @@ Sharpe Ratio: 0.46
|
||||
# Hierarchical risk parity
|
||||
hrp = HRPOpt(returns)
|
||||
weights = hrp.optimize()
|
||||
hrp.portfolio_performance(verbose=True)
|
||||
hrp.verbose = True
|
||||
hrp.portfolio_performance()
|
||||
print(weights)
|
||||
plotting.plot_dendrogram(hrp) # to plot dendrogram
|
||||
|
||||
@@ -150,7 +153,8 @@ Sharpe Ratio: 0.66
|
||||
# Crticial Line Algorithm
|
||||
cla = CLA(mu, S)
|
||||
print(cla.max_sharpe())
|
||||
cla.portfolio_performance(verbose=True)
|
||||
cla.verbose = True
|
||||
cla.portfolio_performance()
|
||||
plotting.plot_efficient_frontier(cla) # to plot
|
||||
|
||||
"""
|
||||
|
||||
@@ -47,6 +47,7 @@ class BaseOptimizer:
|
||||
self.tickers = tickers
|
||||
# Outputs
|
||||
self.weights = None
|
||||
self.verbose = False
|
||||
|
||||
def _make_output_weights(self, weights=None):
|
||||
"""
|
||||
@@ -201,22 +202,20 @@ class BaseConvexOptimizer(BaseOptimizer):
|
||||
self._constraints.append(self._w >= self._lower_bounds)
|
||||
self._constraints.append(self._w <= self._upper_bounds)
|
||||
|
||||
def _solve_cvxpy_opt_problem(self, verbose=False):
|
||||
def _solve_cvxpy_opt_problem(self):
|
||||
"""
|
||||
Helper method to solve the cvxpy problem and check output,
|
||||
once objectives and constraints have been defined
|
||||
|
||||
:param verbose: whether performance should be printed, defaults to False
|
||||
:type verbose: bool, optional
|
||||
:raises exceptions.OptimizationError: if problem is not solvable by cvxpy
|
||||
"""
|
||||
try:
|
||||
opt = cp.Problem(cp.Minimize(self._objective), self._constraints)
|
||||
|
||||
if self.solver is not None:
|
||||
opt.solve(solver=self.solver, verbose=verbose)
|
||||
opt.solve(solver=self.solver, verbose=self.verbose)
|
||||
else:
|
||||
opt.solve(verbose=verbose)
|
||||
opt.solve(verbose=self.verbose)
|
||||
except (TypeError, cp.DCPError):
|
||||
raise exceptions.OptimizationError
|
||||
|
||||
@@ -299,7 +298,7 @@ class BaseConvexOptimizer(BaseOptimizer):
|
||||
is_sector = [sector_mapper[t] == sector for t in self.tickers]
|
||||
self._constraints.append(cp.sum(self._w[is_sector]) >= sector_lower[sector])
|
||||
|
||||
def convex_objective(self, custom_objective, weights_sum_to_one=True, verbose=False, **kwargs):
|
||||
def convex_objective(self, custom_objective, weights_sum_to_one=True, **kwargs):
|
||||
"""
|
||||
Optimise a custom convex objective function. Constraints should be added with
|
||||
``ef.add_constraint()``. Optimiser arguments must be passed as keyword-args. Example::
|
||||
@@ -316,8 +315,6 @@ class BaseConvexOptimizer(BaseOptimizer):
|
||||
:type custom_objective: function with signature (cp.Variable, `**kwargs`) -> cp.Expression
|
||||
:param weights_sum_to_one: whether to add the default objective, defaults to True
|
||||
:type weights_sum_to_one: bool, optional
|
||||
:param verbose: whether performance should be printed, defaults to False
|
||||
:type verbose: bool, optional
|
||||
:raises OptimizationError: if the objective is nonconvex or constraints nonlinear.
|
||||
:return: asset weights for the efficient risk portfolio
|
||||
:rtype: OrderedDict
|
||||
@@ -331,7 +328,7 @@ class BaseConvexOptimizer(BaseOptimizer):
|
||||
if weights_sum_to_one:
|
||||
self._constraints.append(cp.sum(self._w) == 1)
|
||||
|
||||
return self._solve_cvxpy_opt_problem(verbose=verbose)
|
||||
return self._solve_cvxpy_opt_problem()
|
||||
|
||||
def nonconvex_objective(
|
||||
self,
|
||||
|
||||
@@ -451,14 +451,12 @@ class BlackLittermanModel(base_optimizer.BaseOptimizer):
|
||||
"""
|
||||
return self.bl_weights(risk_aversion)
|
||||
|
||||
def portfolio_performance(self, verbose=False, risk_free_rate=0.02):
|
||||
def portfolio_performance(self, risk_free_rate=0.02):
|
||||
"""
|
||||
After optimising, calculate (and optionally print) the performance of the optimal
|
||||
portfolio. Currently calculates expected return, volatility, and the Sharpe ratio.
|
||||
This method uses the BL posterior returns and covariance matrix.
|
||||
|
||||
:param verbose: whether performance should be printed, defaults to False
|
||||
:type verbose: bool, optional
|
||||
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.02.
|
||||
The period of the risk-free rate should correspond to the
|
||||
frequency of expected returns.
|
||||
@@ -473,6 +471,6 @@ class BlackLittermanModel(base_optimizer.BaseOptimizer):
|
||||
self.weights,
|
||||
self.posterior_rets,
|
||||
self.posterior_cov,
|
||||
verbose,
|
||||
self.verbose,
|
||||
risk_free_rate,
|
||||
)
|
||||
|
||||
@@ -445,13 +445,11 @@ class CLA(base_optimizer.BaseOptimizer):
|
||||
# Overrides parent method since set_weights does nothing.
|
||||
raise NotImplementedError("set_weights does nothing for CLA")
|
||||
|
||||
def portfolio_performance(self, verbose=False, risk_free_rate=0.02):
|
||||
def portfolio_performance(self, risk_free_rate=0.02):
|
||||
"""
|
||||
After optimising, calculate (and optionally print) the performance of the optimal
|
||||
portfolio. Currently calculates expected return, volatility, and the Sharpe ratio.
|
||||
|
||||
:param verbose: whether performance should be printed, defaults to False
|
||||
:type verbose: bool, optional
|
||||
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.02
|
||||
:type risk_free_rate: float, optional
|
||||
:raises ValueError: if weights have not been calculated yet
|
||||
@@ -462,6 +460,6 @@ class CLA(base_optimizer.BaseOptimizer):
|
||||
self.weights,
|
||||
self.expected_returns,
|
||||
self.cov_matrix,
|
||||
verbose,
|
||||
self.verbose,
|
||||
risk_free_rate,
|
||||
)
|
||||
|
||||
@@ -134,7 +134,7 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
del self._constraints[0]
|
||||
del self._constraints[0]
|
||||
|
||||
def min_volatility(self, verbose=False):
|
||||
def min_volatility(self):
|
||||
"""
|
||||
Minimise volatility.
|
||||
|
||||
@@ -149,9 +149,9 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
|
||||
self._constraints.append(cp.sum(self._w) == 1)
|
||||
|
||||
return self._solve_cvxpy_opt_problem(verbose=verbose)
|
||||
return self._solve_cvxpy_opt_problem()
|
||||
|
||||
def max_sharpe(self, risk_free_rate=0.02, verbose=False):
|
||||
def max_sharpe(self, risk_free_rate=0.02):
|
||||
"""
|
||||
Maximise the Sharpe Ratio. The result is also referred to as the tangency portfolio,
|
||||
as it is the portfolio for which the capital market line is tangent to the efficient frontier.
|
||||
@@ -209,12 +209,12 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
k >= 0,
|
||||
] + new_constraints
|
||||
|
||||
self._solve_cvxpy_opt_problem(verbose=verbose)
|
||||
self._solve_cvxpy_opt_problem()
|
||||
# Inverse-transform
|
||||
self.weights = (self._w.value / k.value).round(16) + 0.0
|
||||
return self._make_output_weights()
|
||||
|
||||
def max_quadratic_utility(self, risk_aversion=1, market_neutral=False, verbose=False):
|
||||
def max_quadratic_utility(self, risk_aversion=1, market_neutral=False):
|
||||
r"""
|
||||
Maximise the given quadratic utility, i.e:
|
||||
|
||||
@@ -246,9 +246,9 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
else:
|
||||
self._constraints.append(cp.sum(self._w) == 1)
|
||||
|
||||
return self._solve_cvxpy_opt_problem(verbose=verbose)
|
||||
return self._solve_cvxpy_opt_problem()
|
||||
|
||||
def efficient_risk(self, target_volatility, market_neutral=False, verbose=False):
|
||||
def efficient_risk(self, target_volatility, market_neutral=False):
|
||||
"""
|
||||
Maximise return for a target risk. The resulting portfolio will have a volatility
|
||||
less than the target (but not guaranteed to be equal).
|
||||
@@ -285,9 +285,9 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
else:
|
||||
self._constraints.append(cp.sum(self._w) == 1)
|
||||
|
||||
return self._solve_cvxpy_opt_problem(verbose=verbose)
|
||||
return self._solve_cvxpy_opt_problem()
|
||||
|
||||
def efficient_return(self, target_return, market_neutral=False, verbose=False):
|
||||
def efficient_return(self, target_return, market_neutral=False):
|
||||
"""
|
||||
Calculate the 'Markowitz portfolio', minimising volatility for a given target return.
|
||||
|
||||
@@ -331,15 +331,13 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
else:
|
||||
self._constraints.append(cp.sum(self._w) == 1)
|
||||
|
||||
return self._solve_cvxpy_opt_problem(verbose=verbose)
|
||||
return self._solve_cvxpy_opt_problem()
|
||||
|
||||
def portfolio_performance(self, verbose=False, risk_free_rate=0.02):
|
||||
def portfolio_performance(self, risk_free_rate=0.02):
|
||||
"""
|
||||
After optimising, calculate (and optionally print) the performance of the optimal
|
||||
portfolio. Currently calculates expected return, volatility, and the Sharpe ratio.
|
||||
|
||||
:param verbose: whether performance should be printed, defaults to False
|
||||
:type verbose: bool, optional
|
||||
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.02.
|
||||
The period of the risk-free rate should correspond to the
|
||||
frequency of expected returns.
|
||||
@@ -352,6 +350,6 @@ class EfficientFrontier(base_optimizer.BaseConvexOptimizer):
|
||||
self.weights,
|
||||
self.expected_returns,
|
||||
self.cov_matrix,
|
||||
verbose,
|
||||
self.verbose,
|
||||
risk_free_rate,
|
||||
)
|
||||
|
||||
@@ -167,14 +167,12 @@ class HRPOpt(base_optimizer.BaseOptimizer):
|
||||
self.set_weights(weights)
|
||||
return weights
|
||||
|
||||
def portfolio_performance(self, verbose=False, risk_free_rate=0.02, frequency=252):
|
||||
def portfolio_performance(self, risk_free_rate=0.02, frequency=252):
|
||||
"""
|
||||
After optimising, calculate (and optionally print) the performance of the optimal
|
||||
portfolio. Currently calculates expected return, volatility, and the Sharpe ratio
|
||||
assuming returns are daily
|
||||
|
||||
:param verbose: whether performance should be printed, defaults to False
|
||||
:type verbose: bool, optional
|
||||
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.02.
|
||||
The period of the risk-free rate should correspond to the
|
||||
frequency of expected returns.
|
||||
@@ -194,5 +192,5 @@ class HRPOpt(base_optimizer.BaseOptimizer):
|
||||
mu = self.returns.mean() * frequency
|
||||
|
||||
return base_optimizer.portfolio_performance(
|
||||
self.weights, mu, cov, verbose, risk_free_rate
|
||||
self.weights, mu, cov, self.verbose, risk_free_rate
|
||||
)
|
||||
|
||||
@@ -214,6 +214,7 @@ def assert_verbose_option(optimize_for_method, *args, solver=None):
|
||||
# using a random number for `verbose` simply to test that what is received
|
||||
# by the method is passed on to Problem#solve
|
||||
verbose=random()
|
||||
ef.verbose = verbose
|
||||
|
||||
with patch("cvxpy.Problem.solve") as mock:
|
||||
with pytest.raises(exceptions.OptimizationError):
|
||||
@@ -221,7 +222,7 @@ def assert_verbose_option(optimize_for_method, *args, solver=None):
|
||||
# passes the verbose kwarg on to Problem#solve.
|
||||
# mocking Problem#solve causes EfficientFrontier#min_volatility to
|
||||
# raise an error, but it is safe to ignore it
|
||||
optimize_for_method(ef, *args, verbose=verbose)
|
||||
optimize_for_method(ef, *args)
|
||||
|
||||
# mock.assert_called_with(verbose=verbose) doesn't work here because
|
||||
# sometimes the mock is called with more kwargs. all we want to know is
|
||||
|
||||
@@ -208,7 +208,7 @@ def test_lp_allocation_rmse_error():
|
||||
latest_prices = get_latest_prices(df)
|
||||
da = DiscreteAllocation(w, latest_prices)
|
||||
da.lp_portfolio()
|
||||
np.testing.assert_almost_equal(da._allocation_rmse_error(verbose=False), 0.017070218149194846)
|
||||
np.testing.assert_almost_equal(da._allocation_rmse_error(), 0.017070218149194846)
|
||||
|
||||
|
||||
def test_lp_portfolio_allocation_short():
|
||||
@@ -310,18 +310,18 @@ def test_rmse_decreases_with_value():
|
||||
|
||||
da1 = DiscreteAllocation(w, latest_prices, total_portfolio_value=10000)
|
||||
da1.greedy_portfolio()
|
||||
rmse1 = da1._allocation_rmse_error(verbose=False)
|
||||
rmse1 = da1._allocation_rmse_error()
|
||||
da2 = DiscreteAllocation(w, latest_prices, total_portfolio_value=100000)
|
||||
da2.greedy_portfolio()
|
||||
rmse2 = da2._allocation_rmse_error(verbose=False)
|
||||
rmse2 = da2._allocation_rmse_error()
|
||||
assert rmse2 < rmse1
|
||||
|
||||
da3 = DiscreteAllocation(w, latest_prices, total_portfolio_value=10000)
|
||||
da3.lp_portfolio()
|
||||
rmse3 = da3._allocation_rmse_error(verbose=False)
|
||||
rmse3 = da3._allocation_rmse_error()
|
||||
da4 = DiscreteAllocation(w, latest_prices, total_portfolio_value=30000)
|
||||
da4.lp_portfolio()
|
||||
rmse4 = da4._allocation_rmse_error(verbose=False)
|
||||
rmse4 = da4._allocation_rmse_error()
|
||||
assert rmse4 < rmse3
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user