trading-platform-database-v2/migrations/2026-02-03_add_predictions_overlay.sql
Adrian Flores Cortes c651fe5a30 [TASK-2026-02-03-ANALISIS-DDL-MODELADO] feat(ddl): FASE-1 Gaps Críticos P0
ST-1.1: financial.refunds - Already exists with approval flow
ST-1.2: education.instructors - Created with GIN indexes
ST-1.3: trading.price_alerts - FK exists, idempotent migration added
ST-1.4: ml.prediction_overlays - New table + overlay columns

New files:
- ddl/schemas/education/tables/17-instructors.sql
- ddl/schemas/ml/tables/12-prediction_overlays.sql
- migrations/2026-02-03_add_predictions_overlay.sql
- migrations/2026-02-03_add_price_alerts_symbol_fk.sql

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 23:45:39 -06:00

156 lines
5.7 KiB
PL/PgSQL

-- =====================================================
-- MIGRATION: Add overlay columns to ml.predictions
-- =====================================================
-- Date: 2026-02-03
-- Task: TASK-2026-02-03-ANALISIS-DDL-MODELADO / ST-1.4
-- Description: Complete overlay structure for ML predictions visualization
-- =====================================================
-- ===========================================
-- PART 1: ADD COLUMNS TO ml.predictions
-- ===========================================
-- Add overlay visualization data
ALTER TABLE ml.predictions
ADD COLUMN IF NOT EXISTS overlay_data JSONB DEFAULT '{}';
-- Add chart configuration
ALTER TABLE ml.predictions
ADD COLUMN IF NOT EXISTS chart_config JSONB DEFAULT '{
"show_on_chart": true,
"color": "#4CAF50",
"line_style": "dashed",
"opacity": 0.8
}';
-- Add display priority for ordering multiple predictions
ALTER TABLE ml.predictions
ADD COLUMN IF NOT EXISTS display_priority INTEGER DEFAULT 0;
-- ===========================================
-- PART 2: INDEXES FOR OVERLAY QUERIES
-- ===========================================
-- Index for overlay queries
CREATE INDEX IF NOT EXISTS idx_predictions_overlay
ON ml.predictions(symbol, timeframe, display_priority DESC)
WHERE (chart_config->>'show_on_chart')::boolean = true;
-- Index for overlay data
CREATE INDEX IF NOT EXISTS idx_predictions_overlay_data
ON ml.predictions USING GIN (overlay_data)
WHERE overlay_data IS NOT NULL AND overlay_data != '{}';
-- ===========================================
-- PART 3: COLUMN COMMENTS
-- ===========================================
COMMENT ON COLUMN ml.predictions.overlay_data IS 'JSON data for chart overlay visualization (price levels, zones, etc)';
COMMENT ON COLUMN ml.predictions.chart_config IS 'Configuration for how to display this prediction on charts';
COMMENT ON COLUMN ml.predictions.display_priority IS 'Priority for ordering when multiple predictions exist (higher = more prominent)';
-- ===========================================
-- PART 4: CREATE OVERLAY TYPE ENUM (if not exists)
-- ===========================================
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'overlay_type' AND typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'ml')) THEN
CREATE TYPE ml.overlay_type AS ENUM (
'support_resistance',
'trend_line',
'zone',
'arrow',
'label',
'fibonacci',
'order_block',
'fair_value_gap',
'liquidity_level',
'ict_killzone'
);
END IF;
END $$;
-- ===========================================
-- PART 5: CREATE prediction_overlays TABLE
-- ===========================================
CREATE TABLE IF NOT EXISTS ml.prediction_overlays (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
prediction_id UUID NOT NULL REFERENCES ml.predictions(id) ON DELETE CASCADE,
overlay_type ml.overlay_type NOT NULL,
label VARCHAR(100),
price_levels DECIMAL(18,8)[] DEFAULT '{}',
time_range TSTZRANGE,
time_point TIMESTAMPTZ,
price_point DECIMAL(18,8),
coordinates JSONB DEFAULT '[]',
style_config JSONB DEFAULT '{
"color": "#4CAF50",
"line_width": 1,
"line_style": "solid",
"fill_opacity": 0.2,
"text_color": "#FFFFFF",
"font_size": 12
}',
metadata JSONB DEFAULT '{}',
is_active BOOLEAN NOT NULL DEFAULT true,
display_priority INTEGER DEFAULT 0,
z_index INTEGER DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
expires_at TIMESTAMPTZ
);
-- Indexes for prediction_overlays
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_prediction
ON ml.prediction_overlays(prediction_id);
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_active
ON ml.prediction_overlays(prediction_id, is_active)
WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_type
ON ml.prediction_overlays(overlay_type);
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_time_range
ON ml.prediction_overlays USING GIST (time_range)
WHERE time_range IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_priority
ON ml.prediction_overlays(display_priority DESC, z_index DESC)
WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_expires
ON ml.prediction_overlays(expires_at)
WHERE expires_at IS NOT NULL AND is_active = true;
CREATE INDEX IF NOT EXISTS idx_prediction_overlays_metadata
ON ml.prediction_overlays USING GIN (metadata)
WHERE metadata IS NOT NULL AND metadata != '{}';
-- Trigger for updated_at
CREATE OR REPLACE FUNCTION ml.update_prediction_overlays_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trigger_prediction_overlays_updated_at ON ml.prediction_overlays;
CREATE TRIGGER trigger_prediction_overlays_updated_at
BEFORE UPDATE ON ml.prediction_overlays
FOR EACH ROW
EXECUTE FUNCTION ml.update_prediction_overlays_updated_at();
-- Comments
COMMENT ON TABLE ml.prediction_overlays IS 'Complex overlay configurations for chart visualization';
COMMENT ON COLUMN ml.prediction_overlays.prediction_id IS 'Reference to parent ML prediction';
COMMENT ON COLUMN ml.prediction_overlays.overlay_type IS 'Type of overlay for rendering';
COMMENT ON COLUMN ml.prediction_overlays.price_levels IS 'Array of price levels for horizontal overlays';
COMMENT ON COLUMN ml.prediction_overlays.time_range IS 'Time range for time-bounded overlays';
COMMENT ON COLUMN ml.prediction_overlays.coordinates IS 'JSON array of {time, price} coordinates';
COMMENT ON COLUMN ml.prediction_overlays.style_config IS 'Visual styling configuration';
COMMENT ON COLUMN ml.prediction_overlays.is_active IS 'Whether overlay should be displayed';