Files
stonks-oracle/frontend/src/test/mocks/handlers.ts
T
Celes Renata bc077bfcc8 feat: trading feedback engine — periodic performance reports with AI summarization
- Migration 038: trading_reports table + report-summarizer agent seed
- 6 reporting modules: models, collector, sections, validator, summarizer, generator
- API endpoints: GET /api/reports (paginated, filterable), GET /api/reports/{id}
- Frontend hooks: useReports, useReport with TanStack Query
- Scheduler: daily (after 16:30 ET) and weekly (Saturday) report triggers
- Redis queue consumer for async report generation with retry/dedup
- 5 property-based tests (chunking, serialization, validation, accuracy, deltas)
- 109 unit/integration tests across all modules
- 6 frontend hook tests with MSW mocks
2026-05-01 22:13:09 +00:00

357 lines
25 KiB
TypeScript

import { http, HttpResponse } from 'msw';
// Seed data for deterministic tests
export const mockCompanies = [
{ id: '1', ticker: 'AAPL', legal_name: 'Apple Inc.', exchange: 'NASDAQ', sector: 'Technology', industry: 'Consumer Electronics', market_cap_bucket: 'mega', active: true, active_source_count: 3 },
{ id: '2', ticker: 'MSFT', legal_name: 'Microsoft Corporation', exchange: 'NASDAQ', sector: 'Technology', industry: 'Software', market_cap_bucket: 'mega', active: true, active_source_count: 2 },
];
export const mockDocuments = [
{ id: 'd1', document_type: 'news', source_type: 'news_api', publisher: 'Reuters', url: null, title: 'Apple Q4 Earnings Beat', published_at: '2026-04-10T12:00:00Z', retrieved_at: '2026-04-10T12:05:00Z', language: 'en', content_hash: 'abc123', parse_quality_score: 0.92, parse_confidence: 'high', status: 'extracted', created_at: '2026-04-10T12:05:00Z' },
];
export const mockTrends = [
{ id: 't1', entity_type: 'company', entity_id: 'AAPL', window: '7d', trend_direction: 'bullish', trend_strength: 0.75, confidence: 0.82, top_supporting_evidence: ['Strong earnings'], top_opposing_evidence: [], dominant_catalysts: ['earnings'], material_risks: [], contradiction_score: 0.1, market_context: null, generated_at: '2026-04-10T18:00:00Z' },
];
export const mockRecommendations = [
{ id: 'r1', ticker: 'AAPL', action: 'buy', mode: 'paper', confidence: 0.78, time_horizon: '7d', thesis: 'Strong earnings momentum', invalidation_conditions: null, portfolio_pct: 0.05, max_loss_pct: 0.02, model_version: 'v1', risk_classification: 'moderate', generated_at: '2026-04-10T19:00:00Z' },
];
export const mockOrders = [
{ id: 'o1', recommendation_id: 'r1', broker_account_id: null, ticker: 'AAPL', side: 'buy', order_type: 'market', quantity: 10, limit_price: null, stop_price: null, status: 'filled', broker_order_id: null, submitted_at: '2026-04-10T19:01:00Z', fill_price: 185.50, fill_quantity: 10, created_at: '2026-04-10T19:01:00Z' },
];
export const mockPositions = [
{ id: 'p1', broker_account_id: null, ticker: 'AAPL', quantity: 10, avg_entry_price: 185.50, current_price: 188.20, unrealized_pnl: 27.00, realized_pnl: 0, updated_at: '2026-04-11T12:00:00Z' },
];
export const mockMacroEvents = [
{ id: 'me1', event_types: ['trade_barrier', 'cost_increase'], severity: 'high', affected_regions: ['US', 'CN'], affected_sectors: ['Technology'], affected_commodities: ['semiconductors'], summary: 'US tariffs on Chinese semiconductors', key_facts: ['25% tariff', 'Effective in 30 days'], estimated_duration: 'medium_term', confidence: 0.85, source_document_id: 'd1', created_at: '2026-05-15T14:00:00Z' },
];
export const mockMacroImpacts = [
{ id: 'mi1', event_id: 'me1', company_id: '1', ticker: 'AAPL', macro_impact_score: 0.45, impact_direction: 'negative', contributing_factors: ['geographic_overlap:0.650'], confidence: 0.8, computed_at: '2026-05-15T14:00:00Z', legal_name: 'Apple Inc.', sector: 'Technology', event_summary: 'US tariffs on Chinese semiconductors', event_severity: 'high', event_types: ['trade_barrier'], affected_regions: ['US', 'CN'] },
];
export const mockTrendProjection = {
id: 'tp1', trend_window_id: 't1', projected_direction: 'bearish', projected_strength: 0.6, projected_confidence: 0.5, projection_horizon: '7d', driving_factors: ['Macro signals project bearish impact'], macro_contribution_pct: 0.3, diverges_from_current: true, computed_at: '2026-05-15T14:00:00Z',
};
export const mockCompetitors = [
{ id: 'cr1', company_a_id: '1', company_b_id: '2', relationship_type: 'direct_rival', strength: 0.85, bidirectional: true, source: 'manual', active: true, created_at: '2026-04-01T00:00:00Z', updated_at: '2026-04-01T00:00:00Z', ticker: 'MSFT', legal_name: 'Microsoft Corporation' },
];
export const mockHistoricalPatterns = [
{ source_ticker: 'AAPL', target_ticker: 'AAPL', catalyst_type: 'earnings', time_horizon: '7d', sample_count: 12, bullish_pct: 0.75, bearish_pct: 0.25, avg_strength: 0.6, avg_time_to_resolution: 3.5, pattern_confidence: 0.72, data_start: '2025-01-01T00:00:00Z', data_end: '2026-04-01T00:00:00Z', tier: 'routine_signal', insufficient_data: false },
];
export const mockCompetitiveSignals = [
{ id: 'cs1', source_document_id: 'd1', source_ticker: 'MSFT', target_ticker: 'AAPL', catalyst_type: 'product_launch', pattern_confidence: 0.65, signal_direction: 'bearish', signal_strength: 0.4, relationship_strength: 0.85, computed_at: '2026-04-10T15:00:00Z' },
];
export const mockCorporateDecisions = [
{ catalyst_type: 'm_and_a', date: '2026-03-15T00:00:00Z', summary: 'Acquisition of AI startup for $2B', trend_direction: 'bullish', trend_strength: 0.7, sample_count: 5, pattern_confidence: 0.68, document_id: 'd1' },
];
export const mockAgents = [
{ id: 'agent-1', name: 'Document Extractor', slug: 'document-extractor', purpose: 'Extract structured data from documents', model_provider: 'ollama', model_name: 'llama3.1:8b', system_prompt: 'You are a document extractor.', user_prompt_template: 'Extract from: {doc}', prompt_version: 'v1', schema_version: '1.0', temperature: 0.0, max_tokens: 32768, timeout_seconds: 120, max_retries: 2, active: true, source: 'system', created_at: '2026-04-01T00:00:00Z', updated_at: '2026-04-01T00:00:00Z' },
{ id: 'agent-2', name: 'Event Classifier', slug: 'event-classifier', purpose: 'Classify global events', model_provider: 'ollama', model_name: 'llama3.1:8b', system_prompt: 'You classify events.', user_prompt_template: 'Classify: {event}', prompt_version: 'v1', schema_version: '1.0', temperature: 0.1, max_tokens: 16384, timeout_seconds: 60, max_retries: 3, active: true, source: 'system', created_at: '2026-04-02T00:00:00Z', updated_at: '2026-04-02T00:00:00Z' },
];
export const mockAgentVariants = [
{ id: 'var-1', agent_id: 'agent-1', variant_name: 'GPT-4o Variant', variant_slug: 'gpt-4o-variant', description: 'Uses GPT-4o for extraction', model_provider: 'openai', model_name: 'gpt-4o', system_prompt: 'You are a document extractor.', user_prompt_template: 'Extract from: {doc}', prompt_version: 'v2', temperature: 0.2, max_tokens: 65536, context_window: 128000, input_token_limit: 100000, token_budget: 500000, timeout_seconds: 90, max_retries: 3, is_active: true, created_at: '2026-04-05T00:00:00Z', updated_at: '2026-04-05T00:00:00Z' },
{ id: 'var-2', agent_id: 'agent-1', variant_name: 'Mistral Variant', variant_slug: 'mistral-variant', description: 'Uses Mistral for extraction', model_provider: 'ollama', model_name: 'mistral:7b', system_prompt: 'You are a document extractor.', user_prompt_template: 'Extract from: {doc}', prompt_version: 'v1', temperature: 0.0, max_tokens: 32768, context_window: 0, input_token_limit: 0, token_budget: 0, timeout_seconds: 120, max_retries: 2, is_active: false, created_at: '2026-04-06T00:00:00Z', updated_at: '2026-04-06T00:00:00Z' },
];
export const mockVariantPerformance = {
total_invocations: 50, successes: 45, failures: 5, avg_duration_ms: 1200, p95_duration_ms: 2500, avg_confidence: 0.85, avg_retries: 0.3, total_input_tokens: 50000, total_output_tokens: 15000, success_rate: 0.9,
};
export const mockVariantPerfHistory = [
{ hour: '2026-04-10T10:00:00Z', invocations: 10, successes: 9, avg_duration_ms: 1100, avg_confidence: 0.88 },
{ hour: '2026-04-10T11:00:00Z', invocations: 12, successes: 11, avg_duration_ms: 1300, avg_confidence: 0.82 },
];
// Validation: Model Quality & Calibration mock data
export const mockValidationSummary = {
snapshot: {
id: 'ms-1',
generated_at: '2026-04-11T12:00:00Z',
lookback_window: '30d',
horizon: '7d',
prediction_count: 150,
win_rate: 0.58,
directional_accuracy: 0.56,
information_coefficient: 0.045,
rank_information_coefficient: 0.038,
avg_return: 0.012,
avg_excess_return_vs_spy: 0.003,
avg_excess_return_vs_sector: 0.002,
calibration_error: 0.08,
brier_score: 0.21,
buy_win_rate: 0.61,
sell_win_rate: 0.54,
hold_win_rate: 0.50,
metadata: {},
},
gate_status: {
passed: true,
reason: 'all thresholds met',
threshold_results: [
{ name: 'min_prediction_count', threshold: 100, actual: 150, passed: true },
{ name: 'min_ic', threshold: 0.03, actual: 0.045, passed: true },
{ name: 'min_win_rate', threshold: 0.53, actual: 0.58, passed: true },
],
},
};
export const mockValidationCalibration = {
buckets: [
{ bucket_low: 0.50, bucket_high: 0.60, avg_confidence: 0.55, observed_win_rate: 0.52, prediction_count: 30, miscalibrated: false },
{ bucket_low: 0.60, bucket_high: 0.70, avg_confidence: 0.65, observed_win_rate: 0.58, prediction_count: 40, miscalibrated: false },
{ bucket_low: 0.70, bucket_high: 0.80, avg_confidence: 0.75, observed_win_rate: 0.55, prediction_count: 35, miscalibrated: true },
{ bucket_low: 0.80, bucket_high: 0.90, avg_confidence: 0.85, observed_win_rate: 0.70, prediction_count: 25, miscalibrated: false },
{ bucket_low: 0.90, bucket_high: 1.00, avg_confidence: 0.95, observed_win_rate: 0.72, prediction_count: 20, miscalibrated: true },
],
lookback: '30d',
horizon: '7d',
};
export const mockValidationGateStatus = {
gate_status: {
passed: false,
reason: 'failed: min_ic below threshold',
threshold_results: [
{ name: 'min_prediction_count', threshold: 100, actual: 150, passed: true },
{ name: 'min_ic', threshold: 0.03, actual: 0.02, passed: false },
{ name: 'min_win_rate', threshold: 0.53, actual: 0.58, passed: true },
],
},
};
export const mockValidationICByHorizon = {
horizons: [
{ horizon: '1h', information_coefficient: 0.02, rank_information_coefficient: 0.015, prediction_count: 120, generated_at: '2026-04-11T12:00:00Z' },
{ horizon: '7d', information_coefficient: 0.045, rank_information_coefficient: 0.038, prediction_count: 100, generated_at: '2026-04-11T12:00:00Z' },
],
lookback: '30d',
};
export const mockValidationAttributionSources = {
sources: [
{ source: 'Reuters', source_type: 'news_api', prediction_count: 50, avg_weight: 0.6, avg_contribution_score: 0.3, win_rate: 0.62, avg_future_return: 0.015, avg_excess_return_vs_spy: 0.005, information_coefficient: 0.05, duplicate_rate: 0.1 },
],
lookback: '30d',
horizon: '7d',
};
export const mockValidationAttributionCatalysts = {
catalysts: [
{ catalyst_type: 'earnings', prediction_count: 40, win_rate: 0.65, avg_future_return: 0.02, avg_excess_return_vs_spy: 0.008, information_coefficient: 0.06 },
],
lookback: '30d',
horizon: '7d',
};
export const mockValidationAttributionLayers = {
layers: [
{ layer: 'company', avg_contribution_pct: 0.55, dominant_win_rate: 0.60, dominant_ic: 0.04 },
{ layer: 'macro', avg_contribution_pct: 0.30, dominant_win_rate: 0.52, dominant_ic: 0.02 },
{ layer: 'competitive', avg_contribution_pct: 0.15, dominant_win_rate: 0.48, dominant_ic: null },
],
lookback: '30d',
horizon: '7d',
};
export const handlers = [
// Query API (proxied at /api/)
http.get('/api/companies', () => HttpResponse.json(mockCompanies)),
http.get('/api/companies/:id', ({ params }) => {
const c = mockCompanies.find((c) => c.id === params.id);
return c ? HttpResponse.json({ ...c, aliases: [], active_source_count: c.active_source_count }) : new HttpResponse(null, { status: 404 });
}),
http.get('/api/companies/:id/sources', () => HttpResponse.json([])),
http.get('/api/documents', () => HttpResponse.json(mockDocuments)),
http.get('/api/documents/:id', () => HttpResponse.json({ ...mockDocuments[0], canonical_url: null, raw_storage_ref: null, normalized_storage_ref: null, company_mentions: [], intelligence: null })),
http.get('/api/trends', () => HttpResponse.json(mockTrends)),
http.get('/api/trends/:id', () => HttpResponse.json(mockTrends[0])),
http.get('/api/trends/:id/evidence', () => HttpResponse.json({ trend: mockTrends[0], evidence: [] })),
http.get('/api/recommendations', () => HttpResponse.json(mockRecommendations)),
http.get('/api/recommendations/:id', () => HttpResponse.json({ ...mockRecommendations[0], company_id: '1', evidence: [], risk_evaluation: null })),
http.get('/api/orders', () => HttpResponse.json(mockOrders)),
http.get('/api/orders/:id', () => HttpResponse.json({ ...mockOrders[0], idempotency_key: null, decision_trace: null, events: [], audit_trail: [] })),
http.get('/api/positions', () => HttpResponse.json(mockPositions)),
http.get('/api/admin/trading/config', () => HttpResponse.json({ trading_mode: 'paper', config: {} })),
http.get('/api/admin/trading/approval-config', () => HttpResponse.json({ auto_approve_paper: true, require_approval_for_live: true, approval_timeout_minutes: 5 })),
http.put('/api/admin/trading/approval-config', async ({ request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ auto_approve_paper: true, require_approval_for_live: true, approval_timeout_minutes: 5, ...body });
}),
http.get('/api/admin/trading/approvals', () => HttpResponse.json([])),
http.get('/api/admin/trading/lockouts', () => HttpResponse.json([])),
http.post('/api/admin/trading/lockouts', async ({ request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ id: 'lockout-new', ticker: body.ticker, reason: body.reason, lockout_type: body.lockout_type ?? 'manual', expires_at: new Date(Date.now() + ((body.duration_minutes as number) ?? 60) * 60000).toISOString(), created_at: new Date().toISOString() }, { status: 201 });
}),
http.delete('/api/admin/trading/lockouts/:id', () => HttpResponse.json({ status: 'deleted' })),
http.get('/api/ops/pipeline/health', () => HttpResponse.json({ hours: 24, document_stages: [{ status: 'extracted', doc_count: 5 }], parsing: {}, extraction: {}, aggregation: {}, queue_depths: {} })),
http.post('/api/ops/pipeline/retry-failed', () => HttpResponse.json({ retried: 10, message: 'Re-enqueued 10 documents for extraction' })),
http.get('/api/ops/pipeline/toggle', () => HttpResponse.json({ pipeline_enabled: true })),
http.post('/api/ops/pipeline/toggle', () => HttpResponse.json({ pipeline_enabled: true })),
http.get('/api/ops/ingestion/summary', () => HttpResponse.json({ total_runs: 10, completed: 8, failed: 2, total_items_fetched: 50, total_items_new: 12, by_source_type: [] })),
http.get('/api/ops/ingestion/throughput', () => HttpResponse.json([])),
http.get('/api/ops/model/performance', () => HttpResponse.json({ total_extractions: 20, success_rate: 0.9, avg_duration_ms: 1500, retry_rate: 0.05, avg_confidence: 0.8 })),
http.get('/api/ops/model/failures', () => HttpResponse.json([])),
http.get('/api/ops/sources/coverage-gaps', () => HttpResponse.json({ missing_source_types: [], stale_sources: [] })),
http.get('/api/admin/companies/coverage', () => HttpResponse.json([])),
// Symbol Registry (proxied at /registry/)
http.get('/registry/companies', () => HttpResponse.json(mockCompanies)),
http.post('/registry/companies', async ({ request }) => {
const body = await request.json() as Record<string, string>;
return HttpResponse.json({ id: '99', ticker: body.ticker, legal_name: body.legal_name, exchange: body.exchange ?? null, sector: body.sector ?? null, industry: null, market_cap_bucket: null, active: true }, { status: 201 });
}),
http.get('/registry/watchlists', () => HttpResponse.json([])),
http.post('/registry/watchlists', async ({ request }) => {
const body = await request.json() as Record<string, string>;
return HttpResponse.json({ id: 'w1', name: body.name, description: body.description ?? null, active: true }, { status: 201 });
}),
// Analytics: PostgreSQL schema + query
http.get('/api/analytics/pg-schema', () => HttpResponse.json({
catalog: 'postgresql', schema: 'public',
tables: [
{ name: 'companies', row_estimate: 50, columns: [{ name: 'id', type: 'uuid', nullable: false, primary_key: true }, { name: 'ticker', type: 'character varying', nullable: false }, { name: 'legal_name', type: 'text', nullable: false }] },
{ name: 'recommendations', row_estimate: 120, columns: [{ name: 'id', type: 'uuid', nullable: false, primary_key: true }, { name: 'ticker', type: 'character varying', nullable: false }, { name: 'action', type: 'character varying', nullable: false }, { name: 'company_id', type: 'uuid', nullable: false, references: 'companies' }] },
],
})),
http.post('/api/analytics/pg-query', () => HttpResponse.json({
columns: [{ name: 'test', type: 'text' }], rows: [['1']], row_count: 1, elapsed_ms: 5,
})),
http.get('/api/analytics/saved-queries', () => HttpResponse.json([
{ id: 'sq1', name: 'Company Overview', description: 'All tracked companies with sector and status', sql_text: 'SELECT ticker, legal_name, sector, active, created_at FROM companies ORDER BY ticker', created_at: '2026-04-10T12:00:00Z' },
])),
http.post('/api/analytics/saved-queries', async ({ request }) => {
const body = await request.json() as Record<string, string>;
return HttpResponse.json({ id: 'sq-new', name: body.name, description: '', sql_text: body.sql_text, created_at: '2026-04-10T12:00:00Z' }, { status: 201 });
}),
http.delete('/api/analytics/saved-queries/:id', () => HttpResponse.json({ status: 'deleted' })),
// Health
http.get('/api/health', () => HttpResponse.json({ status: 'ok' })),
// System
http.get('/api/system/rate-limits', () => HttpResponse.json({
polygon_global_limit: 45,
polygon_source_types: ['market_api', 'news_api'],
per_type_limits: { market_api: 20, news_api: 20 },
cadences_seconds: { market_api: 300, news_api: 300 },
market_api: { rate_per_minute: 20, cadence_seconds: 300, max_tickers_per_cycle: 100, active_sources: 51 },
news_api: { rate_per_minute: 20, cadence_seconds: 300, active_sources: 50 },
})),
// Macro events and impacts
http.get('/api/macro/events', () => HttpResponse.json(mockMacroEvents)),
http.get('/api/macro/events/:id', ({ params }) => {
const ev = mockMacroEvents.find((e) => e.id === params.id);
return ev ? HttpResponse.json({ ...ev, model_provider: 'ollama', model_name: 'test-model', prompt_version: 'event-v1', schema_version: '1.0.0', impacts: mockMacroImpacts }) : new HttpResponse(null, { status: 404 });
}),
http.get('/api/macro/impacts/:ticker', () => HttpResponse.json({ exposure_profile: null, impacts: mockMacroImpacts })),
http.get('/api/admin/macro/status', () => HttpResponse.json({ macro_enabled: true, source: 'default' })),
http.put('/api/admin/macro/toggle', async ({ request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ macro_enabled: body.enabled, previous_enabled: true, toggled_by: body.operator ?? 'operator' });
}),
http.get('/api/trends/:id/projection', () => HttpResponse.json(mockTrendProjection)),
// Agents
http.get('/api/agents', () => HttpResponse.json(mockAgents)),
http.get('/api/agents/:agent_id', ({ params }) => {
const a = mockAgents.find((a) => a.id === params.agent_id);
return a ? HttpResponse.json(a) : new HttpResponse(null, { status: 404 });
}),
http.get('/api/agents/:agent_id/performance', () => HttpResponse.json(mockVariantPerformance)),
http.get('/api/agents/:agent_id/performance/history', () => HttpResponse.json(mockVariantPerfHistory)),
// Agent Variants
http.get('/api/agents/:agent_id/variants', ({ params }) =>
HttpResponse.json(mockAgentVariants.filter((v) => v.agent_id === params.agent_id)),
),
http.get('/api/agents/:agent_id/variants/:variant_id', ({ params }) => {
const v = mockAgentVariants.find((v) => v.id === params.variant_id && v.agent_id === params.agent_id);
return v ? HttpResponse.json(v) : new HttpResponse(null, { status: 404 });
}),
http.post('/api/agents/:agent_id/variants', async ({ params, request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ id: 'var-new', agent_id: params.agent_id, variant_name: body.variant_name, variant_slug: body.variant_slug ?? 'new-variant', is_active: false, ...body, created_at: '2026-04-10T00:00:00Z', updated_at: '2026-04-10T00:00:00Z' }, { status: 201 });
}),
http.post('/api/agents/:agent_id/clone', async ({ params, request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ id: 'var-cloned', agent_id: params.agent_id, variant_name: body.variant_name, variant_slug: 'cloned-variant', is_active: false, ...body, created_at: '2026-04-10T00:00:00Z', updated_at: '2026-04-10T00:00:00Z' }, { status: 201 });
}),
http.post('/api/agents/:agent_id/variants/:variant_id/clone', async ({ params, request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ id: 'var-clone2', agent_id: params.agent_id, variant_name: body.variant_name, variant_slug: 'clone2', is_active: false, ...body, created_at: '2026-04-10T00:00:00Z', updated_at: '2026-04-10T00:00:00Z' }, { status: 201 });
}),
http.put('/api/agents/:agent_id/variants/:variant_id', async ({ params, request }) => {
const body = await request.json() as Record<string, unknown>;
const v = mockAgentVariants.find((v) => v.id === params.variant_id);
return v ? HttpResponse.json({ ...v, ...body, updated_at: '2026-04-10T12:00:00Z' }) : new HttpResponse(null, { status: 404 });
}),
http.delete('/api/agents/:agent_id/variants/:variant_id', ({ params }) => {
const v = mockAgentVariants.find((v) => v.id === params.variant_id);
if (!v) return new HttpResponse(null, { status: 404 });
if (v.is_active) return HttpResponse.json({ detail: 'Cannot delete active variant' }, { status: 400 });
return HttpResponse.json({ status: 'deleted' });
}),
http.post('/api/agents/:agent_id/variants/:variant_id/activate', ({ params }) => {
const v = mockAgentVariants.find((v) => v.id === params.variant_id);
return v ? HttpResponse.json({ ...v, is_active: true }) : new HttpResponse(null, { status: 404 });
}),
http.post('/api/agents/:agent_id/variants/deactivate', () => HttpResponse.json({ deactivated: true })),
http.get('/api/agents/:agent_id/variants/:variant_id/performance', () => HttpResponse.json(mockVariantPerformance)),
http.get('/api/agents/:agent_id/variants/:variant_id/performance/history', () => HttpResponse.json(mockVariantPerfHistory)),
// Trading Engine: Override order
http.post('/trading/api/trading/override/order', async ({ request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json(
{ job_id: 'job-test-123', status: 'queued', ticker: body.ticker, side: body.side, quantity: body.quantity, auto_registered: false },
{ status: 202 },
);
}),
// Competitive intelligence endpoints
http.get('/registry/companies/:id/competitors', () => HttpResponse.json(mockCompetitors)),
http.post('/registry/companies/:id/competitors/infer', () => HttpResponse.json(mockCompetitors)),
http.get('/api/patterns/:ticker', () => HttpResponse.json(mockHistoricalPatterns)),
http.get('/api/patterns/:ticker/competitive-signals', () => HttpResponse.json(mockCompetitiveSignals)),
http.get('/api/patterns/:ticker/decisions', () => HttpResponse.json(mockCorporateDecisions)),
http.get('/api/admin/competitive/status', () => HttpResponse.json({ enabled: true, toggled_at: '2026-05-15T14:00:00Z', toggled_by: 'operator' })),
http.put('/api/admin/competitive/toggle', async ({ request }) => {
const body = await request.json() as Record<string, unknown>;
return HttpResponse.json({ enabled: body.enabled, previous_enabled: true, toggled_by: 'operator' });
}),
// Trading Reports
http.get('/api/reports', () => HttpResponse.json([
{ id: 'rpt-1', report_type: 'daily', period_start: '2025-01-15', period_end: '2025-01-15', validation_status: 'passed', generated_at: '2025-01-15T21:30:00Z' },
])),
http.get('/api/reports/:id', ({ params }) => {
if (params.id === 'rpt-1') {
return HttpResponse.json({ id: 'rpt-1', report_type: 'daily', period_start: '2025-01-15', period_end: '2025-01-15', report_data: { pnl: { realized_pnl: 125.5 }, executive_summary: 'Test' }, validation_status: 'passed', generated_at: '2025-01-15T21:30:00Z', created_at: '2025-01-15T21:30:05Z' });
}
return new HttpResponse(null, { status: 404 });
}),
// Validation: Model Quality & Calibration endpoints
http.get('/api/validation/summary', () => HttpResponse.json(mockValidationSummary)),
http.get('/api/validation/calibration', () => HttpResponse.json(mockValidationCalibration)),
http.get('/api/validation/gate-status', () => HttpResponse.json(mockValidationGateStatus)),
http.get('/api/validation/ic-by-horizon', () => HttpResponse.json(mockValidationICByHorizon)),
http.get('/api/validation/attribution/sources', () => HttpResponse.json(mockValidationAttributionSources)),
http.get('/api/validation/attribution/catalysts', () => HttpResponse.json(mockValidationAttributionCatalysts)),
http.get('/api/validation/attribution/layers', () => HttpResponse.json(mockValidationAttributionLayers)),
];