@@ -16,7 +16,6 @@ class QuadraticOptimisation:
1616 expected_return : float
1717 turnover : float
1818 execution_cost : float
19- future_decay_cost : float
2019 objective_value : float
2120 iterations : int
2221 gross_constraint_active : bool
@@ -30,7 +29,6 @@ def optimise_linear_position(
3029 pretrade_position : np .ndarray ,
3130 market_beta : np .ndarray ,
3231 linear_execution_cost : float ,
33- future_decay_cost : float ,
3432 quadratic_penalty : float ,
3533 gross_budget : float ,
3634 initial_dual : np .ndarray ,
@@ -49,7 +47,7 @@ def optimise_linear_position(
4947 older .shape != (size ,)
5048 or pretrade .shape != (size ,)
5149 or beta .shape != (size ,)
52- or dual .shape != (2 * size ,)
50+ or dual .shape != (size ,)
5351 or matrix .shape != (size , size )
5452 ):
5553 raise ValueError ("optimizer inputs must share one square asset dimension" )
@@ -59,8 +57,6 @@ def optimise_linear_position(
5957 raise ValueError ("quadratic_penalty must be finite and positive" )
6058 if linear_execution_cost < 0.0 or not np .isfinite (linear_execution_cost ):
6159 raise ValueError ("linear_execution_cost must be finite and non-negative" )
62- if future_decay_cost < 0.0 or not np .isfinite (future_decay_cost ):
63- raise ValueError ("future_decay_cost must be finite and non-negative" )
6460
6561 offset = older - pretrade
6662 if gross_budget == 0.0 :
@@ -71,7 +67,6 @@ def optimise_linear_position(
7167 offset = offset ,
7268 matrix = matrix ,
7369 execution_cost_rate = linear_execution_cost ,
74- future_decay_cost_rate = future_decay_cost ,
7570 quadratic_penalty = quadratic_penalty ,
7671 iterations = 0 ,
7772 gross_constraint_active = True ,
@@ -82,17 +77,12 @@ def optimise_linear_position(
8277 if beta_norm_squared > np .finfo ("float64" ).eps :
8378 projection -= np .outer (beta , beta ) / beta_norm_squared
8479 projected_mu = projection @ mu
85- projected_matrix = np .concatenate ((matrix @ projection , projection ), axis = 0 )
86- projected_offset = np .concatenate ((offset , np .zeros (size )))
87- dual_bound = np .concatenate (
88- (
89- np .full (size , linear_execution_cost ),
90- np .full (size , future_decay_cost ),
91- )
92- )
80+ projected_matrix = matrix @ projection
81+ projected_offset = offset
82+ dual_bound = np .full (size , linear_execution_cost )
9383
9484 iterations = 0
95- if linear_execution_cost == 0.0 and future_decay_cost == 0.0 :
85+ if linear_execution_cost == 0.0 :
9686 allocation = projected_mu / quadratic_penalty
9787 dual .fill (0.0 )
9888 else :
@@ -126,7 +116,6 @@ def optimise_linear_position(
126116 matrix = matrix ,
127117 market_beta = beta ,
128118 execution_cost = linear_execution_cost ,
129- future_decay_cost = future_decay_cost ,
130119 quadratic_penalty = quadratic_penalty ,
131120 gross_budget = gross_budget ,
132121 initial_allocation = allocation * (gross_budget / gross ),
@@ -147,7 +136,6 @@ def optimise_linear_position(
147136 offset = offset ,
148137 matrix = matrix ,
149138 execution_cost_rate = linear_execution_cost ,
150- future_decay_cost_rate = future_decay_cost ,
151139 quadratic_penalty = quadratic_penalty ,
152140 iterations = iterations ,
153141 gross_constraint_active = gross_constraint_active ,
@@ -162,7 +150,6 @@ def _result(
162150 offset : np .ndarray ,
163151 matrix : np .ndarray ,
164152 execution_cost_rate : float ,
165- future_decay_cost_rate : float ,
166153 quadratic_penalty : float ,
167154 iterations : int ,
168155 gross_constraint_active : bool ,
@@ -171,18 +158,14 @@ def _result(
171158 expected_return = float (mu @ allocation )
172159 turnover = float (np .abs (trade ).sum ())
173160 execution_cost = execution_cost_rate * turnover
174- future_cost = future_decay_cost_rate * float (np .abs (allocation ).sum ())
175161 quadratic_cost = 0.5 * quadratic_penalty * float (allocation @ allocation )
176162 return QuadraticOptimisation (
177163 allocation = allocation ,
178164 dual = dual ,
179165 expected_return = expected_return ,
180166 turnover = turnover ,
181167 execution_cost = execution_cost ,
182- future_decay_cost = future_cost ,
183- objective_value = (
184- expected_return - quadratic_cost - execution_cost - future_cost
185- ),
168+ objective_value = expected_return - quadratic_cost - execution_cost ,
186169 iterations = iterations ,
187170 gross_constraint_active = gross_constraint_active ,
188171 )
@@ -195,7 +178,6 @@ def _solve_gross_constrained_qp(
195178 matrix : np .ndarray ,
196179 market_beta : np .ndarray ,
197180 execution_cost : float ,
198- future_decay_cost : float ,
199181 quadratic_penalty : float ,
200182 gross_budget : float ,
201183 initial_allocation : np .ndarray ,
@@ -227,7 +209,6 @@ def objective(values: np.ndarray) -> float:
227209 0.5 * quadratic_penalty * (allocation @ allocation )
228210 - expected_returns @ allocation
229211 + execution_cost * turnover .sum ()
230- + future_decay_cost * values [2 * size :].sum ()
231212 )
232213
233214 def gradient (values : np .ndarray ) -> np .ndarray :
@@ -236,7 +217,7 @@ def gradient(values: np.ndarray) -> np.ndarray:
236217 (
237218 quadratic_penalty * allocation - expected_returns ,
238219 np .full (size , execution_cost ),
239- np .full (size , future_decay_cost ),
220+ np .zeros (size ),
240221 )
241222 )
242223
0 commit comments