diff --git a/ddl/00-extensions.sql b/ddl/00-extensions.sql index 6ed9a68..93f2c65 100644 --- a/ddl/00-extensions.sql +++ b/ddl/00-extensions.sql @@ -19,6 +19,9 @@ CREATE EXTENSION IF NOT EXISTS "unaccent"; -- Trigram similarity for fuzzy text matching CREATE EXTENSION IF NOT EXISTS "pg_trgm"; +-- Vector similarity search for LLM embeddings (pgvector) +CREATE EXTENSION IF NOT EXISTS "vector"; + COMMENT ON EXTENSION "uuid-ossp" IS 'UUID generation functions'; COMMENT ON EXTENSION "pgcrypto" IS 'Cryptographic functions for secure password and token handling'; COMMENT ON EXTENSION "citext" IS 'Case-insensitive text type for email addresses'; diff --git a/ddl/01-schemas.sql b/ddl/01-schemas.sql index ebfcae4..a6e9839 100644 --- a/ddl/01-schemas.sql +++ b/ddl/01-schemas.sql @@ -12,6 +12,10 @@ COMMENT ON SCHEMA auth IS 'Authentication, authorization, and user management'; CREATE SCHEMA IF NOT EXISTS education; COMMENT ON SCHEMA education IS 'Educational content, courses, and learning progress'; +-- Market Data +CREATE SCHEMA IF NOT EXISTS market_data; +COMMENT ON SCHEMA market_data IS 'Market tickers, OHLCV data, and data staging'; + -- Trading Operations CREATE SCHEMA IF NOT EXISTS trading; COMMENT ON SCHEMA trading IS 'Trading bots, orders, positions, and market data'; diff --git a/ddl/schemas/auth/tables/04-sessions.sql b/ddl/schemas/auth/tables/04-sessions.sql index b7d61de..61d78ba 100644 --- a/ddl/schemas/auth/tables/04-sessions.sql +++ b/ddl/schemas/auth/tables/04-sessions.sql @@ -15,6 +15,10 @@ CREATE TABLE auth.sessions ( -- Session Token session_token VARCHAR(255) NOT NULL UNIQUE, + -- Token Rotation (for security) + refresh_token_hash VARCHAR(64), + refresh_token_issued_at TIMESTAMPTZ, + -- Session Lifecycle expires_at TIMESTAMPTZ NOT NULL, is_active BOOLEAN NOT NULL DEFAULT true, @@ -70,6 +74,8 @@ COMMENT ON TABLE auth.sessions IS 'User session management for authentication an COMMENT ON COLUMN auth.sessions.id IS 'Unique identifier for the session'; COMMENT ON COLUMN auth.sessions.user_id IS 'Reference to the user account'; COMMENT ON COLUMN auth.sessions.session_token IS 'Unique session token for authentication'; +COMMENT ON COLUMN auth.sessions.refresh_token_hash IS 'SHA-256 hash of refresh token for rotation security'; +COMMENT ON COLUMN auth.sessions.refresh_token_issued_at IS 'Timestamp when current refresh token was issued'; COMMENT ON COLUMN auth.sessions.expires_at IS 'Session expiration timestamp'; COMMENT ON COLUMN auth.sessions.is_active IS 'Whether the session is currently active'; COMMENT ON COLUMN auth.sessions.ip_address IS 'IP address of the session'; diff --git a/ddl/schemas/education/tables/15-videos.sql b/ddl/schemas/education/tables/15-videos.sql index e8aa1dd..a0712b4 100644 --- a/ddl/schemas/education/tables/15-videos.sql +++ b/ddl/schemas/education/tables/15-videos.sql @@ -13,7 +13,7 @@ CREATE TABLE education.videos ( -- Relaciones course_id UUID NOT NULL REFERENCES education.courses(id) ON DELETE CASCADE, lesson_id UUID REFERENCES education.lessons(id) ON DELETE SET NULL, - uploaded_by UUID NOT NULL REFERENCES core.users(id) ON DELETE RESTRICT, + uploaded_by UUID NOT NULL REFERENCES auth.users(id) ON DELETE RESTRICT, -- Información básica title VARCHAR(200) NOT NULL, diff --git a/ddl/schemas/ml/tables/10-backtest_runs.sql b/ddl/schemas/ml/tables/10-backtest_runs.sql index 4228863..c1e302a 100644 --- a/ddl/schemas/ml/tables/10-backtest_runs.sql +++ b/ddl/schemas/ml/tables/10-backtest_runs.sql @@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS ml.backtest_runs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- User who initiated the backtest (optional for system backtests) - user_id UUID REFERENCES core.users(id) ON DELETE SET NULL, + user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL, -- Symbol and date range symbol VARCHAR(20) NOT NULL, diff --git a/ddl/schemas/ml/tables/11-llm_signals.sql b/ddl/schemas/ml/tables/11-llm_signals.sql new file mode 100644 index 0000000..699bda0 --- /dev/null +++ b/ddl/schemas/ml/tables/11-llm_signals.sql @@ -0,0 +1,123 @@ +-- ===================================================== +-- ML SCHEMA - LLM SIGNALS TABLE +-- ===================================================== +-- Description: Logs ML signals and LLM decisions for feedback and fine-tuning +-- Schema: ml +-- Author: ML-Specialist (NEXUS v4.0) +-- Date: 2026-01-25 +-- Module: OQI-007-llm-strategy-agent +-- ===================================================== + +CREATE TABLE ml.llm_signals ( + id SERIAL PRIMARY KEY, + signal_id UUID NOT NULL UNIQUE DEFAULT gen_random_uuid(), + + -- Symbol and timing + symbol VARCHAR(20) NOT NULL, + timestamp TIMESTAMPTZ NOT NULL, + + -- ML Predictions (from metamodel) + ml_prediction JSONB, + -- Expected structure: + -- { + -- "direction": "BULLISH"|"BEARISH"|"NEUTRAL", + -- "magnitude": 0.5, + -- "confidence": 0.75, + -- "delta_high": 10.5, + -- "delta_low": 8.2, + -- "volatility_regime": "HIGH"|"MEDIUM"|"LOW", + -- "market_phase": "accumulation"|"distribution"|"manipulation"|"trend" + -- } + + -- Strategy predictions (individual strategies) + strategy_predictions JSONB, + -- Expected structure: + -- [ + -- {"name": "PVA", "direction": "BULLISH", "confidence": 0.8, "weight": 0.25}, + -- {"name": "MRD", "direction": "NEUTRAL", "confidence": 0.5, "weight": 0.20}, + -- ... + -- ] + + -- LLM interaction + llm_prompt TEXT, + llm_response TEXT, + + -- Parsed decision from LLM + decision JSONB, + -- Expected structure: + -- { + -- "action": "TRADE"|"NO_TRADE"|"WAIT", + -- "direction": "LONG"|"SHORT"|null, + -- "entry": 2340.50, + -- "stop_loss": 2335.00, + -- "take_profit": [2350.00, 2360.00], + -- "position_size": 1.0, + -- "reasoning": "...", + -- "is_valid": true + -- } + + -- Trade result (updated after trade closes) + trade_result JSONB, + -- Expected structure: + -- { + -- "result": "WIN"|"LOSS"|"BREAKEVEN"|"PARTIAL", + -- "pnl": 50.00, + -- "pnl_pct": 5.0, + -- "entry_price": 2340.50, + -- "exit_price": 2350.00, + -- "stop_loss_hit": false, + -- "take_profit_hit": true, + -- "duration_minutes": 45, + -- "exit_reason": "TP1" + -- } + + -- Timestamps + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +-- Indices for common queries +CREATE INDEX idx_llm_signals_symbol ON ml.llm_signals(symbol); +CREATE INDEX idx_llm_signals_timestamp ON ml.llm_signals(timestamp DESC); +CREATE INDEX idx_llm_signals_created_at ON ml.llm_signals(created_at DESC); + +-- Index for finding signals with results (for training data export) +CREATE INDEX idx_llm_signals_with_results ON ml.llm_signals(timestamp DESC) + WHERE trade_result IS NOT NULL; + +-- Index for decision types +CREATE INDEX idx_llm_signals_decision_action ON ml.llm_signals((decision->>'action')); + +-- GIN index for JSONB queries +CREATE INDEX idx_llm_signals_ml_prediction ON ml.llm_signals USING GIN (ml_prediction); +CREATE INDEX idx_llm_signals_trade_result ON ml.llm_signals USING GIN (trade_result); + +-- Trigger to update updated_at +CREATE OR REPLACE FUNCTION ml.update_llm_signals_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +CREATE TRIGGER trg_llm_signals_updated_at + BEFORE UPDATE ON ml.llm_signals + FOR EACH ROW + EXECUTE FUNCTION ml.update_llm_signals_updated_at(); + +-- Comments +COMMENT ON TABLE ml.llm_signals IS 'Logs ML signals and LLM decisions for performance tracking and fine-tuning dataset generation'; + +COMMENT ON COLUMN ml.llm_signals.id IS 'Auto-incrementing primary key'; +COMMENT ON COLUMN ml.llm_signals.signal_id IS 'Unique UUID for external reference'; +COMMENT ON COLUMN ml.llm_signals.symbol IS 'Trading symbol (e.g., XAUUSD, EURUSD)'; +COMMENT ON COLUMN ml.llm_signals.timestamp IS 'Timestamp of the signal generation'; +COMMENT ON COLUMN ml.llm_signals.ml_prediction IS 'JSONB with metamodel prediction output'; +COMMENT ON COLUMN ml.llm_signals.strategy_predictions IS 'JSONB array with individual strategy predictions'; +COMMENT ON COLUMN ml.llm_signals.llm_prompt IS 'Full prompt sent to the LLM'; +COMMENT ON COLUMN ml.llm_signals.llm_response IS 'Raw response from the LLM'; +COMMENT ON COLUMN ml.llm_signals.decision IS 'JSONB with parsed trading decision'; +COMMENT ON COLUMN ml.llm_signals.trade_result IS 'JSONB with trade outcome (null until trade closes)'; +COMMENT ON COLUMN ml.llm_signals.created_at IS 'Record creation timestamp'; +COMMENT ON COLUMN ml.llm_signals.updated_at IS 'Record last update timestamp'; diff --git a/migrations/2026-01-27_add_token_rotation.sql b/migrations/2026-01-27_add_token_rotation.sql new file mode 100644 index 0000000..7cab835 --- /dev/null +++ b/migrations/2026-01-27_add_token_rotation.sql @@ -0,0 +1,17 @@ +-- ============================================================================ +-- Migration: Add Token Rotation Columns +-- Date: 2026-01-27 +-- Author: Claude Code (BLOCKER-001 Token Refresh Improvements) +-- ============================================================================ + +-- Add columns for token rotation security +ALTER TABLE auth.sessions + ADD COLUMN IF NOT EXISTS refresh_token_hash VARCHAR(64), + ADD COLUMN IF NOT EXISTS refresh_token_issued_at TIMESTAMPTZ; + +-- Add comments +COMMENT ON COLUMN auth.sessions.refresh_token_hash IS 'SHA-256 hash of refresh token for rotation security'; +COMMENT ON COLUMN auth.sessions.refresh_token_issued_at IS 'Timestamp when current refresh token was issued'; + +-- Create index for performance (hash lookups) +CREATE INDEX IF NOT EXISTS idx_sessions_refresh_token_hash ON auth.sessions(refresh_token_hash); diff --git a/scripts/migrate_direct.sh b/scripts/migrate_direct.sh index e135cd5..38961d4 100755 --- a/scripts/migrate_direct.sh +++ b/scripts/migrate_direct.sh @@ -1,88 +1,88 @@ -#!/bin/bash -# Direct MySQL to PostgreSQL migration script -# Uses mysqldump and psql for direct data transfer - -set -e - -# Configuration -MYSQL_HOST="72.60.226.4" -MYSQL_PORT="3306" -MYSQL_USER="root" -MYSQL_PASS="AfcItz2391,." -MYSQL_DB="db_trading_meta" - -PG_HOST="localhost" -PG_PORT="5432" -PG_USER="trading_user" -PG_PASS="trading_dev_2025" -PG_DB="trading_data" - -# Ticker mapping: MySQL symbol -> (PG symbol, ticker_id) -declare -A TICKER_MAP=( - ["X:BTCUSD"]="1" - ["C:EURUSD"]="2" - ["C:GBPUSD"]="3" - ["C:USDJPY"]="4" - ["C:USDCAD"]="5" - ["C:AUDUSD"]="6" - ["C:NZDUSD"]="7" - ["C:EURGBP"]="8" - ["C:EURAUD"]="9" - ["C:EURCHF"]="10" - ["C:GBPJPY"]="11" - ["C:GBPAUD"]="12" - ["C:GBPCAD"]="13" - ["C:GBPNZD"]="14" - ["C:AUDCAD"]="15" - ["C:AUDCHF"]="16" - ["C:AUDNZD"]="17" - ["C:XAUUSD"]="18" -) - -migrate_ticker() { - local mysql_ticker=$1 - local pg_ticker_id=$2 - - echo "Migrating $mysql_ticker (ticker_id=$pg_ticker_id)..." - - # Export from MySQL and import to PostgreSQL - mysql -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER -p"$MYSQL_PASS" $MYSQL_DB \ - -N -e "SELECT $pg_ticker_id, date_agg, open, high, low, close, volume, vwap, ts FROM tickers_agg_data WHERE ticker='$mysql_ticker' ORDER BY date_agg" \ - | PGPASSWORD=$PG_PASS psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB \ - -c "COPY market_data.ohlcv_5m (ticker_id, timestamp, open, high, low, close, volume, vwap, ts_epoch) FROM STDIN WITH (FORMAT csv, DELIMITER E'\t')" - - echo "Completed $mysql_ticker" -} - -# Main -echo "Starting migration..." -echo "MySQL: $MYSQL_HOST:$MYSQL_PORT/$MYSQL_DB" -echo "PostgreSQL: $PG_HOST:$PG_PORT/$PG_DB" -echo "" - -# Migrate specific ticker or all -if [ -n "$1" ]; then - # Migrate specific ticker - mysql_ticker=$1 - pg_ticker_id=${TICKER_MAP[$mysql_ticker]} - if [ -z "$pg_ticker_id" ]; then - echo "Unknown ticker: $mysql_ticker" - exit 1 - fi - migrate_ticker "$mysql_ticker" "$pg_ticker_id" -else - # Migrate all tickers - for mysql_ticker in "${!TICKER_MAP[@]}"; do - pg_ticker_id=${TICKER_MAP[$mysql_ticker]} - migrate_ticker "$mysql_ticker" "$pg_ticker_id" - done -fi - -echo "" -echo "Migration complete!" - -# Verify counts -echo "" -echo "Verification:" -PGPASSWORD=$PG_PASS psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB \ - -c "SELECT t.symbol, COUNT(*) as rows FROM market_data.ohlcv_5m o JOIN market_data.tickers t ON t.id = o.ticker_id GROUP BY t.symbol ORDER BY t.symbol" +#!/bin/bash +# Direct MySQL to PostgreSQL migration script +# Uses mysqldump and psql for direct data transfer + +set -e + +# Configuration +MYSQL_HOST="72.60.226.4" +MYSQL_PORT="3306" +MYSQL_USER="root" +MYSQL_PASS="AfcItz2391,." +MYSQL_DB="db_trading_meta" + +PG_HOST="localhost" +PG_PORT="5432" +PG_USER="trading_user" +PG_PASS="trading_dev_2025" +PG_DB="trading_data" + +# Ticker mapping: MySQL symbol -> (PG symbol, ticker_id) +declare -A TICKER_MAP=( + ["X:BTCUSD"]="1" + ["C:EURUSD"]="2" + ["C:GBPUSD"]="3" + ["C:USDJPY"]="4" + ["C:USDCAD"]="5" + ["C:AUDUSD"]="6" + ["C:NZDUSD"]="7" + ["C:EURGBP"]="8" + ["C:EURAUD"]="9" + ["C:EURCHF"]="10" + ["C:GBPJPY"]="11" + ["C:GBPAUD"]="12" + ["C:GBPCAD"]="13" + ["C:GBPNZD"]="14" + ["C:AUDCAD"]="15" + ["C:AUDCHF"]="16" + ["C:AUDNZD"]="17" + ["C:XAUUSD"]="18" +) + +migrate_ticker() { + local mysql_ticker=$1 + local pg_ticker_id=$2 + + echo "Migrating $mysql_ticker (ticker_id=$pg_ticker_id)..." + + # Export from MySQL and import to PostgreSQL + mysql -h $MYSQL_HOST -P $MYSQL_PORT -u $MYSQL_USER -p"$MYSQL_PASS" $MYSQL_DB \ + -N -e "SELECT $pg_ticker_id, date_agg, open, high, low, close, volume, vwap, ts FROM tickers_agg_data WHERE ticker='$mysql_ticker' ORDER BY date_agg" \ + | PGPASSWORD=$PG_PASS psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB \ + -c "COPY market_data.ohlcv_5m (ticker_id, timestamp, open, high, low, close, volume, vwap, ts_epoch) FROM STDIN WITH (FORMAT csv, DELIMITER E'\t')" + + echo "Completed $mysql_ticker" +} + +# Main +echo "Starting migration..." +echo "MySQL: $MYSQL_HOST:$MYSQL_PORT/$MYSQL_DB" +echo "PostgreSQL: $PG_HOST:$PG_PORT/$PG_DB" +echo "" + +# Migrate specific ticker or all +if [ -n "$1" ]; then + # Migrate specific ticker + mysql_ticker=$1 + pg_ticker_id=${TICKER_MAP[$mysql_ticker]} + if [ -z "$pg_ticker_id" ]; then + echo "Unknown ticker: $mysql_ticker" + exit 1 + fi + migrate_ticker "$mysql_ticker" "$pg_ticker_id" +else + # Migrate all tickers + for mysql_ticker in "${!TICKER_MAP[@]}"; do + pg_ticker_id=${TICKER_MAP[$mysql_ticker]} + migrate_ticker "$mysql_ticker" "$pg_ticker_id" + done +fi + +echo "" +echo "Migration complete!" + +# Verify counts +echo "" +echo "Verification:" +PGPASSWORD=$PG_PASS psql -h $PG_HOST -p $PG_PORT -U $PG_USER -d $PG_DB \ + -c "SELECT t.symbol, COUNT(*) as rows FROM market_data.ohlcv_5m o JOIN market_data.tickers t ON t.id = o.ticker_id GROUP BY t.symbol ORDER BY t.symbol" diff --git a/seeds/prod/auth/01-admin-user.sql b/seeds/prod/auth/01-admin-user.sql new file mode 100644 index 0000000..151d243 --- /dev/null +++ b/seeds/prod/auth/01-admin-user.sql @@ -0,0 +1,72 @@ +-- ===================================================== +-- SEED DATA - Schema Auth (Production) +-- ===================================================== +-- Project: OrbiQuant IA (Trading Platform) +-- Tables: auth.users, auth.user_profiles +-- Description: Admin super user seed for platform bootstrap +-- Date: 2026-01-27 +-- ===================================================== + +SET search_path TO auth, public; + +-- ===================================================== +-- 1. ADMIN USER +-- ===================================================== + +INSERT INTO auth.users ( + id, + email, + email_verified, + email_verified_at, + password_hash, + status, + role, + mfa_enabled, + mfa_method +) VALUES ( + '00000000-0000-0000-0000-000000000000', + 'admin@orbiquant.com', + true, + NOW(), + '$2b$12$LJ3m4yv5E7Qj8K9F2N1P6eR4T6Y8U0I2O4P6A8S0D2F4G6H8J0K2', + 'active', + 'super_admin', + false, + 'none' +) ON CONFLICT (email) DO NOTHING; + +-- ===================================================== +-- 2. ADMIN USER PROFILE +-- ===================================================== + +INSERT INTO auth.user_profiles ( + user_id, + first_name, + last_name, + display_name, + language, + timezone, + newsletter_subscribed, + marketing_emails_enabled, + notifications_enabled, + metadata +) VALUES ( + '00000000-0000-0000-0000-000000000000', + 'System', + 'Administrator', + 'OrbiQuant Admin', + 'en', + 'UTC', + false, + false, + true, + '{"role_description": "Platform super administrator", "created_by": "seed"}'::jsonb +) ON CONFLICT (user_id) DO NOTHING; + +-- ===================================================== +-- VERIFICATION +-- ===================================================== +SELECT 'auth.users (admin) seed:' AS info, COUNT(*) AS count + FROM auth.users WHERE email = 'admin@orbiquant.com'; +SELECT 'auth.user_profiles (admin) seed:' AS info, COUNT(*) AS count + FROM auth.user_profiles WHERE user_id = '00000000-0000-0000-0000-000000000000'; diff --git a/seeds/prod/investment/01-products.sql b/seeds/prod/investment/01-products.sql new file mode 100644 index 0000000..4f2aa27 --- /dev/null +++ b/seeds/prod/investment/01-products.sql @@ -0,0 +1,80 @@ +-- ===================================================== +-- SEED DATA - Schema Investment (Production) +-- ===================================================== +-- Project: OrbiQuant IA (Trading Platform) +-- Table: investment.products +-- Description: PAMM investment products (Atlas, Orion, Nova) +-- Date: 2026-01-27 +-- ===================================================== + +SET search_path TO investment, public; + +-- ===================================================== +-- 1. PAMM INVESTMENT PRODUCTS (3 products) +-- ===================================================== + +INSERT INTO investment.products ( + code, name, description, + trading_agent, + min_investment, max_investment, + target_return_min, target_return_max, + distribution_frequency, + investor_share_percent, platform_share_percent, + recommended_risk_profile, + is_active, is_accepting_new_investors, + total_capacity, current_aum +) VALUES + -- Atlas: Conservative strategy + ( + 'PAMM-ATLAS', + 'Atlas', + 'Conservative PAMM strategy focused on capital preservation with steady returns. ' + 'Targets 3-5% monthly returns through low-risk forex positions and hedging strategies. ' + 'Ideal for investors seeking stable growth with minimal drawdown.', + 'atlas', + 1000.00, 500000.00, + 3.00, 5.00, + 'monthly', + 80.00, 20.00, + 'conservative', + true, true, + 10000000.00, 0.00 + ), + -- Orion: Moderate strategy + ( + 'PAMM-ORION', + 'Orion', + 'Moderate PAMM strategy balancing risk and reward. ' + 'Targets 5-10% monthly returns through diversified forex and commodity positions. ' + 'Suitable for investors comfortable with moderate volatility for higher returns.', + 'orion', + 5000.00, 1000000.00, + 5.00, 10.00, + 'monthly', + 80.00, 20.00, + 'moderate', + true, true, + 25000000.00, 0.00 + ), + -- Nova: Aggressive strategy + ( + 'PAMM-NOVA', + 'Nova', + 'Aggressive PAMM strategy maximizing return potential. ' + 'Targets 10%+ monthly returns through high-conviction forex, crypto, and commodity trades. ' + 'Designed for experienced investors who accept higher volatility for outsized returns.', + 'nova', + 10000.00, 2000000.00, + 10.00, 20.00, + 'monthly', + 80.00, 20.00, + 'aggressive', + true, true, + 50000000.00, 0.00 + ) +ON CONFLICT (code) DO NOTHING; + +-- ===================================================== +-- VERIFICATION +-- ===================================================== +SELECT 'investment.products seed:' AS info, COUNT(*) AS count FROM investment.products; diff --git a/seeds/prod/market_data/01-tickers.sql b/seeds/prod/market_data/01-tickers.sql new file mode 100644 index 0000000..17cf404 --- /dev/null +++ b/seeds/prod/market_data/01-tickers.sql @@ -0,0 +1,73 @@ +-- ===================================================== +-- SEED DATA - Schema Market Data (Production) +-- ===================================================== +-- Project: OrbiQuant IA (Trading Platform) +-- Table: market_data.tickers +-- Description: Market data tickers matching trading symbols +-- Date: 2026-01-27 +-- Note: The DDL (01-tickers.sql) contains inline seeds for +-- the same 6 tickers. This seed file serves as the +-- canonical source and uses ON CONFLICT to be idempotent. +-- ===================================================== + +SET search_path TO market_data, public; + +-- ===================================================== +-- 1. MARKET DATA TICKERS (6 tickers) +-- ===================================================== + +INSERT INTO market_data.tickers ( + symbol, name, + asset_type, base_currency, quote_currency, + is_ml_enabled, supported_timeframes, + polygon_ticker, + is_active +) VALUES + ( + 'XAUUSD', 'Gold / US Dollar', + 'commodity', 'XAU', 'USD', + true, ARRAY['5m', '15m', '1h'], + 'C:XAUUSD', + true + ), + ( + 'EURUSD', 'Euro / US Dollar', + 'forex', 'EUR', 'USD', + true, ARRAY['5m', '15m'], + 'C:EURUSD', + true + ), + ( + 'GBPUSD', 'British Pound / US Dollar', + 'forex', 'GBP', 'USD', + true, ARRAY['5m', '15m'], + 'C:GBPUSD', + true + ), + ( + 'USDJPY', 'US Dollar / Japanese Yen', + 'forex', 'USD', 'JPY', + true, ARRAY['5m', '15m'], + 'C:USDJPY', + true + ), + ( + 'AUDUSD', 'Australian Dollar / US Dollar', + 'forex', 'AUD', 'USD', + true, ARRAY['5m', '15m'], + 'C:AUDUSD', + true + ), + ( + 'BTCUSD', 'Bitcoin / US Dollar', + 'crypto', 'BTC', 'USD', + true, ARRAY['5m', '15m', '1h'], + 'X:BTCUSD', + true + ) +ON CONFLICT (symbol) DO NOTHING; + +-- ===================================================== +-- VERIFICATION +-- ===================================================== +SELECT 'market_data.tickers seed:' AS info, COUNT(*) AS count FROM market_data.tickers; diff --git a/seeds/prod/trading/01-symbols.sql b/seeds/prod/trading/01-symbols.sql new file mode 100644 index 0000000..4fc0726 --- /dev/null +++ b/seeds/prod/trading/01-symbols.sql @@ -0,0 +1,72 @@ +-- ===================================================== +-- SEED DATA - Schema Trading (Production) +-- ===================================================== +-- Project: OrbiQuant IA (Trading Platform) +-- Table: trading.symbols +-- Description: Base trading symbols for forex and crypto pairs +-- Date: 2026-01-27 +-- ===================================================== + +SET search_path TO trading, public; + +-- ===================================================== +-- 1. TRADING SYMBOLS (6 pairs) +-- ===================================================== + +INSERT INTO trading.symbols ( + symbol, name, base_asset, quote_asset, + asset_class, exchange, + price_precision, quantity_precision, + min_quantity, max_quantity, min_notional, + is_active, is_tradeable +) VALUES + -- Forex pairs + ( + 'XAUUSD', 'Gold / US Dollar', 'XAU', 'USD', + 'forex', 'oanda', + 2, 2, + 0.01, 100.00, 10.00, + true, true + ), + ( + 'EURUSD', 'Euro / US Dollar', 'EUR', 'USD', + 'forex', 'oanda', + 5, 2, + 0.01, 1000000.00, 1.00, + true, true + ), + ( + 'GBPUSD', 'British Pound / US Dollar', 'GBP', 'USD', + 'forex', 'oanda', + 5, 2, + 0.01, 1000000.00, 1.00, + true, true + ), + ( + 'USDJPY', 'US Dollar / Japanese Yen', 'USD', 'JPY', + 'forex', 'oanda', + 3, 2, + 0.01, 1000000.00, 1.00, + true, true + ), + ( + 'AUDUSD', 'Australian Dollar / US Dollar', 'AUD', 'USD', + 'forex', 'oanda', + 5, 2, + 0.01, 1000000.00, 1.00, + true, true + ), + -- Crypto pair + ( + 'BTCUSD', 'Bitcoin / US Dollar', 'BTC', 'USD', + 'crypto', 'binance', + 2, 5, + 0.00001, 100.00, 10.00, + true, true + ) +ON CONFLICT (symbol) DO NOTHING; + +-- ===================================================== +-- VERIFICATION +-- ===================================================== +SELECT 'trading.symbols seed:' AS info, COUNT(*) AS count FROM trading.symbols;