trading-platform/docs/02-definicion-modulos/OQI-008-portfolio-manager/especificaciones/ET-PFM-004-motor-rebalanceo.md
rckrdmrd a7cca885f0 feat: Major platform documentation and architecture updates
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>
2026-01-07 05:33:35 -06:00

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