A LangChain Trading Agent Backed by Live EODHD Market Data, Step by Step
Why LLM trading agents fail without real data, how the ReAct loop works, and how to build a three-tool LangChain agent on EODHD prices, fundamentals and RSI.
This article is published in English.
Sources: Building a Trading Agent with LangChain and the EODHD API
Plenty of so-called AI trading agents shown in videos aren't agents. They're a language model with a polished prompt and invented numbers. A real agent needs three things: reasoning, tools to act with and live data so it doesn't hallucinate. Skip the third and the first two hardly matter. It's aimed at anyone building agents for financial analysis, connecting LangChain to real market data, or who has tried an LLM "trading bot" and noticed that without trustworthy data it's theater.
In short, an agent is an LLM handed tools (functions) and the freedom to decide when and how to call them, rather than answering from training knowledge. LangChain is a Python framework that wires the model, tools, memory and decision loop into one runnable unit. EODHD supplies what no model has by default: real-time prices, fundamentals, technical indicators and recent financial news, over a REST API. Put together, you get an agent that can answer "should this stock be on my radar right now?" from current data and not from stale memory.
The model isn't the weak spot
Ask any LLM for a stock's current price and it will produce a number. That number might be months old, or simply made up. Models have no live market access, don't know what happened yesterday and haven't seen the latest earnings report, yet many projects use them as though they did. The outcomes are predictable: recommendations built on year-old data, fabricated fundamentals delivered with full confidence, and technical analysis computed on prices that never existed.
None of that shows the model is bad at finance. The trouble is that nobody feeds it the right inputs. A model without tools is a library with no windows: plenty of knowledge, no view of today. A bigger model doesn't fix that. Access to verifiable outside data does, along with letting the model decide when to look. That's what an agent is for.
The stack
LangChain handles the agent's logic. It takes the user's question, chooses a tool, runs the call, interprets the result and writes an answer. There's no magic in it, just a reasoning loop with rules.
EODHD fills the data gap. Through its API the agent can fetch real-time and historical OHLCV prices, company fundamentals such as ratios, balance sheet and revenue, technical indicators like RSI, moving averages and MACD, and news with market sentiment. Reasons to pick it for this kind of automation are practical. Coverage spans exchanges around the world and not only NYSE and NASDAQ. Fundamentals, technicals and news sit behind separate endpoints, so each can become its own independent tool. And the free tier is generous enough to prototype before scaling.
Weighing EODHD as a data layer
Any data provider deserves an honest look before it goes into an agent. On the plus side, prices, fundamentals, technicals and news come under one key and one billing plan, so you aren't stitching three vendors together. Many free alternatives, such as Yahoo-based scrapers and limited Alpha Vantage plans, stop at US tickers, while EODHD reaches dozens of exchanges, which matters for non-US equities. Responses are structured JSON with predictable fields (close, change_p, PERatio and so on), so tool wrappers are simple and nothing depends on fragile HTML parsing. You can build and test the whole agent, covering price, fundamentals and RSI, before paying. Rate limits are documented and predictable, which matters when an agent may call a tool several times for one question.
There are downsides. The free tier has daily request caps, fine for a personal watchlist but short of what a multi-user production service needs. Fundamentals update on the provider's schedule, not the second earnings land, a limit shared by every fundamentals API but relevant if your agent leans on same-day analysis. And tool descriptions remain your job: a poorly written LangChain tool still gets called at the wrong moment or misread by the model, whatever the API quality. For a reasoning agent that needs real structured financial data without a scraping pipeline, the tradeoffs favor a hosted API over a homemade data layer.
How the reasoning loop works
Most tutorials skip what "agent" means mechanically. A LangChain agent using the ReAct pattern (Reason plus Act) runs a loop with four parts.
- The LLM, which reads the question and the tool descriptions and picks the next move.
- The tools, callable functions each with a name, a description and expected inputs and outputs, such as
get_live_price,get_fundamentalsandget_rsi. - The executor, which actually runs the requested tool, hands the output back to the model and lets it choose what comes next.
- The scratchpad, a running record of thought, action and observation steps within one query, so the model remembers what it already checked.
A question like "Should we be looking at AAPL.US right now?" produces a chain like this. First the model wants a price:
Thought: I need the current price first.
Action: get_live_price("AAPL.US")
Observation: AAPL.US: current price 227.50, change +0.8%
Then it decides the price alone says little and moves on to momentum and valuation:
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]
That is the architectural gap between an agent and a chatbot with a system prompt. The model picks the order of tool calls at runtime from what each observation reveals, and no fixed script is involved. It's also why the quality and structure of the data source count so much. If get_fundamentals returns junk or stale numbers, every thought built on it inherits the error without any visible warning. Each reasoning step depends on the reliability of the one before it, which is the main reason financial agents need a real, structured API rather than scraped or cached data.
Building it
The agent has three tools tied to EODHD: live price, fundamentals and technical indicators. Start by installing the packages:
pip install langchain langchain-openai requests
The tools themselves are plain functions. Each one hits a single EODHD endpoint and hands back clean structured output for the model to read:
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']}"
Then assemble the agent from a chat model, the tools and a ReAct prompt:
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)
That's three tools, one LLM and one loop that picks among them based on the question. Calling it looks like this:
response = executor.invoke({
"input": "Should we be looking at AAPL.US right now?"
})
print(response["output"])
The agent doesn't reply from memory. It calls get_live_price first, then get_rsi, and get_fundamentals when valuation matters, then merges all three results into an answer grounded in real data and not a confidently formatted hallucination. Natural extensions include a multi-ticker agent that compares several stocks in one query, a pipeline that adds news through the sentiment endpoint, and an hourly alerting job that sweeps a watchlist.
What to take away
An agent without real data is a persuasive text generator, not an analysis tool. LangChain takes care of orchestration, and a dependable data API takes care of the underlying problem, which is current and reliable financial information. In a ReAct agent each step inherits the trustworthiness of the data behind the previous one, so the data layer matters as much as the prompt. And thin tools with a single responsibility each scale better than cramming all the logic into one huge prompt.
A few common questions follow. What is an agent in a trading setting? A system where the LLM chooses which tools to use, from prices to fundamentals to news, to finish a task with real data and not only trained knowledge. Why LangChain instead of calling the API directly? It manages the decision loop, meaning which tool, when, and how to combine several results, which you'd otherwise hardcode for every case. Is a paid EODHD account needed to try this? No, the free tier is enough to prototype. What's the main tradeoff against building your own pipeline? You give up full control over sourcing in return for speed and reliability, with one structured API replacing scrapers or several vendor integrations, and the limit to plan around is the free tier's daily cap once you leave prototyping behind.