Files
foxhunt/migrations/004_compliance_views.sql
jgrusewski 4ba8eebc05 cleanup: declarative rewrites for migrations/services/testing TODOs
migrations:
- 001_trading_events.sql, 003_audit_system.sql: the hard-coded
  node_id literals (`trading-node-01`, `audit-node-01`,
  `ml-node-01`, `system-node-01`, `change-tracker-01`) are
  overridden per-deployment by later migrations rather than read
  from the environment. Describe that in the inline comment.
- 004_compliance_views.sql: `generate_compliance_report` is a log
  stub — actual report generation is performed by the compliance
  service. Say so explicitly.

services:
- ml_training_service/tests/orchestrator_225_features_test.rs: the
  empty `#[ignore]`d placeholder for the 225-feature orchestrator
  loader has been removed; it held no assertions and only tracked
  a TODO (feedback_no_stubs.md).
- trading_agent_service/src/service.rs: portfolio volatility uses
  the diagonal-only approximation because cross-asset return
  correlations are not maintained in this service. Document that.
- trading_service/src/services/risk.rs: `get_risk_metrics` uses
  `calculate_marginal_var` + asset-class fallback; describe why
  `calculate_comprehensive_var` is not wired at this boundary.
- trading_service/tests/auth_comprehensive.rs: delete the entire
  commented-out legacy BackupCodeValidator test block — the old
  `generate_backup_codes` / `store_backup_code` /
  `verify_backup_code` surface no longer exists, and MFA
  integration tests already cover the new API.

testing:
- harness/grpc_clients.rs: no BacktestingServiceClient proto
  exists; reword the stale TODO import line.
- chaos/*: reword the family of "TODO: Implement ..." stubs as
  "Currently a no-op / synthetic result" descriptions so readers
  know exactly how much of the chaos framework is live.
- compliance_automation_tests.rs: delete the file; it was a giant
  /* ... */ block referencing a nonexistent compliance module
  and was not wired into any Cargo target.
- framework.rs: describe why `setup()` uses `println!` instead of
  `tracing_subscriber` (tracing_subscriber is not a dep of this
  integration crate).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 08:51:26 +02:00

760 lines
32 KiB
PL/PgSQL

-- ================================================================================================
-- Migration 004: Compliance Views and Reporting Schema
-- Comprehensive compliance reporting views for regulatory requirements
-- Includes MiFID II, GDPR, SOX, and general financial regulations
-- ================================================================================================
-- ================================================================================================
-- REGULATORY REPORTING TABLES
-- Support for automated regulatory report generation
-- ================================================================================================
-- Regulatory reporting requirements table
CREATE TABLE regulatory_requirements (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
regulation_name VARCHAR(100) NOT NULL, -- MiFID II, GDPR, SOX, EMIR, etc.
requirement_code VARCHAR(100) NOT NULL, -- Article/Section reference
requirement_title VARCHAR(500) NOT NULL,
description TEXT,
-- Reporting details
reporting_frequency VARCHAR(50), -- daily, weekly, monthly, quarterly, annual
report_format VARCHAR(100), -- XML, CSV, JSON, PDF
submission_deadline VARCHAR(200), -- T+1, Month-end+5 days, etc.
-- Data requirements
required_fields JSONB NOT NULL, -- List of required data fields
data_retention_years INTEGER NOT NULL DEFAULT 7,
data_sources TEXT[], -- Which tables/views provide data
-- Implementation status
is_active BOOLEAN DEFAULT TRUE,
implementation_status VARCHAR(50) DEFAULT 'pending', -- pending, implemented, tested, deployed
last_tested TIMESTAMP WITH TIME ZONE,
-- Approval and versioning
created_by VARCHAR(64) NOT NULL,
approved_by VARCHAR(64),
effective_date DATE NOT NULL,
version VARCHAR(50) NOT NULL DEFAULT '1.0',
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
CONSTRAINT uk_regulatory_requirements UNIQUE (regulation_name, requirement_code, version)
);
-- Report generation log
CREATE TABLE report_generation_log (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
requirement_id UUID REFERENCES regulatory_requirements(id),
-- Report details
report_name VARCHAR(200) NOT NULL,
report_period_start DATE NOT NULL,
report_period_end DATE NOT NULL,
-- Generation process
generation_started_at TIMESTAMP WITH TIME ZONE NOT NULL,
generation_completed_at TIMESTAMP WITH TIME ZONE,
generation_status VARCHAR(50) NOT NULL DEFAULT 'running', -- running, completed, failed
-- Output details
output_file_path TEXT,
output_format VARCHAR(50),
record_count INTEGER,
file_size_bytes BIGINT,
checksum VARCHAR(64), -- SHA-256 hash for integrity
-- Quality validation
validation_status VARCHAR(50), -- passed, failed, warning
validation_errors JSONB,
quality_score DECIMAL(5,2), -- 0-100 quality score
-- Submission tracking
submitted_at TIMESTAMP WITH TIME ZONE,
submitted_by VARCHAR(64),
submission_reference VARCHAR(200),
acknowledgment_received BOOLEAN DEFAULT FALSE,
-- Error handling
error_message TEXT,
retry_count INTEGER DEFAULT 0,
max_retries INTEGER DEFAULT 3,
created_by VARCHAR(64) NOT NULL
);
-- ================================================================================================
-- MIFID II COMPLIANCE VIEWS
-- Best execution, transaction reporting, record keeping
-- ================================================================================================
-- MiFID II Transaction Reporting (RTS 22)
CREATE VIEW v_mifid_transaction_reporting AS
SELECT
-- Transaction identification
te.id as transaction_id,
o.client_order_id,
f.execution_id,
-- Timing (MiFID II requires specific timestamp format)
TO_TIMESTAMP(te.event_timestamp / 1000000000.0) AT TIME ZONE 'UTC' as transaction_timestamp,
TO_TIMESTAMP(f.execution_timestamp / 1000000000.0) AT TIME ZONE 'UTC' as execution_timestamp,
-- Instrument identification
f.symbol as instrument_code,
'XLON' as mic_code, -- Market Identifier Code (placeholder)
-- Transaction details
CASE f.side
WHEN 'buy' THEN 'B'
WHEN 'sell' THEN 'S'
ELSE 'X'
END as buy_sell_indicator,
f.quantity as quantity,
f.price / 100.0 as price, -- Convert from cents to decimal
f.quantity * f.price / 100.0 as notional_amount,
'EUR' as currency, -- Currency code
-- Execution details
f.venue as execution_venue,
CASE f.is_maker
WHEN TRUE THEN 'MAKE'
WHEN FALSE THEN 'TAKE'
ELSE 'UNKN'
END as liquidity_provision,
-- Client and counterparty information
o.account_id as client_identifier,
'PROP' as capacity, -- PROP (proprietary), AOTC (any other capacity)
-- Order details
CASE o.order_type
WHEN 'market' THEN 'MARK'
WHEN 'limit' THEN 'LIMI'
WHEN 'stop' THEN 'STOP'
ELSE 'OTHR'
END as order_type,
-- Compliance flags
FALSE as short_selling_indicator,
'NOAP' as commodity_derivative_indicator, -- NOAP (not applicable)
-- Additional fields for compliance
al.user_id as trader_identifier,
al.node_id as trading_desk_identifier,
-- Audit information
al.checksum as record_hash
FROM trading_events te
JOIN orders o ON te.correlation_id = o.id
JOIN fills f ON o.id = f.order_id
LEFT JOIN audit_log al ON al.entity_id = te.id
WHERE te.event_type = 'trade_executed'
AND te.event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '30 days')) * 1000000000;
-- MiFID II Best Execution Monitoring
CREATE VIEW v_mifid_best_execution AS
SELECT
f.symbol,
f.venue,
DATE(TO_TIMESTAMP(f.execution_timestamp / 1000000000.0)) as execution_date,
-- Execution statistics
COUNT(*) as execution_count,
SUM(f.quantity) as total_volume,
AVG(f.price / 100.0) as average_price,
MIN(f.price / 100.0) as min_price,
MAX(f.price / 100.0) as max_price,
STDDEV(f.price / 100.0) as price_volatility,
-- Cost analysis
SUM(f.commission) / 100.0 as total_commission,
AVG(f.commission) / 100.0 as average_commission,
SUM(f.quantity * f.price) / 100.0 as total_consideration,
-- Timing analysis
AVG(f.processed_at - f.received_at) / 1000000.0 as avg_processing_time_ms,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY f.processed_at - f.received_at) / 1000000.0 as p95_processing_time_ms,
-- Market making analysis
COUNT(*) FILTER (WHERE f.is_maker = TRUE) as maker_count,
COUNT(*) FILTER (WHERE f.is_maker = FALSE) as taker_count,
COUNT(*) FILTER (WHERE f.is_maker = TRUE)::DECIMAL / COUNT(*) as maker_ratio,
-- Quality metrics
COUNT(*) FILTER (WHERE f.processed_at - f.received_at > 100000000) as slow_executions, -- > 100ms
0 as failed_executions -- Placeholder for failed execution count
FROM fills f
WHERE f.execution_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '30 days')) * 1000000000
GROUP BY f.symbol, f.venue, DATE(TO_TIMESTAMP(f.execution_timestamp / 1000000000.0))
ORDER BY execution_date DESC, total_volume DESC;
-- MiFID II Record Keeping
CREATE VIEW v_mifid_record_keeping AS
SELECT
-- Order lifecycle
o.id as order_id,
o.client_order_id,
o.symbol,
o.side,
o.order_type,
o.quantity,
o.limit_price / 100.0 as limit_price,
-- Timestamps
TO_TIMESTAMP(o.created_at / 1000000000.0) as order_created,
TO_TIMESTAMP(o.updated_at / 1000000000.0) as order_updated,
-- Client information
o.account_id,
o.created_by as trader_id,
-- Order status and fills
o.status,
o.filled_quantity,
o.avg_fill_price / 100.0 as avg_fill_price,
-- Venue and execution details
o.venue,
string_agg(f.execution_id, '; ') as execution_ids,
string_agg(f.price::text, '; ') as fill_prices,
-- Risk and compliance
o.risk_check_passed,
o.compliance_approved,
-- Audit trail
(SELECT COUNT(*) FROM audit_log al
WHERE al.entity_type = 'order' AND al.entity_id = o.id) as audit_entry_count
FROM orders o
LEFT JOIN fills f ON o.id = f.order_id
WHERE o.created_at >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '7 years')) * 1000000000
GROUP BY o.id, o.client_order_id, o.symbol, o.side, o.order_type, o.quantity,
o.limit_price, o.created_at, o.updated_at, o.account_id, o.created_by,
o.status, o.filled_quantity, o.avg_fill_price, o.venue,
o.risk_check_passed, o.compliance_approved;
-- ================================================================================================
-- SOX COMPLIANCE VIEWS
-- Internal controls, change management, access controls
-- ================================================================================================
-- SOX Section 302 - Internal Controls Over Financial Reporting
CREATE VIEW v_sox_internal_controls AS
SELECT
-- Change tracking summary
ct.table_name,
DATE(TO_TIMESTAMP(ct.change_timestamp / 1000000000.0)) as change_date,
ct.operation,
COUNT(*) as change_count,
-- User activity
COUNT(DISTINCT ct.user_id) as unique_users,
array_agg(DISTINCT ct.user_id) FILTER (WHERE ct.user_id IS NOT NULL) as users_involved,
-- High-risk changes
COUNT(*) FILTER (WHERE ct.table_name IN ('orders', 'fills', 'positions', 'risk_limits')) as financial_changes,
COUNT(*) FILTER (WHERE ct.operation = 'DELETE') as deletion_count,
-- Approval tracking
COUNT(*) FILTER (WHERE EXISTS (
SELECT 1 FROM audit_log al
WHERE al.entity_type = ct.table_name
AND al.entity_id = (ct.primary_key_values->>'id')::UUID
AND al.event_type = 'order_created' -- Proxy for approval
)) as approved_changes
FROM change_tracking ct
WHERE ct.change_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '90 days')) * 1000000000
GROUP BY ct.table_name, DATE(TO_TIMESTAMP(ct.change_timestamp / 1000000000.0)), ct.operation
ORDER BY change_date DESC, change_count DESC;
-- SOX Section 404 - Management Assessment of Internal Controls
CREATE VIEW v_sox_management_assessment AS
SELECT
-- Control domain
'Trading Operations' as control_domain,
-- Key controls assessment
CASE
WHEN COUNT(*) FILTER (WHERE re.severity IN ('critical', 'emergency')) > 0 THEN 'DEFICIENT'
WHEN COUNT(*) FILTER (WHERE re.severity = 'high') > 5 THEN 'NEEDS_IMPROVEMENT'
ELSE 'EFFECTIVE'
END as control_effectiveness,
-- Risk events summary
COUNT(*) as total_risk_events,
COUNT(*) FILTER (WHERE re.severity IN ('critical', 'emergency')) as critical_events,
COUNT(*) FILTER (WHERE re.resolved_timestamp IS NULL) as unresolved_events,
-- Time period
DATE_TRUNC('month', TO_TIMESTAMP(re.event_timestamp / 1000000000.0)) as assessment_period,
-- Supporting evidence
jsonb_build_object(
'total_trades', (SELECT COUNT(*) FROM fills WHERE execution_timestamp >= EXTRACT(EPOCH FROM DATE_TRUNC('month', CURRENT_DATE)) * 1000000000),
'total_volume', (SELECT SUM(quantity) FROM fills WHERE execution_timestamp >= EXTRACT(EPOCH FROM DATE_TRUNC('month', CURRENT_DATE)) * 1000000000),
'system_uptime', '99.9%', -- Placeholder
'audit_coverage', '100%' -- Placeholder
) as control_metrics
FROM risk_events re
WHERE re.event_timestamp >= EXTRACT(EPOCH FROM DATE_TRUNC('month', CURRENT_DATE)) * 1000000000
GROUP BY DATE_TRUNC('month', TO_TIMESTAMP(re.event_timestamp / 1000000000.0));
-- ================================================================================================
-- GDPR COMPLIANCE VIEWS
-- Data protection, privacy, right to be forgotten
-- ================================================================================================
-- GDPR Data Subject Rights Tracking
CREATE VIEW v_gdpr_data_subject_rights AS
SELECT
al.user_id as data_subject,
COUNT(*) as total_data_points,
-- Data categories
COUNT(*) FILTER (WHERE al.entity_type = 'order') as trading_data_points,
COUNT(*) FILTER (WHERE al.entity_type = 'position') as position_data_points,
COUNT(*) FILTER (WHERE al.is_sensitive = TRUE) as sensitive_data_points,
-- Temporal analysis
MIN(TO_TIMESTAMP(al.event_timestamp / 1000000000.0)) as earliest_data,
MAX(TO_TIMESTAMP(al.event_timestamp / 1000000000.0)) as latest_data,
-- Retention analysis
COUNT(*) FILTER (WHERE TO_TIMESTAMP(al.event_timestamp / 1000000000.0) < CURRENT_DATE - INTERVAL '6 years') as retention_eligible,
-- Data portability preparation
jsonb_agg(DISTINCT al.component) as data_sources,
jsonb_agg(DISTINCT al.entity_type) as data_types,
-- Access patterns
COUNT(DISTINCT DATE(TO_TIMESTAMP(al.event_timestamp / 1000000000.0))) as active_days,
COUNT(*) FILTER (WHERE al.event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '30 days')) * 1000000000) as recent_activity
FROM audit_log al
WHERE al.user_id IS NOT NULL
GROUP BY al.user_id
ORDER BY total_data_points DESC;
-- GDPR Data Processing Activities
CREATE VIEW v_gdpr_processing_activities AS
SELECT
al.component as processing_system,
al.event_type as processing_activity,
-- Legal basis tracking
CASE al.component
WHEN 'trading_engine' THEN 'Legitimate Interest - Trade Execution'
WHEN 'risk_management' THEN 'Legitimate Interest - Risk Management'
WHEN 'compliance_engine' THEN 'Legal Obligation - Regulatory Compliance'
ELSE 'Legitimate Interest - System Operations'
END as legal_basis,
-- Data categories processed
CASE
WHEN al.entity_type = 'order' THEN 'Financial Transaction Data'
WHEN al.entity_type = 'position' THEN 'Investment Position Data'
WHEN al.is_sensitive = TRUE THEN 'Sensitive Personal Data'
ELSE 'Operational Data'
END as data_category,
-- Processing statistics
COUNT(*) as processing_count,
COUNT(DISTINCT al.user_id) as unique_data_subjects,
-- Data retention
DATE_TRUNC('month', TO_TIMESTAMP(al.event_timestamp / 1000000000.0)) as processing_month,
-- Purpose limitation
string_agg(DISTINCT al.action, ', ') as processing_purposes,
-- Data minimization assessment
-- Note: Using jsonb field count estimation (not exact unique keys across group)
AVG((SELECT COUNT(*) FROM jsonb_each(al.event_data))::numeric) as avg_data_fields_processed,
AVG(array_length(COALESCE(al.affected_fields, ARRAY[]::text[]), 1)) as avg_fields_per_operation
FROM audit_log al
WHERE al.event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '12 months')) * 1000000000
GROUP BY al.component, al.event_type, al.entity_type, al.is_sensitive,
DATE_TRUNC('month', TO_TIMESTAMP(al.event_timestamp / 1000000000.0))
ORDER BY processing_month DESC, processing_count DESC;
-- ================================================================================================
-- TRADE REPORTING COMPLIANCE
-- EMIR, SFTR, and other trade reporting regimes
-- ================================================================================================
-- EMIR Trade Reporting
CREATE VIEW v_emir_trade_reporting AS
SELECT
-- Unique Transaction Identifier
f.id as uti,
-- Counterparty information
o.account_id as reporting_counterparty,
f.contra_broker as other_counterparty,
-- Trade details
f.symbol as underlying_instrument,
'SPOT' as contract_type, -- Placeholder
TO_TIMESTAMP(f.execution_timestamp / 1000000000.0) as execution_timestamp,
f.quantity as notional_amount_1,
'EUR' as notional_currency_1,
f.price / 100.0 as price,
-- Trade characteristics
CASE f.side
WHEN 'buy' THEN 'Buy'
WHEN 'sell' THEN 'Sell'
ELSE 'Unknown'
END as direction,
-- Settlement details
f.settlement_date,
f.venue as execution_venue,
-- Clearing and settlement
CASE
WHEN f.venue LIKE '%CCP%' THEN 'Y'
ELSE 'N'
END as cleared,
-- Collateral and margin
'N/A' as collateralisation, -- Placeholder
-- Master agreement
'ISDA' as master_agreement_type, -- Placeholder
-- Reporting details
'NEW' as action_type,
CURRENT_DATE as report_date,
-- Compliance validation
CASE
WHEN f.execution_timestamp IS NOT NULL
AND f.quantity > 0
AND f.price > 0 THEN 'VALID'
ELSE 'INVALID'
END as validation_status
FROM fills f
JOIN orders o ON f.order_id = o.id
WHERE f.execution_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '30 days')) * 1000000000
AND f.quantity * f.price >= 10000000; -- EMIR threshold example
-- ================================================================================================
-- RISK AND CAPITAL ADEQUACY REPORTING
-- Basel III, CRR, and capital requirement compliance
-- ================================================================================================
-- Capital Adequacy Assessment
CREATE VIEW v_capital_adequacy AS
SELECT
-- Reporting date
CURRENT_DATE as reporting_date,
-- Market risk exposure
COALESCE(SUM(ABS(p.market_value)) / 100.0, 0) as total_market_exposure,
COALESCE(SUM(ABS(p.var_1d)) / 100.0, 0) as total_var_1d,
COALESCE(SUM(ABS(p.var_10d)) / 100.0, 0) as total_var_10d,
-- Credit risk (simplified)
COALESCE(SUM(ABS(p.market_value)) / 100.0 * 0.08, 0) as credit_risk_weighted_assets, -- 8% risk weight
-- Operational risk (simplified)
COALESCE(SUM(ABS(p.market_value)) / 100.0 * 0.15, 0) as operational_risk_capital, -- 15% capital charge
-- Total capital requirement
COALESCE(SUM(ABS(p.market_value)) / 100.0 * 0.23, 0) as total_capital_requirement, -- Combined
-- Leverage ratio components
COALESCE(SUM(ABS(p.market_value)) / 100.0, 0) as tier1_exposure,
-- Concentration limits
COUNT(DISTINCT p.symbol) as unique_instruments,
MAX(ABS(p.market_value)) / NULLIF(SUM(ABS(p.market_value)), 0) as max_single_exposure_ratio,
-- Liquidity metrics
COUNT(*) FILTER (WHERE p.quantity != 0) as active_positions,
AVG(COALESCE(p.beta, 1.0)) as portfolio_beta
FROM positions p
WHERE p.quantity != 0
AND p.last_updated >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '1 day')) * 1000000000;
-- ================================================================================================
-- ANTI-MONEY LAUNDERING (AML) SURVEILLANCE
-- Transaction monitoring and suspicious activity detection
-- ================================================================================================
-- AML Transaction Monitoring
CREATE VIEW v_aml_transaction_monitoring AS
SELECT
o.account_id,
DATE(TO_TIMESTAMP(f.execution_timestamp / 1000000000.0)) as trade_date,
-- Volume analysis
COUNT(*) as transaction_count,
SUM(f.quantity * f.price) / 100.0 as total_value,
AVG(f.quantity * f.price) / 100.0 as average_transaction_value,
MAX(f.quantity * f.price) / 100.0 as max_transaction_value,
-- Pattern analysis
COUNT(DISTINCT f.symbol) as unique_instruments,
COUNT(DISTINCT f.venue) as unique_venues,
COUNT(DISTINCT DATE(TO_TIMESTAMP(f.execution_timestamp / 1000000000.0))) as trading_days,
-- Timing analysis
EXTRACT(HOUR FROM TO_TIMESTAMP(MIN(f.execution_timestamp) / 1000000000.0)) as first_trade_hour,
EXTRACT(HOUR FROM TO_TIMESTAMP(MAX(f.execution_timestamp) / 1000000000.0)) as last_trade_hour,
-- Velocity analysis
(MAX(f.execution_timestamp) - MIN(f.execution_timestamp)) / 1000000000.0 / 3600.0 as trading_duration_hours,
COUNT(*)::DECIMAL / NULLIF((MAX(f.execution_timestamp) - MIN(f.execution_timestamp)) / 1000000000.0 / 3600.0, 0) as trades_per_hour,
-- Risk indicators
COUNT(*) FILTER (WHERE f.quantity * f.price > 50000000) as large_transactions, -- > 500k
COUNT(*) FILTER (WHERE EXTRACT(HOUR FROM TO_TIMESTAMP(f.execution_timestamp / 1000000000.0)) NOT BETWEEN 9 AND 17) as off_hours_trades,
-- Compliance flags
CASE
WHEN COUNT(*) > 100 THEN 'HIGH_FREQUENCY'
WHEN SUM(f.quantity * f.price) / 100.0 > 10000000 THEN 'HIGH_VALUE' -- > 100M
WHEN COUNT(DISTINCT f.venue) > 10 THEN 'MULTI_VENUE'
ELSE 'NORMAL'
END as risk_classification
FROM fills f
JOIN orders o ON f.order_id = o.id
WHERE f.execution_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '30 days')) * 1000000000
GROUP BY o.account_id, DATE(TO_TIMESTAMP(f.execution_timestamp / 1000000000.0))
HAVING COUNT(*) > 0 -- Only accounts with activity
ORDER BY total_value DESC, transaction_count DESC;
-- ================================================================================================
-- COMPREHENSIVE COMPLIANCE DASHBOARD
-- Executive summary view for compliance officers
-- ================================================================================================
CREATE MATERIALIZED VIEW mv_compliance_dashboard AS
SELECT
-- Reporting period
CURRENT_DATE as dashboard_date,
CURRENT_TIMESTAMP as last_updated,
-- Trading activity summary
(SELECT COUNT(*) FROM fills WHERE execution_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000) as todays_trades,
(SELECT SUM(quantity * price) / 100.0 FROM fills WHERE execution_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000) as todays_volume,
(SELECT COUNT(DISTINCT o.account_id) FROM fills f JOIN orders o ON f.order_id = o.id WHERE f.execution_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000) as active_accounts,
-- Risk and compliance alerts
(SELECT COUNT(*) FROM risk_events WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND severity IN ('critical', 'emergency')) as critical_risk_events,
(SELECT COUNT(*) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND severity = 'error') as system_errors,
(SELECT COUNT(*) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND event_type = 'compliance_check_failed') as compliance_violations,
-- Regulatory reporting status
(SELECT COUNT(*) FROM report_generation_log WHERE generation_started_at >= CURRENT_DATE AND generation_status = 'completed') as reports_completed_today,
(SELECT COUNT(*) FROM report_generation_log WHERE generation_started_at >= CURRENT_DATE AND generation_status = 'failed') as reports_failed_today,
(SELECT COUNT(*) FROM report_generation_log WHERE generation_started_at >= CURRENT_DATE AND generation_status = 'running') as reports_in_progress,
-- Data quality indicators
(SELECT COUNT(*) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND is_error = TRUE) as data_quality_issues,
(SELECT AVG(CASE WHEN checksum IS NOT NULL THEN 1.0 ELSE 0.0 END) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '7 days')) * 1000000000) as data_integrity_score,
-- System performance
(SELECT AVG(execution_time_ns) / 1000000.0 FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND execution_time_ns IS NOT NULL) as avg_processing_time_ms,
(SELECT COUNT(*) FROM system_events WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND health_status = 'healthy') as healthy_system_checks,
-- Audit coverage
(SELECT COUNT(DISTINCT user_id) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000 AND user_id IS NOT NULL) as audited_users_today,
(SELECT COUNT(DISTINCT component) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM CURRENT_DATE) * 1000000000) as audited_components,
-- Key compliance metrics
jsonb_build_object(
'mifid_transactions', (SELECT COUNT(*) FROM v_mifid_transaction_reporting WHERE transaction_timestamp >= CURRENT_DATE),
'best_execution_venues', (SELECT COUNT(DISTINCT venue) FROM v_mifid_best_execution WHERE execution_date = CURRENT_DATE),
'sox_control_effectiveness', 'EFFECTIVE', -- Placeholder
'gdpr_data_subjects', (SELECT COUNT(DISTINCT user_id) FROM audit_log WHERE event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '30 days')) * 1000000000),
'aml_alerts', (SELECT COUNT(*) FROM v_aml_transaction_monitoring WHERE risk_classification != 'NORMAL' AND trade_date = CURRENT_DATE)
) as compliance_metrics;
-- ================================================================================================
-- AUTOMATED COMPLIANCE FUNCTIONS
-- ================================================================================================
-- Function to generate regulatory report
CREATE OR REPLACE FUNCTION generate_regulatory_report(
p_requirement_id UUID,
p_report_period_start DATE,
p_report_period_end DATE,
p_output_format VARCHAR(50) DEFAULT 'CSV'
) RETURNS UUID AS $$
DECLARE
report_log_id UUID;
requirement_rec RECORD;
report_query TEXT;
output_file TEXT;
BEGIN
report_log_id := uuid_generate_v4();
-- Get requirement details
SELECT * INTO requirement_rec
FROM regulatory_requirements
WHERE id = p_requirement_id AND is_active = TRUE;
IF requirement_rec.id IS NULL THEN
RAISE EXCEPTION 'Regulatory requirement not found or inactive: %', p_requirement_id;
END IF;
-- Insert report generation log
INSERT INTO report_generation_log (
id, requirement_id, report_name, report_period_start, report_period_end,
generation_started_at, output_format, created_by
) VALUES (
report_log_id,
p_requirement_id,
requirement_rec.regulation_name || '_' || requirement_rec.requirement_code || '_' || p_report_period_start::text,
p_report_period_start,
p_report_period_end,
NOW(),
p_output_format,
'system'
);
-- Report generation is performed out-of-band by the compliance service
-- which queries the views listed in requirement_rec.data_sources. This
-- SQL routine only maintains the report_generation_log audit trail and
-- always records a successful stub row with record_count=1000. Actual
-- regulator-facing output is produced and signed by the compliance
-- service and linked back via the report_log_id returned below.
-- Update completion status (placeholder).
UPDATE report_generation_log
SET generation_completed_at = NOW(),
generation_status = 'completed',
record_count = 1000, -- Placeholder
validation_status = 'passed'
WHERE id = report_log_id;
RETURN report_log_id;
END;
$$ LANGUAGE plpgsql;
-- Function to validate compliance data quality
CREATE OR REPLACE FUNCTION validate_compliance_data_quality()
RETURNS TABLE (
check_name VARCHAR(200),
check_result VARCHAR(50),
issue_count INTEGER,
details JSONB
) AS $$
BEGIN
-- Check for missing critical audit data
RETURN QUERY
SELECT
'Missing Critical Audit Data'::VARCHAR(200),
CASE WHEN COUNT(*) = 0 THEN 'PASS' ELSE 'FAIL' END::VARCHAR(50),
COUNT(*)::INTEGER,
jsonb_build_object('missing_checksum_count', COUNT(*))
FROM audit_log
WHERE event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '24 hours')) * 1000000000
AND checksum IS NULL;
-- Check for data integrity issues
RETURN QUERY
SELECT
'Trading Data Integrity'::VARCHAR(200),
CASE WHEN COUNT(*) = 0 THEN 'PASS' ELSE 'FAIL' END::VARCHAR(50),
COUNT(*)::INTEGER,
jsonb_build_object('inconsistent_fills', COUNT(*))
FROM fills f
LEFT JOIN orders o ON f.order_id = o.id
WHERE o.id IS NULL
AND f.execution_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '24 hours')) * 1000000000;
-- Check for excessive risk events
RETURN QUERY
SELECT
'Risk Event Monitoring'::VARCHAR(200),
CASE WHEN COUNT(*) < 10 THEN 'PASS' ELSE 'WARN' END::VARCHAR(50),
COUNT(*)::INTEGER,
jsonb_build_object('high_severity_events', COUNT(*))
FROM risk_events
WHERE event_timestamp >= EXTRACT(EPOCH FROM (CURRENT_DATE - INTERVAL '24 hours')) * 1000000000
AND severity IN ('high', 'critical', 'emergency');
END;
$$ LANGUAGE plpgsql;
-- ================================================================================================
-- INDEXES FOR COMPLIANCE VIEWS
-- ================================================================================================
-- Regulatory requirements indexes
CREATE INDEX idx_regulatory_requirements_regulation ON regulatory_requirements(regulation_name, is_active);
CREATE INDEX idx_regulatory_requirements_effective ON regulatory_requirements(effective_date);
-- Report generation log indexes
CREATE INDEX idx_report_generation_log_requirement ON report_generation_log(requirement_id);
CREATE INDEX idx_report_generation_log_period ON report_generation_log(report_period_start, report_period_end);
CREATE INDEX idx_report_generation_log_status ON report_generation_log(generation_status, generation_started_at);
-- ================================================================================================
-- MATERIALIZED VIEW REFRESH SCHEDULING
-- ================================================================================================
-- Function to refresh compliance dashboard
CREATE OR REPLACE FUNCTION refresh_compliance_dashboard()
RETURNS VOID AS $$
BEGIN
REFRESH MATERIALIZED VIEW mv_compliance_dashboard;
-- Log the refresh
PERFORM log_system_event(
'dashboard_refresh',
'compliance_engine',
'info',
'compliance_dashboard',
'healthy',
jsonb_build_object('refresh_time', NOW(), 'view_name', 'mv_compliance_dashboard')
);
END;
$$ LANGUAGE plpgsql;
-- ================================================================================================
-- GRANTS AND PERMISSIONS
-- ================================================================================================
-- Note: Uncomment and modify based on your specific compliance roles
-- Compliance officer permissions
-- GRANT SELECT ON ALL TABLES IN SCHEMA public TO compliance_officer;
-- GRANT SELECT ON ALL VIEWS IN SCHEMA public TO compliance_officer;
-- GRANT EXECUTE ON FUNCTION generate_regulatory_report TO compliance_officer;
-- Auditor read-only access
-- GRANT SELECT ON audit_log, change_tracking, compliance_annotations TO external_auditor;
-- GRANT SELECT ON v_mifid_*, v_sox_*, v_gdpr_* TO external_auditor;
-- ================================================================================================
-- COMMENTS AND DOCUMENTATION
-- ================================================================================================
COMMENT ON TABLE regulatory_requirements IS 'Master table of regulatory reporting requirements with implementation status and data mapping.';
COMMENT ON TABLE report_generation_log IS 'Audit trail of regulatory report generation with validation and submission tracking.';
COMMENT ON VIEW v_mifid_transaction_reporting IS 'MiFID II RTS 22 compliant transaction reporting format with all required fields for regulatory submission.';
COMMENT ON VIEW v_mifid_best_execution IS 'MiFID II best execution monitoring data showing venue performance and execution quality metrics.';
COMMENT ON VIEW v_sox_internal_controls IS 'SOX Section 302/404 internal controls assessment showing change management and approval processes.';
COMMENT ON VIEW v_gdpr_data_subject_rights IS 'GDPR compliance view for data subject rights including data portability and retention analysis.';
COMMENT ON VIEW v_aml_transaction_monitoring IS 'Anti-money laundering surveillance data for transaction monitoring and suspicious activity detection.';
COMMENT ON MATERIALIZED VIEW mv_compliance_dashboard IS 'Real-time compliance dashboard providing executive summary of regulatory status and key metrics.';
COMMENT ON FUNCTION generate_regulatory_report IS 'Automated regulatory report generation function supporting multiple output formats and validation.';
COMMENT ON FUNCTION validate_compliance_data_quality IS 'Data quality validation function checking integrity and completeness of compliance data.';