Building a Trading Agent with LangChain and the EODHD API
Originally published on medium.com

Most “AI trading agents” you see on YouTube aren’t agents. They’re an LLM with a nice prompt and made-up data.
A real agent needs three things: the ability to reason, tools to act, and real data so it doesn’t hallucinate. If you’re missing the third one, the other two don’t matter.
This article is for you if:
- you’re building AI agents for financial analysis,
- you want to connect LangChain to real market data,
- or you already tried building a “trading bot” with an LLM and realized that without reliable data, it’s all theater.
Let’s get into it.
TL;DR
- An agent is an LLM given tools (functions) and the ability to decide when and how to use them to complete a task, instead of answering directly from its trained knowledge.
- LangChain is a Python framework that orchestrates that logic: it connects the model, the tools, memory, and the decision loop into one executable piece.
- EODHD provides what no LLM has by default: real-time prices, fundamentals, technical indicators, and up-to-date financial news, all through a REST API.
- The result: an agent that can answer “should I be looking at this stock right now?” with real data, not with its outdated training memory.
The problem isn’t the model’s intelligence
Ask any LLM for the current price of a stock.
It’ll give you a number. That number could be months old, or straight-up invented.
Language models don’t have access to live markets. They don’t know what happened yesterday. They don’t know the latest earnings report. And yet, plenty of “AI trading projects” use them as if they did.
The result is predictable:
- recommendations based on year-old data,
- fabricated fundamentals stated with total confidence,
- technical analysis run on prices that don’t exist.
This isn’t an intelligence problem. GPT-4 or Claude aren’t “bad at finance.”
The problem is that nobody is feeding them the right data.
The real problem: missing tools, not missing reasoning
An LLM without tools is a library with no windows. It knows a lot, but sees nothing of what’s happening today.
The fix isn’t “a bigger model.” It’s giving it access to verifiable external data, and letting it decide when to check it.
That’s exactly what an agent does.
LangChain + EODHD: the stack
LangChain orchestrates the agent’s logic: it takes the user’s question, decides which tool to call, executes the call, interprets the result, and generates a response. It’s not magic, it’s a reasoning loop with rules.
EODHD provides the missing piece: real financial data through a REST API. With it, the agent can query:
- real-time prices and historical OHLCV data,
- company fundamentals (ratios, balance sheet, revenue),
- technical indicators (RSI, moving averages, MACD),
- news and market sentiment.
After testing several data sources for this type of automation, I consistently use EODHD. The reasons are concrete:
- broad coverage across global exchanges, not just NYSE/NASDAQ,
- separate endpoints for fundamentals, technicals, and news, which makes it easy to build independent tools,
- a free tier generous enough to prototype an agent before scaling.
Want to build financial agents with real data?
EODHD gives you access to prices, fundamentals, and technicals via REST API — no scraping, no stale data.
→ Try EODHD for free
Pros and cons of using EODHD as your agent’s data layer
Before you wire any data provider into an agent, it’s worth being honest about tradeoffs. Here’s what stands out after building several agent tools on top of EODHD’s API.
Pros:
- One API, multiple data types. Real-time prices, fundamentals, technicals, and news all live under the same key and billing plan, so you’re not stitching together three different vendors for one agent.
- Global exchange coverage. Most free-tier alternatives (Yahoo-based scrapers, limited Alpha Vantage plans) cap out at US tickers. EODHD covers dozens of exchanges, which matters if your agent needs to reason about non-US equities.
- Structured JSON responses. Every endpoint returns predictable fields (
close,change_p,PERatio, etc.), which makes writing LangChain tool wrappers straightforward — no HTML parsing, no scraping fragility. - Free tier is enough to prototype. You can build and test the full agent — price, fundamentals, RSI — before paying for anything.
- Rate limits are documented and predictable, which matters for agents that might call a tool multiple times per query.
Cons:
- Free tier has daily request caps. Fine for prototyping or a personal watchlist agent; you’ll need a paid plan for production traffic with many users.
- Fundamentals data updates on the provider’s schedule, not instantly after earnings — same limitation any fundamentals API has, but worth knowing if your agent leans heavily on same-day fundamentals reasoning.
- You still need to design good tool descriptions. EODHD gives you the data, but a badly-described LangChain tool will still get called at the wrong time or misinterpreted by the LLM — that part is on you, not the API.
Net: for a project like this — a reasoning agent that needs real, structured financial data without building a scraping pipeline — the tradeoffs favor EODHD over rolling your own data layer.
LLM agent architecture: how the reasoning loop actually works
It helps to open up what “agent” means mechanically, because this is the part most tutorials skip.
A LangChain agent built on the ReAct pattern (Reason + Act) runs a loop with four components:
- The LLM — the reasoning engine. It reads the user’s question and the tool descriptions, and decides what to do next.
- The tools — functions the LLM can call, each with a name, a description, and an expected input/output. This is where
get_live_price,get_fundamentals, andget_rsilive. - The executor — the loop that actually runs the tool the LLM asked for, feeds the result back to the LLM, and lets it decide the next step.
- The scratchpad (memory) — a running log of “thought → action → observation” steps within a single query, so the LLM doesn’t lose track of what it already checked.
In practice, a single query like “Should we be looking at AAPL.US right now?” triggers a chain like this:
Thought: I need the current price first.
Action: get_live_price("AAPL.US")
Observation: AAPL.US: current price 227.50, change +0.8%
Thought: Price alone isn't enough — check momentum.
Action: get_rsi("AAPL.US")
Observation: AAPL.US — RSI(14): 58.3Thought: Not overbought. Check if valuation is reasonable.
Action: get_fundamentals("AAPL.US")
Observation: AAPL.US — PE: 31.2, Market Cap: 3.4T, Dividend Yield: 0.4%Thought: I now have enough data to answer.
Final Answer: [synthesized response]
This is the architectural difference between an agent and a chatbot with a system prompt: the LLM decides the sequence of tool calls at runtime, based on what it learns from each observation — it isn’t a fixed script. That’s also exactly why the quality and structure of your data source matters so much. If get_fundamentals returns garbage or stale numbers, the "Thought" steps built on top of it inherit that error silently, with no warning sign in the output.
This is the core reason financial agents need a real, structured API like EODHD instead of scraped or cached data: every reasoning step downstream depends on the reliability of the step before it.
See the data behind every reasoning step
EODHD’s structured endpoints are built for exactly this kind of tool-calling architecture.
→ Explore the EODHD API
Implementation: building the agent
Let’s build an agent with three tools connected to EODHD: live price, fundamentals, and technical indicators.
1. Installation
pip install langchain langchain-openai requests
2. Define the tools
Each tool is a function that calls an EODHD endpoint and returns a structured response the agent can interpret.
import requests
from langchain.tools import tool
EODHD_API_KEY = "YOUR_API_KEY"
BASE_URL = "https://eodhd.com/api"
@tool
def get_live_price(ticker: str) -> str:
"""Returns the current price of a stock. Example ticker: AAPL.US"""
url = f"{BASE_URL}/real-time/{ticker}"
params = {"api_token": EODHD_API_KEY, "fmt": "json"}
r = requests.get(url, params=params).json()
return f"{ticker}: current price {r['close']}, change {r['change_p']}%"
@tool
def get_fundamentals(ticker: str) -> str:
"""Returns key fundamental metrics: PE ratio, market cap, dividend yield."""
url = f"{BASE_URL}/fundamentals/{ticker}"
params = {"api_token": EODHD_API_KEY}
r = requests.get(url, params=params).json()
highlights = r.get("Highlights", {})
return (
f"{ticker} - PE: {highlights.get('PERatio')}, "
f"Market Cap: {highlights.get('MarketCapitalization')}, "
f"Dividend Yield: {highlights.get('DividendYield')}"
)
@tool
def get_rsi(ticker: str) -> str:
"""Returns the 14-day RSI to assess overbought or oversold conditions."""
url = f"{BASE_URL}/technical/{ticker}"
params = {"api_token": EODHD_API_KEY, "function": "rsi", "period": 14, "fmt": "json"}
r = requests.get(url, params=params).json()
latest = r[-1]
return f"{ticker} - RSI(14): {latest['rsi']} as of {latest['date']}"
3. Create the agent
from langchain_openai import ChatOpenAI
from langchain.agents import create_react_agent, AgentExecutor
from langchain import hub
llm = ChatOpenAI(model="gpt-4o", temperature=0)
tools = [get_live_price, get_fundamentals, get_rsi]
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
Three tools. One LLM. One reasoning loop that decides which one to use based on the question.
Example usage
response = executor.invoke({
"input": "Should we be looking at AAPL.US right now?"
})
print(response["output"])
The agent doesn’t answer directly from memory. It first calls get_live_price, then get_rsi, and if valuation matters, get_fundamentals. It combines all three results into a response grounded in real data, not a confidently-formatted hallucination.
From here you can build:
- a multi-ticker agent that compares several stocks in a single query,
- a pipeline that combines this with news through EODHD’s sentiment endpoint,
- an alerting system that runs the agent hourly over a watchlist.
Key takeaways
- An agent without real data is a convincing text generator, not an analysis tool.
- LangChain solves the orchestration; EODHD solves the underlying problem, which is having reliable, up-to-date financial data.
- In a ReAct-style agent, every reasoning step inherits the reliability (or unreliability) of the data behind the previous step — which is why the data layer matters as much as the prompt.
- This pattern — thin tools, each with a single responsibility — scales better than stuffing all the logic into one giant prompt.
If you’re a software or API company looking to explain your product through high-quality educational content (not marketing fluff), feel free to connect with me on LinkedIn: 👉 linkedin.com/in/kevin-meneses-gonzalez
Ready to build your own financial agent?
Get access to real-time prices, fundamentals, and technicals with the EODHD API.
→ Get started with EODHD
FAQs
❓ What is an AI agent in the context of trading?
✅ It’s a system where an LLM doesn’t just respond with text, but decides which tools to use — prices, fundamentals, news — to complete a task with real data, instead of relying only on its trained knowledge.
❓ Why use LangChain instead of calling the API directly?
✅ Because LangChain manages the decision loop: which tool to use, when, and how to combine multiple results into a coherent response. Without this, you’d have to hardcode that decision logic yourself for every case.
❓ Do I need a paid EODHD account to try this?
✅ No. EODHD’s free tier is enough to prototype the agent with real data before scaling to production.
❓ What’s the main tradeoff of using EODHD instead of building my own data pipeline?
✅ You trade full control over data sourcing for speed and reliability — one structured API instead of maintaining scrapers or multiple vendor integrations. The main limitation to plan around is the free tier’s daily request cap once you move past prototyping.
Looking for technical content for your company? I can help — LinkedIn · kevinmenesesgonzalez@gmail.com