# 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