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>
156 lines
5.7 KiB
PL/PgSQL
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';
|