1use super::*;
2
3pub struct RebalancingEngine {
5 rebalancing_strategies: HashMap<String, RebalancingStrategy>,
6 optimization_engine: OptimizationEngine,
7 execution_engine: ExecutionEngine,
8}
9
10#[derive(Debug, Clone)]
12pub struct RebalancingStrategy {
13 pub strategy_id: String,
14 pub strategy_name: String,
15 pub strategy_type: RebalancingStrategyType,
16 pub parameters: RebalancingParameters,
17 pub constraints: RebalancingConstraints,
18 pub target_weights: HashMap<String, f64>,
22}
23
24#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
26pub struct RebalanceTrade {
27 pub asset_id: String,
29 pub action: TradeAction,
31 pub quantity: f64,
33 pub target_weight: f64,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
39pub enum TradeAction {
40 Buy,
41 Sell,
42}
43
44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46pub enum RebalancingStrategyType {
47 TimeBased,
48 ThresholdBased,
49 OptimizationBased,
50 Hybrid,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct RebalancingParameters {
56 pub rebalance_frequency: u32,
57 pub deviation_threshold: f64,
58 pub min_trade_size: f64,
59 pub max_trade_size: f64,
60 pub transaction_costs: TransactionCosts,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct TransactionCosts {
66 pub commission_rate: f64,
67 pub spread_cost: f64,
68 pub market_impact: f64,
69 pub tax_rate: f64,
70}
71
72#[derive(Debug, Clone)]
74pub struct RebalancingConstraints {
75 pub asset_class_limits: HashMap<String, f64>,
76 pub sector_limits: HashMap<String, f64>,
77 pub liquidity_constraints: LiquidityConstraints,
78 pub regulatory_constraints: RegulatoryConstraints,
79}
80
81#[derive(Debug, Clone)]
83pub struct LiquidityConstraints {
84 pub max_daily_volume: f64,
85 pub min_liquidity_score: f64,
86 pub liquidity_buffer: f64,
87}
88
89#[derive(Debug, Clone)]
91pub struct RegulatoryConstraints {
92 pub concentration_limits: HashMap<String, f64>,
93 pub reporting_requirements: Vec<String>,
94 pub compliance_deadlines: Vec<u64>,
95}
96
97pub struct OptimizationEngine {
99 optimization_algorithms: HashMap<String, OptimizationAlgorithm>,
100 objective_functions: HashMap<String, ObjectiveFunction>,
101 constraints: Vec<OptimizationConstraint>,
102}
103
104#[derive(Debug, Clone)]
106pub struct OptimizationAlgorithm {
107 pub algorithm_id: String,
108 pub algorithm_type: OptimizationAlgorithmType,
109 pub parameters: OptimizationParameters,
110}
111
112#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
114pub enum OptimizationAlgorithmType {
115 MeanVariance,
116 BlackLitterman,
117 RiskParity,
118 EqualWeight,
119 Custom,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct OptimizationParameters {
125 pub risk_aversion: f64,
126 pub expected_returns: Vec<f64>,
127 pub covariance_matrix: Vec<Vec<f64>>,
128 pub constraints: Vec<OptimizationConstraint>,
129}
130
131#[derive(Debug, Clone)]
133pub struct ObjectiveFunction {
134 pub function_id: String,
135 pub function_type: ObjectiveFunctionType,
136 pub parameters: HashMap<String, f64>,
137}
138
139#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
141pub enum ObjectiveFunctionType {
142 MaximizeReturn,
143 MinimizeRisk,
144 MaximizeSharpe,
145 MinimizeDrawdown,
146 Custom,
147}
148
149#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct OptimizationConstraint {
152 pub constraint_id: String,
153 pub constraint_type: ConstraintType,
154 pub bounds: ConstraintBounds,
155}
156
157#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
159pub enum ConstraintType {
160 Equality,
161 Inequality,
162 Bound,
163 Linear,
164 Nonlinear,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct ConstraintBounds {
170 pub lower_bound: f64,
171 pub upper_bound: f64,
172}
173
174impl RebalancingEngine {
175 pub fn new() -> Self {
176 Self {
177 rebalancing_strategies: HashMap::new(),
178 optimization_engine: OptimizationEngine::new(),
179 execution_engine: ExecutionEngine::new(),
180 }
181 }
182
183 pub fn initialize(&mut self) -> Result<(), FinancialError> {
184 self.optimization_engine.initialize()?;
185 self.execution_engine.initialize()?;
186 Ok(())
187 }
188
189 pub fn register_strategy(&mut self, strategy: RebalancingStrategy) {
191 self.rebalancing_strategies
192 .insert(strategy.strategy_id.clone(), strategy);
193 }
194
195 pub fn get_strategy(&self, strategy_id: &str) -> Option<&RebalancingStrategy> {
197 self.rebalancing_strategies.get(strategy_id)
198 }
199
200 pub fn calculate_drift(portfolio: &Portfolio) -> HashMap<String, f64> {
205 let total: f64 = portfolio.assets.iter().map(|a| a.market_value).sum();
206 let mut weights = HashMap::new();
207 if !(total > 0.0) {
208 return weights;
209 }
210 for asset in &portfolio.assets {
211 weights.insert(asset.asset_id.clone(), asset.market_value / total);
212 }
213 weights
214 }
215
216 pub fn rebalance(
225 &self,
226 portfolio: &mut Portfolio,
227 strategy: &RebalancingStrategy,
228 ) -> Result<Vec<RebalanceTrade>, FinancialError> {
229 let total_value: f64 = portfolio.assets.iter().map(|a| a.market_value).sum();
230 if !(total_value > 0.0) {
231 return Err(FinancialError::PortfolioError(
232 "cannot rebalance: total portfolio market value is not positive".to_string(),
233 ));
234 }
235
236 let current_weights = Self::calculate_drift(portfolio);
237 let threshold = strategy.parameters.deviation_threshold;
238 let mut trades = Vec::new();
239
240 for asset in &portfolio.assets {
241 let current_weight = current_weights.get(&asset.asset_id).copied().unwrap_or(0.0);
242 let target_weight = strategy
243 .target_weights
244 .get(&asset.asset_id)
245 .copied()
246 .unwrap_or(0.0);
247 let drift = current_weight - target_weight;
248
249 if drift.abs() > threshold {
250 if asset.current_price <= 0.0 {
251 return Err(FinancialError::AssetError(format!(
252 "asset '{}' has non-positive current price; cannot size a trade",
253 asset.asset_id
254 )));
255 }
256 let target_value = target_weight * total_value;
257 let value_diff = target_value - asset.market_value;
258 let quantity = value_diff / asset.current_price;
259 let action = if quantity >= 0.0 {
260 TradeAction::Buy
261 } else {
262 TradeAction::Sell
263 };
264 trades.push(RebalanceTrade {
265 asset_id: asset.asset_id.clone(),
266 action,
267 quantity: quantity.abs(),
268 target_weight,
269 });
270 }
271 }
272
273 Ok(trades)
274 }
275}
276
277impl OptimizationEngine {
278 pub fn new() -> Self {
279 Self {
280 optimization_algorithms: HashMap::new(),
281 objective_functions: HashMap::new(),
282 constraints: Vec::new(),
283 }
284 }
285
286 pub fn initialize(&mut self) -> Result<(), FinancialError> {
287 Ok(())
288 }
289
290 pub fn add_algorithm(&mut self, algorithm: OptimizationAlgorithm) {
291 self.optimization_algorithms
292 .insert(algorithm.algorithm_id.clone(), algorithm);
293 }
294
295 pub fn get_algorithm(&self, algorithm_id: &str) -> Option<&OptimizationAlgorithm> {
296 self.optimization_algorithms.get(algorithm_id)
297 }
298
299 pub fn list_algorithms(&self) -> Vec<String> {
300 self.optimization_algorithms.keys().cloned().collect()
301 }
302
303 pub fn add_objective_function(&mut self, function: ObjectiveFunction) {
304 self.objective_functions
305 .insert(function.function_id.clone(), function);
306 }
307
308 pub fn get_objective_function(&self, function_id: &str) -> Option<&ObjectiveFunction> {
309 self.objective_functions.get(function_id)
310 }
311
312 pub fn list_objective_functions(&self) -> Vec<String> {
313 self.objective_functions.keys().cloned().collect()
314 }
315
316 pub fn add_constraint(&mut self, constraint: OptimizationConstraint) {
317 self.constraints.push(constraint);
318 }
319
320 pub fn list_constraints(&self) -> &[OptimizationConstraint] {
321 &self.constraints
322 }
323}
324
325impl RebalancingStrategy {
326 pub fn new() -> Self {
327 Self {
328 strategy_id: "strategy_1".to_string(),
329 strategy_name: "Monthly rebalancing".to_string(),
330 strategy_type: RebalancingStrategyType::TimeBased,
331 parameters: RebalancingParameters::new(),
332 constraints: RebalancingConstraints::new(),
333 target_weights: HashMap::new(),
334 }
335 }
336}
337
338impl RebalancingParameters {
339 pub fn new() -> Self {
340 Self {
341 rebalance_frequency: 30, deviation_threshold: 0.05, min_trade_size: 1000.0,
344 max_trade_size: 100000.0,
345 transaction_costs: TransactionCosts::new(),
346 }
347 }
348}
349
350impl TransactionCosts {
351 pub fn new() -> Self {
352 Self {
353 commission_rate: 0.001,
354 spread_cost: 0.0005,
355 market_impact: 0.0002,
356 tax_rate: 0.2,
357 }
358 }
359}
360
361impl RebalancingConstraints {
362 pub fn new() -> Self {
363 Self {
364 asset_class_limits: HashMap::new(),
365 sector_limits: HashMap::new(),
366 liquidity_constraints: LiquidityConstraints::new(),
367 regulatory_constraints: RegulatoryConstraints::new(),
368 }
369 }
370}
371
372impl LiquidityConstraints {
373 pub fn new() -> Self {
374 Self {
375 max_daily_volume: 1000000.0,
376 min_liquidity_score: 0.7,
377 liquidity_buffer: 0.1,
378 }
379 }
380}
381
382impl RegulatoryConstraints {
383 pub fn new() -> Self {
384 Self {
385 concentration_limits: HashMap::new(),
386 reporting_requirements: vec!["Daily report".to_string()],
387 compliance_deadlines: vec![86400], }
389 }
390}
391
392impl OptimizationAlgorithm {
393 pub fn new() -> Self {
394 Self {
395 algorithm_id: "algo_1".to_string(),
396 algorithm_type: OptimizationAlgorithmType::MeanVariance,
397 parameters: OptimizationParameters::new(),
398 }
399 }
400}
401
402impl OptimizationParameters {
403 pub fn new() -> Self {
404 Self {
405 risk_aversion: 1.0,
406 expected_returns: vec![0.1, 0.08, 0.12],
407 covariance_matrix: vec![
408 vec![0.04, 0.02, 0.01],
409 vec![0.02, 0.09, 0.03],
410 vec![0.01, 0.03, 0.16],
411 ],
412 constraints: vec![],
413 }
414 }
415}
416
417impl ObjectiveFunction {
418 pub fn new() -> Self {
419 Self {
420 function_id: "obj_1".to_string(),
421 function_type: ObjectiveFunctionType::MaximizeSharpe,
422 parameters: HashMap::new(),
423 }
424 }
425}
426
427impl OptimizationConstraint {
428 pub fn new() -> Self {
429 Self {
430 constraint_id: "constraint_1".to_string(),
431 constraint_type: ConstraintType::Equality,
432 bounds: ConstraintBounds::new(),
433 }
434 }
435}
436
437impl ConstraintBounds {
438 pub fn new() -> Self {
439 Self {
440 lower_bound: 0.0,
441 upper_bound: 1.0,
442 }
443 }
444}