diff --git a/backtest.py b/backtest.py index 6054b07..c0f96d2 100644 --- a/backtest.py +++ b/backtest.py @@ -26,6 +26,8 @@ inital_holdings = {} inital_cash = 10_000 +# TODO: Should be in a universe class maybe... +instrument_mapping = {} for id, ticker in enumerate(sorted(TEST_YAHOO_STOCK_UNIVERSE_8)): file = f"tests/data/{ticker}.csv" time_series = pd.read_csv(file, index_col='Date') @@ -34,12 +36,13 @@ instruments.append(ins) initial_weights[ins] = 1 / len(TEST_YAHOO_STOCK_UNIVERSE_8) inital_holdings[ins] = 10 + instrument_mapping[ticker] = ins ts = time_series_data["XOM"] start_date = "2020-01-02" -end_date = "2023-05-31" -end_date = "2020-01-05" -pr = pd.period_range(start=start_date, end=end_date, freq='B') +end_date = "2020-01-03" # "2023-05-31" +us_bd = CustomBusinessDay(calendar=USFederalHolidayCalendar()) +pr = pd.date_range(start=start_date, end=end_date, freq='B') portfolio1 = Portfolio(weights=initial_weights) portfolio2 = Portfolio(weights=initial_weights) @@ -49,6 +52,7 @@ wealth = np.zeros(len(pr)) for i, date in enumerate(pr): + # Build universe. for ins in instruments: ins.price_history = time_series_data[ins.identifier].loc[:str(date)] @@ -61,16 +65,19 @@ # Run optimizer on portfolio. optimizer = MPCMaximumReturn(portfolio1, simulator.return_tensor, gamma=10, l1_penalty=0, l2_penalty=1, covariance_matrix=simulator.covariance_matrix) optimizer.solve() - optimizer.solution() - exit() - + solution = optimizer.solution + solution = {instrument_mapping[ticker]: weight for ticker, weight in solution.items()} + print(solution) + # optimizer = MPCMaximumUtility(portfolio2, simulator.return_tensor, gamma=1) + # optimizer.solve() + # optimizer = SPMaximumUtility(portfolio3, simulator.price_tensor, simulator._inital_prices, gamma=-3) + # optimizer.solve() + exit() # Update portfolio weights. - - # Record portfolio wealth. wealth[i] = 0 diff --git a/src/abacus/models/garch.py b/src/abacus/models/garch.py index f6153ab..9ee42fd 100644 --- a/src/abacus/models/garch.py +++ b/src/abacus/models/garch.py @@ -156,7 +156,7 @@ def _sanity_check(self): if not parameter_check or not solution_check: # TODO: Make more stable or catch this error when running loop! - #raise ParameterError("Parameters could not be asceratined succesfully.") + # raise ParameterError("Parameters could not be asceratined succesfully.") ... def _check_parameters(self) -> bool: diff --git a/src/abacus/optimizer/optimizer.py b/src/abacus/optimizer/optimizer.py index a94bf9e..7cd0363 100644 --- a/src/abacus/optimizer/optimizer.py +++ b/src/abacus/optimizer/optimizer.py @@ -25,6 +25,7 @@ def __init__(self, portfolio: Portfolio, simulation_tensor: torch.Tensor, solver self._ampl = None def solve(self): + # TODO: Consider a verbose mode to display command line output. self._initiate_ampl_engine() self._set_ampl_data() self._solve_optimzation_problem() @@ -70,6 +71,7 @@ def solve(self): print(self._ampl.eval("display OBJECTIVE;")) def _set_ampl_data(self): + # TODO: Make consistent parameters. assets = self._portfolio.instruments asset_identifiers = [instrument.identifier for instrument in assets] instrument_holdings = np.array(list(self._portfolio.holdings.values())) @@ -144,19 +146,22 @@ def __init__(self, portfolio: Portfolio, simulation_tensor: torch.Tensor, gamma: def _return_expectation_tensor(self): return torch.mean(self._simulation_tensor, dim=2) + @property def solution(self): self._check_solved() - print(self._ampl.get_variable("weights").get_values()) - print(type(self._ampl.get_variable("weights").get_values())) + # TODO: Should be general? + ampl_output = self._ampl.get_variable("weights").to_pandas().loc[1].to_dict()["weights.val"] + return ampl_output def solve(self): + # TODO: Should weights be a configuration variable? super().solve() - print(self._ampl.get_variable("weights").to_pandas().loc[1]) - print(self._ampl.eval("display OBJECTIVE;")) + #print(self._ampl.eval("display OBJECTIVE;")) + def _set_ampl_data(self): - assets = self._portfolio.instruments inital_weights = self._portfolio.weights + assets = self._portfolio.instruments asset_identifiers = [instrument.identifier for instrument in assets] inital_weights = dict(zip(asset_identifiers, inital_weights.values())) expected_return_tensor = np.array(self._return_expectation_tensor)