How to Build an Agentic Stock Analyst with LangChain and YFinance
Create an intelligent AI agent that performs stock analysis using real tools, technical indicators, economic data, and even triggers mock trades.
· SuperML.dev · agenticAI ·

Imagine a world where your personal stock analyst is always on call — scanning prices, checking news, running technical indicators, and even making trade decisions on your behalf.
In this story, we’ll build that world.
We’ll walk you through how to create a LangChain Agent that:
- Pulls live stock data from Yahoo Finance
- Analyzes dividends, news, and key fundamentals
- Considers macroeconomic conditions
- Computes technical signals like RSI, MACD, and Moving Averages
- And can simulate buy/sell orders through a dummy API
All with the reasoning power of a modern LLM like Claude 3.
🛠️ Meet the Toolkit: What Powers the Agent
To give our Agent its superpowers, we equip it with these tools:
- YFinanceTool – Queries stock prices, dividends, and news
- TechnicalAnalysisTool – Computes indicators like RSI, SMA, MACD
- FundamentalAnalysisTool – Interprets PE ratio, earnings, etc.
- EconomicContextTool – Returns hardcoded economic signals like inflation or rate hikes
- TradeExecutionTool – A mock API call that logs trade decisions
These are all simple Python functions, wrapped as LangChain-compatible tools.
🧰 Assembling the Toolkit — Teaching the Agent What It Can Do
Before our AI can act like a stock analyst, we must show it what actions are available. In LangChain, every tool is like a “function” the agent can optionally call.
We register the following:
tools = [
YFinanceTool(), # Pulls stock price, dividend, and news data
TechnicalAnalysisTool(), # Computes indicators like RSI, MACD
FundamentalAnalysisTool(), # Evaluates P/E, EPS, etc.
EconomicContextTool(), # Returns current macroeconomic context
TradeExecutionTool(), # Simulates buy/sell transactions
WeatherTool(), # Totally irrelevant for stock analysis
]
🧠 Now the agent knows about all these tools — including some it should never use unless absolutely needed.
🧠 Give the Agent Reasoning Power
We’ll use Anthropic’s Claude 3 Sonnet to interpret the investor’s request and decide what tools to call. Here’s the agent’s mental model:
“If the user asks: ‘Is AAPL a good buy?’ → check stock data → apply technical and fundamental reasoning → consider macro signals → give recommendation → simulate a buy if favorable.”
🕹️ Assembling the Agent
Using LangGraph and create_react_agent
, we wire it all up:
from langgraph.prebuilt import create_react_agent
agent_executor = create_react_agent(
model=ChatAnthropic(model="claude-3-sonnet-20240229"),
tools=[YFinanceTool(), TechnicalAnalysisTool(), FundamentalAnalysisTool(), EconomicContextTool(), TradeExecutionTool()]
)
🧪 Try It Out: Ask About a Stock
The conversation begins:
agent_executor.stream({
"messages": [HumanMessage(content="Hey, is TSLA a good buy right now?")]
})
The agent thinks:
- TSLA? Let me get price, RSI, news…
- RSI is below 30 → oversold
- MACD just crossed → bullish signal
- PE ratio is high → overvalued, but growth is strong
- Inflation is falling → favorable macro
Then it replies:
“Based on current RSI (28), MACD crossover, and recent earnings strength, TSLA appears oversold and poised for a rebound. Executing a buy order now.”
Finally, it calls the TradeExecutionTool
:
{
"action": "BUY",
"ticker": "TSLA",
"quantity": 10
}
All fully automatic.
🧵 Add Memory: Stay in Context
You can now follow up with:
“What did I buy last?”
The agent will remember your past mock transaction using memory via MemorySaver
.
agent_executor.stream({
"messages": [HumanMessage(content="What was my last transaction?")],
"configurable": {"thread_id": "session_001"}
})
It responds:
“You bought 10 shares of TSLA in your last interaction.”
🔍 Watch It Think: LangSmith Traces
Every decision the agent makes — which tool it used, what it saw in the news, why it chose to buy — is logged in LangSmith.
You get full transparency into:
- 🧠 Thought process
- 🔧 Tool usage
- 📊 Reasoning chain
Perfect for debugging or compliance auditing.
🔄 Advanced Streaming
Want a real-time experience like Bloomberg Terminal? Stream responses step-by-step or even token-by-token.
for step in agent_executor.stream(..., stream_mode="messages"):
print(step.text(), end="|")
Now you see the agent’s reasoning unfold as it types.
🔐 Security Note
Even though we use a mock TradeExecutionTool
here, in a real-world setup, you’d integrate with:
- Robinhood API
- Alpaca API
- Or a secure broker interface
Add permission checks, logging, and manual approvals as needed.
✅ Recap: What We Built
You now have an Agentic Stock Analyst that can:
- 📈 Analyze stocks using real data
- 🧠 Make buy/sell decisions with LLM reasoning
- 🛠️ Use tools like YFinance, TA, economic signals
- 💬 Talk like a chatbot but think like an analyst
- 🤖 Simulate trade execution
All in under a few hundred lines of Python.
🚀 What’s Next?
Here are some extensions to try:
- 🔔 Add alert triggers for when RSI < 30 or MACD crosses
- 📊 Export analysis to a PDF or dashboard
- 🧠 Integrate sentiment analysis from news
- 💼 Auto-build a portfolio from a basket of stocks
The future of investing isn’t just data-driven — it’s Agent-driven.
Are you ready to build your AI fund manager?
Stay tuned for the full source code and setup guide in the next post. Until then, follow SuperML.dev for more AI x Finance deep dives!
🧰 Sample Tool Definitions (Python Code)
Here’s how some of these tools are implemented:
from langchain.tools import BaseTool
class YFinanceTool(BaseTool):
name = "stock_data"
description = "Fetches stock price, dividend, and news data for a given ticker."
def _run(self, ticker: str):
import yfinance as yf
stock = yf.Ticker(ticker)
info = stock.info
return {
"price": info.get("currentPrice"),
"dividend": info.get("dividendRate"),
"news": stock.news[:3]
}
class TechnicalAnalysisTool(BaseTool):
name = "technical_analysis"
description = "Returns RSI, MACD, and SMA indicators for a given stock ticker."
def _run(self, ticker: str):
import yfinance as yf
import pandas as pd
data = yf.download(ticker, period="3mo", interval="1d")
data["SMA_20"] = data["Close"].rolling(window=20).mean()
delta = data["Close"].diff()
gain = delta.where(delta > 0, 0)
loss = -delta.where(delta < 0, 0)
avg_gain = gain.rolling(window=14).mean()
avg_loss = loss.rolling(window=14).mean()
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
return {
"SMA_20": data["SMA_20"].iloc[-1],
"RSI": rsi.iloc[-1],
}
class EconomicContextTool(BaseTool):
name = "economic_context"
description = "Returns current macroeconomic indicators (hardcoded)."
def _run(self, query: str):
return {
"inflation_rate": 3.2,
"fed_rate": 4.75,
"gdp_growth": 2.1,
}
class TradeExecutionTool(BaseTool):
name = "trade_executor"
description = "Simulates a trade action with ticker, action (BUY/SELL), and quantity."
def _run(self, params: dict):
return f"Simulated {params['action']} of {params['quantity']} shares of {params['ticker']}."
class WeatherTool(BaseTool):
name = "weather"
description = "Gets weather conditions for a given city (not related to stock analysis)."
def _run(self, city: str):
return f"Sunny in {city}, 75°F."