learning_ai_invt_trdg/web/schema_reference.sql

239 lines
10 KiB
PL/PgSQL

/*
# Full Schema Reference — Bytelyst Trading Platform
Last updated: 2026-02-07
This file documents ALL 7 tables used by the Trading Dashboard and Bot Service.
Run individual CREATE TABLE statements or use migration 004_full_schema_sync.sql
in the bot-service/schema/ folder to apply all changes.
Tables:
1. users — User accounts (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 per-profile rule config
6. bot_config — Global config key-value store (dashboard-editable)
7. dynamic_config — Runtime config overrides (bot startup)
*/
-- ════════════════════════════════════════════════════════════
-- 1. USERS TABLE (Created by auth trigger — reference only)
-- ════════════════════════════════════════════════════════════
-- CREATE TABLE IF NOT EXISTS users (
-- user_id uuid PRIMARY KEY REFERENCES auth.users,
-- first_name text,
-- last_name text,
-- email text,
-- "ALPACA_API_KEY" text,
-- "ALPACA_SECRET_KEY" text,
-- "REAL_ALPACA_API_KEY" text,
-- "REAL_ALPACA_SECRET_KEY" text,
-- trade_enable boolean DEFAULT false,
-- role text DEFAULT 'user',
-- drop_threshold_for_buy numeric,
-- gain_threshold_for_sell numeric,
-- market_poll_interval_in_seconds integer
-- );
-- Auth trigger: auto-create user row on signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS trigger AS $$
BEGIN
INSERT INTO public.users (user_id, email, role, trade_enable)
VALUES (new.id, new.email, 'user', false);
RETURN new;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE PROCEDURE public.handle_new_user();
-- ════════════════════════════════════════════════════════════
-- 2. ENTRIES TABLE (Watchlist & Manual Positions)
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS entries (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
stock_instance_id uuid DEFAULT gen_random_uuid(),
user_id uuid REFERENCES auth.users NOT NULL DEFAULT auth.uid(),
-- Core
symbol text NOT NULL,
label text,
notes text,
-- Config
active boolean DEFAULT true,
is_real_trade boolean DEFAULT false,
is_crypto boolean DEFAULT false,
status text DEFAULT 'active', -- 'active', 'sellCompleted', 'closed'
-- Trading Data
quantity numeric,
filled_quantity numeric,
entry_price numeric,
buy_price numeric,
sell_price numeric,
buy_time timestamptz,
sell_time timestamptz,
-- Automation
drop_threshold_for_buy numeric,
gain_threshold_for_sell numeric,
created_at timestamptz DEFAULT now(),
updated_at timestamptz DEFAULT now()
);
ALTER TABLE entries ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage own entries" ON entries
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
-- ════════════════════════════════════════════════════════════
-- 3. TRADE_HISTORY TABLE (Completed Trade Ledger)
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS trade_history (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid REFERENCES auth.users NOT NULL,
profile_id uuid REFERENCES trade_profiles(id) ON DELETE SET NULL,
-- Trade Data
symbol text NOT NULL,
side text NOT NULL, -- 'BUY' or 'SELL'
entry_price numeric,
exit_price numeric,
size numeric,
pnl numeric, -- Realized P&L ($)
pnl_percent numeric, -- Realized P&L (%)
stop_loss numeric, -- SL price at entry
take_profit numeric, -- TP price at entry
-- Context
reason text, -- 'Signal Flip', 'Stop Loss', 'Manual', etc.
rules_metadata jsonb, -- Snapshot of rule statuses at trade time
timestamp bigint, -- Unix ms from bot execution
created_at timestamptz DEFAULT now()
);
ALTER TABLE trade_history ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can view own trade history" ON trade_history
FOR SELECT USING (auth.uid() = user_id);
CREATE INDEX IF NOT EXISTS idx_trade_history_profile_id ON trade_history(profile_id);
CREATE INDEX IF NOT EXISTS idx_trade_history_user_symbol ON trade_history(user_id, symbol);
-- ════════════════════════════════════════════════════════════
-- 4. ORDERS TABLE (Active/Pending Orders)
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS orders (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
user_id uuid REFERENCES auth.users NOT NULL,
profile_id uuid REFERENCES trade_profiles(id) ON DELETE SET NULL,
-- Order Identification
order_id text, -- Exchange order ID
symbol text NOT NULL,
-- Order Details
type text NOT NULL, -- 'Market', 'Limit', 'Stop'
side text NOT NULL, -- 'BUY' or 'SELL'
qty numeric NOT NULL,
price numeric,
stop_loss numeric, -- SL price at order time
take_profit numeric, -- TP price at order time
-- Status
status text DEFAULT 'pending', -- 'pending', 'filled', 'cancelled', 'rejected'
-- Timestamps
timestamp bigint, -- Unix ms when order was placed
filled_at timestamptz,
created_at timestamptz DEFAULT now(),
updated_at timestamptz DEFAULT now()
);
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can view own orders" ON orders
FOR SELECT USING (auth.uid() = user_id);
CREATE INDEX IF NOT EXISTS idx_orders_user_status ON orders(user_id, status);
CREATE INDEX IF NOT EXISTS idx_orders_symbol ON orders(symbol);
CREATE INDEX IF NOT EXISTS idx_orders_profile_id ON orders(profile_id);
-- ════════════════════════════════════════════════════════════
-- 5. TRADE_PROFILES TABLE (Strategy Profiles)
-- ════════════════════════════════════════════════════════════
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": {} },
{ "ruleId": "SessionRule", "enabled": true, "params": {} },
{ "ruleId": "ZoneRule", "enabled": true, "params": {} },
{ "ruleId": "MomentumRule", "enabled": true, "params": {} },
{ "ruleId": "EntryTriggerRule", "enabled": true, "params": {} },
{ "ruleId": "RiskManagementRule", "enabled": true, "params": {} },
{ "ruleId": "AIAnalysisRule", "enabled": false, "params": {} }
],
"riskLimits": {
"maxDailyLossUsd": 50,
"maxConsecutiveLosses": 2,
"maxOpenTrades": 3
},
"execution": {
"orderType": "market",
"cooldownMinutes": 30
}
}'::jsonb,
created_at timestamptz DEFAULT now()
);
ALTER TABLE trade_profiles ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can manage own profiles" ON trade_profiles
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
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);
-- ════════════════════════════════════════════════════════════
-- 6. BOT_CONFIG TABLE (Global Config — Dashboard Editable)
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS bot_config (
key text PRIMARY KEY,
value text,
description text,
updated_at timestamptz DEFAULT now()
);
ALTER TABLE bot_config ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Authenticated users can read bot_config" ON bot_config
FOR SELECT USING (auth.role() = 'authenticated');
-- ════════════════════════════════════════════════════════════
-- 7. DYNAMIC_CONFIG TABLE (Bot Runtime Overrides)
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS dynamic_config (
key text PRIMARY KEY,
value text,
updated_at timestamptz DEFAULT now()
);