From 5232e230a46a98ebf0573827abc6be23c1a4cf6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 26 Feb 2026 22:43:06 +0100 Subject: [PATCH 1/6] monthly freq --- tests/test_efficient_cdar.py | 7 ++++++- tests/test_efficient_cvar.py | 7 ++++++- tests/test_efficient_semivariance.py | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/tests/test_efficient_cdar.py b/tests/test_efficient_cdar.py index 746efdec..650fa486 100644 --- a/tests/test_efficient_cdar.py +++ b/tests/test_efficient_cdar.py @@ -84,9 +84,14 @@ def test_cdar_example_weekly(): def test_cdar_example_monthly(): + if _check_soft_dependencies("pandas<3", severity="none"): + MONTHLY_FREQ = "M" + else: + MONTHLY_FREQ = "ME" + beta = 0.90 df = get_data() - df = df.resample("M").first() + df = df.resample(MONTHLY_FREQ).first() mu = expected_returns.mean_historical_return(df, frequency=12) historical_rets = expected_returns.returns_from_prices(df).dropna() cd = EfficientCDaR(mu, historical_rets, beta=beta) diff --git a/tests/test_efficient_cvar.py b/tests/test_efficient_cvar.py index 2d20c79e..a3117233 100644 --- a/tests/test_efficient_cvar.py +++ b/tests/test_efficient_cvar.py @@ -92,9 +92,14 @@ def test_cvar_example_weekly(): def test_cvar_example_monthly(): + if _check_soft_dependencies("pandas<3", severity="none"): + MONTHLY_FREQ = "M" + else: + MONTHLY_FREQ = "ME" + beta = 0.95 df = get_data() - df = df.resample("M").first() + df = df.resample(MONTHLY_FREQ).first() mu = expected_returns.mean_historical_return(df, frequency=12) historical_rets = expected_returns.returns_from_prices(df).dropna() cv = EfficientCVaR(mu, historical_rets, beta=beta) diff --git a/tests/test_efficient_semivariance.py b/tests/test_efficient_semivariance.py index 7da9655b..9d1dc584 100644 --- a/tests/test_efficient_semivariance.py +++ b/tests/test_efficient_semivariance.py @@ -119,8 +119,13 @@ def test_es_example_weekly(): def test_es_example_monthly(): + if _check_soft_dependencies("pandas<3", severity="none"): + MONTHLY_FREQ = "M" + else: + MONTHLY_FREQ = "ME" + df = get_data() - df = df.resample("M").first() + df = df.resample(MONTHLY_FREQ).first() mu = expected_returns.mean_historical_return(df, frequency=12) historical_rets = expected_returns.returns_from_prices(df).dropna() es = EfficientSemivariance(mu, historical_rets, frequency=12) From 1ad3282e37b2d795df221b07b7c2433751c0e81c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 26 Feb 2026 22:44:35 +0100 Subject: [PATCH 2/6] float --- pypfopt/cla.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pypfopt/cla.py b/pypfopt/cla.py index 884fbb58..b9bf3b59 100644 --- a/pypfopt/cla.py +++ b/pypfopt/cla.py @@ -174,7 +174,9 @@ def _compute_lambda(self, covarF_inv, covarFB, meanF, wB, i, bi): l2 = np.dot(covarF_inv, covarFB) l3 = np.dot(l2, wB) l2 = np.dot(onesF.T, l3) - return float(((1 - l1 + l2) * c4[i] - c1 * (bi + l3[i])) / c), bi + res = float(((1 - l1 + l2) * c4[i] - c1 * (bi + l3[i])) / c) + res = res[0, 0] + return res, bi def _get_matrices(self, f): # Slice covarF,covarFB,covarB,meanF,meanB,wF,wB From dfa3c7e754bdd2a33f92c2030b30edf0630e999a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 26 Feb 2026 22:47:59 +0100 Subject: [PATCH 3/6] Update cla.py --- pypfopt/cla.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pypfopt/cla.py b/pypfopt/cla.py index b9bf3b59..99d11623 100644 --- a/pypfopt/cla.py +++ b/pypfopt/cla.py @@ -174,8 +174,8 @@ def _compute_lambda(self, covarF_inv, covarFB, meanF, wB, i, bi): l2 = np.dot(covarF_inv, covarFB) l3 = np.dot(l2, wB) l2 = np.dot(onesF.T, l3) - res = float(((1 - l1 + l2) * c4[i] - c1 * (bi + l3[i])) / c) - res = res[0, 0] + res = ((1 - l1 + l2) * c4[i] - c1 * (bi + l3[i])) / c + res = float(res[0, 0]) return res, bi def _get_matrices(self, f): From 86b4aba80fb485080d64348e3a171d5e08c0601a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 26 Feb 2026 22:51:45 +0100 Subject: [PATCH 4/6] Update cla.py --- pypfopt/cla.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pypfopt/cla.py b/pypfopt/cla.py index 99d11623..e258564c 100644 --- a/pypfopt/cla.py +++ b/pypfopt/cla.py @@ -145,7 +145,8 @@ def _compute_w(self, covarF_inv, covarFB, meanF, wB): g4 = np.dot(covarF_inv, covarFB) w1 = np.dot(g4, wB) g4 = np.dot(onesF.T, w1) - g = float(-self.ls[-1] * g1 / g2 + (1 - g3 + g4) / g2) + g = -self.ls[-1] * g1 / g2 + (1 - g3 + g4) / g2 + g = float(g[0, 0]) # 2) compute weights w2 = np.dot(covarF_inv, onesF) w3 = np.dot(covarF_inv, meanF) From c19105deca22bf601c3aed30be22632de6c787cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 26 Feb 2026 23:32:36 +0100 Subject: [PATCH 5/6] Update cla.py --- pypfopt/cla.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pypfopt/cla.py b/pypfopt/cla.py index e258564c..e5062692 100644 --- a/pypfopt/cla.py +++ b/pypfopt/cla.py @@ -168,7 +168,9 @@ def _compute_lambda(self, covarF_inv, covarFB, meanF, wB, i, bi): # 3) Lambda if wB is None: # All free assets - return float((c4[i] - c1 * bi) / c), bi + res = (c4[i] - c1 * bi) / c + res = float(res[0, 0]) + return res, bi else: onesB = np.ones(wB.shape) l1 = np.dot(onesB.T, wB) From ef73d224fc85e807310ee2702f7c62af3f2bc24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Kir=C3=A1ly?= Date: Thu, 26 Feb 2026 23:39:07 +0100 Subject: [PATCH 6/6] dry --- pypfopt/cla.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pypfopt/cla.py b/pypfopt/cla.py index e5062692..f5383f28 100644 --- a/pypfopt/cla.py +++ b/pypfopt/cla.py @@ -138,7 +138,8 @@ def _compute_w(self, covarF_inv, covarFB, meanF, wB): g1 = np.dot(np.dot(onesF.T, covarF_inv), meanF) g2 = np.dot(np.dot(onesF.T, covarF_inv), onesF) if wB is None: - g, w1 = float(-self.ls[-1] * g1 / g2 + 1 / g2), 0 + g = -self.ls[-1] * g1 / g2 + 1 / g2 + w1 = 0 else: onesB = np.ones(wB.shape) g3 = np.dot(onesB.T, wB) @@ -146,7 +147,7 @@ def _compute_w(self, covarF_inv, covarFB, meanF, wB): w1 = np.dot(g4, wB) g4 = np.dot(onesF.T, w1) g = -self.ls[-1] * g1 / g2 + (1 - g3 + g4) / g2 - g = float(g[0, 0]) + g = float(g[0, 0]) # 2) compute weights w2 = np.dot(covarF_inv, onesF) w3 = np.dot(covarF_inv, meanF) @@ -169,8 +170,6 @@ def _compute_lambda(self, covarF_inv, covarFB, meanF, wB, i, bi): if wB is None: # All free assets res = (c4[i] - c1 * bi) / c - res = float(res[0, 0]) - return res, bi else: onesB = np.ones(wB.shape) l1 = np.dot(onesB.T, wB) @@ -178,8 +177,8 @@ def _compute_lambda(self, covarF_inv, covarFB, meanF, wB, i, bi): l3 = np.dot(l2, wB) l2 = np.dot(onesF.T, l3) res = ((1 - l1 + l2) * c4[i] - c1 * (bi + l3[i])) / c - res = float(res[0, 0]) - return res, bi + res = float(res[0, 0]) + return res, bi def _get_matrices(self, f): # Slice covarF,covarFB,covarB,meanF,meanB,wF,wB