Equity Research Workflow

VerifiedSafe

Produces equity research briefs and full stock pitch memos with financial models using SEC filings, news, and financial data.

Sby Skills Guide Bot
Data & AIIntermediate
207/24/2026
Claude Code
#equity-research#financial-analysis#sec-filings#stock-pitch#investment-research

Recommended for

Our review

Automates fundamental equity research by gathering SEC filings, earnings, news, and financials for a ticker, then producing a research brief or full stock pitch memo with a 3-statement financial model Excel.

Strengths

  • Automates data collection from multiple financial sources
  • Produces structured deliverables (brief or full pitch) adapted to the chosen mode
  • Handles errors and source unavailability gracefully by continuing with partial data

Limitations

  • Subject to API rate limits (yfinance, SEC EDGAR) that can slow down the process
  • Depth of analysis depends on the quality of accessible web sources
  • Does not replace human judgment for investment decisions
When to use it

Use this workflow to get a quick, structured summary of financial data and fundamental analysis for a publicly traded company.

When not to use it

Avoid this workflow for highly specific analyses that require deep manual adjustments or when financial APIs are currently unreliable.

Security analysis

Safe
Quality score85/100

The skill uses bash and python for legitimate purposes like validating ticker symbols and creating directories, and fetches public financial data via web tools. It does not exfiltrate secrets, run destructive commands, or use obfuscation. The fixed output path is harmless but environment-specific.

No concerns found

Examples

Brief equity research
/equity-research AAPL
Full stock pitch
/equity-research MSFT

name: equity-research description: "Equity research workflow — gathers SEC filings, earnings, news, and financials for a ticker, then produces a research brief or full stock pitch memo with a 3-statement financial model Excel." argument-hint: "equity-research AAPL" allowed-tools: Agent, AskUserQuestion, Bash, Read, Write, Glob, Grep, WebSearch, WebFetch user-invocable: true

Equity Research Workflow

Produce professional equity research for the given ticker. The ticker is provided as the skill argument (e.g., /equity-research AAPL).

Step 1: Validate Ticker & Setup

  1. Extract the ticker symbol from the skill argument. If no ticker is provided, ask the user for one.
  2. Validate the ticker by running:
    python3 -c "
    import yfinance as yf
    import time
    t = yf.Ticker('TICKER')
    for attempt in range(3):
        try:
            info = t.info
            name = info.get('shortName', 'UNKNOWN')
            print(name)
            break
        except Exception as e:
            if 'Rate' in str(e) and attempt < 2:
                time.sleep(3 * (attempt + 1))
            else:
                raise
    "
    
    • If the ticker is invalid (returns empty, errors, or 'UNKNOWN'), inform the user and stop.
    • If rate-limited after retries, inform the user to wait ~15 minutes and try again.
  3. Create the output directory:
    mkdir -p "/Users/yanhaolin/Desktop/Yale/claude code/TICKER/data"
    
  4. Check for prior research — look for existing brief.md or pitch.md in the ticker folder. If found, note the prior research date from the metadata header.
  5. Ask the user to choose a mode:
    • Brief: ~1-2 page research note (company snapshot, key metrics, recent developments, what to watch)
    • Full pitch: ~4-6 page stock pitch memo (executive summary, company overview, industry context, thesis, catalysts, risks, valuation, conclusion)

Step 2: Parallel Data Gathering

Spawn all 4 agents simultaneously using the Agent tool in a SINGLE message with 4 Agent tool calls so they run in parallel. Each agent writes its findings to the ticker's data/ subfolder.

Mode-dependent depth:

  • Brief mode: latest quarter only, 30-day news window
  • Full pitch mode: multiple quarters, 90-day news window, industry comps

Error handling: If an agent fails (e.g., EDGAR is down, no transcript found), the workflow continues with partial data. The checkpoint in Step 3 will note which sources returned data and which had gaps.

Agent 1: SEC Filings Agent

Spawn with Agent tool (subagent_type: general-purpose):

Prompt:

You are researching SEC filings for {TICKER} ({COMPANY_NAME}).

Your task:

  1. Use WebFetch to access https://data.sec.gov/submissions/CIK{CIK_NUMBER}.json to find recent filings. To find the CIK, WebSearch for "SEC EDGAR {TICKER} CIK number".
  2. Identify the most recent 10-K, 10-Q, and any 8-Ks from the last 90 days.
  3. For each filing, use WebFetch or WebSearch to access the filing and extract:
    • Key financial figures (revenue, net income, EPS, cash flow)
    • Risk factors (new or changed risks)
    • Management commentary / MD&A highlights
    • Any material events (for 8-Ks)
  4. If EDGAR API is unavailable, fall back to WebSearch for "{TICKER} SEC filing 10-K 10-Q summary".

Mode: {MODE}

  • Brief: latest quarter filing only
  • Full pitch: last 2-3 filings for trend analysis

Write your findings as structured markdown. Save to: /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/data/sec.md

Format:

# {TICKER} — SEC Filings Summary
**Date gathered:** {TODAY}

## Latest 10-Q / 10-K
- Filing date:
- Period:
- Revenue:
- Net income:
- EPS:
- Key highlights:

## Risk Factors (New/Changed)
- ...

## MD&A Highlights
- ...

## Recent 8-Ks
- ...

Agent 2: Earnings Agent

Spawn with Agent tool (subagent_type: general-purpose):

Prompt:

You are researching recent earnings for {TICKER} ({COMPANY_NAME}).

Your task:

  1. WebSearch for "{TICKER} earnings call Q[latest quarter] {YEAR}" and "{TICKER} earnings results".
  2. Find earnings press releases and any publicly available transcript excerpts.
  3. Extract:
    • Reported vs. expected EPS and revenue
    • Management guidance for next quarter / full year
    • Key quotes from management
    • Analyst Q&A highlights (topics of concern)
    • Any surprises or notable changes in tone
  4. Note: full transcripts are often paywalled. Pull whatever is publicly available. Flag if only partial data was found.

Mode: {MODE}

  • Brief: latest quarter only
  • Full pitch: last 2 quarters for trend comparison

Write your findings as structured markdown. Save to: /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/data/earnings.md

Format:

# {TICKER} — Earnings Summary
**Date gathered:** {TODAY}
**Data completeness:** Full transcript / Partial (press release + quotes only)

## Q[X] {YEAR} Results
- EPS: reported vs. expected
- Revenue: reported vs. expected
- Guidance:

## Key Management Commentary
- ...

## Analyst Q&A Highlights
- ...

Agent 3: News Agent

Spawn with Agent tool (subagent_type: general-purpose):

Prompt:

You are researching recent news for {TICKER} ({COMPANY_NAME}).

Your task:

  1. WebSearch for "{TICKER} news" and "{COMPANY_NAME} news" covering recent developments.
  2. Also search for: "{TICKER} press release", "{COMPANY_NAME} analyst upgrade downgrade", "{COMPANY_NAME} M&A acquisition".
  3. Identify and summarize:
    • Major press releases
    • Analyst upgrades/downgrades and price target changes
    • M&A activity
    • Management changes
    • Product launches or strategic pivots
    • Sector/industry developments affecting the company
    • Regulatory or legal developments
  4. Prioritize material, stock-moving news over routine items.

Mode: {MODE}

  • Brief: last 30 days only
  • Full pitch: last 90 days, broader sector context

Write your findings as structured markdown. Save to: /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/data/news.md

Format:

# {TICKER} — News Summary
**Date gathered:** {TODAY}
**Coverage window:** Last {30/90} days

## Key Headlines
1. [Date] Headline — summary
2. ...

## Analyst Actions
- ...

## Sector Developments
- ...

Agent 4: Financials Agent

Spawn with Agent tool (subagent_type: general-purpose):

Prompt:

You are pulling financial data for {TICKER} using yfinance.

Your task: Run Python code using Bash to pull data from Yahoo Finance:

import yfinance as yf
import json

t = yf.Ticker("{TICKER}")
info = t.info
hist = t.history(period="1y")

# Key metrics
metrics = {
    "Company": info.get("shortName"),
    "Sector": info.get("sector"),
    "Industry": info.get("industry"),
    "Market Cap": info.get("marketCap"),
    "Price": info.get("currentPrice") or info.get("regularMarketPrice"),
    "52W High": info.get("fiftyTwoWeekHigh"),
    "52W Low": info.get("fiftyTwoWeekLow"),
    "P/E (Trailing)": info.get("trailingPE"),
    "P/E (Forward)": info.get("forwardPE"),
    "EV/EBITDA": info.get("enterpriseToEbitda"),
    "Revenue": info.get("totalRevenue"),
    "Revenue Growth": info.get("revenueGrowth"),
    "Gross Margin": info.get("grossMargins"),
    "Operating Margin": info.get("operatingMargins"),
    "Net Margin": info.get("profitMargins"),
    "ROE": info.get("returnOnEquity"),
    "Debt/Equity": info.get("debtToEquity"),
    "Free Cash Flow": info.get("freeCashflow"),
    "Dividend Yield": info.get("dividendYield"),
    "Beta": info.get("beta"),
}
print(json.dumps(metrics, indent=2, default=str))

Also pull: quarterly financials (t.quarterly_financials), price performance (1M, 3M, 6M, 1Y returns from history), and if in full pitch mode, identify 3-5 comparable companies in the same sector/industry and pull their key multiples.

Mode: {MODE}

  • Brief: key metrics + price performance only
  • Full pitch: add quarterly trends, comps table, historical multiple ranges

Write your findings as structured markdown. Save to: /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/data/financials.md

Format:

# {TICKER} — Financial Data
**Date gathered:** {TODAY}
**Price at time of research:** $X.XX

## Key Metrics
| Metric | Value |
|--------|-------|
| ... | ... |

## Price Performance
- 1M: X%
- 3M: X%
- 6M: X%
- 1Y: X%

## Quarterly Trends (Full Pitch Only)
...

## Comparable Companies (Full Pitch Only)
| Company | P/E | EV/EBITDA | Margin | Growth |
|---------|-----|-----------|--------|--------|
| ... | ... | ... | ... | ... |

Spawning All Agents

Spawn all 4 agents in a SINGLE message with 4 Agent tool calls so they run in parallel. Replace {TICKER}, {COMPANY_NAME}, {MODE}, {TODAY}, and {CIK_NUMBER} with actual values. Get {COMPANY_NAME} from the yfinance validation in Step 1.

Step 3: Interactive Checkpoint

After all 4 agents complete, consolidate their findings:

  1. Read all data files from the data/ subfolder:
    • data/sec.md
    • data/earnings.md
    • data/news.md
    • data/financials.md
  2. Note which files exist and which are missing (agent failures).
  3. Present a consolidated summary to the user:

Data gathered for {TICKER} — here's what I found:

Financials: [2-3 line summary of key metrics, valuation, performance]

SEC Filings: [1-2 line summary of filing highlights] (or "No filing data available" if agent failed)

Earnings: [1-2 line summary of latest results and guidance] (note if partial data)

News: [Top 2-3 headlines with dates]


Anything you want me to focus on, skip, or add? For example: "dig deeper into the services segment" or "I think the AI capex angle is the real story" or "looks good, go ahead"

  1. Wait for user input. Incorporate their direction into Step 4.

Step 4: Output Generation

Read all data files from data/ subfolder. Incorporate any user direction from the checkpoint. Write the output file.

Brief Mode

Write to /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/brief.md:

---
ticker: {TICKER}
date: {TODAY}
price: ${PRICE}
mode: brief
---

# {TICKER} — Research Brief

## Company Snapshot
{What the company does, market cap, sector, industry. 2-3 sentences.}

## Key Metrics

| Metric | Value |
|--------|-------|
| Market Cap | |
| Price | |
| P/E (Trailing / Forward) | |
| EV/EBITDA | |
| Revenue | |
| Revenue Growth | |
| Gross Margin | |
| Operating Margin | |
| Net Margin | |
| FCF | |

## Price Performance

| Period | Return |
|--------|--------|
| 1M | |
| 3M | |
| 6M | |
| 1Y | |

## Recent Developments
{Synthesize from earnings, news, and SEC filings. 3-5 bullet points covering the most material developments from the last quarter. Each bullet: date + what happened + why it matters.}

## What to Watch
{3-4 bullets: upcoming earnings date, pending catalysts, key risks, sector events to monitor.}

If prior research exists (previous brief.md with metadata header), prepend a "What's Changed" section noting material differences since the prior research date.

Full Pitch Mode

Write to /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/pitch.md:

---
ticker: {TICKER}
date: {TODAY}
price: ${PRICE}
mode: full-pitch
---

# {TICKER} — Stock Pitch

## Executive Summary
{One paragraph: what the company does, your investment thesis in 1-2 sentences, and a directional recommendation (bullish/bearish/neutral with conviction level). This should be compelling enough to open an interview pitch.}

## Company Overview
{Business model, revenue segments, key products/services, competitive positioning (moat), management quality. 2-3 paragraphs.}

## Industry Context
{Market size, growth dynamics, secular trends, competitive landscape, regulatory environment. How does {TICKER} fit within the industry? 1-2 paragraphs.}

## Investment Thesis
{3-4 numbered thesis points. Each point: bold headline + 2-3 sentences of supporting evidence drawn from the data. This is the core of the pitch.}

### 1. {Thesis Point 1}
{Evidence and reasoning}

### 2. {Thesis Point 2}
{Evidence and reasoning}

### 3. {Thesis Point 3}
{Evidence and reasoning}

## Catalysts
**Near-term (0-6 months):**
- {Catalyst with expected timing}

**Long-term (6-24 months):**
- {Catalyst with expected timing}

## Key Risks & Mitigants

| Risk | Severity | Mitigant |
|------|----------|----------|
| {Risk 1} | High/Med/Low | {Why it's manageable} |
| {Risk 2} | | |
| {Risk 3} | | |

## Valuation

### Comparable Companies

| Company | Ticker | P/E | EV/EBITDA | Rev Growth | Margin |
|---------|--------|-----|-----------|------------|--------|
| {Comp 1} | | | | | |
| {Comp 2} | | | | | |
| {Comp 3} | | | | | |
| **{TICKER}** | | | | | |

### Historical Multiples
{Where the stock has traded historically on P/E and EV/EBITDA — current vs. 3-year average. Is it cheap or expensive relative to its own history?}

### Fair Value Range
{Based on comps and historical multiples, provide a rough fair value range. State assumptions clearly. This is a directional estimate, not a DCF.}

## Conclusion
{2-3 sentences wrapping up the thesis. Restate the recommendation and key points. End with what would change your mind (bull case breaker / bear case breaker).}

If prior research exists (previous pitch.md with metadata header), prepend a "What's Changed" section noting material differences since the prior research date.

Step 5: Financial Statements Excel

After writing the brief or pitch, generate a formatted Excel workbook with 3 tabs containing the company's financial statements: 3 years annual + 4 trailing quarters.

Data Collection

Run the following Python script via Bash to pull financial data from yfinance:

import yfinance as yf
import json

t = yf.Ticker("{TICKER}")

# Annual financials (3 years)
annual_income = t.financials  # income statement
annual_balance = t.balance_sheet
annual_cashflow = t.cashflow

# Quarterly financials (4 quarters)
quarterly_income = t.quarterly_financials
quarterly_balance = t.quarterly_balance_sheet
quarterly_cashflow = t.quarterly_cashflow

# Print as JSON for parsing
for name, df in [
    ("annual_income", annual_income),
    ("annual_balance", annual_balance),
    ("annual_cashflow", annual_cashflow),
    ("quarterly_income", quarterly_income),
    ("quarterly_balance", quarterly_balance),
    ("quarterly_cashflow", quarterly_cashflow),
]:
    if df is not None and not df.empty:
        print(f"=== {name} ===")
        print(df.to_json(date_format='iso'))

If yfinance is rate-limited, retry with exponential backoff (3s base, 3 attempts). If still unavailable, fall back to extracting financial figures from the SEC filing data already gathered in data/sec.md.

Cross-Reference with SEC Data

After pulling yfinance data, compare key figures (revenue, net income, total assets, operating cash flow) against the SEC filing data in data/sec.md. If discrepancies exist (>5% difference), note them in a "Data Notes" comment in the Excel file and prefer the SEC-sourced figure.

Excel Generation

Run the following Python script via Bash to generate the Excel file using openpyxl:

import openpyxl
from openpyxl.styles import Font, Alignment, Border, Side, PatternFill, numbers
from openpyxl.utils import get_column_letter

wb = openpyxl.Workbook()

# --- Styling ---
header_font = Font(bold=True, size=12)
subheader_font = Font(bold=True, size=10)
currency_format = '#,##0'
pct_format = '0.0%'
thin_border = Border(
    bottom=Side(style='thin')
)
header_fill = PatternFill(start_color='4472C4', end_color='4472C4', fill_type='solid')
header_font_white = Font(bold=True, size=10, color='FFFFFF')

def format_sheet(ws, title, headers, rows):
    """Format a financial statement tab."""
    # Title row
    ws.append([title])
    ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(headers))
    ws['A1'].font = Font(bold=True, size=14)
    ws.append([])  # blank row

    # Column headers (Line Item | Annual columns | Quarterly columns)
    ws.append(headers)
    for col_idx, _ in enumerate(headers, 1):
        cell = ws.cell(row=3, column=col_idx)
        cell.font = header_font_white
        cell.fill = header_fill
        cell.alignment = Alignment(horizontal='center')

    # Data rows
    for row in rows:
        ws.append(row)

    # Auto-width columns
    for col_idx in range(1, len(headers) + 1):
        max_len = max(
            len(str(ws.cell(row=r, column=col_idx).value or ''))
            for r in range(1, ws.max_row + 1)
        )
        ws.column_dimensions[get_column_letter(col_idx)].width = max(max_len + 4, 15)

    # Format numbers
    for row in ws.iter_rows(min_row=4, min_col=2, max_col=len(headers)):
        for cell in row:
            if isinstance(cell.value, (int, float)):
                cell.number_format = currency_format
                cell.alignment = Alignment(horizontal='right')

# Create three tabs with the pulled data
# Tab 1: Income Statement
# Tab 2: Balance Sheet
# Tab 3: Cash Flow

# Headers: Line Item | FY(year-3) | FY(year-2) | FY(year-1) | Q1 | Q2 | Q3 | Q4

# ... populate with actual data from yfinance/SEC ...

wb.save("/Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/financials.xlsx")

Important implementation notes:

  • The script above is a template. When executing, populate headers and rows with actual data from the yfinance output and SEC cross-reference.
  • Annual columns should be labeled by fiscal year (e.g., "FY2023", "FY2024", "FY2025")
  • Quarterly columns should be labeled by quarter (e.g., "Q1 2025", "Q2 2025", "Q3 2025", "Q4 2025")
  • All dollar values in thousands ($000s) — note this in the title row
  • Key line items for each statement:

Income Statement: Total Revenue, Cost of Revenue, Gross Profit, R&D Expenses, SG&A Expenses, Total Operating Expenses, Operating Income, Interest Expense, Other Income/Expense, Pretax Income, Income Tax, Net Income, EPS (Basic), EPS (Diluted), Shares Outstanding

Balance Sheet: Cash & Equivalents, Short-term Investments, Accounts Receivable, Inventory, Other Current Assets, Total Current Assets, PP&E (Net), Goodwill, Intangible Assets, Other Non-Current Assets, Total Assets, Accounts Payable, Short-term Debt, Other Current Liabilities, Total Current Liabilities, Long-term Debt, Other Non-Current Liabilities, Total Liabilities, Common Stock, Retained Earnings, Total Stockholders' Equity, Total Liabilities & Equity

Cash Flow: Net Income, Depreciation & Amortization, Stock-Based Compensation, Changes in Working Capital, Other Operating Activities, Cash from Operations, Capital Expenditures, Acquisitions, Other Investing Activities, Cash from Investing, Debt Issued/Repaid, Equity Issued/Repurchased, Dividends Paid, Other Financing Activities, Cash from Financing, Net Change in Cash, Free Cash Flow (CFO - CapEx)

Output

Save to: /Users/yanhaolin/Desktop/Yale/claude code/{TICKER}/financials.xlsx

After saving, inform the user:

"Financial statements Excel saved to {TICKER}/financials.xlsx with 3 tabs (Income Statement, Balance Sheet, Cash Flow) — 3 years annual + 4 trailing quarters. Key figures cross-referenced with SEC filings."

Related skills