
How to Build an Agentic Stock Analyst with LangChain and YFinance
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."
Enjoyed this post? Join our community for more insights and discussions!
👉 Share this article with your friends and colleagues 👉 Follow us on