trading-platform-database-v2/schemas/03_trading_schema.sql
rckrdmrd 45e77e9a9c feat: Initial commit - Database schemas and scripts
DDL schemas for Trading Platform:
- User management
- Authentication
- Payments
- Education
- ML predictions
- Trading data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 04:30:23 -06:00

429 lines
14 KiB
SQL

-- ============================================================================
-- OrbiQuant IA - Esquema TRADING
-- ============================================================================
-- Archivo: 03_trading_schema.sql
-- Descripción: Bots, señales, estrategias y operaciones de trading
-- Fecha: 2025-12-05
-- ============================================================================
SET search_path TO trading;
-- ============================================================================
-- TIPOS ENUMERADOS
-- ============================================================================
CREATE TYPE bot_status_enum AS ENUM ('active', 'paused', 'stopped', 'error', 'maintenance');
CREATE TYPE signal_status_enum AS ENUM ('pending', 'active', 'triggered', 'expired', 'cancelled');
CREATE TYPE position_status_enum AS ENUM ('open', 'closed', 'pending');
CREATE TYPE timeframe_enum AS ENUM ('1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w');
CREATE TYPE amd_phase_enum AS ENUM ('accumulation', 'manipulation', 'distribution', 'unknown');
CREATE TYPE volatility_regime_enum AS ENUM ('low', 'medium', 'high', 'extreme');
-- ============================================================================
-- TABLA: symbols
-- Descripción: Instrumentos financieros disponibles
-- ============================================================================
CREATE TABLE IF NOT EXISTS symbols (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Identificación
symbol VARCHAR(20) NOT NULL UNIQUE, -- 'XAUUSD', 'EURUSD', 'BTCUSD'
name VARCHAR(100) NOT NULL,
description TEXT,
-- Clasificación
asset_class VARCHAR(50), -- 'forex', 'crypto', 'commodities', 'indices', 'stocks'
base_currency VARCHAR(10),
quote_currency VARCHAR(10),
-- Trading info
pip_value DECIMAL(10,6),
lot_size DECIMAL(10,2),
min_lot DECIMAL(10,4),
max_lot DECIMAL(10,2),
tick_size DECIMAL(10,6),
-- Estado
is_active BOOLEAN DEFAULT TRUE,
trading_hours JSONB, -- [{day, open, close}]
-- Data provider
data_provider VARCHAR(50),
provider_symbol VARCHAR(50),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_symbols_symbol ON symbols(symbol);
CREATE INDEX idx_symbols_asset_class ON symbols(asset_class);
-- ============================================================================
-- TABLA: strategies
-- Descripción: Estrategias de trading disponibles
-- ============================================================================
CREATE TABLE IF NOT EXISTS strategies (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
name VARCHAR(100) NOT NULL,
slug VARCHAR(100) NOT NULL UNIQUE,
description TEXT,
-- Tipo
strategy_type VARCHAR(50), -- 'intraday', 'swing', 'scalping', 'position'
-- Configuración
default_timeframe timeframe_enum DEFAULT '15m',
supported_symbols TEXT[], -- NULL = todos
risk_reward_ratio DECIMAL(4,2) DEFAULT 2.0,
-- Parámetros configurables (JSON Schema)
parameters_schema JSONB,
default_parameters JSONB,
-- ML Model asociado
uses_ml_model BOOLEAN DEFAULT TRUE,
ml_model_id UUID, -- Referencia a ml.models
-- AMD
uses_amd BOOLEAN DEFAULT TRUE,
favorable_phases amd_phase_enum[],
-- Estado
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_strategies_slug ON strategies(slug);
-- ============================================================================
-- TABLA: bots (Agentes de Trading)
-- Descripción: Instancias de bots/agentes de trading
-- ============================================================================
CREATE TABLE IF NOT EXISTS bots (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Identificación
name VARCHAR(100) NOT NULL,
slug VARCHAR(100) NOT NULL UNIQUE,
description TEXT,
avatar_url TEXT,
-- Perfil de riesgo
risk_profile public.risk_profile_enum NOT NULL,
-- Objetivos
target_monthly_return DECIMAL(5,2), -- % objetivo
max_drawdown DECIMAL(5,2), -- % máximo
max_position_size DECIMAL(5,2), -- % del capital
-- Estrategias
strategy_id UUID REFERENCES strategies(id),
strategy_parameters JSONB,
-- Configuración
supported_symbols TEXT[],
default_timeframe timeframe_enum DEFAULT '15m',
min_confidence DECIMAL(3,2) DEFAULT 0.55,
-- Horarios de operación
trading_schedule JSONB, -- Horarios permitidos
-- Estado
status bot_status_enum DEFAULT 'stopped',
last_activity_at TIMESTAMPTZ,
error_message TEXT,
-- Métricas globales (actualizadas periódicamente)
total_trades INT DEFAULT 0,
winning_trades INT DEFAULT 0,
total_profit DECIMAL(15,2) DEFAULT 0,
sharpe_ratio DECIMAL(5,2),
sortino_ratio DECIMAL(5,2),
max_drawdown_actual DECIMAL(5,2),
-- Público
is_public BOOLEAN DEFAULT TRUE, -- Visible para asignar a cuentas
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_bots_slug ON bots(slug);
CREATE INDEX idx_bots_risk_profile ON bots(risk_profile);
CREATE INDEX idx_bots_status ON bots(status);
-- ============================================================================
-- TABLA: signals
-- Descripción: Señales de trading generadas
-- ============================================================================
CREATE TABLE IF NOT EXISTS signals (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Origen
bot_id UUID REFERENCES bots(id),
strategy_id UUID REFERENCES strategies(id),
symbol_id UUID REFERENCES symbols(id),
symbol VARCHAR(20) NOT NULL,
-- Señal
direction public.trade_direction_enum NOT NULL,
timeframe timeframe_enum NOT NULL,
-- Precios
entry_price DECIMAL(20,8) NOT NULL,
stop_loss DECIMAL(20,8) NOT NULL,
take_profit DECIMAL(20,8) NOT NULL,
current_price DECIMAL(20,8),
-- Predicción ML
predicted_delta_high DECIMAL(20,8),
predicted_delta_low DECIMAL(20,8),
prob_tp_first DECIMAL(5,4), -- Probabilidad de tocar TP antes que SL
confidence_score DECIMAL(5,4),
-- Contexto de mercado
amd_phase amd_phase_enum,
volatility_regime volatility_regime_enum,
market_context JSONB, -- Datos adicionales del contexto
-- R:R
risk_reward_ratio DECIMAL(4,2),
risk_pips DECIMAL(10,4),
reward_pips DECIMAL(10,4),
-- Estado
status signal_status_enum DEFAULT 'pending',
triggered_at TIMESTAMPTZ,
expired_at TIMESTAMPTZ,
-- Resultado (si se operó)
outcome VARCHAR(20), -- 'tp_hit', 'sl_hit', 'manual_close', 'expired'
pnl DECIMAL(15,2),
-- Timestamps
valid_until TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_signals_bot ON signals(bot_id);
CREATE INDEX idx_signals_symbol ON signals(symbol);
CREATE INDEX idx_signals_status ON signals(status);
CREATE INDEX idx_signals_created ON signals(created_at DESC);
CREATE INDEX idx_signals_direction ON signals(direction);
-- ============================================================================
-- TABLA: positions
-- Descripción: Posiciones de trading (abiertas y cerradas)
-- ============================================================================
CREATE TABLE IF NOT EXISTS positions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
-- Referencias
bot_id UUID REFERENCES bots(id),
signal_id UUID REFERENCES signals(id),
investment_account_id UUID, -- Referencia a investment.accounts
symbol_id UUID REFERENCES symbols(id),
symbol VARCHAR(20) NOT NULL,
-- Posición
direction public.trade_direction_enum NOT NULL,
lot_size DECIMAL(10,4) NOT NULL,
-- Precios
entry_price DECIMAL(20,8) NOT NULL,
stop_loss DECIMAL(20,8),
take_profit DECIMAL(20,8),
exit_price DECIMAL(20,8),
-- Broker
broker_order_id VARCHAR(100),
broker_position_id VARCHAR(100),
-- Estado
status position_status_enum DEFAULT 'open',
opened_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
closed_at TIMESTAMPTZ,
close_reason VARCHAR(50), -- 'tp', 'sl', 'manual', 'forced', 'margin_call'
-- P&L
realized_pnl DECIMAL(15,2),
unrealized_pnl DECIMAL(15,2),
commission DECIMAL(10,2) DEFAULT 0,
swap DECIMAL(10,2) DEFAULT 0,
-- Metadata
metadata JSONB,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_positions_bot ON positions(bot_id);
CREATE INDEX idx_positions_signal ON positions(signal_id);
CREATE INDEX idx_positions_account ON positions(investment_account_id);
CREATE INDEX idx_positions_status ON positions(status);
CREATE INDEX idx_positions_opened ON positions(opened_at DESC);
-- ============================================================================
-- TABLA: price_alerts
-- Descripción: Alertas de precio configuradas por usuarios
-- ============================================================================
CREATE TYPE alert_condition_enum AS ENUM ('above', 'below', 'crosses_above', 'crosses_below');
CREATE TABLE IF NOT EXISTS price_alerts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
symbol VARCHAR(20) NOT NULL,
condition alert_condition_enum NOT NULL,
price DECIMAL(20,8) NOT NULL,
note TEXT,
-- Estado
is_active BOOLEAN DEFAULT TRUE,
triggered_at TIMESTAMPTZ,
triggered_price DECIMAL(20,8),
-- Notificación
notify_email BOOLEAN DEFAULT TRUE,
notify_push BOOLEAN DEFAULT TRUE,
-- Recurrencia
is_recurring BOOLEAN DEFAULT FALSE, -- Si se reactiva después de triggear
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_price_alerts_user ON price_alerts(user_id);
CREATE INDEX idx_price_alerts_symbol ON price_alerts(symbol);
CREATE INDEX idx_price_alerts_active ON price_alerts(is_active) WHERE is_active = TRUE;
-- ============================================================================
-- TABLA: watchlists
-- Descripción: Listas de seguimiento de usuarios
-- ============================================================================
CREATE TABLE IF NOT EXISTS watchlists (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
is_default BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_watchlists_user ON watchlists(user_id);
-- ============================================================================
-- TABLA: watchlist_items
-- Descripción: Items en watchlists
-- ============================================================================
CREATE TABLE IF NOT EXISTS watchlist_items (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE,
symbol VARCHAR(20) NOT NULL,
sort_order INT DEFAULT 0,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
UNIQUE(watchlist_id, symbol)
);
CREATE INDEX idx_watchlist_items_watchlist ON watchlist_items(watchlist_id);
-- ============================================================================
-- TABLA: paper_trading_accounts
-- Descripción: Cuentas de paper trading (simulación)
-- ============================================================================
CREATE TABLE IF NOT EXISTS paper_trading_accounts (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
name VARCHAR(100) DEFAULT 'Paper Account',
initial_balance DECIMAL(15,2) NOT NULL DEFAULT 100000,
current_balance DECIMAL(15,2) NOT NULL DEFAULT 100000,
currency CHAR(3) DEFAULT 'USD',
-- Métricas
total_trades INT DEFAULT 0,
winning_trades INT DEFAULT 0,
total_pnl DECIMAL(15,2) DEFAULT 0,
max_drawdown DECIMAL(5,2) DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_paper_accounts_user ON paper_trading_accounts(user_id);
-- ============================================================================
-- TABLA: paper_trading_positions
-- Descripción: Posiciones de paper trading
-- ============================================================================
CREATE TABLE IF NOT EXISTS paper_trading_positions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
account_id UUID NOT NULL REFERENCES paper_trading_accounts(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
symbol VARCHAR(20) NOT NULL,
direction public.trade_direction_enum NOT NULL,
lot_size DECIMAL(10,4) NOT NULL,
entry_price DECIMAL(20,8) NOT NULL,
stop_loss DECIMAL(20,8),
take_profit DECIMAL(20,8),
exit_price DECIMAL(20,8),
status position_status_enum DEFAULT 'open',
opened_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
closed_at TIMESTAMPTZ,
close_reason VARCHAR(50),
realized_pnl DECIMAL(15,2),
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_paper_positions_account ON paper_trading_positions(account_id);
CREATE INDEX idx_paper_positions_user ON paper_trading_positions(user_id);
CREATE INDEX idx_paper_positions_status ON paper_trading_positions(status);
-- ============================================================================
-- TRIGGERS
-- ============================================================================
CREATE TRIGGER update_symbols_updated_at
BEFORE UPDATE ON symbols
FOR EACH ROW
EXECUTE FUNCTION public.update_updated_at_column();
CREATE TRIGGER update_strategies_updated_at
BEFORE UPDATE ON strategies
FOR EACH ROW
EXECUTE FUNCTION public.update_updated_at_column();
CREATE TRIGGER update_bots_updated_at
BEFORE UPDATE ON bots
FOR EACH ROW
EXECUTE FUNCTION public.update_updated_at_column();
CREATE TRIGGER update_signals_updated_at
BEFORE UPDATE ON signals
FOR EACH ROW
EXECUTE FUNCTION public.update_updated_at_column();
CREATE TRIGGER update_positions_updated_at
BEFORE UPDATE ON positions
FOR EACH ROW
EXECUTE FUNCTION public.update_updated_at_column();