"""Deterministic seed data for integration test sandbox. All UUIDs and timestamps are hardcoded for reproducible assertions. No external API calls — all data is synthetic. Usage: python -m tests.integration.seed_sandbox Environment variables: POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD """ import asyncio import json import os from datetime import date, datetime, timedelta, timezone from uuid import UUID import asyncpg # ── Fixed base timestamp ───────────────────────────────────── BASE_TS = datetime(2025, 1, 15, 12, 0, 0, tzinfo=timezone.utc) BASE_DATE = date(2025, 1, 15) # ── Deterministic UUIDs ────────────────────────────────────── # Companies COMPANY_AAPL = UUID("00000000-0000-4000-a000-000000000001") COMPANY_MSFT = UUID("00000000-0000-4000-a000-000000000002") COMPANY_JPM = UUID("00000000-0000-4000-a000-000000000003") COMPANY_JNJ = UUID("00000000-0000-4000-a000-000000000004") COMPANY_XOM = UUID("00000000-0000-4000-a000-000000000005") # Sources (one per company) SOURCE_AAPL = UUID("00000000-0000-4000-b000-000000000001") SOURCE_MSFT = UUID("00000000-0000-4000-b000-000000000002") SOURCE_JPM = UUID("00000000-0000-4000-b000-000000000003") SOURCE_JNJ = UUID("00000000-0000-4000-b000-000000000004") SOURCE_XOM = UUID("00000000-0000-4000-b000-000000000005") # Company aliases ALIAS_AAPL = UUID("00000000-0000-4000-b100-000000000001") ALIAS_MSFT = UUID("00000000-0000-4000-b100-000000000002") ALIAS_JPM = UUID("00000000-0000-4000-b100-000000000003") ALIAS_JNJ = UUID("00000000-0000-4000-b100-000000000004") ALIAS_XOM = UUID("00000000-0000-4000-b100-000000000005") # Competitor relationships COMPETITOR_REL_1 = UUID("00000000-0000-4000-b200-000000000001") COMPETITOR_REL_2 = UUID("00000000-0000-4000-b200-000000000002") # Documents (10) DOC_01 = UUID("00000000-0000-4000-c000-000000000001") DOC_02 = UUID("00000000-0000-4000-c000-000000000002") DOC_03 = UUID("00000000-0000-4000-c000-000000000003") DOC_04 = UUID("00000000-0000-4000-c000-000000000004") DOC_05 = UUID("00000000-0000-4000-c000-000000000005") DOC_06 = UUID("00000000-0000-4000-c000-000000000006") DOC_07 = UUID("00000000-0000-4000-c000-000000000007") DOC_08 = UUID("00000000-0000-4000-c000-000000000008") DOC_09 = UUID("00000000-0000-4000-c000-000000000009") DOC_10 = UUID("00000000-0000-4000-c000-000000000010") # Document intelligence (one per document) INTEL_01 = UUID("00000000-0000-4000-c100-000000000001") INTEL_02 = UUID("00000000-0000-4000-c100-000000000002") INTEL_03 = UUID("00000000-0000-4000-c100-000000000003") INTEL_04 = UUID("00000000-0000-4000-c100-000000000004") INTEL_05 = UUID("00000000-0000-4000-c100-000000000005") INTEL_06 = UUID("00000000-0000-4000-c100-000000000006") INTEL_07 = UUID("00000000-0000-4000-c100-000000000007") INTEL_08 = UUID("00000000-0000-4000-c100-000000000008") INTEL_09 = UUID("00000000-0000-4000-c100-000000000009") INTEL_10 = UUID("00000000-0000-4000-c100-000000000010") # Document impact records IMPACT_01 = UUID("00000000-0000-4000-c200-000000000001") IMPACT_02 = UUID("00000000-0000-4000-c200-000000000002") IMPACT_03 = UUID("00000000-0000-4000-c200-000000000003") IMPACT_04 = UUID("00000000-0000-4000-c200-000000000004") IMPACT_05 = UUID("00000000-0000-4000-c200-000000000005") IMPACT_06 = UUID("00000000-0000-4000-c200-000000000006") IMPACT_07 = UUID("00000000-0000-4000-c200-000000000007") IMPACT_08 = UUID("00000000-0000-4000-c200-000000000008") IMPACT_09 = UUID("00000000-0000-4000-c200-000000000009") IMPACT_10 = UUID("00000000-0000-4000-c200-000000000010") # Document company mentions MENTION_01 = UUID("00000000-0000-4000-c300-000000000001") MENTION_02 = UUID("00000000-0000-4000-c300-000000000002") MENTION_03 = UUID("00000000-0000-4000-c300-000000000003") MENTION_04 = UUID("00000000-0000-4000-c300-000000000004") MENTION_05 = UUID("00000000-0000-4000-c300-000000000005") MENTION_06 = UUID("00000000-0000-4000-c300-000000000006") MENTION_07 = UUID("00000000-0000-4000-c300-000000000007") MENTION_08 = UUID("00000000-0000-4000-c300-000000000008") MENTION_09 = UUID("00000000-0000-4000-c300-000000000009") MENTION_10 = UUID("00000000-0000-4000-c300-000000000010") # Trend windows (5) TREND_01 = UUID("00000000-0000-4000-d000-000000000001") TREND_02 = UUID("00000000-0000-4000-d000-000000000002") TREND_03 = UUID("00000000-0000-4000-d000-000000000003") TREND_04 = UUID("00000000-0000-4000-d000-000000000004") TREND_05 = UUID("00000000-0000-4000-d000-000000000005") # Trend projections (one per trend) PROJECTION_01 = UUID("00000000-0000-4000-d100-000000000001") PROJECTION_02 = UUID("00000000-0000-4000-d100-000000000002") PROJECTION_03 = UUID("00000000-0000-4000-d100-000000000003") PROJECTION_04 = UUID("00000000-0000-4000-d100-000000000004") PROJECTION_05 = UUID("00000000-0000-4000-d100-000000000005") # Recommendations (5) REC_01 = UUID("00000000-0000-4000-e000-000000000001") REC_02 = UUID("00000000-0000-4000-e000-000000000002") REC_03 = UUID("00000000-0000-4000-e000-000000000003") REC_04 = UUID("00000000-0000-4000-e000-000000000004") REC_05 = UUID("00000000-0000-4000-e000-000000000005") # Recommendation evidence (one per recommendation) REC_EV_01 = UUID("00000000-0000-4000-e100-000000000001") REC_EV_02 = UUID("00000000-0000-4000-e100-000000000002") REC_EV_03 = UUID("00000000-0000-4000-e100-000000000003") REC_EV_04 = UUID("00000000-0000-4000-e100-000000000004") REC_EV_05 = UUID("00000000-0000-4000-e100-000000000005") # Risk evaluations RISK_EVAL_01 = UUID("00000000-0000-4000-e200-000000000001") # Broker account BROKER_ACCT_01 = UUID("00000000-0000-4000-f000-000000000001") # Orders (3) ORDER_01 = UUID("00000000-0000-4000-f100-000000000001") ORDER_02 = UUID("00000000-0000-4000-f100-000000000002") ORDER_03 = UUID("00000000-0000-4000-f100-000000000003") # Order events ORDER_EVT_01 = UUID("00000000-0000-4000-f200-000000000001") ORDER_EVT_02 = UUID("00000000-0000-4000-f200-000000000002") ORDER_EVT_03 = UUID("00000000-0000-4000-f200-000000000003") ORDER_EVT_04 = UUID("00000000-0000-4000-f200-000000000004") ORDER_EVT_05 = UUID("00000000-0000-4000-f200-000000000005") # Positions (2) POSITION_01 = UUID("00000000-0000-4000-f300-000000000001") POSITION_02 = UUID("00000000-0000-4000-f300-000000000002") # Global events (2) GLOBAL_EVT_01 = UUID("00000000-0000-4000-a100-000000000001") GLOBAL_EVT_02 = UUID("00000000-0000-4000-a100-000000000002") # Macro impact records (4 — 2 per global event, across multiple companies) MACRO_IMPACT_01 = UUID("00000000-0000-4000-a200-000000000001") MACRO_IMPACT_02 = UUID("00000000-0000-4000-a200-000000000002") MACRO_IMPACT_03 = UUID("00000000-0000-4000-a200-000000000003") MACRO_IMPACT_04 = UUID("00000000-0000-4000-a200-000000000004") # Exposure profiles (2) EXPOSURE_01 = UUID("00000000-0000-4000-a300-000000000001") EXPOSURE_02 = UUID("00000000-0000-4000-a300-000000000002") # Competitive signal records (2) COMP_SIGNAL_01 = UUID("00000000-0000-4000-a400-000000000001") COMP_SIGNAL_02 = UUID("00000000-0000-4000-a400-000000000002") # Trading decisions TRADING_DECISION_01 = UUID("00000000-0000-4000-a500-000000000001") # Portfolio snapshot PORTFOLIO_SNAP_01 = UUID("00000000-0000-4000-a600-000000000001") # AI agents (use slugs to match migration 026 seed rows) AGENT_EXTRACTOR = UUID("00000000-0000-4000-a700-000000000001") AGENT_CLASSIFIER = UUID("00000000-0000-4000-a700-000000000002") AGENT_THESIS = UUID("00000000-0000-4000-a700-000000000003") # Agent variants (1 per agent) VARIANT_EXTRACTOR = UUID("00000000-0000-4000-a800-000000000001") VARIANT_CLASSIFIER = UUID("00000000-0000-4000-a800-000000000002") VARIANT_THESIS = UUID("00000000-0000-4000-a800-000000000003") # Agent performance log entries PERF_LOG_01 = UUID("00000000-0000-4000-a900-000000000001") PERF_LOG_02 = UUID("00000000-0000-4000-a900-000000000002") PERF_LOG_03 = UUID("00000000-0000-4000-a900-000000000003") # Risk config RISK_CONFIG_01 = UUID("00000000-0000-4000-aa00-000000000001") # Audit events AUDIT_01 = UUID("00000000-0000-4000-ab00-000000000001") AUDIT_02 = UUID("00000000-0000-4000-ab00-000000000002") AUDIT_03 = UUID("00000000-0000-4000-ab00-000000000003") # Watchlists WATCHLIST_01 = UUID("00000000-0000-4000-ac00-000000000001") WATCHLIST_02 = UUID("00000000-0000-4000-ac00-000000000002") # Watchlist members WL_MEMBER_01 = UUID("00000000-0000-4000-ac10-000000000001") WL_MEMBER_02 = UUID("00000000-0000-4000-ac10-000000000002") WL_MEMBER_03 = UUID("00000000-0000-4000-ac10-000000000003") # Operator Approvals APPROVAL_PENDING = UUID("00000000-0000-4000-ad00-000000000001") APPROVAL_APPROVED = UUID("00000000-0000-4000-ad00-000000000002") # Symbol Lockouts LOCKOUT_ACTIVE = UUID("00000000-0000-4000-ae00-000000000001") LOCKOUT_EXPIRED = UUID("00000000-0000-4000-ae00-000000000002") # Notifications NOTIFICATION_01 = UUID("00000000-0000-4000-af00-000000000001") # Ingestion Runs INGESTION_RUN_01 = UUID("00000000-0000-4000-b300-000000000001") INGESTION_RUN_02 = UUID("00000000-0000-4000-b300-000000000002") # Saved Queries SAVED_QUERY_01 = UUID("00000000-0000-4000-b400-000000000001") # Daily Risk Snapshot RISK_SNAPSHOT_01 = UUID("00000000-0000-4000-b500-000000000001") # ── Exported lookup dicts for test imports ──────────────────── SEED_COMPANY_IDS = { "AAPL": str(COMPANY_AAPL), "MSFT": str(COMPANY_MSFT), "JPM": str(COMPANY_JPM), "JNJ": str(COMPANY_JNJ), "XOM": str(COMPANY_XOM), } SEED_DOCUMENT_IDS = { f"DOC_{i:02d}": str(uid) for i, uid in enumerate( [DOC_01, DOC_02, DOC_03, DOC_04, DOC_05, DOC_06, DOC_07, DOC_08, DOC_09, DOC_10], start=1, ) } SEED_TREND_IDS = { f"TREND_{i:02d}": str(uid) for i, uid in enumerate( [TREND_01, TREND_02, TREND_03, TREND_04, TREND_05], start=1 ) } SEED_RECOMMENDATION_IDS = { f"REC_{i:02d}": str(uid) for i, uid in enumerate( [REC_01, REC_02, REC_03, REC_04, REC_05], start=1 ) } SEED_ORDER_IDS = { f"ORDER_{i:02d}": str(uid) for i, uid in enumerate([ORDER_01, ORDER_02, ORDER_03], start=1) } SEED_POSITION_IDS = { f"POS_{i:02d}": str(uid) for i, uid in enumerate([POSITION_01, POSITION_02], start=1) } SEED_GLOBAL_EVENT_IDS = { f"EVT_{i:02d}": str(uid) for i, uid in enumerate([GLOBAL_EVT_01, GLOBAL_EVT_02], start=1) } SEED_AGENT_IDS = { "extractor": str(AGENT_EXTRACTOR), "classifier": str(AGENT_CLASSIFIER), "thesis": str(AGENT_THESIS), } SEED_VARIANT_IDS = { "extractor": str(VARIANT_EXTRACTOR), "classifier": str(VARIANT_CLASSIFIER), "thesis": str(VARIANT_THESIS), } SEED_BROKER_ACCOUNT_ID = str(BROKER_ACCT_01) SEED_TRADING_DECISION_ID = str(TRADING_DECISION_01) SEED_PORTFOLIO_SNAPSHOT_ID = str(PORTFOLIO_SNAP_01) SEED_RISK_CONFIG_ID = str(RISK_CONFIG_01) SEED_WATCHLIST_IDS = { "WL_01": str(WATCHLIST_01), "WL_02": str(WATCHLIST_02), } SEED_APPROVAL_IDS = { "PENDING": str(APPROVAL_PENDING), "APPROVED": str(APPROVAL_APPROVED), } SEED_LOCKOUT_IDS = { "ACTIVE": str(LOCKOUT_ACTIVE), "EXPIRED": str(LOCKOUT_EXPIRED), } SEED_NOTIFICATION_IDS = {"NOTIF_01": str(NOTIFICATION_01)} SEED_INGESTION_RUN_IDS = { "RUN_01": str(INGESTION_RUN_01), "RUN_02": str(INGESTION_RUN_02), } SEED_SAVED_QUERY_IDS = {"SQ_01": str(SAVED_QUERY_01)} SEED_RISK_SNAPSHOT_IDS = {"SNAP_01": str(RISK_SNAPSHOT_01)} # ── Seed function ───────────────────────────────────────────── async def seed() -> None: """Populate the database with deterministic test data.""" dsn = ( f"postgresql://{os.environ['POSTGRES_USER']}" f":{os.environ['POSTGRES_PASSWORD']}" f"@{os.environ['POSTGRES_HOST']}" f":{os.environ.get('POSTGRES_PORT', '5432')}" f"/{os.environ['POSTGRES_DB']}" ) conn = await asyncpg.connect(dsn) try: await _seed_companies(conn) await _seed_sources(conn) await _seed_aliases(conn) await _seed_competitor_relationships(conn) await _seed_documents(conn) await _seed_document_mentions(conn) await _seed_document_intelligence(conn) await _seed_document_impact_records(conn) await _seed_trend_windows(conn) await _seed_trend_projections(conn) await _seed_recommendations(conn) await _seed_recommendation_evidence(conn) await _seed_risk_evaluations(conn) await _seed_broker_accounts(conn) await _seed_orders(conn) await _seed_order_events(conn) await _seed_positions(conn) await _seed_global_events(conn) await _seed_macro_impact_records(conn) await _seed_exposure_profiles(conn) await _seed_competitive_signals(conn) await _seed_trading_engine_config(conn) await _seed_trading_decisions(conn) await _seed_portfolio_snapshots(conn) await _seed_ai_agents(conn) await _seed_agent_variants(conn) await _seed_agent_performance_log(conn) await _seed_risk_configs(conn) await _seed_audit_events(conn) await _seed_watchlists(conn) await _seed_operator_approvals(conn) await _seed_symbol_lockouts(conn) await _seed_notifications(conn) await _seed_ingestion_runs(conn) await _seed_saved_queries(conn) await _seed_daily_risk_snapshots(conn) finally: await conn.close() # ── Companies ───────────────────────────────────────────────── async def _seed_companies(conn: asyncpg.Connection) -> None: companies = [ (COMPANY_AAPL, "AAPL", "Apple Inc", "NASDAQ", "Technology", "Consumer Electronics", "mega", True, BASE_TS), (COMPANY_MSFT, "MSFT", "Microsoft Corp", "NASDAQ", "Technology", "Software - Infrastructure", "mega", True, BASE_TS), (COMPANY_JPM, "JPM", "JPMorgan Chase & Co", "NYSE", "Financial Services", "Banks - Diversified", "mega", True, BASE_TS), (COMPANY_JNJ, "JNJ", "Johnson & Johnson", "NYSE", "Healthcare", "Drug Manufacturers", "mega", True, BASE_TS), (COMPANY_XOM, "XOM", "Exxon Mobil Corp", "NYSE", "Energy", "Oil & Gas Integrated", "mega", True, BASE_TS), ] await conn.executemany( """INSERT INTO companies (id, ticker, legal_name, exchange, sector, industry, market_cap_bucket, active, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT DO NOTHING""", companies, ) # ── Sources ─────────────────────────────────────────────────── async def _seed_sources(conn: asyncpg.Connection) -> None: sources = [ (SOURCE_AAPL, COMPANY_AAPL, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS), (SOURCE_MSFT, COMPANY_MSFT, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS), (SOURCE_JPM, COMPANY_JPM, "filing", "SEC EDGAR", json.dumps({"cik": "0000019617"}), 0.95, True, BASE_TS), (SOURCE_JNJ, COMPANY_JNJ, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS), (SOURCE_XOM, COMPANY_XOM, "news", "Polygon News", json.dumps({"provider": "polygon"}), 0.8, True, BASE_TS), ] await conn.executemany( """INSERT INTO sources (id, company_id, source_type, source_name, config, credibility_score, active, created_at) VALUES ($1, $2, $3, $4, $5::jsonb, $6, $7, $8) ON CONFLICT DO NOTHING""", sources, ) # ── Aliases ─────────────────────────────────────────────────── async def _seed_aliases(conn: asyncpg.Connection) -> None: aliases = [ (ALIAS_AAPL, COMPANY_AAPL, "Apple", "brand", BASE_TS), (ALIAS_MSFT, COMPANY_MSFT, "Microsoft", "brand", BASE_TS), (ALIAS_JPM, COMPANY_JPM, "JP Morgan", "brand", BASE_TS), (ALIAS_JNJ, COMPANY_JNJ, "J&J", "brand", BASE_TS), (ALIAS_XOM, COMPANY_XOM, "Exxon", "brand", BASE_TS), ] await conn.executemany( """INSERT INTO company_aliases (id, company_id, alias, alias_type, created_at) VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING""", aliases, ) # ── Competitor Relationships ────────────────────────────────── async def _seed_competitor_relationships(conn: asyncpg.Connection) -> None: rels = [ (COMPETITOR_REL_1, COMPANY_AAPL, COMPANY_MSFT, "direct_rival", 0.85, True, "manual", True, BASE_TS), (COMPETITOR_REL_2, COMPANY_JPM, COMPANY_JNJ, "same_sector", 0.3, True, "inferred", True, BASE_TS), ] await conn.executemany( """INSERT INTO competitor_relationships (id, company_a_id, company_b_id, relationship_type, strength, bidirectional, source, active, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT DO NOTHING""", rels, ) # ── Documents (10) ──────────────────────────────────────────── async def _seed_documents(conn: asyncpg.Connection) -> None: # Mix: 6 news, 2 filings, 2 macro_event docs = [ (DOC_01, "news", "news", "Reuters", "https://example.com/aapl-1", "Apple Q4 Earnings Beat", BASE_TS - timedelta(days=5), "hash_doc_01", "ingested", BASE_TS), (DOC_02, "news", "news", "Bloomberg", "https://example.com/msft-1", "Microsoft Cloud Revenue Surges", BASE_TS - timedelta(days=4), "hash_doc_02", "processed", BASE_TS), (DOC_03, "filing", "filing", "SEC EDGAR", "https://sec.gov/jpm-10k", "JPM Annual Report 10-K", BASE_TS - timedelta(days=10), "hash_doc_03", "processed", BASE_TS), (DOC_04, "news", "news", "CNBC", "https://example.com/jnj-1", "J&J Drug Trial Results", BASE_TS - timedelta(days=3), "hash_doc_04", "processed", BASE_TS), (DOC_05, "news", "news", "Reuters", "https://example.com/xom-1", "Exxon Oil Production Update", BASE_TS - timedelta(days=2), "hash_doc_05", "processed", BASE_TS), (DOC_06, "news", "news", "WSJ", "https://example.com/aapl-2", "Apple Vision Pro Sales", BASE_TS - timedelta(days=1), "hash_doc_06", "processed", BASE_TS), (DOC_07, "filing", "filing", "SEC EDGAR", "https://sec.gov/msft-10q", "MSFT Quarterly Filing 10-Q", BASE_TS - timedelta(days=8), "hash_doc_07", "processed", BASE_TS), (DOC_08, "macro_event", "news", "Reuters", "https://example.com/fed-1", "Fed Rate Decision January 2025", BASE_TS - timedelta(days=6), "hash_doc_08", "processed", BASE_TS), (DOC_09, "macro_event", "news", "Bloomberg", "https://example.com/trade-1", "US-China Trade Tensions Escalate", BASE_TS - timedelta(days=7), "hash_doc_09", "processed", BASE_TS), (DOC_10, "news", "news", "MarketWatch", "https://example.com/jpm-2", "JPM Investment Banking Revenue", BASE_TS - timedelta(days=1), "hash_doc_10", "processed", BASE_TS), ] await conn.executemany( """INSERT INTO documents (id, document_type, source_type, publisher, url, title, published_at, content_hash, status, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT DO NOTHING""", docs, ) # ── Document Company Mentions ───────────────────────────────── async def _seed_document_mentions(conn: asyncpg.Connection) -> None: mentions = [ (MENTION_01, DOC_01, COMPANY_AAPL, "AAPL", "direct", 0.95, BASE_TS), (MENTION_02, DOC_02, COMPANY_MSFT, "MSFT", "direct", 0.95, BASE_TS), (MENTION_03, DOC_03, COMPANY_JPM, "JPM", "direct", 0.90, BASE_TS), (MENTION_04, DOC_04, COMPANY_JNJ, "JNJ", "direct", 0.90, BASE_TS), (MENTION_05, DOC_05, COMPANY_XOM, "XOM", "direct", 0.90, BASE_TS), (MENTION_06, DOC_06, COMPANY_AAPL, "AAPL", "direct", 0.95, BASE_TS), (MENTION_07, DOC_07, COMPANY_MSFT, "MSFT", "direct", 0.90, BASE_TS), (MENTION_08, DOC_08, COMPANY_JPM, "JPM", "indirect", 0.60, BASE_TS), (MENTION_09, DOC_09, COMPANY_AAPL, "AAPL", "indirect", 0.50, BASE_TS), (MENTION_10, DOC_10, COMPANY_JPM, "JPM", "direct", 0.90, BASE_TS), ] await conn.executemany( """INSERT INTO document_company_mentions (id, document_id, company_id, ticker, mention_type, confidence, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT DO NOTHING""", mentions, ) # ── Document Intelligence ───────────────────────────────────── async def _seed_document_intelligence(conn: asyncpg.Connection) -> None: intels = [ (INTEL_01, DOC_01, "Apple beats Q4 expectations with strong iPhone sales.", 0.85, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_02, DOC_02, "Microsoft Azure revenue grows 29% year-over-year.", 0.90, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_03, DOC_03, "JPMorgan reports record annual profit driven by investment banking.", 0.88, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_04, DOC_04, "J&J Phase 3 trial shows positive results for new cancer drug.", 0.82, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_05, DOC_05, "Exxon increases Permian Basin output by 15%.", 0.78, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_06, DOC_06, "Apple Vision Pro sees moderate adoption in enterprise segment.", 0.75, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_07, DOC_07, "Microsoft quarterly filing shows strong cloud and AI growth.", 0.87, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), (INTEL_08, DOC_08, "Fed holds rates steady, signals potential cuts in Q2.", 0.92, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", "valid", BASE_TS), (INTEL_09, DOC_09, "US-China trade tensions rise with new tariff proposals.", 0.88, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", "valid", BASE_TS), (INTEL_10, DOC_10, "JPM investment banking fees up 20% in Q4.", 0.80, "ollama", "qwen3.5:9b", "document-intel-v2", "2.0.0", "valid", BASE_TS), ] await conn.executemany( """INSERT INTO document_intelligence (id, document_id, summary, confidence, model_provider, model_name, prompt_version, schema_version, validation_status, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT DO NOTHING""", intels, ) # ── Document Impact Records ─────────────────────────────────── async def _seed_document_impact_records(conn: asyncpg.Connection) -> None: impacts = [ (IMPACT_01, INTEL_01, COMPANY_AAPL, "AAPL", 0.9, "positive", 0.8, "short_term", "earnings", json.dumps(["Strong iPhone sales"]), json.dumps([]), json.dumps(["beat expectations"]), BASE_TS), (IMPACT_02, INTEL_02, COMPANY_MSFT, "MSFT", 0.9, "positive", 0.85, "medium_term", "growth", json.dumps(["Azure 29% growth"]), json.dumps([]), json.dumps(["cloud revenue surge"]), BASE_TS), (IMPACT_03, INTEL_03, COMPANY_JPM, "JPM", 0.85, "positive", 0.7, "short_term", "earnings", json.dumps(["Record profit"]), json.dumps(["Rate sensitivity"]), json.dumps(["investment banking"]), BASE_TS), (IMPACT_04, INTEL_04, COMPANY_JNJ, "JNJ", 0.8, "positive", 0.75, "long_term", "product", json.dumps(["Phase 3 success"]), json.dumps(["Regulatory risk"]), json.dumps(["cancer drug trial"]), BASE_TS), (IMPACT_05, INTEL_05, COMPANY_XOM, "XOM", 0.8, "positive", 0.6, "medium_term", "operational", json.dumps(["Production increase"]), json.dumps(["Oil price risk"]), json.dumps(["Permian Basin"]), BASE_TS), (IMPACT_06, INTEL_06, COMPANY_AAPL, "AAPL", 0.7, "neutral", 0.4, "medium_term", "product", json.dumps(["Enterprise adoption"]), json.dumps(["Consumer demand weak"]), json.dumps(["Vision Pro"]), BASE_TS), (IMPACT_07, INTEL_07, COMPANY_MSFT, "MSFT", 0.85, "positive", 0.8, "medium_term", "growth", json.dumps(["AI and cloud growth"]), json.dumps([]), json.dumps(["quarterly filing"]), BASE_TS), (IMPACT_08, INTEL_08, COMPANY_JPM, "JPM", 0.6, "positive", 0.5, "medium_term", "macro", json.dumps(["Rate cut signal"]), json.dumps(["Inflation risk"]), json.dumps(["Fed decision"]), BASE_TS), (IMPACT_09, INTEL_09, COMPANY_AAPL, "AAPL", 0.5, "negative", -0.3, "short_term", "geopolitical", json.dumps(["Supply chain risk"]), json.dumps(["Tariff impact"]), json.dumps(["trade tensions"]), BASE_TS), (IMPACT_10, INTEL_10, COMPANY_JPM, "JPM", 0.85, "positive", 0.65, "short_term", "earnings", json.dumps(["IB fees up 20%"]), json.dumps([]), json.dumps(["investment banking"]), BASE_TS), ] await conn.executemany( """INSERT INTO document_impact_records (id, intelligence_id, company_id, ticker, relevance, sentiment, impact_score, impact_horizon, catalyst_type, key_facts, risks, evidence_spans, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10::jsonb, $11::jsonb, $12::jsonb, $13) ON CONFLICT DO NOTHING""", impacts, ) # ── Trend Windows (5) ──────────────────────────────────────── async def _seed_trend_windows(conn: asyncpg.Connection) -> None: # entity_id is VARCHAR, not UUID trends = [ (TREND_01, "company", str(COMPANY_AAPL), "7d", "bullish", 0.72, 0.80, json.dumps([{"fact": "Strong iPhone sales", "weight": 0.9}]), json.dumps([{"fact": "Trade tensions", "weight": 0.3}]), json.dumps(["earnings", "product"]), json.dumps(["tariff_risk"]), 0.15, json.dumps({"market_phase": "expansion"}), BASE_TS, BASE_TS), (TREND_02, "company", str(COMPANY_MSFT), "7d", "bullish", 0.85, 0.88, json.dumps([{"fact": "Azure growth 29%", "weight": 0.95}]), json.dumps([]), json.dumps(["growth", "cloud"]), json.dumps([]), 0.05, json.dumps({"market_phase": "expansion"}), BASE_TS, BASE_TS), (TREND_03, "company", str(COMPANY_JPM), "7d", "bullish", 0.60, 0.70, json.dumps([{"fact": "Record profit", "weight": 0.8}]), json.dumps([{"fact": "Rate sensitivity", "weight": 0.4}]), json.dumps(["earnings"]), json.dumps(["interest_rate_risk"]), 0.25, json.dumps({"market_phase": "stable"}), BASE_TS, BASE_TS), (TREND_04, "company", str(COMPANY_JNJ), "30d", "bullish", 0.55, 0.65, json.dumps([{"fact": "Drug trial success", "weight": 0.75}]), json.dumps([{"fact": "Regulatory risk", "weight": 0.3}]), json.dumps(["product"]), json.dumps(["regulatory"]), 0.20, json.dumps({"market_phase": "stable"}), BASE_TS, BASE_TS), (TREND_05, "company", str(COMPANY_XOM), "7d", "mixed", 0.40, 0.55, json.dumps([{"fact": "Production increase", "weight": 0.6}]), json.dumps([{"fact": "Oil price volatility", "weight": 0.5}]), json.dumps(["operational"]), json.dumps(["commodity_risk"]), 0.35, json.dumps({"market_phase": "uncertain"}), BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO trend_windows (id, entity_type, entity_id, "window", trend_direction, trend_strength, confidence, top_supporting_evidence, top_opposing_evidence, dominant_catalysts, material_risks, contradiction_score, market_context, generated_at, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9::jsonb, $10::jsonb, $11::jsonb, $12, $13::jsonb, $14, $15) ON CONFLICT DO NOTHING""", trends, ) # ── Trend Projections ───────────────────────────────────────── async def _seed_trend_projections(conn: asyncpg.Connection) -> None: projections = [ (PROJECTION_01, TREND_01, "bullish", 0.70, 0.75, "7d", json.dumps(["earnings_momentum"]), 0.10, False, BASE_TS), (PROJECTION_02, TREND_02, "bullish", 0.88, 0.85, "7d", json.dumps(["cloud_growth"]), 0.05, False, BASE_TS), (PROJECTION_03, TREND_03, "bullish", 0.55, 0.60, "7d", json.dumps(["banking_recovery"]), 0.20, False, BASE_TS), (PROJECTION_04, TREND_04, "bullish", 0.50, 0.58, "30d", json.dumps(["drug_pipeline"]), 0.15, False, BASE_TS), (PROJECTION_05, TREND_05, "bearish", 0.45, 0.50, "7d", json.dumps(["oil_price_decline"]), 0.30, True, BASE_TS), ] await conn.executemany( """INSERT INTO trend_projections (id, trend_window_id, projected_direction, projected_strength, projected_confidence, projection_horizon, driving_factors, macro_contribution_pct, diverges_from_current, computed_at) VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9, $10) ON CONFLICT DO NOTHING""", projections, ) # ── Recommendations (5) ────────────────────────────────────── async def _seed_recommendations(conn: asyncpg.Connection) -> None: recs = [ (REC_01, "AAPL", COMPANY_AAPL, "buy", "autonomous", 0.80, "7d", "Strong earnings momentum with iPhone sales beat.", json.dumps(["Trade war escalation"]), 0.03, 0.01, "v1.0", BASE_TS, BASE_TS), (REC_02, "MSFT", COMPANY_MSFT, "buy", "autonomous", 0.88, "14d", "Azure cloud growth accelerating with AI tailwinds.", json.dumps(["Cloud competition"]), 0.04, 0.008, "v1.0", BASE_TS, BASE_TS), (REC_03, "JPM", COMPANY_JPM, "watch", "informational", 0.65, "7d", "Mixed signals: strong IB but rate uncertainty.", json.dumps(["Rate hike"]), 0.02, 0.005, "v1.0", BASE_TS, BASE_TS), (REC_04, "JNJ", COMPANY_JNJ, "buy", "paper", 0.70, "30d", "Positive drug trial results support long-term thesis.", json.dumps(["FDA rejection"]), 0.025, 0.007, "v1.0", BASE_TS, BASE_TS), (REC_05, "XOM", COMPANY_XOM, "sell", "informational", 0.55, "7d", "Oil price headwinds outweigh production gains.", json.dumps(["Oil price spike"]), 0.02, 0.01, "v1.0", BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO recommendations (id, ticker, company_id, action, mode, confidence, time_horizon, thesis, invalidation_conditions, portfolio_pct, max_loss_pct, model_version, generated_at, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9::jsonb, $10, $11, $12, $13, $14) ON CONFLICT DO NOTHING""", recs, ) # ── Recommendation Evidence ─────────────────────────────────── async def _seed_recommendation_evidence(conn: asyncpg.Connection) -> None: evidence = [ (REC_EV_01, REC_01, DOC_01, INTEL_01, "supporting", 0.9, BASE_TS), (REC_EV_02, REC_02, DOC_02, INTEL_02, "supporting", 0.95, BASE_TS), (REC_EV_03, REC_03, DOC_03, INTEL_03, "supporting", 0.7, BASE_TS), (REC_EV_04, REC_04, DOC_04, INTEL_04, "supporting", 0.8, BASE_TS), (REC_EV_05, REC_05, DOC_05, INTEL_05, "opposing", 0.6, BASE_TS), ] await conn.executemany( """INSERT INTO recommendation_evidence (id, recommendation_id, document_id, intelligence_id, evidence_type, weight, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT DO NOTHING""", evidence, ) # ── Risk Evaluations ────────────────────────────────────────── async def _seed_risk_evaluations(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO risk_evaluations (id, recommendation_id, eligible, allowed_mode, rejection_reasons, risk_checks, evaluated_at) VALUES ($1, $2, $3, $4, $5::jsonb, $6::jsonb, $7) ON CONFLICT DO NOTHING""", RISK_EVAL_01, REC_01, True, "autonomous", json.dumps([]), json.dumps({"portfolio_heat": "pass", "sector_exposure": "pass", "daily_loss": "pass"}), BASE_TS, ) # ── Broker Accounts ─────────────────────────────────────────── async def _seed_broker_accounts(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO broker_accounts (id, provider, account_id, mode, config, active, created_at) VALUES ($1, $2, $3, $4, $5::jsonb, $6, $7) ON CONFLICT DO NOTHING""", BROKER_ACCT_01, "alpaca", "PAPER-001", "paper", json.dumps({"base_url": "https://paper-api.alpaca.markets"}), True, BASE_TS, ) # ── Orders (3: filled, pending, cancelled) ─────────────────── async def _seed_orders(conn: asyncpg.Connection) -> None: orders = [ # Filled order (ORDER_01, REC_01, BROKER_ACCT_01, "AAPL", "buy", "market", 10, None, None, "filled", "inttest-order-001", "broker-ord-001", json.dumps({"reason": "earnings_momentum"}), BASE_TS, BASE_TS + timedelta(seconds=5), BASE_TS + timedelta(seconds=30), None, None, None, 185.50, 10, BASE_TS, BASE_TS), # Pending order (ORDER_02, REC_02, BROKER_ACCT_01, "MSFT", "buy", "limit", 5, 410.00, None, "pending", "inttest-order-002", None, json.dumps({"reason": "cloud_growth"}), BASE_TS, None, None, None, None, None, None, None, BASE_TS, BASE_TS), # Cancelled order (ORDER_03, REC_05, BROKER_ACCT_01, "XOM", "sell", "market", 20, None, None, "cancelled", "inttest-order-003", "broker-ord-003", json.dumps({"reason": "oil_headwinds"}), BASE_TS, BASE_TS + timedelta(seconds=3), None, BASE_TS + timedelta(minutes=5), None, None, None, None, BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO orders (id, recommendation_id, broker_account_id, ticker, side, order_type, quantity, limit_price, stop_price, status, idempotency_key, broker_order_id, decision_trace, submitted_at, acknowledged_at, filled_at, cancelled_at, rejected_at, rejection_reason, fill_price, fill_quantity, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13::jsonb, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23) ON CONFLICT DO NOTHING""", orders, ) # ── Order Events ────────────────────────────────────────────── async def _seed_order_events(conn: asyncpg.Connection) -> None: events = [ (ORDER_EVT_01, ORDER_01, "submitted", json.dumps({"qty": 10}), BASE_TS, BASE_TS), (ORDER_EVT_02, ORDER_01, "acknowledged", json.dumps({"broker_id": "broker-ord-001"}), BASE_TS + timedelta(seconds=5), BASE_TS + timedelta(seconds=5)), (ORDER_EVT_03, ORDER_01, "filled", json.dumps({"fill_price": 185.50, "fill_qty": 10}), BASE_TS + timedelta(seconds=30), BASE_TS + timedelta(seconds=30)), (ORDER_EVT_04, ORDER_02, "submitted", json.dumps({"qty": 5, "limit": 410.00}), BASE_TS, BASE_TS), (ORDER_EVT_05, ORDER_03, "cancelled", json.dumps({"reason": "user_request"}), BASE_TS + timedelta(minutes=5), BASE_TS + timedelta(minutes=5)), ] await conn.executemany( """INSERT INTO order_events (id, order_id, event_type, data, broker_timestamp, created_at) VALUES ($1, $2, $3, $4::jsonb, $5, $6) ON CONFLICT DO NOTHING""", events, ) # ── Positions (2) ───────────────────────────────────────────── async def _seed_positions(conn: asyncpg.Connection) -> None: positions = [ (POSITION_01, BROKER_ACCT_01, "AAPL", 10, 185.50, 192.30, 68.00, 0.0, BASE_TS), (POSITION_02, BROKER_ACCT_01, "MSFT", 15, 405.00, 412.75, 116.25, 50.00, BASE_TS), ] await conn.executemany( """INSERT INTO positions (id, broker_account_id, ticker, quantity, avg_entry_price, current_price, unrealized_pnl, realized_pnl, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT DO NOTHING""", positions, ) # ── Global Events (2) ──────────────────────────────────────── async def _seed_global_events(conn: asyncpg.Connection) -> None: events = [ (GLOBAL_EVT_01, ["interest_rate_decision"], "medium", ["North America"], ["Financial Services", "Real Estate"], [], "Federal Reserve holds rates steady, signals potential cuts in Q2 2025.", json.dumps(["Fed holds rates", "Potential Q2 cuts", "Inflation moderating"]), "weeks", 0.88, DOC_08, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", BASE_TS), (GLOBAL_EVT_02, ["trade_war", "tariff"], "high", ["North America", "East Asia"], ["Technology", "Consumer Electronics"], [], "US-China trade tensions escalate with new tariff proposals on tech imports.", json.dumps(["New tariffs proposed", "Tech sector targeted", "Supply chain disruption"]), "months", 0.82, DOC_09, "ollama", "qwen3.5:9b", "event-classification-v1", "1.0.0", BASE_TS), ] await conn.executemany( """INSERT INTO global_events (id, event_types, severity, affected_regions, affected_sectors, affected_commodities, summary, key_facts, estimated_duration, confidence, source_document_id, model_provider, model_name, prompt_version, schema_version, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::jsonb, $9, $10, $11, $12, $13, $14, $15, $16) ON CONFLICT DO NOTHING""", events, ) # ── Macro Impact Records (4) ───────────────────────────────── async def _seed_macro_impact_records(conn: asyncpg.Connection) -> None: records = [ # Fed rate decision impacts JPM and JNJ (MACRO_IMPACT_01, GLOBAL_EVT_01, COMPANY_JPM, "JPM", 0.75, "positive", json.dumps(["Rate-sensitive banking sector benefits"]), 0.80, BASE_TS), (MACRO_IMPACT_02, GLOBAL_EVT_01, COMPANY_JNJ, "JNJ", 0.25, "neutral", json.dumps(["Healthcare less rate-sensitive"]), 0.70, BASE_TS), # Trade tensions impact AAPL and MSFT (MACRO_IMPACT_03, GLOBAL_EVT_02, COMPANY_AAPL, "AAPL", -0.60, "negative", json.dumps(["China manufacturing exposure", "Tariff on electronics"]), 0.85, BASE_TS), (MACRO_IMPACT_04, GLOBAL_EVT_02, COMPANY_MSFT, "MSFT", -0.30, "negative", json.dumps(["Cloud infrastructure less exposed"]), 0.75, BASE_TS), ] await conn.executemany( """INSERT INTO macro_impact_records (id, event_id, company_id, ticker, macro_impact_score, impact_direction, contributing_factors, confidence, computed_at) VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9) ON CONFLICT DO NOTHING""", records, ) # ── Exposure Profiles (2) ──────────────────────────────────── async def _seed_exposure_profiles(conn: asyncpg.Connection) -> None: profiles = [ (EXPOSURE_01, COMPANY_AAPL, json.dumps({"North America": 0.45, "Europe": 0.25, "China": 0.20, "Rest of Asia": 0.10}), ["China", "Taiwan", "India"], ["semiconductors", "rare_earth"], ["US", "EU", "China"], "global_leader", 0.55, "manual", 1.0, 1, True, BASE_TS, BASE_TS), (EXPOSURE_02, COMPANY_JPM, json.dumps({"North America": 0.70, "Europe": 0.20, "Asia": 0.10}), ["North America", "Europe"], [], ["US", "UK", "EU"], "global_leader", 0.30, "manual", 1.0, 1, True, BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO exposure_profiles (id, company_id, geographic_revenue_mix, supply_chain_regions, key_input_commodities, regulatory_jurisdictions, market_position_tier, export_dependency_pct, source, confidence, version, active, created_at, updated_at) VALUES ($1, $2, $3::jsonb, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) ON CONFLICT DO NOTHING""", profiles, ) # ── Competitive Signal Records (2) ─────────────────────────── async def _seed_competitive_signals(conn: asyncpg.Connection) -> None: signals = [ (COMP_SIGNAL_01, DOC_01, "AAPL", "MSFT", "earnings_beat", 0.75, "positive", 0.6, 0.85, BASE_TS), (COMP_SIGNAL_02, DOC_05, "XOM", "JPM", "production_change", 0.50, "neutral", 0.3, 0.30, BASE_TS), ] await conn.executemany( """INSERT INTO competitive_signal_records (id, source_document_id, source_ticker, target_ticker, catalyst_type, pattern_confidence, signal_direction, signal_strength, relationship_strength, computed_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT DO NOTHING""", signals, ) # ── Trading Engine Config (UPDATE existing row from migration 018) ─ async def _seed_trading_engine_config(conn: asyncpg.Connection) -> None: # Migration 018 inserts a default row. Update it rather than insert. await conn.execute( """UPDATE trading_engine_config SET enabled = TRUE, paused = FALSE, risk_tier = 'moderate', max_open_positions = 10, updated_at = $1""", BASE_TS, ) # ── Trading Decisions ───────────────────────────────────────── async def _seed_trading_decisions(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO trading_decisions (id, recommendation_id, decision, ticker, computed_position_size, computed_share_quantity, risk_tier_at_decision, portfolio_heat_at_decision, active_pool_at_decision, reserve_pool_at_decision, circuit_breaker_status, correlation_check_result, sector_exposure_check_result, earnings_proximity_flag, is_micro_trade, decision_trace, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12::jsonb, $13::jsonb, $14, $15, $16::jsonb, $17) ON CONFLICT DO NOTHING""", TRADING_DECISION_01, REC_01, "execute", "AAPL", 1855.00, 10, "moderate", 0.15, 10000.00, 2500.00, "inactive", json.dumps({"correlated_tickers": [], "max_correlation": 0.0}), json.dumps({"Technology": 0.15}), False, False, json.dumps({"recommendation_id": str(REC_01), "action": "buy", "confidence": 0.80}), BASE_TS, ) # ── Portfolio Snapshots ─────────────────────────────────────── async def _seed_portfolio_snapshots(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO portfolio_snapshots (id, snapshot_date, portfolio_value, active_pool, reserve_pool, daily_return, cumulative_return, unrealized_pnl, realized_pnl, win_count, loss_count, win_rate, sharpe_ratio, max_drawdown, current_drawdown_pct, portfolio_heat, risk_tier, positions, metrics, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18::jsonb, $19::jsonb, $20) ON CONFLICT DO NOTHING""", PORTFOLIO_SNAP_01, BASE_DATE, 12500.00, 10000.00, 2500.00, 0.012, 0.025, 184.25, 50.00, 3, 1, 0.75, 1.45, 0.03, 0.01, 0.15, "moderate", json.dumps([ {"ticker": "AAPL", "quantity": 10, "unrealized_pnl": 68.00}, {"ticker": "MSFT", "quantity": 15, "unrealized_pnl": 116.25}, ]), json.dumps({"total_trades": 4, "avg_hold_days": 5}), BASE_TS, ) # ── AI Agents (3 — match migration 026 slugs, use ON CONFLICT) ─ async def _seed_ai_agents(conn: asyncpg.Connection) -> None: # Migration 026 seeds these by slug. We insert with our deterministic IDs # using ON CONFLICT on slug to capture the ID if already present. # First, try to insert; if slug exists, just update the id isn't possible # so we delete-and-reinsert with our IDs for test determinism. # Safer approach: delete existing system agents and re-insert with our IDs. await conn.execute( "DELETE FROM agent_performance_log WHERE agent_id IN (SELECT id FROM ai_agents WHERE slug IN ('document-extractor', 'event-classifier', 'thesis-rewriter'))" ) await conn.execute( "DELETE FROM agent_variants WHERE agent_id IN (SELECT id FROM ai_agents WHERE slug IN ('document-extractor', 'event-classifier', 'thesis-rewriter'))" ) await conn.execute( "DELETE FROM ai_agents WHERE slug IN ('document-extractor', 'event-classifier', 'thesis-rewriter')" ) agents = [ (AGENT_EXTRACTOR, "Document Intelligence Extractor", "document-extractor", "Extracts structured intelligence from documents.", "ollama", "qwen3.5:9b-fast", "You are a financial document analyst.", "document-intel-v2", "2.0.0", 0.0, 32768, 120, 2, True, "system", BASE_TS, BASE_TS), (AGENT_CLASSIFIER, "Global Event Classifier", "event-classifier", "Classifies global news into structured macro events.", "ollama", "qwen3.5:9b-fast", "You classify MACRO-LEVEL global news.", "event-classification-v1", "1.0.0", 0.0, 32768, 120, 2, True, "system", BASE_TS, BASE_TS), (AGENT_THESIS, "Thesis Rewriter", "thesis-rewriter", "Rewrites trade thesis summaries into professional prose.", "ollama", "qwen3.5:9b-fast", "You are a concise financial analyst.", "thesis-rewrite-v1", "1.0.0", 0.0, 32768, 120, 2, True, "system", BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO ai_agents (id, name, slug, purpose, model_provider, model_name, system_prompt, prompt_version, schema_version, temperature, max_tokens, timeout_seconds, max_retries, active, source, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)""", agents, ) # ── Agent Variants (1 per agent) ───────────────────────────── async def _seed_agent_variants(conn: asyncpg.Connection) -> None: variants = [ (VARIANT_EXTRACTOR, AGENT_EXTRACTOR, "Extractor GPT-4o Variant", "extractor-gpt4o", "Testing GPT-4o for extraction quality comparison.", "openai", "gpt-4o", "You are a financial document analyst.", "", "document-intel-v2-gpt4o", 0.1, 16384, 0, 0, 0, 60, 3, False, BASE_TS, BASE_TS), (VARIANT_CLASSIFIER, AGENT_CLASSIFIER, "Classifier Claude Variant", "classifier-claude", "Testing Claude for event classification.", "anthropic", "claude-sonnet-4-20250514", "You classify MACRO-LEVEL global news.", "", "event-classification-v1-claude", 0.0, 16384, 0, 0, 0, 90, 2, False, BASE_TS, BASE_TS), (VARIANT_THESIS, AGENT_THESIS, "Thesis GPT-4o-mini Variant", "thesis-gpt4o-mini", "Testing GPT-4o-mini for thesis rewriting cost efficiency.", "openai", "gpt-4o-mini", "You are a concise financial analyst.", "", "thesis-rewrite-v1-mini", 0.2, 8192, 0, 0, 0, 30, 2, False, BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO agent_variants (id, agent_id, variant_name, variant_slug, description, model_provider, model_name, system_prompt, user_prompt_template, prompt_version, temperature, max_tokens, context_window, input_token_limit, token_budget, timeout_seconds, max_retries, is_active, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20) ON CONFLICT DO NOTHING""", variants, ) # ── Agent Performance Log ───────────────────────────────────── async def _seed_agent_performance_log(conn: asyncpg.Connection) -> None: logs = [ (PERF_LOG_01, AGENT_EXTRACTOR, DOC_01, "AAPL", True, 2500, 0.85, 0, 1200, 800, None, VARIANT_EXTRACTOR, BASE_TS), (PERF_LOG_02, AGENT_CLASSIFIER, DOC_08, None, True, 1800, 0.88, 0, 900, 600, None, VARIANT_CLASSIFIER, BASE_TS), (PERF_LOG_03, AGENT_THESIS, None, "AAPL", True, 1200, 0.90, 0, 500, 300, None, VARIANT_THESIS, BASE_TS), ] await conn.executemany( """INSERT INTO agent_performance_log (id, agent_id, document_id, ticker, success, duration_ms, confidence, retry_count, input_tokens, output_tokens, error_message, variant_id, recorded_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) ON CONFLICT DO NOTHING""", logs, ) # ── Risk Configs ────────────────────────────────────────────── async def _seed_risk_configs(conn: asyncpg.Connection) -> None: config = json.dumps({ "max_portfolio_heat": 0.25, "max_single_position_pct": 0.05, "max_sector_concentration": 0.30, "daily_loss_limit_pct": 0.03, "macro_enabled": True, "competitive_enabled": True, }) await conn.execute( """INSERT INTO risk_configs (id, name, trading_mode, config, active, created_at, updated_at) VALUES ($1, $2, $3, $4::jsonb, $5, $6, $7) ON CONFLICT DO NOTHING""", RISK_CONFIG_01, "inttest-default", "paper", config, True, BASE_TS, BASE_TS, ) # ── Audit Events ───────────────────────────────────────────── async def _seed_audit_events(conn: asyncpg.Connection) -> None: events = [ (AUDIT_01, "order.submitted", "order", ORDER_01, "system", json.dumps({"ticker": "AAPL", "side": "buy", "qty": 10}), BASE_TS), (AUDIT_02, "order.filled", "order", ORDER_01, "system", json.dumps({"ticker": "AAPL", "fill_price": 185.50, "fill_qty": 10}), BASE_TS + timedelta(seconds=30)), (AUDIT_03, "order.cancelled", "order", ORDER_03, "system", json.dumps({"ticker": "XOM", "reason": "user_request"}), BASE_TS + timedelta(minutes=5)), ] await conn.executemany( """INSERT INTO audit_events (id, event_type, entity_type, entity_id, actor, data, created_at) VALUES ($1, $2, $3, $4, $5, $6::jsonb, $7) ON CONFLICT DO NOTHING""", events, ) # ── Watchlists ──────────────────────────────────────────────── async def _seed_watchlists(conn: asyncpg.Connection) -> None: watchlists = [ (WATCHLIST_01, "Tech Leaders", "Top technology companies", True, BASE_TS, BASE_TS), (WATCHLIST_02, "Value Picks", "Undervalued large caps", True, BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO watchlists (id, name, description, active, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT DO NOTHING""", watchlists, ) members = [ (WL_MEMBER_01, WATCHLIST_01, COMPANY_AAPL, BASE_TS), (WL_MEMBER_02, WATCHLIST_01, COMPANY_MSFT, BASE_TS), (WL_MEMBER_03, WATCHLIST_02, COMPANY_JPM, BASE_TS), ] await conn.executemany( """INSERT INTO watchlist_members (id, watchlist_id, company_id, added_at) VALUES ($1, $2, $3, $4) ON CONFLICT DO NOTHING""", members, ) # ── Operator Approvals ──────────────────────────────────────── async def _seed_operator_approvals(conn: asyncpg.Connection) -> None: approvals = [ (APPROVAL_PENDING, json.dumps({"ticker": "AAPL", "side": "buy", "qty": 5}), REC_01, "AAPL", "buy", 5, 927.50, "pending", RISK_EVAL_01, "system", None, None, BASE_TS + timedelta(hours=24), # expires in 24h BASE_TS, None, BASE_TS, BASE_TS), (APPROVAL_APPROVED, json.dumps({"ticker": "MSFT", "side": "buy", "qty": 3}), REC_02, "MSFT", "buy", 3, 1230.00, "approved", None, "system", "test-operator", "Approved for paper trading", BASE_TS + timedelta(hours=24), BASE_TS - timedelta(hours=2), BASE_TS - timedelta(hours=1), BASE_TS, BASE_TS), ] await conn.executemany( """INSERT INTO operator_approvals (id, order_job, recommendation_id, ticker, side, quantity, estimated_value, status, risk_evaluation_id, requested_by, reviewed_by, review_note, expires_at, requested_at, reviewed_at, created_at, updated_at) VALUES ($1, $2::jsonb, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) ON CONFLICT DO NOTHING""", approvals, ) # ── Symbol Lockouts ─────────────────────────────────────────── async def _seed_symbol_lockouts(conn: asyncpg.Connection) -> None: now = datetime.now(timezone.utc) lockouts = [ (LOCKOUT_ACTIVE, "AAPL", "news_shock", "Earnings volatility cooldown", now + timedelta(days=7), now - timedelta(hours=1)), (LOCKOUT_EXPIRED, "XOM", "cooldown", "Post-trade cooldown period", now - timedelta(days=1), now - timedelta(days=3)), ] await conn.executemany( """INSERT INTO symbol_lockouts (id, ticker, lockout_type, reason, expires_at, created_at) VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT DO NOTHING""", lockouts, ) # ── Notifications ───────────────────────────────────────────── async def _seed_notifications(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO notifications (id, channel, event_type, message, delivery_status, retry_count, error_message, created_at, delivered_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) ON CONFLICT DO NOTHING""", NOTIFICATION_01, "email", "order.filled", "Order filled: AAPL buy 10 shares at $185.50", "delivered", 0, None, BASE_TS, BASE_TS + timedelta(seconds=5), ) # ── Ingestion Runs ──────────────────────────────────────────── async def _seed_ingestion_runs(conn: asyncpg.Connection) -> None: runs = [ (INGESTION_RUN_01, SOURCE_AAPL, COMPANY_AAPL, "news", "completed", BASE_TS - timedelta(hours=2), BASE_TS - timedelta(hours=1, minutes=55), 15, 8, None, 0, None), (INGESTION_RUN_02, SOURCE_JPM, COMPANY_JPM, "filing", "failed", BASE_TS - timedelta(hours=1), None, 0, 0, "Connection timeout to SEC EDGAR", 2, BASE_TS + timedelta(hours=1)), ] await conn.executemany( """INSERT INTO ingestion_runs (id, source_id, company_id, source_type, status, started_at, completed_at, items_fetched, items_new, error_message, retry_count, next_retry_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) ON CONFLICT DO NOTHING""", runs, ) # ── Saved Queries ───────────────────────────────────────────── async def _seed_saved_queries(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO saved_queries (id, name, description, sql_text, created_by, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT DO NOTHING""", SAVED_QUERY_01, "Top Recommendations", "Shows highest confidence recommendations", "SELECT ticker, action, confidence FROM recommendations ORDER BY confidence DESC LIMIT 10", "operator", BASE_TS, BASE_TS, ) # ── Daily Risk Snapshots ────────────────────────────────────── async def _seed_daily_risk_snapshots(conn: asyncpg.Connection) -> None: await conn.execute( """INSERT INTO daily_risk_snapshots (id, account_id, snapshot_date, portfolio_value, daily_pnl, daily_trade_count, positions_by_sector, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7::jsonb, $8, $9) ON CONFLICT DO NOTHING""", RISK_SNAPSHOT_01, "PAPER-001", BASE_DATE, 12500.00, 150.25, 4, json.dumps({"Technology": 0.45, "Financial Services": 0.30, "Energy": 0.25}), BASE_TS, BASE_TS, ) # ── Entry point ─────────────────────────────────────────────── if __name__ == "__main__": asyncio.run(seed())