Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.1 KiB
4.1 KiB
| id | title | type | status | priority | epic | project | version | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|---|
| ET-PFM-004 | Motor de Rebalanceo | Technical Specification | Done | Alta | OQI-008 | trading-platform | 1.0.0 | 2025-12-05 | 2026-01-04 |
ET-PFM-004: Motor de Rebalanceo
Épica: OQI-008 - Portfolio Manager Versión: 1.0 Fecha: 2025-12-05 Estado: Planificado
Arquitectura
┌─────────────────────────────────────────────────────────────┐
│ REBALANCING ENGINE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Allocation │ │ Deviation │ │ Plan │ │
│ │ Manager │──▶│ Calculator │──▶│ Generator │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Order │ │
│ │ Executor │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
Algoritmo de Rebalanceo
@Injectable()
export class RebalanceService {
async generatePlan(
portfolioId: string,
targetAllocation: Allocation[]
): Promise<RebalancePlan> {
const positions = await this.portfolioService.getPositions(portfolioId);
const totalValue = this.calculateTotalValue(positions);
const orders: RebalanceOrder[] = [];
// Calcular diferencias
for (const target of targetAllocation) {
const current = positions.find(p => p.symbol === target.symbol);
const currentValue = current?.marketValue || 0;
const targetValue = totalValue * (target.percent / 100);
const difference = targetValue - currentValue;
if (Math.abs(difference) > 100) { // Min $100 para operar
orders.push({
symbol: target.symbol,
action: difference > 0 ? 'BUY' : 'SELL',
amount: Math.abs(difference),
currentAllocation: (currentValue / totalValue) * 100,
targetAllocation: target.percent,
});
}
}
// Ordenar: ventas primero
orders.sort((a, b) => {
if (a.action === 'SELL' && b.action === 'BUY') return -1;
if (a.action === 'BUY' && b.action === 'SELL') return 1;
return b.amount - a.amount;
});
return {
portfolioId,
orders,
estimatedCost: this.estimateCosts(orders),
timestamp: new Date().toISOString(),
};
}
async executePlan(planId: string): Promise<RebalanceResult> {
const plan = await this.getPlan(planId);
const results = [];
for (const order of plan.orders) {
const result = await this.orderService.createOrder({
symbol: order.symbol,
side: order.action.toLowerCase(),
amount: order.amount,
type: 'market',
});
results.push(result);
}
return {
planId,
executed: results.filter(r => r.success).length,
failed: results.filter(r => !r.success).length,
results,
};
}
}
Referencias
Especificación técnica - Sistema NEXUS