trading-platform-database-v2/ddl/schemas/broker_integration/tables/003_spread_statistics.sql
rckrdmrd 4631a58b42 [DDL] feat: Sprint 6 - Add broker_integration and portfolio_management schemas
broker_integration (5 tables):
- broker_accounts: Cuentas MT4/MT5/API conectadas
- broker_prices: Precios en tiempo real
- spread_statistics: Estadisticas historicas de spread
- price_adjustment_model: Modelos de ajuste de precio
- trade_execution: Ejecucion de ordenes

portfolio_management (6 tables):
- portfolios: Portafolios de inversion
- portfolio_accounts: Cuentas vinculadas a portafolios
- investment_goals: Metas de inversion
- rebalance_suggestions: Sugerencias de rebalanceo
- portfolio_snapshots: Snapshots historicos
- monte_carlo_projections: Proyecciones Monte Carlo

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 20:19:27 -06:00

260 lines
9.0 KiB
PL/PgSQL

-- ============================================================================
-- SCHEMA: broker_integration
-- TABLE: spread_statistics, price_adjustment_model
-- DESCRIPTION: Estadisticas de spread y modelos de ajuste de precio
-- VERSION: 1.0.0
-- CREATED: 2026-01-16
-- SPRINT: Sprint 6 - DDL Implementation Roadmap Q1-2026
-- ============================================================================
-- Tabla de Estadisticas de Spread
CREATE TABLE IF NOT EXISTS broker_integration.spread_statistics (
-- Identificadores
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
broker_account_id UUID REFERENCES broker_integration.broker_accounts(id) ON DELETE CASCADE,
-- Simbolo y periodo
symbol VARCHAR(20) NOT NULL,
period_start TIMESTAMPTZ NOT NULL,
period_end TIMESTAMPTZ NOT NULL,
period_type VARCHAR(20) NOT NULL, -- 'hourly', 'daily', 'session'
-- Estadisticas de spread
spread_min DECIMAL(10, 4),
spread_max DECIMAL(10, 4),
spread_avg DECIMAL(10, 4),
spread_median DECIMAL(10, 4),
spread_stddev DECIMAL(10, 4),
spread_percentile_95 DECIMAL(10, 4),
-- Spread por sesion
spread_asia_avg DECIMAL(10, 4),
spread_london_avg DECIMAL(10, 4),
spread_ny_avg DECIMAL(10, 4),
-- Frecuencia de widening
widening_events INTEGER NOT NULL DEFAULT 0,
max_widening_factor DECIMAL(10, 2),
-- Samples
sample_count INTEGER NOT NULL DEFAULT 0,
trading_hours_covered INTEGER, -- Horas de trading cubiertas
-- Comparacion historica
spread_vs_7d_avg DECIMAL(10, 4), -- % vs promedio 7 dias
spread_vs_30d_avg DECIMAL(10, 4), -- % vs promedio 30 dias
-- Metadata
metadata JSONB DEFAULT '{}'::JSONB,
-- Timestamps
calculated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Constraints
CONSTRAINT spread_stats_unique UNIQUE (broker_account_id, symbol, period_start, period_type)
);
COMMENT ON TABLE broker_integration.spread_statistics IS
'Estadisticas historicas de spread por simbolo, broker y periodo';
-- Indices
CREATE INDEX IF NOT EXISTS idx_spread_stats_account
ON broker_integration.spread_statistics(broker_account_id);
CREATE INDEX IF NOT EXISTS idx_spread_stats_symbol
ON broker_integration.spread_statistics(symbol, period_start DESC);
CREATE INDEX IF NOT EXISTS idx_spread_stats_period
ON broker_integration.spread_statistics(period_type, period_start DESC);
-- ============================================================================
-- TABLE: price_adjustment_model
-- ============================================================================
-- Tabla de Modelos de Ajuste de Precio
CREATE TABLE IF NOT EXISTS broker_integration.price_adjustment_model (
-- Identificadores
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
-- Simbolo
symbol VARCHAR(20) NOT NULL,
-- Tipo de modelo
model_type VARCHAR(50) NOT NULL DEFAULT 'spread_based',
-- Parametros del modelo
base_spread_pips DECIMAL(10, 4) NOT NULL DEFAULT 1,
slippage_avg_pips DECIMAL(10, 4) NOT NULL DEFAULT 0.2,
slippage_max_pips DECIMAL(10, 4) NOT NULL DEFAULT 2,
-- Ajustes por sesion
asia_adjustment DECIMAL(5, 4) DEFAULT 1.2, -- Multiplicador
london_adjustment DECIMAL(5, 4) DEFAULT 1.0,
ny_adjustment DECIMAL(5, 4) DEFAULT 1.0,
overlap_adjustment DECIMAL(5, 4) DEFAULT 0.9, -- London-NY overlap
-- Ajustes por volatilidad
low_volatility_adjustment DECIMAL(5, 4) DEFAULT 0.8,
high_volatility_adjustment DECIMAL(5, 4) DEFAULT 1.5,
extreme_volatility_adjustment DECIMAL(5, 4) DEFAULT 2.5,
-- Ajustes por horario
market_open_adjustment DECIMAL(5, 4) DEFAULT 1.5,
market_close_adjustment DECIMAL(5, 4) DEFAULT 1.3,
news_event_adjustment DECIMAL(5, 4) DEFAULT 2.0,
-- Limites
max_total_adjustment DECIMAL(5, 2) DEFAULT 5.0, -- Max pips de ajuste total
min_acceptable_spread DECIMAL(10, 4),
max_acceptable_spread DECIMAL(10, 4),
-- Estado
is_active BOOLEAN NOT NULL DEFAULT TRUE,
-- Validez
valid_from TIMESTAMPTZ NOT NULL DEFAULT NOW(),
valid_until TIMESTAMPTZ,
-- Performance
accuracy_score DECIMAL(5, 2), -- 0-100
last_accuracy_check TIMESTAMPTZ,
predictions_count INTEGER NOT NULL DEFAULT 0,
accurate_predictions INTEGER NOT NULL DEFAULT 0,
-- Metadata
training_data_range JSONB, -- {"start": "...", "end": "..."}
metadata JSONB DEFAULT '{}'::JSONB,
notes TEXT,
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
-- Constraints
CONSTRAINT price_adj_model_unique UNIQUE (tenant_id, symbol, model_type)
);
COMMENT ON TABLE broker_integration.price_adjustment_model IS
'Modelos para ajustar precios de entrada considerando spread y slippage';
-- Indices
CREATE INDEX IF NOT EXISTS idx_price_adj_symbol
ON broker_integration.price_adjustment_model(symbol);
CREATE INDEX IF NOT EXISTS idx_price_adj_active
ON broker_integration.price_adjustment_model(symbol, is_active)
WHERE is_active = TRUE;
-- Funcion para calcular ajuste de precio
CREATE OR REPLACE FUNCTION broker_integration.calculate_price_adjustment(
p_symbol VARCHAR,
p_direction VARCHAR,
p_current_price DECIMAL,
p_session VARCHAR DEFAULT NULL,
p_volatility VARCHAR DEFAULT 'normal'
)
RETURNS TABLE (
adjusted_entry DECIMAL,
adjusted_sl DECIMAL,
adjusted_tp DECIMAL,
total_adjustment_pips DECIMAL,
adjustment_breakdown JSONB
) AS $$
DECLARE
v_model broker_integration.price_adjustment_model;
v_adjustment DECIMAL;
v_session_mult DECIMAL;
v_volatility_mult DECIMAL;
BEGIN
SELECT * INTO v_model
FROM broker_integration.price_adjustment_model
WHERE symbol = p_symbol
AND is_active = TRUE
AND (valid_until IS NULL OR valid_until > NOW())
ORDER BY valid_from DESC
LIMIT 1;
IF NOT FOUND THEN
-- Retornar sin ajuste
RETURN QUERY SELECT
p_current_price,
p_current_price,
p_current_price,
0::DECIMAL,
'{}'::JSONB;
RETURN;
END IF;
-- Determinar multiplicador de sesion
v_session_mult := CASE p_session
WHEN 'asia' THEN v_model.asia_adjustment
WHEN 'london' THEN v_model.london_adjustment
WHEN 'ny' THEN v_model.ny_adjustment
WHEN 'overlap' THEN v_model.overlap_adjustment
ELSE 1.0
END;
-- Determinar multiplicador de volatilidad
v_volatility_mult := CASE p_volatility
WHEN 'low' THEN v_model.low_volatility_adjustment
WHEN 'high' THEN v_model.high_volatility_adjustment
WHEN 'extreme' THEN v_model.extreme_volatility_adjustment
ELSE 1.0
END;
-- Calcular ajuste total en pips
v_adjustment := (v_model.base_spread_pips + v_model.slippage_avg_pips)
* v_session_mult * v_volatility_mult;
-- Limitar ajuste
v_adjustment := LEAST(v_adjustment, v_model.max_total_adjustment);
-- Convertir a precio
v_adjustment := v_adjustment * 0.0001; -- 1 pip = 0.0001
RETURN QUERY SELECT
CASE p_direction
WHEN 'long' THEN p_current_price + v_adjustment
ELSE p_current_price - v_adjustment
END,
p_current_price, -- SL sin ajustar
p_current_price, -- TP sin ajustar
v_adjustment * 10000, -- En pips
jsonb_build_object(
'base_spread', v_model.base_spread_pips,
'slippage', v_model.slippage_avg_pips,
'session_multiplier', v_session_mult,
'volatility_multiplier', v_volatility_mult
);
END;
$$ LANGUAGE plpgsql;
-- Trigger para updated_at
DROP TRIGGER IF EXISTS price_adj_updated_at ON broker_integration.price_adjustment_model;
CREATE TRIGGER price_adj_updated_at
BEFORE UPDATE ON broker_integration.price_adjustment_model
FOR EACH ROW
EXECUTE FUNCTION broker_integration.update_broker_timestamp();
-- RLS
ALTER TABLE broker_integration.spread_statistics ENABLE ROW LEVEL SECURITY;
ALTER TABLE broker_integration.price_adjustment_model ENABLE ROW LEVEL SECURITY;
CREATE POLICY spread_stats_tenant ON broker_integration.spread_statistics
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
CREATE POLICY price_adj_tenant ON broker_integration.price_adjustment_model
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
-- Grants
GRANT SELECT, INSERT, UPDATE, DELETE ON broker_integration.spread_statistics TO trading_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON broker_integration.price_adjustment_model TO trading_app;
GRANT SELECT ON broker_integration.spread_statistics TO trading_readonly;
GRANT SELECT ON broker_integration.price_adjustment_model TO trading_readonly;
GRANT EXECUTE ON FUNCTION broker_integration.calculate_price_adjustment TO trading_app;