
Claude Codeでオッズ変動モニターを作る:claude-fable-5とCrazyrouterでJSON分析まで検証
Claude Codeでオッズ変動モニターを作る:claude-fable-5とCrazyrouterでJSON分析まで検証#
前回のWorld Cup分析デモでは、Claude Codeに小さな試合予測パイプラインを作らせました。Python側でElo/Poissonに近い透明な計算を行い、LLMは構造化されたプレビュー文を生成する、という分担です。
今回は同じスポーツ分析テーマでも、予測ではなく監視システムに寄せます。
Claude Codeでオッズ変動モニターを作り、検出したアラートを
claude-fable-5にJSONで要約させられるか?
この記事は開発チュートリアルです。**賭けの助言、予想、購入推奨ではありません。**扱うのは、数値データの取り込み、派生指標、しきい値、アラート、LLM出力の検証というエンジニアリング上のパターンです。
今回のLLM呼び出しはCrazyrouter経由で検証しました。
Base URL: https://cn.crazyrouter.com/v1
Model tested: claude-fable-5
Task: odds movement alerts を、賭けの助言なしでJSON要約する

なぜ「オッズ変動」はClaude Codeの題材に向いているのか#
オッズという単語だけを見るとベッティング寄りに見えますが、開発者目線ではかなり素直な時系列監視問題です。
必要になる部品は、たとえば次のようなものです。
- 数値データの入力
- 開始値と最新値の比較
- 暗黙確率への変換
- 差分の計算
- しきい値ベースのアラート
- JSON形式の要約
- 出力検証
- 「助言しない」ための明示的な境界条件
つまり、Claude Codeに「どちらが勝つかを当てて」と頼むより、ずっと安全で再現性のあるタスクです。
このデモでシステムが答えるべきなのは、次のような質問です。
- 暗黙確率は何ポイント変化したか?
- どの市場が一番大きく動いたか?
- 同じ試合の反対側の市場も整合的に動いているか?
- ニュース、ラインアップ、流動性、データ品質を確認すべきか?
- LLMは賭けの推奨に踏み込まず、監視ログとして使える説明を返せるか?
この線引きが重要です。LLMは意思決定の魔法の箱ではなく、計算済みシグナルを人間が読みやすく整理する補助役として使います。
全体アーキテクチャ#
今回のデモは、小さく再現できる構成にしました。
sample odds CSV
↓
Python parser
↓
decimal odds → implied probability
↓
movement calculation
↓
alert threshold
↓
Crazyrouter経由でclaude-fable-5に分析依頼
↓
JSON validation
↓
記事・チャート・監査ログ
作成したプロジェクトの主要ファイルは次のとおりです。
generated/claude_code_odds_monitor_fable_20260613/
├── build_odds_monitor.py
├── sample_odds_movements.csv
├── odds_monitor_output.json
├── odds_movement_chart.svg
├── crazyrouter_raw_claude-fable-5.json
├── claude_fable_5_test_result.json
└── claude_fable_5_final_test_result.json
役割分担はシンプルです。
Pythonが変動を検出する。
claude-fable-5がアラートを説明する。
JSON検証が、その説明を使ってよいか判断する。
サンプルCSVを用意する#
このチュートリアルでは、有料のスポーツデータAPIではなく、合成したサンプルデータを使います。目的は外部データ取得ではなく、監視パイプラインの形を確認することだからです。
match,market,opening_decimal,latest_decimal,timestamp
USA vs Paraguay,USA win,2.20,2.08,2026-06-12T08:00:00Z
USA vs Paraguay,Draw,3.55,3.65,2026-06-12T08:00:00Z
USA vs Paraguay,Paraguay win,3.10,3.25,2026-06-12T08:00:00Z
Brazil vs Morocco,Brazil win,1.78,1.72,2026-06-13T08:00:00Z
Qatar vs Canada,Canada win,2.08,1.92,2026-06-13T08:00:00Z
Germany vs Curaçao,Germany win,1.20,1.16,2026-06-14T08:00:00Z
本番環境なら、ここは複数ブックメーカー、タイムスタンプ付きスナップショット、データ欠損チェック、APIリトライ、監査ログに置き換わります。
decimal oddsを暗黙確率に変換する#
decimal oddsから暗黙確率を出すだけなら、関数は非常に短く書けます。
def implied_prob(decimal_odds):
return 1.0 / decimal_odds
開始値と最新値の暗黙確率を比較します。
open_p = implied_prob(opening)
latest_p = implied_prob(latest)
delta_pp = (latest_p - open_p) * 100
ここでdelta_ppはpercentage point単位の変化です。絶対値がしきい値を超えたらアラートにします。
if abs(delta_pp) >= 2.5:
alerts.append({
"match": match,
"market": market,
"direction": movement_direction,
"delta_pp": round(delta_pp, 2),
"note": "Large implied-probability movement; review news, lineup, liquidity, and data quality."
})
大事なのは、アラート判定をLLMに丸投げしないことです。ここでは決定的な計算でアラートを作り、LLMはその後段で説明を生成します。
アラート出力の例#
スクリプトは4件の大きな変動を検出しました。
[
{
"match": "USA vs Paraguay",
"market": "USA win",
"direction": "shortened",
"delta_pp": 2.62
},
{
"match": "Qatar vs Canada",
"market": "Qatar win",
"direction": "drifted",
"delta_pp": -3.18
},
{
"match": "Qatar vs Canada",
"market": "Canada win",
"direction": "shortened",
"delta_pp": 4.01
},
{
"match": "Germany vs Curaçao",
"market": "Germany win",
"direction": "shortened",
"delta_pp": 2.87
}
]
最大の変動はQatar vs CanadaのCanada winで、暗黙確率が4.01ポイント上昇しました。
繰り返しますが、これは賭けのシグナルではありません。監視システムとしては「十分に動いたので、背景ニュース、流動性、データ品質を確認する」という意味です。

Crazyrouter経由でclaude-fable-5を呼び出す#
次に、検出したアラートをclaude-fable-5へ渡し、構造化JSONで要約させます。
OpenAI互換APIとして呼べるので、Python側の初期化は次の形です。
from openai import OpenAI
client = OpenAI(
api_key="YOUR_CRAZYROUTER_API_KEY",
base_url="https://cn.crazyrouter.com/v1",
)
リクエストはコンパクトにします。
{
"model": "claude-fable-5",
"messages": [
{
"role": "user",
"content": "Return raw JSON only. Analyze these odds movement alerts for an engineering demo..."
}
],
"max_tokens": 1200
}
プロンプトには必ず次の制約を入れました。
No betting advice.
Output raw JSON only.
LLM出力を運用に入れるなら、「よさそうな文章が返った」では不十分です。後段でJSON parseに通すこと、必須キーを検査すること、免責文が入っていることを確認します。
claude-fable-5の検証結果#
最終的に成功したテストは次の結果でした。
| Model | HTTP | Latency | Prompt tokens | Completion tokens | Total tokens | Valid JSON |
|---|---|---|---|---|---|---|
claude-fable-5 | 200 | 12.14s | 833 | 599 | 1432 | True |
返ってきたJSONは、後処理なしでparseできました。
{
"summary": "4 significant odds movements detected across 3 matches. The Qatar vs Canada match shows the largest activity, with Canada win shortening by 4.01pp while Qatar win drifted by -3.18pp, indicating a consistent directional shift within the same market pair. USA win and Germany win both shortened moderately (2.62pp and 2.87pp respectively).",
"alerts_count": 4,
"top_movement": {
"match": "Qatar vs Canada",
"market": "Canada win",
"direction": "shortened",
"delta_pp": 4.01
},
"checks": [
"Verify lineup announcements and injury news for all flagged matches, especially Qatar vs Canada",
"Confirm market liquidity at the time of movement to rule out thin-market noise",
"Validate data feed integrity and timestamp consistency across sources",
"Cross-check movements against multiple bookmakers to confirm market-wide vs single-source shifts",
"Check whether Qatar/Canada movements are mirrored (overround-consistent) or indicate a data anomaly"
],
"recommendations": [
"Treat the paired Qatar vs Canada movements as a single correlated event in downstream analytics",
"Add automated correlation detection for opposing markets in the same match",
"Log raw odds snapshots around alert timestamps for audit and replay",
"Set per-market thresholds since a 4pp move may be normal in volatile markets but anomalous in stable ones",
"Flag movements lacking corresponding news events for manual data-quality review"
],
"disclaimer": "This analysis is for engineering and data-quality demonstration purposes only. It does not constitute betting advice, predictions, or recommendations to wager. Odds movements reflect market activity and data signals, not outcome probabilities endorsed by this system."
}
この出力のよい点は、アラートを賭けの推奨に変換していないことです。代わりに、データ品質・ニュース確認・相関検出・監査ログという運用チェックリストに落としています。
実装で見つかった注意点:payload shapeは重要#
テスト中に一度、claude-fable-5へのリクエストがHTTP 400になりました。
HTTP 400
Invalid request
原因はモデル名ではありませんでした。/v1/modelsではモデルが確認できていました。問題は、リクエストpayloadの形です。
別のJSON出力プロンプトではHTTP 200になったものの、Markdownコードフェンスで包まれたり、出力上限に近づいたりしました。
最終的に安定したパターンは次のとおりです。
model: claude-fable-5を指定する- 入力をコンパクトにする
- 余計な未対応パラメータを避け、
max_tokensを使う - raw JSONだけを返すよう明示する
- それでも必ずJSON検証を行う
モデルの品質は「賢いかどうか」だけではありません。API互換性、schema遵守、出力長、失敗時の挙動、リトライ、最終的な有効出力あたりのコストまで含めて評価する必要があります。
Crazyrouterを挟むメリット#
このような監視パイプラインでは、LLMに任せたいタスクが複数あります。
- 変動アラートの要約
- データ品質チェックの列挙
- 同一試合内の相関した動きの説明
- 運用担当者向けレポート生成
- 禁止したい助言を避ける文面制御
モデルによって、JSON遵守や説明の癖は変わります。Crazyrouterを使うと、アプリ側は次の形に揃えられます。
one API key
one OpenAI-compatible base URL
multiple model routes
same validation layer
今回もベースURLは次のままです。
https://cn.crazyrouter.com/v1
後からclaude-fable-5以外のGPT、Gemini、Qwen系モデルと比較したい場合も、アプリ本体を書き換える量を抑えられます。
Claude Codeに作らせるべきもの#
Claude Codeに期待するのは、単発スクリプトだけではありません。再現可能なプロジェクトとして、周辺のファイルまで作らせます。
sample_odds_movements.csv:再現可能な入力odds_monitor_output.json:決定的なアラート出力odds_movement_chart.svg:可視化crazyrouter_raw_claude-fable-5.json:API監査ログclaude_fable_5_final_test_result.json:検証結果- 公開できる技術記事
この形にしておくと、あとからモデル比較、しきい値調整、チャート差し替え、別データソースへの接続がやりやすくなります。
本番化するなら追加したいもの#
今回のデモは合成データです。本番のオッズ監視として使うなら、最低でも次の要素が必要になります。
- 実データAPIとの接続
- 複数ブックメーカーの比較
- overroundの正規化
- 流動性または市場厚みの推定
- タイムスタンプ整合性チェック
- ラインアップ、怪我、ニュースとの突合
- アラート重複排除
- 履歴データによるしきい値の校正
- コンプライアンスレビュー
この記事の目的は、賭け判断を作ることではありません。安全な監視ワークフローを、Claude CodeとLLM APIでどう組み立てるかを見ることです。
次に改善するなら#
次のステップとしては、以下を追加したいところです。
- 定期スナップショット取得
- 複数データプロバイダ対応
- overround調整済み暗黙確率
- 同一試合内の相関変動検出
- ニュース・ラインアップとの関連付け
claude-fable-5、GPT、Gemini、Qwenルートの比較- valid JSON 1件あたりのコスト計測
- 小さなWebダッシュボード
見るべき指標は単純なトークン単価だけではありません。
cost per valid alert report
失敗リクエスト、リトライ、壊れたJSON、payload調整の時間まで含めて、運用コストとして評価すべきです。
まとめ#
Claude Codeは、オッズ変動モニターのような小さな監視パイプラインを十分に構築できます。ただし、設計の中心は予測ではなく、検出・説明・検証に置くべきです。
今回のおすすめ構成は次のとおりです。
Pythonが暗黙確率の変動を計算する。
Claude Codeがパイプラインと成果物を作る。
claude-fable-5がCrazyrouter経由でアラートを要約する。
JSON validationが出力を採用できるか判断する。
World Cup分析シリーズの2本目として、この題材は予測から監視へ一歩進めた例になりました。同じ考え方は、スポーツ分析だけでなく、金融ダッシュボード、API監視、ログ異常検知、SaaS運用アラートにも応用できます。
claude-fable-5や他のモデルをOpenAI互換APIで試したい場合は、Crazyrouterを使えます。





