PRISM

Modules/Intel-Financial-Public.md

Module: intel-financial-public

SPOKE MODULE. Runs only for public companies. If the company has no ticker (is_private=True or ticker=None), skipped=True is returned immediately with zero API calls. Surfacing executive quotes from earnings calls is the highest-value output — gold for sales personalization.


Identity

Field Value
Name intel-financial-public
Version 0.1.0
Layer Intelligence (Wave 1)
Wave 1 (runs in parallel with other spoke modules after intel-company)
Description Financial intelligence for publicly traded companies via Yahoo Finance (market data + analyst consensus), SEC EDGAR (10-K/10-Q filing metadata and excerpts), and Perplexity-powered investor presentation analysis with executive quote extraction.
LLM Tier Claude via Instructor (structuring SEC insights, investor presentations, comparative summary) + Perplexity sonar (investor presentation research)
Timeout 300 seconds (5 minutes)
Max Retries 2 (module level)
Gate Module NO. Failure degrades financial context but does not abort the audit.

Dependencies

Module Field Read Why
intel-company ticker (via ExecutionContext) Required to pull Yahoo Finance and SEC EDGAR data — no ticker = skip
intel-company company_name Used in SEC EDGAR full-text search and Perplexity investor presentation queries
intel-company is_private Skip gate: if True, module returns skipped=True immediately
intel-company competitors (via ExecutionContext) Competitor tickers extracted for comparative financial data (TODO: implemented once DB read is wired)

Hub-and-Spoke Position

intel-financial-public is a spoke module. It reads from intel-company and writes its output to module_executions. Downstream synthesis modules (intel-competitors, audit-report) consume its output when building the ROI business case and financial narrative.


Input Schema

Field Type Required Description
domain str yes Website domain to analyze, e.g. "dell.com"
ticker str yes Stock ticker symbol, e.g. "DELL"

Additionally reads from ExecutionContext at runtime:

Context Field Type Used For
is_private bool Skip gate — returns skipped=True if True
ticker str or None Drives all Yahoo Finance and SEC EDGAR calls
company_name str SEC EDGAR search + Perplexity investor presentation queries
audit_id str Structured logging

Output Schema: FinancialPublicOutput

Top-Level Fields

Field Type Required Description
domain str yes Primary website domain, e.g. "dell.com"
ticker str yes Stock ticker symbol, e.g. "DELL"
skipped bool yes True if module was skipped (private company or no ticker)
skip_reason str or None no Reason the module was skipped, if applicable
annual_financials list[AnnualFinancials] no Up to 3 years of annual financial data from Yahoo Finance
market_data MarketData or None no Current market snapshot (price, market cap, P/E)
analyst_data AnalystData or None no Analyst consensus (recommendation, target price, analyst count)
sec_insights list[SECInsight] no Enriched insights from recent 10-K and 10-Q filings
investor_presentations list[InvestorPresentation] no Executive quotes and priorities from investor presentations
competitor_financials list[CompetitorFinancials] no Basic Yahoo Finance data for competitor tickers
comparative_summary str no Narrative comparing company financial position to competitors

Sub-Schema: AnnualFinancials

Field Type Required Description
fiscal_year str yes Fiscal year label, e.g. "FY2025"
revenue float or None no Annual revenue in USD as float, e.g. 88400000000.0
net_income float or None no Annual net income in USD as float
gross_margin_pct float or None no Gross margin as a percentage, e.g. 23.5 for 23.5%
operating_margin_pct float or None no Operating margin as a percentage, e.g. 6.2 for 6.2%
revenue_growth_pct float or None no Year-over-year revenue growth as a percentage

Sub-Schema: MarketData

Field Type Required Description
market_cap float or None no Market capitalization in USD
stock_price float or None no Current stock price in USD
fifty_two_week_high float or None no 52-week high stock price in USD
fifty_two_week_low float or None no 52-week low stock price in USD
pe_ratio float or None no Trailing price-to-earnings ratio
forward_pe float or None no Forward price-to-earnings ratio

Sub-Schema: AnalystData

Field Type Required Description
recommendation str or None no Analyst consensus, e.g. "Buy", "Hold", "Sell"
target_price float or None no Mean analyst target price in USD
number_of_analysts int or None no Number of analysts covering the stock

Sub-Schema: SECInsight

Field Type Required Description
filing_type Literal["10-K", "10-Q"] yes Annual (10-K) or quarterly (10-Q) filing
filing_date str yes Filing date in YYYY-MM-DD format
filing_url str or None no URL to the filing on SEC EDGAR
digital_revenue_pct float or None no Digital revenue as % of total, if disclosed
technology_mentions list[str] no Technology keywords mentioned: "search", "AI", "personalization", etc.
key_excerpts list[str] no Notable excerpts relevant to digital/tech strategy
management_discussion_summary str no Summary of Management Discussion & Analysis section

Sub-Schema: InvestorPresentation

Field Type Required Description
title str yes Presentation title
date str yes Presentation date in YYYY-MM-DD or approximate format
url str or None no URL to the presentation or IR page
strategic_priorities list[str] no Strategic priorities mentioned
digital_commitments list[str] no Commitments to digital transformation or e-commerce
technology_roadmap list[str] no Technology roadmap items mentioned
search_mentions list[str] no Any mentions of search, discovery, or recommendation technology
key_quotes list[str] no Verbatim executive quotes about strategy or technology

Sub-Schema: CompetitorFinancials

Field Type Required Description
company_name str yes Competitor company name
ticker str yes Competitor stock ticker symbol
revenue float or None no Most recent annual revenue in USD
revenue_growth_pct float or None no Year-over-year revenue growth as a percentage
market_cap float or None no Market capitalization in USD
gross_margin_pct float or None no Gross margin as a percentage

Collection Strategy

Source 1: Yahoo Finance (yfinance library)

Aspect Detail
Adapter yfinance Python library (direct, no adapter abstraction yet)
Data 3-year revenue trend, net income, margin percentages, market cap, stock price, 52-week high/low, P/E ratio (trailing + forward), analyst recommendation and target price
Input Ticker symbol
Evidence Tier VERIFIED
Method direct_api
Retry Module-level max_retries=2
Cost Free (no API key required)

Source 2: SEC EDGAR (EFTS API)

Aspect Detail
Adapter Direct httpx calls to EFTS full-text search API
Endpoint https://efts.sec.gov/LATEST/search-index?q={company_name}&dateRange=custom&startdt={one_year_ago}&forms=10-K,10-Q
Data Recent 10-K and 10-Q filing metadata: dates, URLs, accession numbers
Evidence Tier VERIFIED
Method direct_api
Cost Free (no API key required)

Source 3: Perplexity API (investor presentations)

Aspect Detail
Adapter Perplexity sonar model (same adapter as intel-company)
Model sonar ($0.25/M input tokens)
Input Query: "{company_name} investor presentation annual report earnings call transcript 2024 2025 site:ir.{domain} OR site:sec.gov"
Output Raw text with citations, passed to Claude (Instructor) for structuring
Evidence Tier WEBSEARCH
Method llm_extraction
Retry 3 attempts with exponential backoff

Source 4: Claude via Instructor (structuring)

Aspect Detail
Usage Structures raw Perplexity text into InvestorPresentation Pydantic models; enriches SEC filing metadata with technology analysis; generates comparative_summary
Models Configured via settings.get_enricher_provider() (typically claude-3-5-haiku)
Evidence Tier ESTIMATE (for comparative_summary) / WEBSEARCH (for investor presentations)
Method llm_extraction
Max Retries (Instructor) 3 per completion call

Enrichment Strategy

The module uses a two-phase approach:

Phase 1 — Deterministic collection (Yahoo Finance + SEC EDGAR) Raw structured data is pulled via API with no LLM involvement. Yahoo Finance returns typed numerical data. SEC EDGAR returns filing metadata (accession numbers, dates, form types).

Phase 2 — LLM enrichment (Perplexity + Claude/Instructor) - Perplexity searches for investor presentations and earnings call transcripts by IR page domain - Claude/Instructor structures the raw search results into InvestorPresentation objects - Claude/Instructor enriches SEC filing metadata with technology keyword extraction and MDA summaries - Claude generates a comparative_summary narrative from the competitor financial data

Why This Matters for Sales

The InvestorPresentation.key_quotes field captures verbatim CEO/CFO statements about digital strategy from earnings calls. These are the highest-value output of this module — enabling AEs to open discovery calls by reflecting the prospect's own language back at them.


Validation Rules (9 Checks)

# Rule Severity Threshold
1 If skipped=True, skip_reason must be set required Early return pass if both true
2 annual_financials has at least 2 years required >= 2 AnnualFinancials entries
3 market_data is not None required market_data != None
4 market_data.market_cap > 0 required market_cap > 0
5 At least 1 SEC insight present warning len(sec_insights) >= 1
6 domain matches expected input required Case-insensitive match
7 ticker matches expected input required Case-insensitive match
8 At least 1 source provenance record warning len(sources) >= 1
9 comparative_summary not empty when competitors present warning Not empty string when competitor_financials populated

Required failures -> status "partial". Warning failures -> logged but passed.


Evidence Requirements

Field Minimum Tier Rationale
annual_financials VERIFIED Yahoo Finance direct API — not modeled or estimated
market_data VERIFIED Yahoo Finance direct API — real-time data
analyst_data VERIFIED Yahoo Finance direct API — institutional analyst consensus
sec_insights VERIFIED SEC EDGAR direct API — regulatory filings
investor_presentations WEBSEARCH Perplexity + LLM extraction — acceptable for narrative quotes
comparative_summary ESTIMATE LLM synthesis — clearly labeled as narrative, not raw data
competitor_financials VERIFIED Yahoo Finance direct API

Persistence

intel-financial-public writes only to module_executions (not the accounts table directly). Synthesis modules read from module_executions.output JSONB.

Columns Written to module_executions

module_name="intel-financial-public"
module_version="0.1.0"
status           # "success" | "partial" | "failed"
output           # FinancialPublicOutput.model_dump() -> JSONB
sources          # list[Source] -> JSONB array
duration_ms      # int
llm_calls        # int (Perplexity + Claude calls combined)
llm_cost_usd     # float

Cost Profile

Metric Expected Value
LLM Calls 3-6 (1-2 Perplexity + 2-4 Claude/Instructor for structuring)
Yahoo Finance Calls 1 (ticker lookup, all data in one call)
SEC EDGAR Calls 1-2 (EFTS search + optional filing fetch)
Estimated Cost ~$0.05-0.15 per audit (Perplexity + Claude enrichment)
Expected Duration 30-90 seconds
External API Calls 3-5 total

Retry Architecture (Two Layers)

Layer 1: Collector Retries (network errors)

Trigger Retry Backoff
Timeout 3 attempts Exponential (2^attempt seconds)
Rate limit (429) 3 attempts Exponential
Connection error 3 attempts Exponential
Other HTTP error No retry Fail immediately

Layer 2: Module Retries (data quality)

Trigger Retry Backoff
Instructor validation failure 3 attempts per completion Instructor native retry
Module-level failure max_retries=2 Module level

If all retries exhausted: return ModuleExecutorResult with status="failed". Module failure is non-fatal to the audit — other modules continue.


Skip Logic

The skip check runs before any API calls:

if context.is_private or context.ticker is None:
    return ModuleExecutorResult(status="success", output=FinancialPublicOutput(skipped=True, ...))

Skip costs: 0 LLM calls, 0 API calls, ~1ms duration. The skip result is recorded in module_executions so downstream modules know this module ran but found no applicable data.


Runtime Notes

SaaS Runtime (Temporal/Python)

  • Module: prism_platform/v2/modules/intel_financial_public/module.py
  • Collector: prism_platform/v2/modules/intel_financial_public/collector.py
  • Enricher: prism_platform/v2/modules/intel_financial_public/enricher.py
  • Validator: prism_platform/v2/modules/intel_financial_public/validator.py
  • Schemas: prism_platform/v2/modules/intel_financial_public/schemas.py

Skill Runtime (Claude Code)

  • Skill file: ~/.claude/skills/algolia-intel-financial-public/SKILL.md (or algolia-audit-financials)
  • Reads from: 01-company-context.json (for ticker)
  • Writes to: 08-financial-profile.md, 08-financial-profile.json
  • MCP tools used: WebFetch (IR pages, SEC EDGAR direct), WebSearch (Perplexity-equivalent for earnings calls)

What Makes This Production-Grade (vs a Simple Prompt)

Aspect Simple Prompt PRISM Module
Skip logic Runs always, wastes money on private companies Hard gate: skip if is_private or no ticker, zero API calls
Financial data "Research their revenue" Yahoo Finance direct API — 3 years, typed numeric fields
Market data LLM estimates stock price Real-time yfinance: price, market cap, P/E, 52-week range
Analyst consensus Not captured yfinance analyst recommendation + target price + analyst count
SEC filings LLM doesn't know about EDGAR EFTS API search: actual 10-K/10-Q metadata with URLs
Executive quotes Fabricated or generic Perplexity searches IR pages for actual earnings call transcripts
Structuring Hope for good JSON Instructor + Claude with Pydantic retry on each structured extraction
Source provenance None Every field has EvidenceTier (VERIFIED/WEBSEARCH/ESTIMATE)
Validation Trust the LLM 9-point checklist: market cap > 0, 2+ years of data, domain/ticker match

Evolution: v1 → v2

v1 (Current — Implemented)

  • Yahoo Finance via yfinance library (direct Python import)
  • SEC EDGAR via EFTS full-text search API (httpx)
  • Perplexity sonar for investor presentation discovery
  • Claude/Instructor for structuring all LLM-returned data
  • Competitor financials read: TODO (DB integration incomplete)
  • Module pattern: v2 agentic (config.py + playbook.md + schemas.py + ModuleExecutor harness)

v2 (Planned — Agentic Module Pattern)

  • Becomes a playbook-based agent following the unified module architecture
  • Config: intel_financial_public/config.yaml (API endpoints, timeouts, thresholds)
  • Playbook: intel_financial_public/playbook.md (step-by-step agent instructions)
  • Schema: intel_financial_public/schema.py (unchanged Pydantic models)
  • Executor: intel_financial_public/executor.py (runs Claude agent against playbook)
  • Sources split across 3 structured APIs:
  • SEC EDGAR API (structured endpoint, not just EFTS full-text search)
  • Yahoo Finance (unchanged)
  • Perplexity for earnings call research (unchanged)
  • Executive quotes from earnings calls become a first-class output with their own sub-schema
  • Competitor ticker lookup wired to accounts table (removes the TODO)
  • No code changes to skip logic or validation contract

Changelog

Date Change Reason
2026-04-14 Module spec written to vault Knowledge extraction for v2 planning
2026-03-30 Initial implementation Backend phase 1

  • Module-Catalog -- all 20 modules overview
  • Intel-Company -- foundation hub this module depends on
  • Intel-Financial-Private -- the private company counterpart
  • Module-Spec-Template -- the template this spec follows
  • Evidence-Tier-Spec -- evidence tier system
  • Adapter-Interfaces -- PerplexityAdapter and WebFetchAdapter