feat: competitive intelligence & historical pattern matching layer

This commit is contained in:
Celes Renata
2026-04-14 19:42:48 +00:00
parent b478022ba3
commit f7a11d14ea
203 changed files with 20155 additions and 97 deletions
+54
View File
@@ -26,6 +26,34 @@ 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 handlers = [
// Query API (proxied at /api/)
http.get('/api/companies', () => HttpResponse.json(mockCompanies)),
@@ -69,4 +97,30 @@ export const handlers = [
// Health
http.get('/api/health', () => HttpResponse.json({ status: 'ok' })),
// 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', affected_companies: mockMacroImpacts }) : new HttpResponse(null, { status: 404 });
}),
http.get('/api/macro/impacts/:ticker', () => HttpResponse.json(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)),
// 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' });
}),
];
+16
View File
@@ -152,3 +152,19 @@ describe('Watchlists page', () => {
});
});
});
describe('Global Events page', () => {
it('renders global events list with severity filter', async () => {
renderRoute('/macro/events');
await waitFor(() => {
expect(screen.getByText('Global Events')).toBeInTheDocument();
});
});
it('renders event summary from mock data', async () => {
renderRoute('/macro/events');
await waitFor(() => {
expect(screen.getByText(/US tariffs on Chinese semiconductors/)).toBeInTheDocument();
});
});
});