Strona główna / Artykuły

Agent handlowy LangChain wspierany przez aktualne dane rynkowe EODHD, krok po kroku

Dlaczego agenci handlowe oparte na LLM zawodzą bez rzeczywistych danych, jak działa pętla ReAct oraz jak stworzyć agenta LangChain z trzema narzędziami wykorzystującym ceny EODHD, dane fundamentalne i RSI.

Wydawca: REACTAPP.TOP8 min czytania1769 słów

Źródła: Building a Trading Agent with LangChain and the EODHD API

Bardzo wiele tak zwanych agentów handlowych opartych na sztucznej inteligencji pokazywanych w filmikach w rzeczywistości nie są agentami. Są to modele językowe z dopracowanymi instrukcjami oraz sfabrykowanymi danymi. Prawdziwy agent wymaga trzech rzeczy: zdolności rozumowania, narzędzi do działania oraz aktualnych danych, aby nie tworzył iluzji. Jeśli pominąć trzecią z tych rzeczy, pierwsze dwie prawie nie mają znaczenia. To rozwiązanie jest przeznaczone dla wszystkich, którzy tworzą agenty do analizy finansowej, łączą LangChain z rzeczywistymi danymi rynkowymi, lub dla tych, którzy próbowali „botów handlowych” opartych na LLM i zauważyli, że bez wiarygodnych danych są to jedynie pozory.

Krótko mówiąc, agent to model LLM wyposażony w narzędzia (funkcje) oraz swobodę decydowania, kiedy i w jaki sposób je używać, zamiast odpowiadać na podstawie wiedzy pochodzącej z treningu. LangChain to framework w Pythonie, który łączy model, narzędzia, pamięć oraz mechanizm podejmowania decyzji w jedną działającą całość. EODHD dostarcza to, czego model nie ma domyślnie: ceny w czasie rzeczywistym, dane fundamentalne, wskaźniki techniczne oraz najnowsze wiadomości finansowe, dostępne przez REST API. W połączeniu dają one agenta, który potrafi odpowiedzieć na pytanie „Czy ten akcja powinien być obecnie na moim radarze?”, opierając się na aktualnych danych, a nie na przestarzałej pamięci.

Model nie jest słabym punktem

Zapytaj dowolny model językowy o aktualną cenę akcji, a on poda ci liczbę. Ta liczba może być już kilka miesięcy przestarzała lub po prostu sfabrykowana. Modele nie mają dostępu do żywego rynku, nie wiedzą, co wydarzyło się wczoraj, ani nie widziały najnowszego raportu finansowego, a mimo to wiele projektów używa ich tak, jakby miały takie możliwości. Skutki są przewidywalne: rekomendacje oparte na danych sprzed roku, sfabrykowane dane fundamentalne przedstawiane z pełnym przekonaniem oraz analiza techniczna obliczana na podstawie cen, których nigdy nie istniało.

Żadne z tego nie oznacza, że model słabo radzi sobie w finansach. Problem polega na tym, że nikt nie dostarcza mu odpowiednich danych wejściowych. Model bez narzędzi to biblioteka bez okien: mnóstwo wiedzy, ale brak możliwości spojrzenia na dzisiejszą rzeczywistość. Większy model tego nie naprawia. Rozwiązaniem jest dostęp do weryfikowalnych danych z zewnątrz oraz możliwość decydowania przez model, kiedy szukać informacji. Właśnie do tego służy agent.

Stack

LangChain zajmuje się logiką agenta. Bierze pytanie użytkownika, wybiera narzędzie, wykonuje żądanie, interpretuje wynik i pisze odpowiedź. Nie ma w tym nic tajemniczego – to po prostu pętla rozumowania oparta na regułach.

EODHD wypełnia lukę w danych. Dzięki swojemu API agent może pobierać ceny OHLCV w czasie rzeczywistym oraz z historii, podstawowe dane firmy takie jak wskaźniki, bilans i przychody, wskaźniki techniczne jak RSI, średnie kroczące i MACD, a także wiadomości odzwierciedlające nastroje rynkowe. Powody wyboru tego rozwiązania do tego typu automatyzacji są praktyczne – obejmuje ono giełdy z całego świata, a nie tylko NYSE i NASDAQ. Dane fundamentalne, techniczne i wiadomości znajdują się w oddzielnych punktach dostępu, dzięki czemu każdy z nich może stanowić odrębne narzędzie. Ponadto wersja darmowa jest na tyle hojna, że pozwala na tworzenie prototypów przed rozszerzaniem skali działania.

Względy dotyczące wykorzystania EODHD jako warstwy danych

Każdy dostawca danych zasługuje na dokładną ocenę przed tym, jak zostanie włączony do agenta. Z pozytywnej strony ceny, dane fundamentalne, wskaźniki techniczne oraz wiadomości są objęte jednym kluczem i jednym planem opłat, więc nie trzeba łączyć trzech różnych dostawców. Wiele darmowych alternatyw, takich jak narzędzia scrapujące oparte na Yahoo oraz ograniczone plany Alpha Vantage, obejmują tylko giełdy amerykańskie, podczas gdy EODHD dostępna jest na dziesiątkach giełd, co ma znaczenie dla akcji spoza USA. Odpowiedzi są w formacie JSON z przewidywalnymi polami (close, change_p, PERatio itp.), dzięki czemu tworzenie narzędzi pomocniczych jest proste, a nic nie zależy od niestabilnego parsowania HTML. Można stworzyć i przetestować cały agent, obejmujący ceny, dane fundamentalne oraz wskaźnik RSI, zanim dokona się płatności. Limity szybkości są udokumentowane i przewidywalne, co jest ważne, gdy agent może kilka razy korzystać z narzędzia w celu odpowiedzi na jedno pytanie.

Istnieją też wady. Wersja darmowa ma dziienne limity liczby zapytań, co jest wystarczające dla osobistej listy obserwacji, ale niewystarczające dla usługi produkcyjnej używanej przez wielu użytkowników. Dane fundamentalne są aktualizowane według harmonogramu dostawcy, a nie natychmiast po publikacji wyników, co jest cechą wspólną wszystkich interfejsów API do danych fundamentalnych, ale ma znaczenie, jeśli twój agent polega na analizie dokonywanej w tym samym dniu. Opisy narzędzi pozostają twoją odpowiedzialnością: źle napisane narzędzie LangChain nadal może być wywoływane we złym momencie lub błędnie zinterpretowane przez model, niezależnie od jakości API. Dla agenta potrzebującego rzeczywistych, ustrukturyzowanych danych finansowych bez konieczności tworzenia własnego pipeline do pobierania danych, korzyści przemawiają za użyciem API hostowanego zamiast samodzielnie stworzonej warstwy danych.

Jak działa pętla rozumowania

Większość tutoriali pomija to, co dokładnie oznacza „agent” z punktu widzenia mechaniki jego działania. Agent LangChain wykorzystujący wzorzec ReAct (Rozumowanie plus Działanie) uruchamia pętlę składającą się z czterech części.

  1. LLM, które czyta pytanie oraz opisy narzędzi i wybiera następny krok.
  2. Narzędzia, czyli funkcje możliwe do wywołania, z których każda ma nazwę, opis oraz oczekiwane dane wejściowe i wyjściowe, takie jak get_live_price, get_fundamentals i get_rsi.
  3. Egzekutor, który faktycznie uruchamia wybrane narzędzie, przekazuje wynik z powrotem do modelu i pozwala mu wybrać dalsze działanie.
  4. Zapis interakcji, czyli ciągły zapis kroków myślenia, działań i obserwacji w ramach jednego zapytania, dzięki czemu model pamięta to, co już sprawdził.

Pytanie takie jak „Czy powinniśmy teraz obserwować AAPL.US?” generuje taki łańcuch działań. Najpierw model żąda ceny:

Thought: I need the current price first.
Action: get_live_price("AAPL.US")
Observation: AAPL.US: current price 227.50, change +0.8%

Następnie stwierdza, że sama cena mówi niewiele, i przechodzi do dynamiki rynku oraz wyceny:

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]

To jest różnica architektoniczna pomiędzy agentem a chatbotem z promptem systemowym. Model wybiera kolejność wywołań narzędzi w trakcie działania na podstawie informacji uzyskanych z każdej obserwacji, bez użycia żadnego sztywnego skryptu. To również powód, dla którego jakość i struktura źródła danych mają tak wielkie znaczenie. Jeśli get_fundamentals zwraca nieprawidłowe lub przestarzałe dane, każda decyzja oparta na nich dziedziczy ten błąd bez żadnego widocznego ostrzeżenia. Każdy krok rozumowania zależy od niezawodności poprzedniego, co jest głównym powodem, dla którego agenci finansowi potrzebują prawdziwej, zstrukturyzowanej API zamiast danych zebranych ręcznie lub zapisanych w pamięci.

Budowanie go

Agent posiada trzy narzędzia powiązane z EODHD: aktualne ceny, dane fundamentalne oraz wskaźniki techniczne. Zacznij od zainstalowania odpowiednich pakietów:

pip install langchain langchain-openai requests

Samymi narzędziami są zwykłe funkcje. Każda z nich łączy się z jednym punktem końcowym EODHD i zwraca uporządkowany, czytelny wynik, który model może odczytać:

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']}"

Następnie zbuduj agenta na podstawie modelu do rozmów, narzędzi oraz promptu ReAct:

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)

To trzy narzędzia: jeden LLM oraz jeden pętla, która wybiera spośród nich w zależności od pytania. Wywołanie wygląda tak:

response = executor.invoke({
    "input": "Should we be looking at AAPL.US right now?"
})
print(response["output"])

Agent nie odpowiada na podstawie pamięci. Najpierw wywołuje funkcję get_live_price, potem get_rsi, a funkcję get_fundamentals wtedy, gdy ważna jest ocena wartości akcji; następnie łączy wszystkie trzy wyniki w odpowiedź opartą na rzeczywistych danych, a nie na fałszywych informacjach w przekonującym formacie. Naturalnymi rozwinięciami są agent obsługujący wiele instrumentów finansowych, który porównuje kilka akcji w jednej zapytaniu, system przetwarzania danych integrujący wiadomości za pośrednictwem interfejsu do analizy nastrojów rynkowych, oraz zadań alertowe uruchamiane co godzinę do sprawdzania listy akcji do obserwacji.

Co wynika z tego

Agent bez rzeczywistych danych to generator tekstów o dużej sile przekonywania, a nie narzędzie analityczne. LangChain zajmuje się orkiestracją, natomiast niezawodna API danych rozwiązuje podstawowy problem, jakim są aktualne i wiarygodne informacje finansowe. W agencie typu ReAct każdy krok odziedzicza wiarygodność danych z poprzedniego etapu, dlatego warstwa danych ma takie samo znaczenie jak sam prompt. Ponadto proste narzędzia pełniące po jednej responsywności radzą sobie lepiej niż sytuacja, gdy cała logika zostaje umieszczona w jednym, ogromnym promptzie.

Poniżej znajdują się kilka często zadawanych pytań. Czym jest agent w środowisku handlowym? To system, w którym LLM wybiera narzędzia do użycia – od cen, przez dane fundamentalne, aż po wiadomości – aby wykonać zadanie przy użyciu rzeczywistych danych, a nie tylko wiedzy nabytej podczas szkolenia. Dlaczego LangChain zamiast bezpośredniego wywoływania API? Zarządza pętlą decyzyjną, określając, jakie narzędzie użyć, kiedy i w jaki sposób połączyć kilka wyników – co inaczej trzebałoby ustalać ręcznie dla każdego przypadku. Czy potrzebne jest płatne konto EODHD, aby to wypróbować? Nie, darmowy plan wystarcza do tworzenia prototypów. Jaka jest główna cena, jaką trzeba zapłacić za rezygnację z budowy własnego procesu? Traci się pełną kontrolę nad źródłami danych w zamian za szybkość i niezawodność – jeden uporządkowany API zastępuje skrapery lub kilka integracji z dostawcami, a ograniczeniem do uwzględnienia jest dzienny limit darmowego planu po zakończeniu fazy prototypowania.

Literatura pokrewna

  • Szkolenie modelu dostosowanego w Azure ML i jego wykorzystanie przez agenta Foundry — Szkolenie, rejestracja i wdrożenie modelu do wykrywania odejść klientów na zarządzanym punkcie końcowym Azure ML, a następnie udostępnienie go agentowi Foundry jako FunctionTool wraz z informacjami dotyczącymi autoryzacji i warunków produkcji.
  • Notatki praktyczne: Budowa agenta do badań zaawansowanych przy użyciu LangChain Deep Agents — Szczegółowy przewodnik po notatkach praktycznych dotyczących budowy agenta do badań zaawansowanych z wykorzystaniem LangChain Deep Agents, w tym informacje o kontraktach, sprawdzaniach oraz elementach kodu gotowych do użycia przez zespoły wdrażające ten model.
  • Asystent do dokumentów w dwóch plikach Pythona: ChromaDB, LangChain i Claude — Przekształć 187-stronicowy PDF z standardami dbt w asystenta do wyszukiwania za pomocą skryptu do pobierania danych, lokalnych embeddingów Hugging Face, ChromaDB oraz odpowiedzi Claude opartych na dokumentacji.