opncrafter

Tutorial: Stock Analysis Agents

Dec 30, 2025 • 22 min read

In this tutorial, we build a "hedge fund in a box" using CrewAI. Two autonomous agents collaborate: a Senior Research Analyst gathers breaking news and recent financial data, and a Financial Strategist synthesizes that research into a concrete Buy/Hold/Sell recommendation with supporting rationale. This Research → Analyze pipeline is the foundational pattern behind most real-world agentic AI systems.

1. The Agent Team Design

Before writing code, design your agent team by thinking about roles a human team would fill:

Research Analyst

Goal: Find all relevant recent information

Tools: Tavily search, news APIs, yfinance

Output: Comprehensive notes with sources

Financial Strategist

Goal: Synthesize research into recommendation

Tools: No external tools — reasoning only

Output: Structured report: Buy/Hold/Sell with thesis

2. Setup

pip install crewai crewai-tools langchain-community yfinance

# .env
OPENAI_API_KEY=sk-...
TAVILY_API_KEY=tvly-...  # Get free key at app.tavily.com

3. Define Custom Tools

In addition to Tavily web search, we'll build a custom yfinance tool for pulling live stock data:

from crewai.tools import tool
from langchain_community.tools.tavily_search import TavilySearchResults
import yfinance as yf
import json

# Built-in Tavily search tool
search_tool = TavilySearchResults(max_results=5, search_depth="advanced")

@tool("Stock Data Fetcher")
def get_stock_data(ticker: str) -> str:
    """
    Fetches current stock price, P/E ratio, market cap, 52-week range,
    and recent earnings data for a given stock ticker symbol.
    Use when you need factual financial metrics about a company.
    """
    try:
        stock = yf.Ticker(ticker.upper())
        info = stock.info
        hist = stock.history(period="3mo")
        
        return json.dumps({
            "ticker": ticker.upper(),
            "current_price": info.get("currentPrice", "N/A"),
            "market_cap_bn": round(info.get("marketCap", 0) / 1e9, 2),
            "pe_ratio": info.get("trailingPE", "N/A"),
            "52w_high": info.get("fiftyTwoWeekHigh", "N/A"),
            "52w_low": info.get("fiftyTwoWeekLow", "N/A"),
            "revenue_growth": info.get("revenueGrowth", "N/A"),
            "profit_margins": info.get("profitMargins", "N/A"),
            "3mo_price_change_pct": ((hist['Close'].iloc[-1] - hist['Close'].iloc[0]) / hist['Close'].iloc[0] * 100).round(2),
            "analyst_recommendation": info.get("recommendationKey", "N/A"),
        }, indent=2)
    except Exception as e:
        return f"Error fetching data for {ticker}: {str(e)}"

@tool("SEC Filings Search")
def search_sec_filings(ticker: str) -> str:
    """Searches recent SEC filings (10-K, 10-Q, 8-K) for the given ticker."""
    results = search_tool.invoke(f"{ticker} SEC filing 10-K 10-Q site:sec.gov OR site:edgar.sec.gov")
    return str(results)

4. Define the Agents

from crewai import Agent
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o", temperature=0.3)

researcher = Agent(
    role="Senior Research Analyst",
    goal="Conduct comprehensive research on {ticker} stock, finding recent news, earnings, competitive dynamics, and analyst opinions.",
    backstory="""You are a veteran Wall Street analyst with 15 years at Goldman Sachs.
    You are known for your thorough due diligence and ability to synthesize complex information.
    You always cite your sources and indicate information recency.""",
    tools=[search_tool, get_stock_data, search_sec_filings],
    llm=llm,
    verbose=True,
    max_iter=5,          # Max tool call loops before giving up
    memory=True,         # Remember context within the task
)

financial_analyst = Agent(
    role="Chief Investment Officer",
    goal="Write a clear, decisive investment recommendation on {ticker} based on the research provided.",
    backstory="""You are a CIO with a proven track record of outperforming the S&P 500.
    You are known for your direct, no-nonsense investment theses.
    You always provide a concrete recommendation: BUY, HOLD, or SELL with a 12-month price target.""",
    tools=[],           # This agent reasons only — no external tool access
    llm=llm,
    verbose=True,
)

5. Define the Tasks

from crewai import Task

research_task = Task(
    description="""Conduct thorough research on {ticker} stock. Your research must cover:
    
    1. Latest financial metrics: P/E, revenue growth, profit margins, market cap
    2. Recent news (last 2 weeks): earnings, product launches, executive changes, regulatory news
    3. Competitive landscape: how is {ticker} positioned vs. key competitors?
    4. Analyst sentiment: what are major banks saying? Any recent upgrades/downgrades?
    5. Technical picture: 52-week range, recent price trend, volume patterns
    
    Use the Stock Data Fetcher for metrics and Tavily search for news and analyst reports.
    Present findings in a structured research brief, citing all sources with dates.""",
    
    expected_output="A structured 500-750 word research brief with data, sources, and dates",
    agent=researcher,
)

analysis_task = Task(
    description="""Based on the research brief provided, write a professional investment recommendation for {ticker}.
    
    Your recommendation must include:
    1. Executive summary: BUY / HOLD / SELL in the first sentence
    2. 12-month price target with bull/base/bear case scenarios
    3. Top 3 reasons for your recommendation (the investment thesis)
    4. Risk factors: what could make you wrong?
    5. Suggested position sizing for a diversified portfolio
    
    Write in a style suitable for a hedge fund investor letter — clear, direct, data-driven.""",
    
    expected_output="A professional 400-600 word investment recommendation with a clear BUY/HOLD/SELL verdict",
    agent=financial_analyst,
    context=[research_task],  # Receives output from research_task
)

6. Assemble and Run the Crew

from crewai import Crew, Process

stock_crew = Crew(
    agents=[researcher, financial_analyst],
    tasks=[research_task, analysis_task],
    process=Process.sequential,  # Research THEN analyze (not parallel)
    verbose=2,                   # Full agent thinking logs
    memory=True,                 # Shared memory between agents
)

# Run analysis — can take 2-5 minutes as agents search and reason
result = stock_crew.kickoff(inputs={"ticker": "NVDA"})

print("=" * 60)
print("INVESTMENT RECOMMENDATION")
print("=" * 60)
print(result.raw)

# Save as a report
with open("NVDA_analysis.txt", "w") as f:
    f.write(result.raw)

7. Extending the System

This two-agent pattern can be extended significantly:

  • Add a Risk Manager agent that reviews the recommendation and flags regulatory or ESG risks
  • Add a Sector Analyst agent that benchmarks the company against all competitors simultaneously using Parallel CrewAI process
  • Add a Portfolio Optimizer agent that considers how the new position affects overall portfolio correlation
  • Schedule it with cron to run weekly on your top 20 holdings and email you the summaries

Frequently Asked Questions

Can I trust these AI recommendations for real investment decisions?

No — this system is for research assistance and learning, not financial advice. LLMs can hallucinate financial metrics, misinterpret news significance, and lack access to proprietary data that professional analysts use. Always verify all data points and consult a licensed financial advisor before making investment decisions.

How do I control costs?

The main cost driver is the number of tool calls (each search result consumes tokens). Set max_iter=5 on agents to cap their loop count. Use gpt-4o-mini for the researcher and reserve gpt-4o for the analyst. A typical analysis run costs $0.05-0.20.

Conclusion

The Research → Analyze agent pipeline is the "Hello World" of multi-agent systems, and stock analysis is a perfect domain to learn it — the output is concrete, verifiable, and immediately interesting. Once you understand how to design agent roles, craft effective backstories, and use context passing between tasks, you can apply the same pattern to content creation, technical due diligence, or literature review in any domain.

Continue Reading

👨‍💻
Written by

Vivek

AI Engineer

Full-stack AI engineer with 4+ years building LLM-powered products, autonomous agents, and RAG pipelines. I've shipped AI features to production for startups and worked hands-on with GPT-4o, LangChain, LlamaIndex, and the Vercel AI SDK. I started OpnCrafter to share everything I wish I had when learning — no fluff, just working code and real-world context.

GPT-4oLangChainNext.jsVector DBsRAGVercel AI SDK