Tracks
大規模言語モデルは、特化した役割やツール、ライブデータへのアクセスを与えることで、より有用になります。単一モデルに頼る代わりに、各エージェントが分析の異なる部分に集中する小さなリサーチチームを構築できます。
このチュートリアルではまさにそれを行います。GLM-5.3-FlashとCrewAIを使って-エージェントの株式アナリストを構築します。3つのエージェントがファンダメンタルズ、テクニカル指標、最近のニュースを分析し、ポートフォリオマネージャーがそれらの所見を統合して最終的なBUY、HOLD、SELLのリサーチシグナルを出します。
まずJupyter Notebookでワークフローをテストし、その後、株式を分析してフォローアップの質問に答えられるシンプルなターミナルUIに変換します。
このプロジェクトで使用するもの:
- GLM-5.3-Flash(推論)
- CrewAI(エージェントの調整)
- Finnhub(マーケット・ファンダメンタルデータ)
- Yahoo Finance(過去価格)
- Tavily(最近のニュース)
- PandasとNumPy(テクニカル指標)
フレームワークに不慣れですか?Building AI Agents with CrewAIコースでは、エージェント、クルー、フローをゼロから解説しています。
マルチエージェントアプリでGLM-5.3-Flashを使う理由
GLM-5.3-Flashは性能・効率・価格のバランスに優れています。全体像は、GLM-5.3-FlashガイドやQwen3.8-Flash-Nextとの比較記事をご覧ください。
競争力のある性能と効率
Artificial Analysis Intelligence Indexでは57を獲得し、リーディングモデルの一角に位置します。はるかに高価なフロンティアモデルとも競合します。例えば:
-
GPT-5.6 Solも57(
highの推論努力)ですが、トークンあたりの入出力でそれぞれ25倍超/40倍超のコストです。 -
Claude Sonnet 5は
maxの推論努力で55とやや低く、トークンの入出力コストはGLM-5.3-Flashの20倍/30倍です。
総パラメータは320Bですが、トークンあたりで実際にアクティブなのは約18Bのため、高い性能を維持しつつ計算効率も良好です。

出典:AI Model & API Providers Analysis | Artificial Analysis
魅力的な価格
前述の性能が比較的低価格のAPIで提供されています。執筆時点では、OpenRouterがGLM-5.3-Flashを50%オフで提供しており、入力100万トークンあたり$0.075、出力100万トークンあたり$0.25です。
通常価格の$0.15/$0.50でも、OpenAIのGPT-5.6 Luna(max推論でAA Intelligence Indexが52、価格は$0.20/$1.20)より割安です。これは実験だけでなく、本番レベルのエージェントアプリにも有力な選択肢となります。

出典:GLM 5.3 Flash - API Pricing & Benchmarks | OpenRouter
マルチエージェントシステムでは、この点はさらに重要です。1回のユーザーリクエストが裏側で多数のLLM呼び出しを引き起こすからです。単一のLLMエージェントでも、推論、ツール選択、ツール出力の処理、最終応答の生成で複数回呼び出す場合があります。仮に1エージェントが7回程度呼び出し、ワークフローに5エージェントを使えば、1リクエストで35回以上の呼び出しが容易に発生します。
正確な回数は設計によりますが、要点はシンプルです。エージェント型ワークフローはコストがすぐに膨らみます。GLM-5.3-Flashのような有能かつ低単価のモデルは、小規模デモから本番アプリへ移る際に大きな差を生みます。
1. GLM-5.3-Flashの環境をセットアップする
マルチエージェントのワークフローを構築する前に、Z.ai、Finnhub、TavilyのAPIキーを作成してください。
APIキーを作成
Z.aiでは、通常のAPIを使用し、GLM Coding Planは使わないでください。Coding Planはサポート対象のAIコーディングツール向けであり、独自のマルチエージェントアプリの汎用APIとして使うべきではありません。
通常のZ.ai APIキーを生成し、少額のクレジットをアカウントに追加します。GLM-5.3-Flashは低価格なので、テスト開始には少額で十分です。

出典:Z.ai API Platform — Start building with GLM-5.3
また、FinnhubとTavilyで無料アカウントを作成し、APIキーを発行できます。本プロジェクトのテストには無料枠で十分です。
プロジェクトファイルを準備
次に、プロジェクトフォルダに.envファイルを作成し、APIキーを追加します:
ZAI_API_KEY="your_zai_api_key"
FINNHUB_API_KEY="your_finnhub_api_key"
TAVILY_API_KEY="your_tavily_api_key"
続いて新しいJupyter Notebookを作成します。まずここでマルチエージェントの完全なワークフローを構築・テストし、各エージェントの出力を確認・修正してから、アプリケーション化します。
必要なライブラリをインストール
CrewAIでエージェントを作成・調整し、Finnhubで株式市場データ、Tavilyでリアルタイムのウェブ検索を行います。必要なPythonパッケージをインストールしてください:
!pip install -q crewai crewai-tools finnhub-python tavily-python pandas numpy requests python-dotenv openai
ライブラリとAPIキーをインポート
次に必要なライブラリをインポートし、APIキーを読み込みます:
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")
最後に、エージェントに分析させたい銘柄を選びます:
TICKER = "NVDA"
Notebook全体ではNVIDIA(NVDA)を使いますが、AAPL、MSFT、TSLAなど関心のある別のティッカーに置き換えて構いません。
2. GLM-5.3-FlashとデータAPIを設定する
APIキーの準備ができたので、プロジェクト全体でエージェントが使用するサービスに接続します。
まず株式市場データのFinnhub、ウェブ検索のTavilyを初期化します:
finnhub_client = finnhub.Client(
api_key=os.environ["FINNHUB_API_KEY"]
)
tavily_client = TavilyClient(
api_key=os.environ["TAVILY_API_KEY"]
)
金融エージェントを作りたいがデータソース選びに迷っている場合は、適切な株式市場データAPIの選び方ガイドを参照してください。
次に、CrewAIエージェントのメインLLMとしてGLM-5.3-Flashを設定します。Z.aiはOpenAI互換のAPIを提供しているため、CrewAIのLLMクラス経由で直接接続できます:
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,
)
このアプリは金融の調査・分析に焦点を当てるため、温度は低めに設定し、より一貫性と集中度の高い応答を狙います。
モデル、マーケットデータ、ウェブ検索APIの接続ができたので、次にエージェントが使用するツールを構築します。
3. 過去のマーケットデータを収集する
次に、株価の推移を把握するために、過去の価格データが必要です。
ここではYahoo Financeの公開チャートエンドポイントを使用し、日次の始値・高値・安値・終値・出来高を取得します。
価格履歴をダウンロード
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)
約450日分の履歴を取得します。これで200日移動平均などの長期指標を計算するのに十分です。
テクニカル指標を計算
次に、よく使われる指標をいくつか計算します:
- 移動平均:20日・50日・200日の平均
- RSI(相対力指数):0〜100でスケールし、70超で買われ過ぎ、30未満で売られ過ぎを示唆
- MACD:長期と短期の指数平滑移動平均(EMA)の差
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
これらの指標により、テクニカル分析エージェントはトレンドやモメンタムを素早く把握できます。LLMにすべての計算を任せる必要がなくなります。
最新値を確認
データを取得し、指標を計算して、最新の行を表示します:
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",
]
]

上記のように、最新の株価と移動平均、RSI、MACDが表示されるはずです。
後ほど、このデータをテクニカル分析エージェントに渡し、価格トレンドやモメンタム、強気・弱気シグナルを特定させます。
4. データソースをCrewAIツールに変換する
データソースが機能するようになったので、CrewAIのツールに変換します。これにより、エージェントは必要に応じて財務・テクニカル・ニュース情報を直接呼び出せます。
株式データのツールを作成
まず、数値表現を整える小さなヘルパー関数を作ります:
def _number(value, decimals: int = 2) -> str:
if value is None or pd.isna(value):
return "N/A"
return f"{float(value):,.{decimals}f}"
次にファンダメンタルズ用ツールを作成します。Finnhubを使って最新の株価、バリュエーション、成長性、収益性、その他の企業ファンダメンタルを取得します。
@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'))}"""
また、先ほどの履歴データと指標を用いたテクニカル分析ツールも作成します。
@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)}%"""
重要なのは@toolデコレータです。通常のPython関数を、CrewAIのエージェントがタスク中に呼び出せるツールに変換します。
ウェブ検索ツールを追加
企業ニュースや最近の動向には、CrewAIのTavily検索ツールを使用します:
web_search = TavilySearchTool(
api_key=os.environ["TAVILY_API_KEY"],
topic="news",
search_depth="advanced",
days=30,
max_results=5,
)
検索範囲を直近30日に限定し、最大5件を返します。これで、不要な情報に埋もれず、研究エージェントに十分な最新情報を与えられます。
株式ツールをテスト
エージェントを作成する前に、2つのカスタムツールを直接実行します:
print(get_fundamentals.run(ticker=TICKER))
print()
print(get_technicals.run(ticker=TICKER))

選択した株式について、最新のファンダメンタル指標に続いてテクニカル指標が表示されるはずです。
5. マルチエージェントのリサーチチームを構築
ツールの準備ができたので、マルチエージェントのリサーチチームを作成します。
ファンダメンタル、テクニカル、最近のニュースを担当する3人の専門エージェントと、その所見を統合するポートフォリオマネージャーを用います。
専門エージェントを作成
まず、ファンダメンタルアナリストを作成します:
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,
)
次にテクニカルアナリストを作成します:
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,
)
続いて、金融ニュースアナリストを作成します:
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,
)
各専門家は必要なツールのみを受け取ります。これによりワークフローが焦点化され、無関係なツール呼び出しを防げます。
ポートフォリオマネージャーを作成
最後に、3人の専門家レポートをレビューするマネージャーエージェントを作成します:
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,
)
ポートフォリオマネージャーはデータツールへ直接アクセスする必要はありません。3人の専門家が作成したレポートを扱います。
allow_delegation=Falseはワークフローを予測可能に保ち、max_iterは各エージェントの推論・ツール使用サイクルの上限を制限します。
6. 専門のリサーチタスクを割り当てる
エージェントの作成は、彼らが誰かを定義します。次に、各エージェントに対して何をするべきか、最終出力に何を含めるべきかを正確に指示します。
リサーチタスクを定義
まずファンダメンタル分析のタスクから:
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,
)
次にテクニカル分析のタスクを定義します:
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,
)
最近の動向についてはニュース調査タスクを作成します:
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,
)
各エージェントに明確なタスクと出力形式を与えることが重要です。これにより、ポートフォリオマネージャーは各レポートを比較しやすくなり、バラバラの形式の応答を受け取る事態を避けられます。
最終判断タスクを作成
最後のタスクで3つのレポートをまとめます:
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,
],
)
重要なのはcontextです。これにより、ポートフォリオマネージャーは3つの専門タスクの出力へアクセスでき、ファンダメンタル・テクニカル・ニュースのシグナルを比較して最終的なBUY/HOLD/SELLの判断を下せます。
ここまででエージェント、ツール、タスクの準備が整いました。次にCrewAIのワークフローに接続し、リサーチチーム全体を実行します。
7. マルチエージェントのリサーチクルーを実行
すべてをまとめて、株式リサーチの完全なワークフローを実行します。
クルーを作成
3人の専門エージェントとポートフォリオマネージャーを含むCrewAIのクルーを作成します:
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,
)
Process.sequentialを使用しているため、リサーチタスクは順番に実行されます。まずファンダメンタル、次にテクニカル、ニュースの各エージェントが分析を完了し、最後にポートフォリオマネージャーがそれらのレポートを受け取り最終評価を作成します。
リサーチチームを実行
ワークフローを非同期で開始します:
result = await crew.kickoff_async()
このステップには時間がかかる場合があります。エージェントが複数回のLLM・ツール呼び出しを行うためです。筆者のテストでは、リサーチ全体の完了に約4〜5分かかりました。
完了したら、ポートフォリオマネージャーの最終レポートを表示します:
print(result.raw)

上記のような詳細レポートが得られるはずです。内容には以下が含まれます:
- BUY、HOLD、SELLのシグナル
- 総合スコア
- 確信度
- 各専門家のスコア
- 強気シナリオ
- 弱気シナリオ
- カタリスト
- リスク
- 根拠となる情報源
この例では、各エージェントが独立してNVIDIAを分析し、所見を統合して証拠に基づく単一のリサーチレポートを作成しました。これこそがマルチエージェント手法の利点です。1つのモデルに一度にすべてを任せるのではなく、各エージェントが自分の領域に集中し、最後にポートフォリオマネージャーが研究結果をまとめます。
上記コードの実行で問題がある場合は、すべてのコードと出力を含むJupyter Notebookも用意しています。参照・実行はこちら:glm-stock-swarm/stock_analyst_crew.ipynb
8. ターミナルUIを構築・実行する
Jupyter Notebook内でのテスト後、完全なワークフローをターミナルユーザーインターフェース(TUI)に変換しました。Notebookの各セルを手動で実行する代わりに、単一コマンドでマルチエージェント株式アナリスト全体を起動できます。
コードとセットアップ手順を含む完全なプロジェクトはGitHubで公開しています:glm-stock-swarm GitHubリポジトリ。
アプリをインストール・実行
まずリポジトリをクローンします:
git clone https://github.com/kingabzpro/glm-stock-swarm.git
cd glm-stock-swarm
.envファイルにZ.ai、Finnhub、TavilyのAPIキーを追加し、uvで依存関係をインストールします:
uv sync
最後にTUIを起動します:
uv run glm-stock-swarm
株式を分析
インターフェースには、分析対象のサポート済みティッカーを入力できるシンプルな入力欄があります。

チケットを送信すると、エージェントが順に作業する様子を確認できます。まずファンダメンタルアナリスト、次にテクニカルアナリスト、ニュースアナリスト、最後にポートフォリオマネージャーが最終判断をまとめます。

最終的に、TUIはターミナル内で完全なレポートを生成します。ファンダメンタルスコア、テクニカルスコア、ニューススコア、総合スコア、確信度、強気・弱気シナリオ、リスク、カタリスト、最終のBUY/HOLD/SELLシグナルが含まれます。
フォローアップの質問を行う
また、毎回マルチエージェントのパイプライン全体を再実行せずに済むよう、フォローアップ用のチャットも追加しました。

例えば、SELLの提案を受けた後、保有株をすべて売るべきか、一部だけにすべきかを尋ねました。

アプリケーションは4つのエージェントを再度起動する代わりに、生成済みのリサーチレポートのコンテキストを用いて、より素早いフォローアップ応答を返します。
これにより、コストのかかるマルチエージェントのリサーチは1回で済み、フォローアップ質問は既存の分析を再利用できるため、実用性が高まります。
まとめ
テスト実行から報告すべき点は、ツール呼び出しの信頼性です。3人の専門家はいずれも適切なツールを選び、欠損データをゼロではなくN/Aとして扱い、ポートフォリオマネージャーが求めるスコア+根拠の形式で返してくれました。これは低価格モデルがつまずきがちな点です。
トレードオフは速度です。Artificial Analysisによると、Z.aiのAPIでのGLM-5.3-Flashの出力速度は毎秒約45トークンで、同規模のオープンウェイトモデルとしては低めです。フルのクルー実行で4〜5分かかるのもそれを感じます。インテリジェンス指数でもGLM-5.3の60に対して57と、推論品質をわずかに手放しますが、価格が約10分の1であることを考えると妥当なトレードです。
いずれにもロックインされません。OpenRouter、Hugging Face Inference、Ollama経由のローカルモデルへ切り替える場合も、通常はAPIキー、モデル名、ベースURLの3点を変えるだけです。ツールも同様で、この例でFinnhubとYahooが担っている部分はyfinanceでも代替可能です。
次の一歩としては、ペーパートレードAPIに接続して朝の定期実行をスケジューリングすることです。ただしデモ口座に留めてください。これはエージェント設計を学ぶために作られており、取引目的ではありません。
エージェント型AIを基礎から学ぶなら、AI Agent Fundamentalsスキルトラックを強くお勧めします。