Skip to content

Commit

Permalink
problems with clarabel?
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Schmelzer committed Dec 9, 2023
1 parent fc9839d commit 5875355
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 14 deletions.
10 changes: 8 additions & 2 deletions experiments/markowitz.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ class Parameters:


def markowitz(
data: Data, param: Parameters, **kwargs
data: Data, param: Parameters, solver=None
) -> tuple[np.ndarray, float, cp.Problem]:
"""
Markowitz portfolio optimization.
This function contains the code listing for the accompanying paper.
"""

solver = solver or _get_solver()

w, c = cp.Variable(data.n_assets), cp.Variable()

z = w - data.w_prev
Expand Down Expand Up @@ -121,11 +123,15 @@ def markowitz(
]

problem = cp.Problem(cp.Maximize(objective), constraints)
problem.solve(**kwargs)
problem.solve(solver=solver)
assert problem.status in {cp.OPTIMAL, cp.OPTIMAL_INACCURATE}, problem.status
return w.value, c.value, problem


def _get_solver():
return cp.MOSEK if cp.MOSEK in cp.installed_solvers() else cp.CLARABEL


# if __name__ == "__main__":
# # Create empty data and parameters objects to check types and shapes,
# # will be replaced by example data
Expand Down
33 changes: 21 additions & 12 deletions experiments/taming.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import numpy as np
import pandas as pd
import cvxpy as cp
from cvxpy import Problem
from numpy import ndarray

from experiments.backtest import BacktestResult, OptimizationInput, run_backtest
from experiments.markowitz import Data, Parameters, markowitz


def _basic_markowitz(inputs: OptimizationInput) -> np.ndarray:
def _basic_markowitz(inputs: OptimizationInput, solver=None) -> np.ndarray:
"""Compute the basic Markowitz portfolio weights."""

mu, Sigma = inputs.mean.values, inputs.covariance.values
Expand All @@ -21,7 +24,7 @@ def _basic_markowitz(inputs: OptimizationInput) -> np.ndarray:
]

problem = cp.Problem(cp.Maximize(objective), constraints)
problem.solve(solver=_get_solver())
problem.solve(solver=solver)
assert problem.status in {cp.OPTIMAL, cp.OPTIMAL_INACCURATE}, problem.status
return w.value, c.value, problem

Expand All @@ -34,7 +37,7 @@ def _equal_weights(inputs: OptimizationInput) -> np.ndarray:
return w, c, None


def _weight_limits_markowitz(inputs: OptimizationInput) -> np.ndarray:
def _weight_limits_markowitz(inputs: OptimizationInput, solver=None) -> np.ndarray:
lb = np.ones(inputs.n_assets) * (-0.05)
ub = np.ones(inputs.n_assets) * 0.1

Expand All @@ -46,30 +49,36 @@ def _weight_limits_markowitz(inputs: OptimizationInput) -> np.ndarray:
param.c_upper = 1.0
param.risk_target = inputs.risk_target
param.gamma_risk = 5.0
return markowitz(data, param, solver=_get_solver())
return markowitz(data, param, solver=solver)


def _leverage_limit_markowitz(inputs: OptimizationInput) -> np.ndarray:
def _leverage_limit_markowitz(
inputs: OptimizationInput, solver=None
) -> tuple[ndarray, float, Problem]:
data, param = _get_basic_data_and_parameters(inputs)

param.L_max = 1.6
return markowitz(data, param, solver=_get_solver())
return markowitz(data, param, solver=solver)


def _turnover_limit_markowitz(inputs: OptimizationInput) -> np.ndarray:
def _turnover_limit_markowitz(
inputs: OptimizationInput, solver=None
) -> tuple[ndarray, float, Problem]:
data, param = _get_basic_data_and_parameters(inputs)

param.T_max = 50 / 252 # Maximum TO per year
return markowitz(data, param, solver=_get_solver())
return markowitz(data, param, solver=solver)


def _robust_markowitz(inputs: OptimizationInput) -> np.ndarray:
def _robust_markowitz(
inputs: OptimizationInput, solver=None
) -> tuple[ndarray, float, Problem]:
data, param = _get_basic_data_and_parameters(inputs)
param.rho_mean = np.percentile(np.abs(inputs.mean.values), 20, axis=0) * np.ones(
inputs.n_assets
)
param.rho_covariance = 0.02
return markowitz(data, param, solver=_get_solver())
return markowitz(data, param, solver=solver)


def _get_basic_data_and_parameters(
Expand Down Expand Up @@ -244,8 +253,8 @@ def _generate_table(
)


def _get_solver():
return cp.MOSEK if cp.MOSEK in cp.installed_solvers() else cp.CLARABEL
# def _get_solver():
# return cp.MOSEK if cp.MOSEK in cp.installed_solvers() else cp.CLARABEL


if __name__ == "__main__":
Expand Down

0 comments on commit 5875355

Please sign in to comment.