diff --git a/run.py b/run.py index a67fbd2..9e3fe55 100644 --- a/run.py +++ b/run.py @@ -8,7 +8,7 @@ from src.abacus.utils.portfolio import Portfolio from src.abacus.simulator.simulator import Simulator from src.abacus.assessor.risk_assessor import RiskAssessor -from src.abacus.optimizer.optimizer import SPMaximumUtility +from src.abacus.optimizer.optimizer import SPMaximumUtility, SPMaximumGain @@ -44,13 +44,16 @@ # Mock prices... -# price_tensor = torch.tensor([ [[1000]], [[0]], [[0]], [[0]]]) -# inital_prices = torch.tensor([ [[10]], [[10]], [[10]], [[10]]]) +price_tensor = torch.tensor([ [[1000]], [[0]], [[0]], [[0]]]) +inital_prices = torch.tensor([ [[10]], [[10]], [[10]], [[10]]]) # Create optimizer with different optimization models... -optimizer = SPMaximumUtility(portfolio, simulator._price_tensor, simulator._inital_prices) +optimizer = SPMaximumGain(portfolio, price_tensor, inital_prices) optimizer.solve() +print() +optimizer = SPMaximumUtility(portfolio, price_tensor, inital_prices) +optimizer.solve() print("OK!") diff --git a/src/abacus/optimizer/optimization_models/sp_maximize_gain.mod b/src/abacus/optimizer/optimization_models/sp_maximize_gain.mod new file mode 100644 index 0000000..bae0a96 --- /dev/null +++ b/src/abacus/optimizer/optimization_models/sp_maximize_gain.mod @@ -0,0 +1,35 @@ +problem spMaximizeGain; + +set assets; + +param dt > 0; +param risk_free_rate; +param inital_cash > 0; +param number_of_scenarios > 0 integer; +param number_of_assets > 0 integer; +param inital_holdings {assets}; +param inital_prices {assets}; +param prices {1..number_of_scenarios, assets}; + +var x_buy {assets}; +var x_sell {assets}; + +maximize Objective: + sum{i in 1..number_of_scenarios} 1/number_of_scenarios * ((inital_cash + sum{j in assets} (inital_prices[j] * (x_sell[j] - x_buy[j]))) * exp(risk_free_rate * dt) + sum{j in assets} (prices[i, j] * (inital_holdings[j] + x_buy[j] - x_sell[j]))); + + +subject to SHORTING_CONSTRAINT {j in assets}: + inital_holdings[j] + x_buy[j] - x_sell[j] >= 0 +; + +subject to LEVERAGE_CONSTRAINT: + inital_cash + sum{j in assets} ( (x_sell[j] - x_buy[j]) * inital_prices[j]) >= 0 +; + +subject to FEASIBLE_CONSTRAINT_BUY {j in assets}: + x_buy[j] >= 0 +; + +subject to FEASIBLE_CONSTRAINT_SELL {j in assets}: + x_sell[j] >= 0 +; diff --git a/src/abacus/optimizer/optimization_models/sp_maximize_utility.mod b/src/abacus/optimizer/optimization_models/sp_maximize_utility.mod index 8663154..6a982bb 100644 --- a/src/abacus/optimizer/optimization_models/sp_maximize_utility.mod +++ b/src/abacus/optimizer/optimization_models/sp_maximize_utility.mod @@ -4,6 +4,7 @@ set assets; param dt > 0; param risk_free_rate; +param gamma; param inital_cash > 0; param number_of_scenarios > 0 integer; param number_of_assets > 0 integer; @@ -15,7 +16,7 @@ var x_buy {assets}; var x_sell {assets}; maximize Objective: - sum{i in 1..number_of_scenarios} 1/number_of_scenarios * ((inital_cash + sum{j in assets} (inital_prices[j] * (x_sell[j] - x_buy[j]))) * exp(risk_free_rate * dt) + sum{j in assets} (prices[i, j] * (inital_holdings[j] + x_buy[j] - x_sell[j]))); + sum{i in 1..number_of_scenarios} 1/number_of_scenarios * ((inital_cash + sum{j in assets} (inital_prices[j] * (x_sell[j] - x_buy[j]))) * exp(risk_free_rate * dt) + sum{j in assets} (prices[i, j] * (inital_holdings[j] + x_buy[j] - x_sell[j]))) ** gamma / gamma; subject to SHORTING_CONSTRAINT {j in assets}: diff --git a/src/abacus/optimizer/optimizer.py b/src/abacus/optimizer/optimizer.py index f0dfa55..5329412 100644 --- a/src/abacus/optimizer/optimizer.py +++ b/src/abacus/optimizer/optimizer.py @@ -52,9 +52,42 @@ def _check_initialization(self): if not self._ampl: raise ValueError("AMPL has not been initalized.") - def _check_valid_model_specification(self): - # TODO: Implement when approriate. - ... + + +class SPMaximumGain(OptimizationModel): + + _model_specification = OptimizationSpecifications.SP_MAXIMIZE_GAIN + + def __init__(self, portfolio: Portfolio, price_tensor: torch.Tensor, inital_prices: torch.Tensor): + super().__init__(portfolio, price_tensor) + self._inital_prices = inital_prices + + def solve(self): + super().solve() + print(self._ampl.get_variable("x_buy").get_values()) + print(self._ampl.get_variable("x_sell").get_values()) + print(self._ampl.eval("display Objective;")) + + def _set_ampl_data(self): + assets = self._portfolio.instruments + asset_identifiers = [instrument.identifier for instrument in assets] + instrument_holdings = np.array(list(self._portfolio.holdings.values())) + price_tensor = np.array(self._simulation_tensor[:,-1,:]) + inital_prices = dict(zip(asset_identifiers, np.array(self._inital_prices.reshape(4)))) + tensor_size = price_tensor.shape + number_of_assets = tensor_size[0] + number_of_scenarios = tensor_size[1] + price_dict = {(j+1, asset.identifier): price_tensor[asset.id][j] for asset in assets for j in range(number_of_scenarios)} + + self._ampl.get_set("assets").set_values(asset_identifiers) + self._ampl.param["risk_free_rate"] = 0.05 + self._ampl.param["dt"] = 10/365 + self._ampl.param["number_of_assets"] = number_of_assets + self._ampl.param["number_of_scenarios"] = number_of_scenarios + self._ampl.param["inital_cash"] = self._portfolio._cash + self._ampl.param["inital_holdings"] = instrument_holdings + self._ampl.param["inital_prices"] = inital_prices + self._ampl.param["prices"] = price_dict @@ -86,6 +119,7 @@ def _set_ampl_data(self): self._ampl.get_set("assets").set_values(asset_identifiers) self._ampl.param["risk_free_rate"] = 0.05 self._ampl.param["dt"] = 10/365 + self._ampl.param["gamma"] = -2 self._ampl.param["number_of_assets"] = number_of_assets self._ampl.param["number_of_scenarios"] = number_of_scenarios self._ampl.param["inital_cash"] = self._portfolio._cash @@ -94,6 +128,7 @@ def _set_ampl_data(self): self._ampl.param["prices"] = price_dict + class MPCMaximumUtility(OptimizationModel): _model_specification = OptimizationSpecifications.MPC_MAXIMIZE_UTILITY diff --git a/src/abacus/utils/enumerations.py b/src/abacus/utils/enumerations.py index 0deb7a5..f150cf7 100644 --- a/src/abacus/utils/enumerations.py +++ b/src/abacus/utils/enumerations.py @@ -4,4 +4,5 @@ class OptimizationSpecifications(Enum): SP_MAXIMIZE_UTILITY = "sp_maximize_utility.mod" + SP_MAXIMIZE_GAIN = "sp_maximize_gain.mod" MPC_MAXIMIZE_UTILITY = "mpc_maximize_utility.mod"