データフロー
全体フロー
┌──────────┐
│ 起動 │
└────┬─────┘
│
▼
┌──────────────────────────────────────┐
│ race_calendar.py │
│ 当日レーススケジュール取得 │
│ GET race_list_sub.html │
└────┬─────────────────────────────────┘
│ List[RaceInfo]
▼
┌──────────────────────────────────────┐
│ horse_info.py │
│ 各レースの出馬表取得 (キャッシュ) │
│ GET shutuba.html │
└────┬─────────────────────────────────┘
│ Dict[race_id → Dict[馬番 → HorseEntry]]
▼
┌═══════════════════════════════════════════════════┐
║ メインポーリングループ (poll_interval秒ごと) ║
║ ║
║ ┌────────────────────────────────────────┐ ║
║ │ odds_fetcher.py │ ║
║ │ 各レースのオッズ取得 │ ║
║ │ GET api_get_jra_odds.html (JSON API) │ ║
║ └────┬───────────────────────────────────┘ ║
║ │ Dict[馬番 → OddsData] ║
║ ▼ ║
║ ┌────────────────────────────────────────┐ ║
║ │ snapshot_store.py │ ║
║ │ スナップショット保存 │ ║
║ │ ├── in-memory deque (直近2件) │ ║
║ │ └── SQLite (全履歴) │ ║
║ └────┬───────────────────────────────────┘ ║
║ │ prev_snapshot + curr_snapshot ║
║ ▼ ║
║ ┌────────────────────────────────────────┐ ║
║ │ change_detector.py │ ║
║ │ 変動率計算・急騰/急落判定 │ ║
║ │ abs(変動率)降順ソート │ ║
║ └────┬──────────────┬────────────────────┘ ║
║ │ │ ║
║ ▼ ▼ ║
║ ┌──────────┐ ┌──────────────┐ ║
║ │ terminal │ │ slack │ ║
║ │ _display │ │ _notifier │ ║
║ │ .py │ │ .py │ ║
║ │ │ │ │ ║
║ │ rich │ │ Webhook POST │ ║
║ │ テーブル │ │ (閾値超過時) │ ║
║ └──────────┘ └──────────────┘ ║
║ ║
║ ← poll_interval秒待機 → ║
╚═══════════════════════════════════════════════════╝データ取得タイミング
適応的ポーリング
| 条件 | ポーリング間隔 |
|---|---|
| 発走10分以上前 | POLL_INTERVAL (デフォルト60秒) |
| 発走10分以内 | POLL_INTERVAL_NEAR_POST (デフォルト30秒) |
レート制限対策
- 各HTTPリクエスト間に
REQUEST_DELAY(デフォルト1.0秒) の待機 - 例: 3会場×12R = 最大36レースの場合、1巡に約36秒
ストレージ構成
┌─────────────────────────────────┐
│ SnapshotStore │
├────────────────┬────────────────┤
│ in-memory │ SQLite │
│ deque │ odds.db │
│ │ │
│ 直近2件のみ保持 │ 全履歴を保存 │
│ O(1) アクセス │ 後から分析可能 │
│ リアルタイム比較│ レース後の検証 │
└────────────────┴────────────────┘race_id フォーマット
YYYY AA BB CC DD
│ │ │ │ └── レース番号 (01-12)
│ │ │ └───── 日目
│ │ └──────── 開催回
│ └─────────── 会場コード (01-10)
└──────────────── 年 (4桁)
例: 202609010711
2026年 / 阪神(09) / 1回 / 7日目 / 11R