Skip to content

Commit 9060b3e

Browse files
author
Mengtao Zhang
committed
fix optimiser
1 parent 6e9193f commit 9060b3e

2 files changed

Lines changed: 8 additions & 30 deletions

File tree

‎environment/mcp-server/feature_engineering/core/dual_optimiser.py‎

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -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

‎environment/mcp-server/feature_engineering/core/ema_smoothed_engine.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def __init__(
5858
dtype="float64",
5959
)
6060
self.ema_tail = np.zeros(symbol_count, dtype="float64")
61-
self.previous_dual = np.zeros(2 * symbol_count, dtype="float64")
61+
self.previous_dual = np.zeros(symbol_count, dtype="float64")
6262
self.identity = np.eye(symbol_count, dtype="float64")
6363
self.fee_rate = fee_rate
6464
self.max_gross_exposure = max_gross_exposure
@@ -82,7 +82,6 @@ def rebalance(self, request: RebalanceRequest) -> RebalanceDecision:
8282
pretrade_position=request.pretrade_weights,
8383
market_beta=beta,
8484
linear_execution_cost=self.fee_rate,
85-
future_decay_cost=self.fee_rate * self.ema_entry_weight,
8685
quadratic_penalty=self.quadratic_penalty,
8786
gross_budget=self.max_gross_exposure,
8887
initial_dual=self.previous_dual,
@@ -101,8 +100,6 @@ def rebalance(self, request: RebalanceRequest) -> RebalanceDecision:
101100
"expected_return": solved.expected_return,
102101
"turnover": solved.turnover,
103102
"objective_execution_cost": solved.execution_cost,
104-
"objective_future_decay_cost": solved.future_decay_cost,
105-
"future_decay_cost_rate": self.fee_rate * self.ema_entry_weight,
106103
"objective_value": solved.objective_value,
107104
"iterations": solved.iterations,
108105
"quadratic_penalty": self.quadratic_penalty,

0 commit comments

Comments
 (0)