Comprehensive analysis of 101 DDL tables across 11 schemas: - Phase 1-2: Schema validation, 37 gaps cataloged (3 resolved) - Phase 3: Integrity audit (80 FKs, 89 CHECKs, 17 issues: 2 CRIT/5 HIGH) - Phase 4: DDL-Backend mapping (84% interfaces, 75% services, 61% controllers) - Phase 5: Documentation purge catalog (201 files analyzed) - Phase 6: Remediation plan (4 sprints, 204h) Key finding: Backend uses raw SQL + pg Pool (NOT TypeORM). 13 deliverables + updated inventories to v2.0.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
214 lines
7.6 KiB
Markdown
214 lines
7.6 KiB
Markdown
# RECOMENDACIONES DE MODELADO - Trading Platform
|
|
|
|
**Tarea:** TASK-2026-02-05-ANALISIS-VALIDACION-MODELADO-BD
|
|
**Fecha:** 2026-02-05
|
|
**Perfil:** Especialista en Base de Datos y Modelado de Datos
|
|
|
|
---
|
|
|
|
## R1. Consolidar Catalogos de Simbolos (PRIORIDAD ALTA)
|
|
|
|
**Problema:** `trading.symbols` (UUID PK) y `market_data.tickers` (SERIAL PK) son catalogos
|
|
paralelos del mismo concepto con PKs incompatibles.
|
|
|
|
**Recomendacion:**
|
|
1. Designar `trading.symbols` como tabla maestra (ya usa UUID, mas campos)
|
|
2. Agregar campos ML de tickers a symbols: `is_ml_enabled`, `polygon_ticker`, `supported_timeframes`
|
|
3. Migrar `market_data.tickers` a vista o tabla dependiente con FK a `trading.symbols`
|
|
4. Actualizar todas las referencias de `market_data.tickers.id` (SERIAL) a usar `trading.symbols.id` (UUID)
|
|
|
|
**Impacto:** Afecta ml schema, market_data schema, data-service Python
|
|
**Esfuerzo:** 12h (4h analisis + 8h implementacion)
|
|
|
|
---
|
|
|
|
## R2. Ejecutar Migraciones de Enums (PRIORIDAD ALTA)
|
|
|
|
**Problema:** Existen archivos de migracion para 2 de 3 conflictos, pero estan comentados y
|
|
nunca se ejecutaron.
|
|
|
|
**Hallazgo clave:** Ambos archivos de migracion existen pero son **solo documentacion** (SQL comentado).
|
|
`public.trading_timeframe` ya fue creado en `00-global-types.sql` pero las tablas no fueron migradas.
|
|
|
|
**Recomendacion por conflicto:**
|
|
|
|
1. **transaction_type (CONF-001, ALTA):** NO renombrar (breaking change). Mantener separados
|
|
con calificacion de schema estricta. Los schemas son separados y sirven propositos distintos.
|
|
Documentar la distincion en backend y enforcer `schema.enum` en todas las queries.
|
|
|
|
2. **timeframe (DUP-001, MEDIA):** `public.trading_timeframe` ya existe con 9 valores.
|
|
Ejecutar migracion de columnas en 3 tablas: `trading.bots`, `trading.signals`, `trading.drawing_tools`.
|
|
Non-breaking change (valores compatibles). Luego DROP tipos viejos.
|
|
|
|
3. **risk_profile (DUP-002, BAJA):** Valores identicos en ambos schemas. Opcional:
|
|
crear `public.risk_profile` para consistencia. No es urgente.
|
|
|
|
**Secuencia de ejecucion (solo timeframe - unico ejecutable sin riesgo):**
|
|
```sql
|
|
-- Paso 1: Migrar trading.bots.timeframe
|
|
ALTER TABLE trading.bots ADD COLUMN timeframe_new public.trading_timeframe;
|
|
UPDATE trading.bots SET timeframe_new = timeframe::text::public.trading_timeframe;
|
|
ALTER TABLE trading.bots DROP COLUMN timeframe;
|
|
ALTER TABLE trading.bots RENAME COLUMN timeframe_new TO timeframe;
|
|
|
|
-- Paso 2: Repetir para trading.signals y trading.drawing_tools
|
|
-- Paso 3: DROP TYPE trading.timeframe; DROP TYPE market_data.timeframe;
|
|
```
|
|
|
|
---
|
|
|
|
## R3. Agregar Foreign Keys Cross-Schema (PRIORIDAD ALTA)
|
|
|
|
**Problema:** Relaciones logicas entre schemas no estan formalizadas con FK.
|
|
|
|
**Recomendacion:**
|
|
|
|
### R3.1 investment.accounts -> financial.wallets
|
|
```sql
|
|
ALTER TABLE investment.accounts
|
|
ADD COLUMN wallet_id UUID REFERENCES financial.wallets(id);
|
|
```
|
|
Nota: La columna `wallet_id` ya existe en el DDL actual de `investment.accounts`. Verificar si el FK esta creado.
|
|
|
|
### R3.2 trading.bots -> financial.wallets
|
|
```sql
|
|
ALTER TABLE trading.bots
|
|
ADD COLUMN wallet_id UUID REFERENCES financial.wallets(id);
|
|
```
|
|
Para vincular capital de bots con wallets formalmente.
|
|
|
|
### R3.3 market_data.tickers -> trading.symbols
|
|
```sql
|
|
ALTER TABLE market_data.tickers
|
|
ADD COLUMN symbol_id UUID REFERENCES trading.symbols(id);
|
|
```
|
|
Vincula catalogos hasta que se consoliden (R1).
|
|
|
|
---
|
|
|
|
## R4. Documentar feature_flags Schema (PRIORIDAD ALTA)
|
|
|
|
**Problema:** Schema completo invisible para backend y documentacion.
|
|
|
|
**Recomendacion:**
|
|
1. Agregar a CLAUDE.md del proyecto en la seccion de schemas
|
|
2. Crear entity `Flag` en backend
|
|
3. Crear servicio `FeatureFlagService` con cache Redis
|
|
4. Documentar tabla `flags` en docs/ con ET (especificacion tecnica)
|
|
5. Integrar en middleware de Express para feature gating
|
|
|
|
**Patron sugerido:**
|
|
```typescript
|
|
// Middleware
|
|
const featureFlag = async (flagName: string) => {
|
|
const flag = await featureFlagService.getFlag(flagName);
|
|
return flag?.is_enabled ?? false;
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
## R5. Estandarizar Nomenclatura (PRIORIDAD MEDIA)
|
|
|
|
**Problema:** Inconsistencias en nombres de campos entre schemas.
|
|
|
|
| Caso | Tabla A | Tabla B | Recomendacion |
|
|
|------|---------|---------|---------------|
|
|
| asset_type vs asset_class | market_data.tickers | trading.symbols | Usar `asset_class` |
|
|
| strategy_type (VARCHAR) | trading.bots | - | Considerar FK a catalogo |
|
|
| timeframe (multiples) | public, trading, market_data | - | Consolidar en 1 enum |
|
|
|
|
---
|
|
|
|
## R6. Crear Servicios para audit Schema (PRIORIDAD MEDIA)
|
|
|
|
**Problema:** 7 tablas de audit sin ningun servicio backend (0% coherencia).
|
|
|
|
**Recomendacion:** Crear un modulo audit con:
|
|
1. `AuditService` - queries sobre audit_logs, data_access_logs
|
|
2. `SecurityEventService` - queries sobre security_events
|
|
3. `TradingAuditService` - queries sobre trading_audit
|
|
4. `ComplianceService` - queries sobre compliance_logs
|
|
5. `AuditController` - endpoints admin-only con paginacion
|
|
|
|
**Endpoints sugeridos:**
|
|
```
|
|
GET /api/admin/audit/logs?user_id=&event_type=&from=&to=&page=&limit=
|
|
GET /api/admin/audit/security?severity=&from=&to=
|
|
GET /api/admin/audit/trading?bot_id=&from=&to=
|
|
GET /api/admin/audit/compliance?type=&status=
|
|
GET /api/admin/audit/export?format=csv|json&from=&to=
|
|
```
|
|
|
|
---
|
|
|
|
## R7. Patron de Soft Delete (PRIORIDAD BAJA)
|
|
|
|
**Problema:** `financial.wallets` usa `ON DELETE RESTRICT` en FK a `auth.users`, lo que
|
|
impide eliminar usuarios con wallet.
|
|
|
|
**Recomendacion:**
|
|
1. Documentar como decision arquitectural (no es bug)
|
|
2. Implementar soft delete: agregar `deleted_at TIMESTAMPTZ` a `auth.users`
|
|
3. Actualizar queries para filtrar `WHERE deleted_at IS NULL`
|
|
4. Mantener RESTRICT para proteger integridad financiera
|
|
|
|
---
|
|
|
|
## R8. Indices Compuestos para Performance (PRIORIDAD BAJA)
|
|
|
|
**Recomendacion de indices adicionales:**
|
|
|
|
```sql
|
|
-- Alertas activas por usuario y simbolo (query frecuente)
|
|
CREATE INDEX idx_price_alerts_user_symbol_active
|
|
ON trading.price_alerts(user_id, symbol_id)
|
|
WHERE status = 'active';
|
|
|
|
-- Predicciones recientes por simbolo y tipo
|
|
CREATE INDEX idx_predictions_symbol_type_created
|
|
ON ml.predictions(symbol, prediction_type, created_at DESC);
|
|
|
|
-- Enrollments activos por usuario
|
|
CREATE INDEX idx_enrollments_user_active
|
|
ON education.enrollments(user_id)
|
|
WHERE status IN ('active', 'in_progress');
|
|
|
|
-- OHLCV queries recientes
|
|
CREATE INDEX idx_ohlcv_5m_recent
|
|
ON market_data.ohlcv_5m(symbol, timestamp DESC);
|
|
```
|
|
|
|
---
|
|
|
|
## R9. Considerar Particionamiento para Tablas de Alto Volumen (FUTURO)
|
|
|
|
Las siguientes tablas pueden beneficiarse de particionamiento por fecha:
|
|
|
|
| Tabla | Razon | Estrategia |
|
|
|-------|-------|------------|
|
|
| market_data.ohlcv_5m | Alto volumen (288 registros/dia/simbolo) | Range partition por mes |
|
|
| market_data.ohlcv_15m | Alto volumen (96 registros/dia/simbolo) | Range partition por mes |
|
|
| audit.audit_logs | Crecimiento continuo | Range partition por mes |
|
|
| audit.api_request_logs | Alto volumen por request | Range partition por semana |
|
|
|
|
---
|
|
|
|
## Resumen de Prioridades
|
|
|
|
| # | Recomendacion | Prioridad | Esfuerzo | Impacto |
|
|
|---|---------------|-----------|----------|---------|
|
|
| R1 | Consolidar catalogos simbolos | ALTA | 12h | Elimina duplicacion |
|
|
| R2 | Ejecutar migraciones enums | ALTA | 5h | Elimina 3 conflictos |
|
|
| R3 | Agregar FKs cross-schema | ALTA | 4h | Integridad referencial |
|
|
| R4 | Documentar feature_flags | ALTA | 8h | Schema invisible |
|
|
| R5 | Estandarizar nomenclatura | MEDIA | 2h | Consistencia |
|
|
| R6 | Servicios audit | MEDIA | 32h | 0% -> 100% coherencia |
|
|
| R7 | Soft delete pattern | BAJA | 4h | Mejora UX admin |
|
|
| R8 | Indices compuestos | BAJA | 2h | Performance |
|
|
| R9 | Particionamiento | FUTURO | 16h | Escalabilidad |
|
|
|
|
---
|
|
|
|
*Generado por Claude Code (Opus 4.6) - TASK-2026-02-05-ANALISIS-VALIDACION-MODELADO-BD*
|