learning_ai_invt_trdg/backend/schema/004_full_schema_sync.sql

162 lines
8.4 KiB
SQL

-- ============================================================
-- Migration 004: Full Schema Sync
-- Date: 2026-02-07
-- Purpose: Create missing tables, add missing columns,
-- and align DB schema with application code.
-- ============================================================
-- ────────────────────────────────────────────────────────────
-- 1. TRADE_PROFILES TABLE (Missing CREATE TABLE)
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS trade_profiles (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid REFERENCES auth.users NOT NULL,
name text NOT NULL,
allocated_capital numeric DEFAULT 1000,
risk_per_trade_percent numeric DEFAULT 1.0,
symbols text DEFAULT 'BTC/USDT, ETH/USDT',
is_active boolean DEFAULT true,
strategy_config jsonb DEFAULT '{
"rules": [
{ "ruleId": "TrendBiasRule", "enabled": true, "params": { "timeframe": "4h", "emaFast": 50, "emaSlow": 200 } },
{ "ruleId": "SessionRule", "enabled": true, "params": { "allowedSessions": ["NY", "LDN"] } },
{ "ruleId": "ZoneRule", "enabled": true, "params": { "emaPeriod": 20, "tolerancePercent": 0.5 } },
{ "ruleId": "MomentumRule", "enabled": true, "params": { "timeframe": "1h", "rsiPeriod": 14, "rsiOverbought": 70, "rsiOversold": 30 } },
{ "ruleId": "EntryTriggerRule", "enabled": true, "params": { "triggerType": "ema_cross" } },
{ "ruleId": "RiskManagementRule", "enabled": true, "params": { "atrPeriod": 14, "riskRewardRatio": 1.5 } },
{ "ruleId": "AIAnalysisRule", "enabled": false, "params": { "minConfidence": 80 } }
],
"riskLimits": {
"maxDailyLossUsd": 50,
"maxConsecutiveLosses": 2,
"maxOpenTrades": 3
},
"execution": {
"orderType": "market",
"cooldownMinutes": 30,
"entryMode": "both"
}
}'::jsonb,
created_at timestamptz DEFAULT now()
);
COMMENT ON TABLE trade_profiles IS 'Trading strategy profiles with per-profile rule config, risk limits, and execution settings';
COMMENT ON COLUMN trade_profiles.strategy_config IS 'JSON configuration: { rules[], riskLimits{}, execution{} }';
CREATE INDEX IF NOT EXISTS idx_trade_profiles_user_id ON trade_profiles(user_id);
CREATE INDEX IF NOT EXISTS idx_trade_profiles_is_active ON trade_profiles(is_active);
-- RLS
ALTER TABLE trade_profiles ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Users can manage own profiles" ON trade_profiles;
CREATE POLICY "Users can manage own profiles" ON trade_profiles
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- ────────────────────────────────────────────────────────────
-- 2. ORDERS TABLE — Add missing columns
-- ────────────────────────────────────────────────────────────
-- profile_id: links order to the trade profile that triggered it
ALTER TABLE orders
ADD COLUMN IF NOT EXISTS profile_id uuid REFERENCES trade_profiles(id) ON DELETE SET NULL;
-- stop_loss & take_profit: stored by TradeExecutor.logOrderToDb()
ALTER TABLE orders
ADD COLUMN IF NOT EXISTS stop_loss numeric;
ALTER TABLE orders
ADD COLUMN IF NOT EXISTS take_profit numeric;
CREATE INDEX IF NOT EXISTS idx_orders_profile_id ON orders(profile_id);
COMMENT ON COLUMN orders.profile_id IS 'Trade profile that triggered this order (NULL = manual)';
COMMENT ON COLUMN orders.stop_loss IS 'Stop loss price set at order time';
COMMENT ON COLUMN orders.take_profit IS 'Take profit price set at order time';
-- ────────────────────────────────────────────────────────────
-- 3. TRADE_HISTORY TABLE — Add missing columns
-- ────────────────────────────────────────────────────────────
-- profile_id: links trade to the profile that triggered it
ALTER TABLE trade_history
ADD COLUMN IF NOT EXISTS profile_id uuid REFERENCES trade_profiles(id) ON DELETE SET NULL;
-- stop_loss & take_profit: for post-trade analysis
ALTER TABLE trade_history
ADD COLUMN IF NOT EXISTS stop_loss numeric;
ALTER TABLE trade_history
ADD COLUMN IF NOT EXISTS take_profit numeric;
-- rules_metadata: stores which rules passed/failed for this trade
ALTER TABLE trade_history
ADD COLUMN IF NOT EXISTS rules_metadata jsonb;
CREATE INDEX IF NOT EXISTS idx_trade_history_profile_id ON trade_history(profile_id);
COMMENT ON COLUMN trade_history.profile_id IS 'Trade profile that triggered this trade (NULL = manual)';
COMMENT ON COLUMN trade_history.stop_loss IS 'Stop loss price at trade entry';
COMMENT ON COLUMN trade_history.take_profit IS 'Take profit price at trade entry';
COMMENT ON COLUMN trade_history.rules_metadata IS 'JSON snapshot of rule statuses at trade time: { ruleName: { passed, reason } }';
-- ────────────────────────────────────────────────────────────
-- 4. BOT_CONFIG TABLE (Missing CREATE TABLE)
-- Used by: ConfigTab.tsx, GlobalConfigManager.tsx
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS bot_config (
key text PRIMARY KEY,
value text,
description text,
updated_at timestamptz DEFAULT now()
);
COMMENT ON TABLE bot_config IS 'Key-value store for global bot configuration (editable from dashboard)';
-- RLS: allow authenticated users to read, admins to write
ALTER TABLE bot_config ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS "Authenticated users can read bot_config" ON bot_config;
CREATE POLICY "Authenticated users can read bot_config" ON bot_config
FOR SELECT
USING (auth.role() = 'authenticated');
DROP POLICY IF EXISTS "Admins can manage bot_config" ON bot_config;
CREATE POLICY "Admins can manage bot_config" ON bot_config
USING (
EXISTS (SELECT 1 FROM users WHERE user_id = auth.uid() AND role = 'admin')
)
WITH CHECK (
EXISTS (SELECT 1 FROM users WHERE user_id = auth.uid() AND role = 'admin')
);
-- ────────────────────────────────────────────────────────────
-- 5. DYNAMIC_CONFIG TABLE (Missing CREATE TABLE)
-- Used by: bot-service config/index.ts (loadDynamicConfig)
-- ────────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS dynamic_config (
key text PRIMARY KEY,
value text,
updated_at timestamptz DEFAULT now()
);
COMMENT ON TABLE dynamic_config IS 'Runtime-overridable bot settings loaded at startup (SYMBOLS, intervals, etc.)';
-- ────────────────────────────────────────────────────────────
-- 6. UPDATE schema_reference.sql sync comment
-- ────────────────────────────────────────────────────────────
-- After running this migration, all 7 tables are fully defined:
-- 1. users (auth trigger-created)
-- 2. entries (watchlist & manual positions)
-- 3. trade_history (completed trade ledger)
-- 4. orders (active/pending orders)
-- 5. trade_profiles (strategy profiles with rule config)
-- 6. bot_config (global config key-value store)
-- 7. dynamic_config (runtime config overrides)