Lernpfad
Große Sprachmodelle werden hilfreicher, wenn wir ihnen spezialisierte Rollen, Tools und Zugriff auf Live-Daten geben. Anstatt uns auf ein einzelnes Modell zu verlassen, können wir ein kleines Research-Team aufsetzen, in dem jeder Agent einen anderen Teil der Analyse übernimmt.
Genau das bauen wir in diesem Tutorial: einen Multi-Agenten-Aktienanalysten mit GLM-5.3-Flash und CrewAI. Drei Agenten analysieren Fundamentaldaten, technische Indikatoren und aktuelle Nachrichten, während ein Portfoliomanager ihre Ergebnisse zu einem finalen BUY-, HOLD- oder SELL-Signal zusammenführt.
Wir testen den Workflow zunächst in einem Jupyter-Notebook und verwandeln ihn dann in eine einfache Terminal-UI, die Aktien analysiert und Rückfragen beantwortet.
Das Projekt nutzt:
- GLM-5.3-Flash für Reasoning
- CrewAI für die Agentenkoordination
- Finnhub für Markt- und Fundamentaldaten
- Yahoo Finance für historische Preise
- Tavily für aktuelle News
- Pandas und NumPy für technische Indikatoren
Neu im Framework? Unser Kurs Building AI Agents with CrewAI führt dich von Grund auf in Agents, Crews und Flows ein.
Einführung in KI-Agenten
Warum GLM-5.3-Flash für Multi-Agenten-Anwendungen?
GLM-5.3-Flash bietet ein starkes Verhältnis aus Performance, Effizienz und Preis. Für den kompletten Überblick lies unseren GLM-5.3-Flash-Guide und den Vergleich mit Qwen3.8-Flash-Next.
Wettbewerbsfähige Performance und Effizienz
Im Artificial Analysis Intelligence Index erzielt es 57 Punkte, rangiert damit unter den führenden Modellen und konkurriert mit deutlich teureren Frontier-Modellen. Zum Beispiel:
-
GPT-5.6 Sol erzielt ebenfalls 57 (bei
highReasoning-Effort), kostet aber über 25-mal mehr für Input- und 40-mal mehr für Output-Tokens. -
Claude Sonnet 5 liegt sogar etwas darunter mit 55 bei
maxReasoning-Effort. Es ist 20x/30x teurer für Input/Output-Tokens als GLM-5.3-Flash.
Es hat 320B Gesamtparameter, aber nur etwa 18B Parameter sind pro Token aktiv. So liefert es starke Leistung bei gleichzeitig hoher Recheneffizienz.

Quelle: AI Model & API Providers Analysis | Artificial Analysis
Attraktive Preise
Wie erwähnt, kommt diese Performance zu einem vergleichsweise niedrigen API-Preis. Zum Zeitpunkt des Schreibens bietet OpenRouter GLM-5.3-Flash mit 50% Rabatt an: $0,075 pro Million Input-Tokens und $0,25 pro Million Output-Tokens.
Auch zum regulären Preis von $0,15/$0,50 bleibt es günstiger als Modelle wie OpenAI's GPT-5.6 Luna mit $0,20/$1,20 (52 im AA Intelligence Index bei max Reasoning). Damit eignet es sich nicht nur für Experimente, sondern auch für größere, produktionsreife Agentenanwendungen.

Quelle: GLM 5.3 Flash - API Pricing & Benchmarks | OpenRouter
Das zählt umso mehr bei Multi-Agenten-Systemen, weil eine Nutzeranfrage im Hintergrund viele LLM-Calls auslösen kann. Ein einzelner LLM-Agent ruft das Modell womöglich mehrfach auf: für Reasoning, Toolauswahl, Verarbeitung der Tool-Ausgaben und die finale Antwort. Wenn ein Agent etwa sieben LLM-Calls macht und dein Workflow fünf Agenten hat, kann eine einzige Anfrage leicht 35 oder mehr LLM-Calls erzeugen.
Die genaue Zahl hängt vom Systemdesign ab. Der Punkt ist: Agentische Workflows werden schnell teuer. Ein fähiges Modell mit niedrigen Tokenpreisen wie GLM-5.3-Flash macht beim Schritt vom kleinen Demo zur echten Produktionsanwendung einen großen Unterschied.
1. Umgebung für GLM-5.3-Flash einrichten
Bevor wir den Multi-Agenten-Workflow bauen, lege API-Schlüssel für Z.ai, Finnhub und Tavily an.
API-Schlüssel erstellen
Achte bei Z.ai darauf, die reguläre API zu verwenden, nicht den GLM Coding Plan. Der Coding Plan ist für unterstützte KI-Coding-Tools gedacht und nicht als generische API für eigene Multi-Agenten-Apps.
Erzeuge einen regulären Z.ai-API-Schlüssel und lade ein kleines Guthaben auf. Da GLM-5.3-Flash günstig ist, reicht ein kleiner Betrag für die ersten Tests.

Quelle: Z.ai API Platform — Start building with GLM-5.3
Du kannst auch kostenlose Accounts bei Finnhub und Tavily anlegen und API-Schlüssel generieren. Deren Free-Tiers reichen zum Testen dieses Projekts.
Projektdateien vorbereiten
Lege anschließend eine .env-Datei im Projektordner an und füge die API-Schlüssel hinzu:
ZAI_API_KEY="your_zai_api_key"
FINNHUB_API_KEY="your_finnhub_api_key"
TAVILY_API_KEY="your_tavily_api_key"
Erstelle jetzt ein neues Jupyter-Notebook. Wir bauen und testen hier zuerst den kompletten Multi-Agenten-Workflow, prüfen die Ausgaben der Agenten und beheben Probleme, bevor wir daraus eine Anwendung machen.
Benötigte Bibliotheken installieren
Wir verwenden CrewAI für Aufbau und Koordination der Agenten, Finnhub für Marktdaten und Tavily für Websuche in Echtzeit. Installiere die erforderlichen Python-Pakete:
!pip install -q crewai crewai-tools finnhub-python tavily-python pandas numpy requests python-dotenv openai
Bibliotheken und API-Schlüssel importieren
Importiere als Nächstes die benötigten Bibliotheken und lade die API-Schlüssel:
import os
import re
import time
import finnhub
import numpy as np
import pandas as pd
import requests
from dotenv import load_dotenv
from openai import OpenAI
from tavily import TavilyClient
from crewai import Agent, Crew, LLM, Process, Task
from crewai.tools import tool
from crewai_tools import TavilySearchTool
# Load environment variables
load_dotenv()
# Disable CrewAI tracing
os.environ.setdefault("CREWAI_TRACING_ENABLED", "false")
os.environ.setdefault("OTEL_SDK_DISABLED", "true")
Lege zuletzt fest, welche Aktie die Agenten analysieren sollen:
TICKER = "NVDA"
Ich verwende im Notebook NVIDIA (NVDA). Du kannst den Ticker aber jederzeit austauschen, z. B. gegen AAPL, MSFT oder TSLA.
2. GLM-5.3-Flash und Daten-APIs konfigurieren
Mit fertigen API-Schlüsseln verbinden wir nun die Services, die unsere Agenten im Projekt nutzen.
Starte mit Finnhub für Marktdaten und Tavily für die Websuche:
finnhub_client = finnhub.Client(
api_key=os.environ["FINNHUB_API_KEY"]
)
tavily_client = TavilyClient(
api_key=os.environ["TAVILY_API_KEY"]
)
Wenn du Finanzagenten bauen möchtest und unsicher bist, welche Datenquelle du nehmen solltest, lies unseren Guide zum Auswählen der passenden Stock-Market-Data-API.
Als Nächstes konfigurieren wir GLM-5.3-Flash als Haupt-LLM für unsere CrewAI-Agenten. Z.ai bietet eine OpenAI-kompatible API, daher können wir sie direkt über CrewAIs LLM-Klasse anbinden:
llm = LLM(
model="openai/glm-5.3-flash",
api_key=os.environ["ZAI_API_KEY"],
base_url="https://api.z.ai/api/paas/v4/",
temperature=0.1,
)
Wir halten die Temperatur niedrig, da es hier um Finanzresearch und Analyse geht. Wir wollen konsistente, fokussierte Antworten.
Mit Modell, Marktdaten und Websuche verbunden, können wir nun die Tools bauen, die unsere Agenten nutzen.
3. Historische Marktdaten sammeln
Wir benötigen historische Preisdaten, damit die Agenten die Kursentwicklung über die Zeit verstehen.
Dafür nutzen wir den öffentlichen Chart-Endpunkt von Yahoo Finance, um tägliche Open-, High-, Low-, Close- und Volumen-Daten zu laden.
Kursverlauf herunterladen
HTTP = requests.Session()
HTTP.headers.update({"User-Agent": "glm-stock-swarm/1.0"})
def _yahoo_history(ticker: str, days: int) -> pd.DataFrame:
end = int(time.time())
start = end - days * 24 * 60 * 60
response = HTTP.get(
f"https://query1.finance.yahoo.com/v8/finance/chart/{ticker}",
params={
"period1": start,
"period2": end,
"interval": "1d",
"events": "history",
},
timeout=30,
)
response.raise_for_status()
result = response.json()["chart"]["result"][0]
values = result["indicators"]["quote"][0]
frame = pd.DataFrame({
"date": pd.to_datetime(
result["timestamp"], unit="s", utc=True
).tz_localize(None),
"open": values["open"],
"high": values["high"],
"low": values["low"],
"close": values["close"],
"volume": values["volume"],
})
frame = (
frame.dropna(subset=["close"])
.sort_values("date")
.reset_index(drop=True)
)
frame.attrs["source"] = "Yahoo public chart"
return frame
def get_price_history(ticker: str, days: int = 450) -> pd.DataFrame:
return _yahoo_history(ticker.strip().upper(), days)
Wir sammeln rund 450 Tage Historie. Das reicht für langfristige Indikatoren wie den 200-Tage-Durchschnitt.
Technische Indikatoren berechnen
Berechnen wir nun ein paar gängige Indikatoren:
- Gleitende Durchschnitte: Mittelwerte über 20, 50 und 200 Tage
- Relative Strength Index (RSI): Skala von 0 bis 100, zeigt überkaufte (>70) bzw. überverkaufte (<30) Zonen
- Moving Average Convergence/Divergence (MACD): Differenz der langfristigen und kurzfristigen exponentiellen Durchschnitte (EMAs)
def add_indicators(frame: pd.DataFrame) -> pd.DataFrame:
if frame.empty:
return frame.copy()
result = frame.copy()
result.attrs.update(frame.attrs)
# Moving averages
result["SMA20"] = result["close"].rolling(20).mean()
result["SMA50"] = result["close"].rolling(50).mean()
result["SMA200"] = result["close"].rolling(200).mean()
# RSI
delta = result["close"].diff()
gain = delta.clip(lower=0)
loss = -delta.clip(upper=0)
avg_gain = gain.ewm(
alpha=1 / 14, min_periods=14, adjust=False
).mean()
avg_loss = loss.ewm(
alpha=1 / 14, min_periods=14, adjust=False
).mean()
result["RSI14"] = 100 - (
100 / (1 + avg_gain / avg_loss.replace(0, np.nan))
)
# MACD
result["EMA12"] = result["close"].ewm(
span=12, adjust=False
).mean()
result["EMA26"] = result["close"].ewm(
span=26, adjust=False
).mean()
result["MACD"] = result["EMA12"] - result["EMA26"]
return result
Diese Indikatoren helfen dem Technical-Agenten, Trends und Momentum schnell zu erkennen, ohne dass das LLM alles selbst berechnen muss.
Neueste Werte prüfen
Sammle nun die Daten, berechne die Indikatoren und zeige die letzten Zeilen an:
history = add_indicators(
get_price_history(TICKER)
)
if len(history) < 200:
raise RuntimeError(
f"Need at least 200 daily observations; received {len(history)}."
)
print(
f"Loaded {len(history)} rows "
f"from {history.attrs['source']}."
)
history.tail(3)[
[
"date",
"close",
"SMA20",
"SMA50",
"SMA200",
"RSI14",
"MACD",
]
]

Du solltest den aktuellen Kurs zusammen mit gleitenden Durchschnitten, RSI und MACD sehen – ähnlich wie oben.
Diese Daten geben wir später an den Technical-Agenten, damit er Trends, Momentum sowie bullische oder bärische Signale identifizieren kann.
4. Datenquellen als CrewAI-Tools bereitstellen
Da unsere Datenquellen funktionieren, verwandeln wir sie in CrewAI-Tools. So können die Agenten bei Bedarf direkt auf Fundamentaldaten, Technik oder News zugreifen.
Tools für Kurs- und Fundamentaldaten erstellen
Zuerst eine kleine Hilfsfunktion, um Zahlen einheitlich zu formatieren:
def _number(value, decimals: int = 2) -> str:
if value is None or pd.isna(value):
return "N/A"
return f"{float(value):,.{decimals}f}"
Als Nächstes das Fundamentals-Tool. Es nutzt Finnhub für aktuellen Kurs, Bewertung, Wachstum, Profitabilität und weitere Unternehmenskennzahlen.
@tool("Get Stock Fundamentals")
def get_fundamentals(ticker: str) -> str:
"""Get current price and company fundamentals from Finnhub for one ticker."""
ticker = ticker.strip().upper()
quote = finnhub_client.quote(ticker)
metrics = finnhub_client.company_basic_financials(ticker, "all")
m = metrics.get("metric", {})
return f"""Ticker: {ticker}
Source: Finnhub
Current price: {_number(quote.get('c'))}
Previous close: {_number(quote.get('pc'))}
Daily change %: {_number(quote.get('dp'))}
Day high / low: {_number(quote.get('h'))} / {_number(quote.get('l'))}
Market cap (USD millions): {_number(m.get('marketCapitalization'))}
52-week high / low: {_number(m.get('52WeekHigh'))} / {_number(m.get('52WeekLow'))}
Normalized annual P/E: {_number(m.get('peNormalizedAnnual'))}
Annual P/B: {_number(m.get('pbAnnual'))}
Annual P/S: {_number(m.get('psAnnual'))}
ROE TTM: {_number(m.get('roeTTM'))}
Net margin TTM: {_number(m.get('netProfitMarginTTM'))}
Revenue growth TTM YoY: {_number(m.get('revenueGrowthTTMYoy'))}
EPS growth TTM YoY: {_number(m.get('epsGrowthTTMYoy'))}
Annual debt/equity: {_number(m.get('totalDebt/totalEquityAnnual'))}"""
Außerdem erstellen wir ein Tool für die technische Analyse auf Basis der historischen Daten und Indikatoren aus dem vorherigen Abschnitt.
@tool("Analyze Stock Technicals")
def get_technicals(ticker: str) -> str:
"""Calculate price trends, returns, moving averages, RSI, and MACD."""
ticker = ticker.strip().upper()
frame = add_indicators(get_price_history(ticker))
if len(frame) < 200:
return (
f"Technical data unavailable for {ticker}: "
"fewer than 200 observations."
)
latest = frame.iloc[-1]
return f"""Ticker: {ticker}
Source: {frame.attrs.get('source', 'unknown')}
Last market date: {latest['date'].date()}
Close: {_number(latest['close'])}
SMA20 / SMA50 / SMA200: {_number(latest['SMA20'])} / {_number(latest['SMA50'])} / {_number(latest['SMA200'])}
RSI14: {_number(latest['RSI14'])}
MACD: {_number(latest['MACD'])}
20-day return: {_number((latest['close'] / frame['close'].iloc[-21] - 1) * 100)}%
50-day return: {_number((latest['close'] / frame['close'].iloc[-51] - 1) * 100)}%
Price vs SMA20: {_number((latest['close'] / latest['SMA20'] - 1) * 100)}%
Price vs SMA50: {_number((latest['close'] / latest['SMA50'] - 1) * 100)}%
Price vs SMA200: {_number((latest['close'] / latest['SMA200'] - 1) * 100)}%"""
Wichtig ist hier der @tool-Decorator. Er macht aus einer normalen Python-Funktion ein Tool, das ein CrewAI-Agent während einer Aufgabe gezielt aufrufen kann.
Websuche hinzufügen
Für Unternehmensnews und aktuelle Entwicklungen verwenden wir das Tavily-Suchtool von CrewAI:
web_search = TavilySearchTool(
api_key=os.environ["TAVILY_API_KEY"],
topic="news",
search_depth="advanced",
days=30,
max_results=5,
)
Wir begrenzen die Suche auf die letzten 30 Tage und maximal fünf Treffer. So bekommen die Research-Agenten genug aktuelle Informationen, ohne in unnötigen Details zu versinken.
Aktien-Tools testen
Bevor wir die Agenten erstellen, rufe die beiden Custom-Tools direkt auf:
print(get_fundamentals.run(ticker=TICKER))
print()
print(get_technicals.run(ticker=TICKER))

Du solltest nun zuerst die neuesten Fundamentalkennzahlen und anschließend die technischen Indikatoren der ausgewählten Aktie sehen.
5. Das Multi-Agenten-Research-Team bauen
Jetzt, da die Tools bereitstehen, erstellen wir unser Multi-Agenten-Research-Team.
Wir nutzen drei Spezialisten – für Fundamentalanalyse, technische Analyse und aktuelle Nachrichten – plus einen Portfoliomanager, der daraus die finale Bewertung ableitet.
Spezialisten anlegen
Zuerst der Fundamental-Analyst:
fundamental_agent = Agent(
role="Fundamental Analyst",
goal=(
"Evaluate financial health, growth, profitability, "
"valuation, and balance-sheet risk."
),
backstory=(
"You are a careful long-term equity analyst. "
"Use the fundamentals tool and never invent a figure. "
"Treat N/A as missing, not as zero."
),
tools=[get_fundamentals],
llm=llm,
allow_delegation=False,
max_iter=4,
verbose=False,
)
Als Nächstes der Technical-Analyst:
technical_agent = Agent(
role="Technical Analyst",
goal=(
"Determine whether the current price setup is "
"bullish, bearish, or neutral."
),
backstory=(
"You interpret indicators calculated by Python. "
"Never guess market prices or indicator values."
),
tools=[get_technicals],
llm=llm,
allow_delegation=False,
max_iter=4,
verbose=False,
)
Dann der News-Analyst:
news_agent = Agent(
role="Financial News Analyst",
goal=(
"Find material recent developments and distinguish "
"confirmed reporting from speculation."
),
backstory=(
"You are a skeptical financial-news researcher. "
"Prioritize primary and reputable sources, dates, and links."
),
tools=[web_search],
llm=llm,
allow_delegation=False,
max_iter=5,
verbose=False,
)
Jeder Spezialist bekommt nur das Tool, das er wirklich braucht. So bleibt der Workflow fokussiert und Agenten rufen keine irrelevanten Tools auf.
Portfoliomanager erstellen
Zum Schluss der Manager, der alle drei Spezialistenberichte prüft:
manager_agent = Agent(
role="Portfolio Manager",
goal=(
"Combine the specialist reports into a balanced, "
"evidence-based research signal."
),
backstory=(
"You lead an equity research team. "
"Weigh bullish and bearish evidence, use HOLD when evidence "
"is mixed, and never add unsupported facts."
),
llm=llm,
allow_delegation=False,
max_iter=4,
verbose=False,
)
Der Portfoliomanager braucht keinen direkten Zugriff auf die Datentools. Er arbeitet mit den Berichten der drei Spezialisten.
Mit allow_delegation=False bleibt der Ablauf vorhersagbar. max_iter begrenzt die Zyklen aus Reasoning und Toolnutzung je Agent.
6. Spezialisierte Research-Aufgaben definieren
Mit den Agenten ist definiert, wer sie sind. Jetzt sagen wir jedem Agenten genau, was er tun und was sein Endergebnis enthalten soll.
Research-Tasks festlegen
Beginne mit der Fundamentalanalyse:
fundamental_task = Task(
description=(
f"Analyze {TICKER}'s growth, profitability, valuation, "
"balance sheet, and business quality. "
"Use Get Stock Fundamentals. "
"Return a Fundamental Score from 0-100, strongest positive, "
"biggest risk, and note all material missing data."
),
expected_output=(
"A concise fundamental assessment with a 0-100 score, "
"evidence, strongest positive, biggest risk, "
"and missing-data note."
),
agent=fundamental_agent,
)
Als Nächstes die technische Analyse:
technical_task = Task(
description=(
f"Analyze {TICKER}'s technical setup. "
"Use Analyze Stock Technicals. "
"Consider SMA20/50/200, RSI14, MACD, recent returns, and trend. "
"Return Technical Score 0-100, Bullish/Neutral/Bearish signal, "
"trend, momentum, and main technical risk."
),
expected_output=(
"A concise technical assessment with score, signal, trend, "
"momentum, data source, and main risk."
),
agent=technical_agent,
)
Für aktuelle Entwicklungen der News-Task:
news_task = Task(
description=(
f"Research the most important recent news for {TICKER}, "
"focusing on the last 30 days: earnings, guidance, analyst "
"revisions, products, partnerships, M&A, regulation, lawsuits, "
"management, and industry developments. "
"Use Tavily Search. "
"Return News Score 0-100, sentiment, positive and negative "
"catalysts, publication dates, and source URLs. "
"Ignore low-quality speculation."
),
expected_output=(
"A sourced recent-news assessment with score, sentiment, "
"catalysts, dates, and clickable URLs."
),
agent=news_agent,
)
Klare Aufgaben und Output-Formate sind entscheidend. So kann der Portfoliomanager die Reports besser vergleichen, statt völlig unterschiedliche Antworten zu erhalten.
Finale Entscheidungsaufgabe erstellen
Die letzte Aufgabe führt alle drei Berichte zusammen:
decision_task = Task(
description=(
f"Review all three specialist reports and make the final "
f"educational research assessment for {TICKER}. "
"Return exactly one signal: BUY, HOLD, or SELL. "
"Use HOLD when evidence is mixed or confidence is insufficient. "
"Base every claim only on the supplied reports."
),
expected_output=(
"Ticker; Signal; Overall Score /100; Confidence %; "
"Fundamental, Technical, and News scores; Bull Case; "
"Bear Case; Main Catalyst; Main Risk; Final Explanation; "
"Sources; and an educational-not-financial-advice disclaimer."
),
agent=manager_agent,
context=[
fundamental_task,
technical_task,
news_task,
],
)
Der wichtige Teil ist context. So erhält der Portfoliomanager Zugriff auf die Ausgaben aller drei Spezialisten und kann Fundamentals, Technik und News abwägen, bevor er das finale BUY-, HOLD- oder SELL-Urteil fällt.
Damit sind Agenten, Tools und Tasks bereit. Jetzt verbinden wir alles in einem CrewAI-Workflow und lassen das komplette Research-Team laufen.
7. Die Multi-Agenten-Crew ausführen
Bringen wir nun alles zusammen und starten den vollständigen Aktienresearch-Workflow.
Die Crew erstellen
Erstelle eine CrewAI-Crew mit unseren drei Spezialisten und dem Portfoliomanager:
crew = Crew(
agents=[
fundamental_agent,
technical_agent,
news_agent,
manager_agent,
],
tasks=[
fundamental_task,
technical_task,
news_task,
decision_task,
],
process=Process.sequential,
verbose=False,
tracing=False,
)
Wir verwenden Process.sequential, sodass die Research-Aufgaben nacheinander laufen. Fundamental-, Technical- und News-Agent schließen zuerst ab, dann erstellt der Portfoliomanager die finale Einschätzung.
Research-Team starten
Starte den Workflow asynchron:
result = await crew.kickoff_async()
Dieser Schritt dauert etwas, da die Agenten mehrere LLM- und Tool-Calls durchführen. In meinem Test brauchte der komplette Workflow etwa 4 bis 5 Minuten.
Ist er fertig, gib den finalen Report des Portfoliomanagers aus:
print(result.raw)

Du solltest einen ausführlichen Report ähnlich dem obigen sehen, inklusive:
- BUY-, HOLD- oder SELL-Signal
- Gesamtscore
- Konfidenzniveau
- Scores der Spezialisten
- Bull Case
- Bear Case
- Katalysatoren
- Risiken
- Quellen
In diesem Beispiel analysierten die Agenten NVIDIA unabhängig und kombinierten ihre Ergebnisse in einem evidenzbasierten Research-Report. Hier zeigt sich der Vorteil des Multi-Agenten-Ansatzes: Anstatt ein Modell alles auf einmal machen zu lassen, fokussiert sich jeder Agent auf sein Gebiet, bevor der Portfoliomanager alles zusammenführt.
Falls es Probleme mit dem Code gibt: Das vollständige Jupyter-Notebook mit allen Snippets und Ausgaben ist ebenfalls verlinkt. Du kannst es ansehen oder selbst ausführen: glm-stock-swarm/stock_analyst_crew.ipynb
8. Terminal-UI bauen und ausführen
Nach den Tests im Jupyter-Notebook habe ich den kompletten Workflow in eine Terminal-User-Interface (TUI) übertragen. Statt einzelne Notebook-Zellen manuell zu starten, kannst du den gesamten Multi-Agenten-Aktienanalysten mit einem einzigen Befehl ausführen.
Das komplette Projekt inklusive Code und Setup-Anleitung findest du auf GitHub: glm-stock-swarm GitHub-Repository.
App installieren und starten
Starte mit dem Klonen des Repositories:
git clone https://github.com/kingabzpro/glm-stock-swarm.git
cd glm-stock-swarm
Füge deine Z.ai-, Finnhub- und Tavily-API-Schlüssel in die .env-Datei ein und installiere dann alle Abhängigkeiten mit uv:
uv sync
Starte anschließend die TUI:
uv run glm-stock-swarm
Eine Aktie analysieren
Die Oberfläche bietet ein simples Eingabefeld. Gib dort einen unterstützten Ticker ein, um die Analyse zu starten.

Nach dem Absenden siehst du, wie die Agenten nacheinander arbeiten. Zuerst der Fundamental-Analyst, gefolgt vom Technical-Analyst, dann der News-Analyst und schließlich der Portfoliomanager, der alles zur finalen Entscheidung zusammenführt.

Am Ende erzeugt die TUI direkt im Terminal einen vollständigen Report mit Fundamental-, Technical- und News-Score, Gesamtscore, Konfidenz, Bull Case, Bear Case, Risiken, Katalysatoren und dem finalen BUY-, HOLD- oder SELL-Signal.
Rückfragen stellen
Ich habe außerdem einen Follow-up-Chat ergänzt, damit du nicht für jede Rückfrage die gesamte Multi-Agenten-Pipeline neu starten musst.

Beispiel: Nach einer SELL-Empfehlung fragte ich, ob ich die gesamte Position oder nur einen Teil verkaufen sollte.

Statt erneut alle vier Agenten zu starten, nutzt die Anwendung den Kontext aus dem erzeugten Research-Report und liefert eine deutlich schnellere Folgeantwort.
So wird die App praktischer: Der teure Multi-Agenten-Research läuft einmal, Rückfragen nutzen die bestehende Analyse.
Abschließende Gedanken
Bemerkenswert in meinen Testruns war die Zuverlässigkeit beim Tool-Aufruf. Alle drei Spezialisten wählten das richtige Tool, hielten sich an die N/A-Konvention statt fehlende Daten als Null zu deuten, und lieferten das Score-und-Evidence-Format, das der Portfoliomanager brauchte. Genau hier stolpern günstige Modelle oft.
Der Trade-off ist Geschwindigkeit. Artificial Analysis misst GLM-5.3-Flash auf Z.ai's API mit rund 45 Output-Tokens pro Sekunde – am unteren Ende für Open-Weight-Modelle dieser Größe. Das merkt man an den 4 bis 5 Minuten für einen kompletten Crew-Run. Auf ihrem Index erzielt es 57 vs. 60 für GLM-5.3. Du gibst also ein wenig Reasoning-Qualität ab, bekommst dafür aber ungefähr ein Zehntel des Preises. Ein guter Tausch.
Nichts davon bindet dich fest. Ein Wechsel zu OpenRouter, Hugging Face Inference oder einem lokalen Modell über Ollama bedeutet meist nur drei Änderungen: API-Schlüssel, Modellname, Base-URL. Ähnlich bei den Tools, wo yfinance hier die Aufgaben von Finnhub und Yahoo übernehmen könnte.
Als nächsten Schritt würde ich das an eine Paper-Trading-API anbinden und morgens automatisch laufen lassen. Aber bitte nur mit Demokonto. Dieses Projekt soll Agentendesign vermitteln, nicht zum Traden anregen.
Wenn du agentische KI von Grund auf lernen willst, empfehle ich unseren AI Agent Fundamentals Lernpfad als idealen Einstieg.
Als zertifizierter Data Scientist ist es meine Leidenschaft, modernste Technologien zu nutzen, um innovative Machine Learning-Anwendungen zu entwickeln. Mit meinem fundierten Hintergrund in den Bereichen Spracherkennung, Datenanalyse und Reporting, MLOps, KI und NLP habe ich meine Fähigkeiten bei der Entwicklung intelligenter Systeme verfeinert, die wirklich etwas bewirken können. Neben meinem technischen Fachwissen bin ich auch ein geschickter Kommunikator mit dem Talent, komplexe Konzepte in eine klare und prägnante Sprache zu fassen. Das hat dazu geführt, dass ich ein gefragter Blogger zum Thema Datenwissenschaft geworden bin und meine Erkenntnisse und Erfahrungen mit einer wachsenden Gemeinschaft von Datenexperten teile. Zurzeit konzentriere ich mich auf die Erstellung und Bearbeitung von Inhalten und arbeite mit großen Sprachmodellen, um aussagekräftige und ansprechende Inhalte zu entwickeln, die sowohl Unternehmen als auch Privatpersonen helfen, das Beste aus ihren Daten zu machen.
