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>
7.6 KiB
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:
- Designar
trading.symbolscomo tabla maestra (ya usa UUID, mas campos) - Agregar campos ML de tickers a symbols:
is_ml_enabled,polygon_ticker,supported_timeframes - Migrar
market_data.tickersa vista o tabla dependiente con FK atrading.symbols - Actualizar todas las referencias de
market_data.tickers.id(SERIAL) a usartrading.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:
-
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.enumen todas las queries. -
timeframe (DUP-001, MEDIA):
public.trading_timeframeya 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. -
risk_profile (DUP-002, BAJA): Valores identicos en ambos schemas. Opcional: crear
public.risk_profilepara consistencia. No es urgente.
Secuencia de ejecucion (solo timeframe - unico ejecutable sin riesgo):
-- 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
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
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
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:
- Agregar a CLAUDE.md del proyecto en la seccion de schemas
- Crear entity
Flagen backend - Crear servicio
FeatureFlagServicecon cache Redis - Documentar tabla
flagsen docs/ con ET (especificacion tecnica) - Integrar en middleware de Express para feature gating
Patron sugerido:
// 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:
AuditService- queries sobre audit_logs, data_access_logsSecurityEventService- queries sobre security_eventsTradingAuditService- queries sobre trading_auditComplianceService- queries sobre compliance_logsAuditController- 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:
- Documentar como decision arquitectural (no es bug)
- Implementar soft delete: agregar
deleted_at TIMESTAMPTZaauth.users - Actualizar queries para filtrar
WHERE deleted_at IS NULL - Mantener RESTRICT para proteger integridad financiera
R8. Indices Compuestos para Performance (PRIORIDAD BAJA)
Recomendacion de indices adicionales:
-- 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