Sprint 4 deliverables: - DATABASE-SCHEMA.md: ER diagrams for 12 schemas (~90 tables) - TESTING-STRATEGY.md: Testing pyramid (70/20/10), frameworks, CI/CD Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
46 KiB
46 KiB
DATABASE-SCHEMA.md - Trading Platform
Version: 1.0.0 Fecha: 2026-01-30 Motor: PostgreSQL 16+ Proyecto: trading-platform
Resumen de Schemas
| Schema | Tablas | Descripción |
|---|---|---|
auth |
10 | Autenticación, usuarios, sesiones, OAuth |
education |
14 | Cursos, lecciones, quizzes, gamificación |
trading |
10+ | Símbolos, órdenes, posiciones, watchlists |
investment |
7 | Productos PAMM, cuentas, distribuciones |
financial |
10 | Wallets, transacciones, suscripciones |
portfolio |
5+ | Perfiles de riesgo, allocations, goals |
market_data |
4 | OHLCV 5m/15m, staging |
ml |
9 | Modelos, predicciones, feature store |
llm |
5 | Conversaciones, mensajes, embeddings |
audit |
7 | Logs de auditoría, seguridad, compliance |
notifications |
3+ | Notificaciones, preferencias |
feature_flags |
3 | Flags, user overrides, evaluations |
Total estimado: ~90 tablas
Diagrama ER por Schema
1. Schema: auth
┌─────────────────────────────────────────────────────────────────────────┐
│ auth │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ users │──┬──<│ user_profiles │ │ oauth_accounts │ │
│ ├─────────────────┤ │ ├─────────────────┤ ├─────────────────┤ │
│ │ id (PK) │ │ │ user_id (FK) │ │ user_id (FK) │ │
│ │ email │ │ │ first_name │ │ provider │ │
│ │ password_hash │ │ │ last_name │ │ provider_id │ │
│ │ status │ │ │ avatar_url │ │ access_token │ │
│ │ role │ │ │ subscription_id │ │ refresh_token │ │
│ │ mfa_enabled │ │ │ trading_exp │ └─────────────────┘ │
│ │ mfa_secret │ │ │ risk_tolerance │ │
│ │ backup_codes │ │ │ ... │ │
│ │ ... │ │ └─────────────────┘ │
│ └─────────────────┘ │ │
│ │ │ ┌─────────────────┐ ┌─────────────────┐ │
│ │ └──<│ sessions │ │ auth_logs │ │
│ │ ├─────────────────┤ ├─────────────────┤ │
│ │ │ user_id (FK) │ │ user_id (FK) │ │
│ │ │ token_hash │ │ event │ │
│ │ │ ip_address │ │ ip_address │ │
│ │ │ user_agent │ │ success │ │
│ │ │ expires_at │ │ created_at │ │
│ │ └─────────────────┘ └─────────────────┘ │
│ │ │
│ │ ┌──────────────────┐ ┌──────────────────┐ │
│ └──<│ email_verify │ │ password_resets │ │
│ ├──────────────────┤ ├──────────────────┤ │
│ │ user_id (FK) │ │ user_id (FK) │ │
│ │ token │ │ token │ │
│ │ expires_at │ │ expires_at │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘
2. Schema: education
┌─────────────────────────────────────────────────────────────────────────┐
│ education │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐│
│ │ categories │───<│ courses │───<│ modules │──<│ lessons ││
│ ├─────────────┤ ├─────────────┤ ├─────────────┤ ├───────────┤│
│ │ id (PK) │ │ id (PK) │ │ id (PK) │ │ id (PK) ││
│ │ name │ │ category_id │ │ course_id │ │ module_id ││
│ │ slug │ │ title │ │ title │ │ title ││
│ │ description │ │ difficulty │ │ order │ │ type ││
│ └─────────────┘ │ duration │ └─────────────┘ │ content ││
│ │ price │ │ video_url ││
│ │ status │ │ duration ││
│ └─────────────┘ └───────────┘│
│ │ │ │
│ │ │ │
│ ┌─────────────────┐ │ ┌─────────────────┐ │ │
│ │ enrollments │<──┘ │ quizzes │<───────────┘ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ user_id (FK) │ │ lesson_id (FK) │ │
│ │ course_id (FK) │ │ title │ │
│ │ progress_pct │ │ passing_score │ │
│ │ status │ │ time_limit │ │
│ │ completed_at │ └────────┬────────┘ │
│ └────────┬────────┘ │ │
│ │ │ │
│ ┌────────┴────────┐ ┌────────────┴──────────┐ │
│ │ progress │ │ quiz_questions │ │
│ ├─────────────────┤ ├───────────────────────┤ │
│ │ enrollment_id │ │ quiz_id (FK) │ │
│ │ lesson_id (FK) │ │ question_text │ │
│ │ completed │ │ question_type │ │
│ │ completed_at │ │ options (JSONB) │ │
│ └─────────────────┘ │ correct_answer │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────┐ ┌───────────────────┐ ┌─────────────────┐ │
│ │ certificates │ │ user_achievements │ │ gamification │ │
│ ├───────────────────┤ ├───────────────────┤ │ _profile │ │
│ │ user_id (FK) │ │ user_id (FK) │ ├─────────────────┤ │
│ │ course_id (FK) │ │ achievement_type │ │ user_id (FK) │ │
│ │ issued_at │ │ earned_at │ │ xp_total │ │
│ │ certificate_url │ │ metadata │ │ level │ │
│ └───────────────────┘ └───────────────────┘ │ streak_days │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3. Schema: trading
┌─────────────────────────────────────────────────────────────────────────┐
│ trading │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ │
│ │ symbols │──────────────────────────────┐ │
│ ├─────────────────┤ │ │
│ │ id (PK) │ │ │
│ │ name (XAUUSD) │ │ │
│ │ base_currency │ │ │
│ │ quote_currency │ │ │
│ │ pip_value │ │ │
│ │ is_active │ │ │
│ └─────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────┐ ┌────────────┴──────────┐ │
│ └────<│ watchlists │ │ paper_accounts │ │
│ ├─────────────────┤ ├───────────────────────┤ │
│ │ user_id (FK) │ │ user_id (FK) │ │
│ │ name │ │ balance │ │
│ │ symbols[] │ │ equity │ │
│ │ is_default │ │ margin_used │ │
│ └─────────────────┘ │ realized_pnl │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌─────────────────┐ ┌─────────────────┐ │ │
│ │ trade_bots │───<│ bot_positions │ │ │
│ ├─────────────────┤ ├─────────────────┤ │ │
│ │ id (PK) │ │ bot_id (FK) │ │ │
│ │ user_id (FK) │ │ symbol │ │ │
│ │ name │ │ side (BUY/SELL) │ │ │
│ │ strategy │ │ size │ │ │
│ │ status │ │ entry_price │ │ │
│ │ risk_per_trade │ │ current_price │ │ │
│ └─────────────────┘ │ pnl │ │ │
│ └─────────────────┘ │ │
│ │ │
│ ┌─────────────────────┐ ┌─────────────────┴───────┐ │
│ │ paper_orders │ │ paper_positions │ │
│ ├─────────────────────┤ ├─────────────────────────┤ │
│ │ account_id (FK) │ │ account_id (FK) │ │
│ │ symbol │ │ symbol │ │
│ │ type (MARKET/LIMIT) │ │ side │ │
│ │ side │ │ quantity │ │
│ │ quantity │ │ entry_price │ │
│ │ price │ │ current_price │ │
│ │ status │ │ unrealized_pnl │ │
│ │ filled_at │ │ stop_loss │ │
│ └─────────────────────┘ │ take_profit │ │
│ └─────────────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ signals │ │ user_signals │ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ id (PK) │ │ user_id (FK) │ │
│ │ symbol │ │ signal_id (FK) │ │
│ │ direction │ │ followed_at │ │
│ │ entry_price │ │ status │ │
│ │ confidence │ └─────────────────┘ │
│ │ created_at │ │
│ └─────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
4. Schema: investment
┌─────────────────────────────────────────────────────────────────────────┐
│ investment │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ │
│ │ products │ (PAMM accounts: Atlas, Orion, Nova) │
│ ├─────────────────────┤ │
│ │ id (PK) │ │
│ │ name │───────────────────────────────┐ │
│ │ code (ATLAS/ORION) │ │ │
│ │ risk_profile │ │ │
│ │ target_return │ │ │
│ │ max_drawdown │ │ │
│ │ min_investment │ │ │
│ │ management_fee │ │ │
│ │ performance_fee │ │ │
│ │ status │ │ │
│ └─────────────────────┘ │ │
│ │ │
│ ┌─────────────────────┐ ┌─────────────────────┐│ │
│ │ risk_questionnaire │ │ accounts ││ │
│ ├─────────────────────┤ ├─────────────────────┤│ │
│ │ user_id (FK) │ │ id (PK) ││ │
│ │ answers (JSONB) │ │ user_id (FK) │┘ │
│ │ risk_score │ │ product_id (FK) │ │
│ │ profile_type │ │ balance │ │
│ │ completed_at │ │ status │ │
│ └─────────────────────┘ │ performance_pct │ │
│ │ opened_at │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌─────────────────────┐ │ │
│ │ distributions │<─────────────┤ │
│ ├─────────────────────┤ │ │
│ │ account_id (FK) │ │ │
│ │ amount │ │ │
│ │ distribution_date │ │ │
│ │ status │ │ │
│ └─────────────────────┘ │ │
│ │ │
│ ┌─────────────────────┐ ┌────────┴────────────┐ │
│ │ withdrawal_requests │ │ transactions │ │
│ ├─────────────────────┤ ├─────────────────────┤ │
│ │ account_id (FK) │ │ account_id (FK) │ │
│ │ amount │ │ type (deposit/ │ │
│ │ status │ │ withdrawal) │ │
│ │ requested_at │ │ amount │ │
│ │ processed_at │ │ status │ │
│ └─────────────────────┘ │ created_at │ │
│ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ │
│ │ daily_performance │ │
│ ├─────────────────────┤ │
│ │ product_id (FK) │ │
│ │ date │ │
│ │ nav │ │
│ │ return_pct │ │
│ │ drawdown │ │
│ └─────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
5. Schema: financial
┌─────────────────────────────────────────────────────────────────────────┐
│ financial │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ customers │ │ subscriptions │ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ user_id (FK) │────────────────────│ user_id (FK) │ │
│ │ stripe_id │ │ plan_id │ │
│ │ created_at │ │ status │ │
│ └─────────────────┘ │ stripe_sub_id │ │
│ │ │ current_period │ │
│ │ └─────────────────┘ │
│ │ │
│ ┌───────┴─────────┐ ┌─────────────────┐ │
│ │ wallets │───<│ wallet_trans │ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ user_id (FK) │ │ wallet_id (FK) │ │
│ │ balance │ │ type │ │
│ │ currency │ │ amount │ │
│ │ updated_at │ │ status │ │
│ └─────────────────┘ │ reference_id │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ invoices │───<│ payments │ │ payment_methods │ │
│ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ │
│ │ user_id (FK) │ │ invoice_id (FK) │ │ user_id (FK) │ │
│ │ amount │ │ amount │ │ type │ │
│ │ status │ │ method │ │ stripe_pm_id │ │
│ │ due_date │ │ status │ │ is_default │ │
│ │ paid_at │ │ processed_at │ │ last_four │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ currency_exchange_rates │ │ wallet_limits │ │
│ ├─────────────────────────┤ ├─────────────────────────┤ │
│ │ from_currency │ │ user_id (FK) │ │
│ │ to_currency │ │ daily_limit │ │
│ │ rate │ │ monthly_limit │ │
│ │ updated_at │ │ single_tx_limit │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────┘
6. Schema: ml
┌─────────────────────────────────────────────────────────────────────────┐
│ ml │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ models │───<│ model_versions │ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ id (PK) │ │ model_id (FK) │ │
│ │ name │ │ version │ │
│ │ type │ │ metrics (JSONB) │ │
│ │ symbol │ │ file_path │ │
│ │ status │ │ is_active │ │
│ └─────────────────┘ │ created_at │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────────┐ │
│ │ predictions │───<│ prediction_outcomes │ │
│ ├─────────────────┤ ├─────────────────────┤ │
│ │ model_id (FK) │ │ prediction_id (FK) │ │
│ │ symbol │ │ actual_high │ │
│ │ horizon │ │ actual_low │ │
│ │ predicted_high │ │ accuracy │ │
│ │ predicted_low │ │ evaluated_at │ │
│ │ confidence │ └─────────────────────┘ │
│ │ created_at │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ feature_store │ │ llm_predictions │ │ llm_decisions │ │
│ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ │
│ │ symbol │ │ id (PK) │ │ prediction_id │ │
│ │ timestamp │ │ user_id (FK) │ │ decision │ │
│ │ features (JSONB)│ │ symbol │ │ reasoning │ │
│ │ created_at │ │ analysis │ │ confidence │ │
│ └─────────────────┘ │ recommendation │ │ created_at │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ │
│ │ risk_events │ (Risk management alerts) │
│ ├─────────────────┤ │
│ │ user_id (FK) │ │
│ │ event_type │ │
│ │ severity │ │
│ │ details (JSONB) │ │
│ │ created_at │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
7. Schema: llm
┌─────────────────────────────────────────────────────────────────────────┐
│ llm │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ conversations │───<│ messages │ │
│ ├─────────────────┤ ├─────────────────┤ │
│ │ id (PK) │ │ conversation_id │ │
│ │ user_id (FK) │ │ role │ │
│ │ title │ │ content │ │
│ │ created_at │ │ tools_used │ │
│ │ updated_at │ │ tokens_used │ │
│ └─────────────────┘ │ created_at │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │user_preferences │ │ user_memory │ │ embeddings │ │
│ ├─────────────────┤ ├─────────────────┤ ├─────────────────┤ │
│ │ user_id (FK) │ │ user_id (FK) │ │ id (PK) │ │
│ │ model_provider │ │ key │ │ content_type │ │
│ │ temperature │ │ value │ │ content_id │ │
│ │ context_length │ │ category │ │ embedding │ │ (pgvector)
│ │ system_prompt │ │ expires_at │ │ metadata │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
8. Schema: audit
┌─────────────────────────────────────────────────────────────────────────┐
│ audit │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ audit_logs │ │ security_events │ │
│ ├─────────────────────┤ ├─────────────────────┤ │
│ │ id (PK) │ │ id (PK) │ │
│ │ event_type │ │ category │ │
│ │ event_status │ │ severity │ │
│ │ severity │ │ user_id (FK) │ │
│ │ user_id (FK) │ │ ip_address │ │
│ │ resource_type │ │ event_code │ │
│ │ resource_id │ │ is_blocked │ │
│ │ action │ │ requires_review │ │
│ │ old_values (JSONB) │ │ raw_data (JSONB) │ │
│ │ new_values (JSONB) │ │ created_at │ │
│ │ ip_address │ └─────────────────────┘ │
│ │ created_at │ │
│ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ compliance_logs │ │ trading_audit │ │
│ ├─────────────────────┤ ├─────────────────────┤ │
│ │ id (PK) │ │ id (PK) │ │
│ │ regulation │ │ user_id (FK) │ │
│ │ requirement │ │ action │ │
│ │ compliance_status │ │ symbol │ │
│ │ risk_level │ │ order_details │ │
│ │ evidence (JSONB) │ │ execution_time │ │
│ │ remediation_req │ │ created_at │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ api_request_logs │ │ data_access_logs │ │
│ ├─────────────────────┤ ├─────────────────────┤ │
│ │ endpoint │ │ user_id (FK) │ │
│ │ method │ │ table_name │ │
│ │ status_code │ │ operation │ │
│ │ response_time_ms │ │ record_id │ │
│ │ user_id (FK) │ │ fields_accessed │ │
│ │ created_at │ │ created_at │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
9. Schema: feature_flags
┌─────────────────────────────────────────────────────────────────────────┐
│ feature_flags │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ flags │───<│ user_flags │ │
│ ├─────────────────────┤ ├─────────────────────┤ │
│ │ id (PK) │ │ user_id (FK) │ │
│ │ code (UNIQUE) │ │ flag_id (FK) │ │
│ │ name │ │ is_enabled │ │
│ │ description │ │ reason │ │
│ │ category │ │ expires_at │ │
│ │ status │ └─────────────────────┘ │
│ │ rollout_percentage │ │
│ │ targeting_rules │ ┌─────────────────────┐ │
│ │ expires_at │───<│ evaluations │ │
│ └─────────────────────┘ ├─────────────────────┤ │
│ │ flag_id (FK) │ │
│ │ user_id (FK) │ │
│ │ flag_code │ │
│ │ result │ │
│ │ evaluation_reason │ │
│ │ created_at │ │
│ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Extensiones PostgreSQL Utilizadas
| Extensión | Uso |
|---|---|
uuid-ossp |
Generación de UUIDs |
pgcrypto |
Funciones criptográficas |
citext |
Texto case-insensitive (emails) |
pgvector |
Embeddings para LLM (schema llm) |
Convenciones de Nomenclatura
| Elemento | Convención | Ejemplo |
|---|---|---|
| Tablas | snake_case, plural | audit_logs, user_profiles |
| Columnas | snake_case | created_at, user_id |
| PKs | id (UUID) |
id UUID PRIMARY KEY |
| FKs | {tabla}_id |
user_id, course_id |
| Índices | idx_{tabla}_{columnas} |
idx_users_email |
| Enums | {schema}.{nombre} |
auth.user_status |
| Timestamps | _at suffix |
created_at, updated_at |
Credenciales de Conexión
Database: trading_platform
User: trading_user
Password: trading_dev_2026
Host: localhost
Port: 5432
Última actualización: 2026-01-30 Generado por: Claude Code (Opus 4.5) - Sprint 4