kabuステーション venue 統合: 仕様 (Phase 1)¶
本ファイルは kabuステーション API(v1.5)固有 の仕様(X-API-KEY / 50 銘柄 PUSH 上限 / WebSocket / 流量制限など)を扱う。venue 横断の抽象契約(注文ライフサイクル / VenueReady / VenueError 共通 code 等)は docs/specs/live-strategy.md に分離する。本ファイル末尾の「kabusapi 共通 hook」セクションが live-strategy.md に統合される候補項目を列挙する。
1. ゴール¶
本アプリの venue として三菱UFJ eスマート証券(旧 auカブコム)kabuステーション API(v1.5) を追加し、
検証環境 localhost:18081 に接続して kabu の板情報・気配・直近約定をチャートに表示できる状態
を成立させる。Phase 1 はリードオンリー(閲覧のみ)。
2. スコープ¶
2.1 含めるもの(Phase 1 = MVP)¶
- 新 venue
Venue::KabuStationおよびExchange::KabuStationStock(東証のみ、Phase 1) - IPC venue キー
"kabu_station"でRequestVenueLogin/VenueReady/VenueErrorを受理 - Python モジュール群
python/engine/exchanges/kabusapi*.py kabusapi_url.py— URL 定数(BASE_URL_PROD / BASE_URL_VERIFY)の唯一の所在地kabusapi_auth.py—POST /tokenトークン取得・エラー判定kabusapi_codec.py— UTF-8 JSON encode/decode(Shift-JIS 拒否 assert)kabusapi_login_flow.py— startup_login、debug env 自動ログイン、本体疎通チェックkabusapi_login_dialog.py— tkinter サブプロセス(API パスワード収集)kabusapi_ratelimit.py— token-bucket(発注 5/s、余力 10/s、情報 10/s)kabusapi_register.py— RegisterSet LRU 管理(50 銘柄上限)kabusapi_ws.py— WebSocket 接続・板パース・DepthSnapshot IPC 送出kabusapi_rest.py— REST 読取(/board//symbol//orders//positions//wallet/*)kabusapi.py— KabuStationVenue ファサード- PUSH WebSocket 再接続: 5s × 5 回打ち切り、再接続後は RegisterSet 全件 re-register
- capabilities 追加:
Ready.capabilities.venue_capabilities["kabu_station"]キー - テスト:
pytest-httpx(HTTPXMock) + WebSocket mock で全 9 件のテストファイル - CI:
.github/workflows/kabu-mock.yml(pytest -m demo_kabu、HTTPXMock のみ) - URL lint: Rust/Python の
kabusapi_url.py以外への URL リテラル漏出を CI で阻止
2.2 含めないもの(Phase 1 非ゴール)¶
- 発注・取消(
POST /sendorder/PUT /cancelorder) - 訂正(kabu API に訂正エンドポイントは無い。取消→再発注で代替するが Phase 2)
- 先物・OP・OCO
- 本番接続(
KABU_ALLOW_PROD=1ガードのみ用意) - 24h 連続稼働の安定性検証(kabuステーション本体の早朝強制ログアウト仕様による中断は許容)
- 早朝強制ログアウトのバナー文言確定(
docs/roadmap/kabusapi/_invariants-fragment.mdの分岐定義で暫定窓を定義) - 市場細分化(東証 / 名証 / 福証 / 札証の区別は Phase 3 以降)
kabusapi_master.py— 銘柄マスタは/symbol/{key}で都度取得、一括 DL 不要kabusapi_file_store.py— トークン短命のためファイルキャッシュ無し
2.3 安全不変条件(必ず守る)¶
- 本番接続は
KABU_ALLOW_PROD=1opt-in 必須。デフォルトは検証環境(localhost:18081)固定。 Python 側で多層ガードを敷き、Phase 1 では実弾発注経路を一切作らない。 - クレデンシャル・トークンは Python メモリのみ保持。Rust 経路に流さない。ファイル永続化しない。
- URL リテラルは
kabusapi_url.py1 箇所。Rust / engine-client / その他 Python ファイルに書かない。 - ログイン UI は Python tkinter サブプロセス。Rust にダイアログコードを書かない。
3. 非機能要件¶
3.1 セキュリティ¶
- API パスワード・トークンはログに生で出力しない(
***マスクまたは末尾 4 文字のみ) caplogに token / API パスワード / 取引パスワードが出力されないことをテストで確認DEV_KABU_API_PASSWORDは Python 側kabusapi_login_flow.pyのみが読む- release ビルドでは自動ログインを禁止(Python 側でガード)
3.2 接続・再接続¶
- kabuステーション本体(Windows)が起動していることが前提(TCP 接続失敗 =
ConnectionRefusedError) - 本体プロセス落ち:
ConnectionRefusedError→ 5s backoff × 3 回 →VenueError{code:"local_app_down"} - WebSocket 再接続失敗: 5s × 5 回連続失敗 →
VenueError{code:"local_app_down"}再発火 - 再接続後は RegisterSet 全件を
PUT /registerで再登録(サーバ側保持に依存しない)
3.3 PUSH 銘柄登録上限¶
- PUSH 銘柄は REST/PUSH 合算 50 銘柄上限
- RegisterSet の LRU で枠管理。51 件目は
KabuRegisterFullErrorを投げユーザーに通知 GET /boardが自動的に PUSH 登録を発火するため、fetch_board()内でRegisterSet.touch()を必ず呼ぶ
3.4 流量制限¶
- 発注系: 5 req/sec (
OrderBucket) - 余力系: 10 req/sec (
WalletBucket) - 情報系: 10 req/sec (
InfoBucket) async with bucket:で事前抑制が原則。サーバから4002006が返ったらバックオフリトライ
4. 受け入れ条件(Phase 1 完了の定義)¶
cargo check --workspace/cargo clippy --workspace -- -D warnings/cargo fmt --check全通過cargo test --workspace全通過(kabu 関連 Rust test を含む)uv run pytest python/tests/test_kabusapi_*.py python/tests/test_live_session_kabu.py全通過- 9 つのテストファイル(roadmap 参照)が実在し、各代表 assert を満たす
- K8.5 URL リテラル lint が CI(
.github/workflows/kabu-mock.yml)で強制されている LiveSession.login(venue="kabu_station", ...)がVenueReadyを発火する E2E が pass- WS 再接続 5s × 5 回打ち切り / RegisterSet 全件 re-register / SubscriptionEvicted 通知等の 不変条件テストが pass
kabusapi 共通 hook(live-strategy.md に統合予定)¶
以下は kabu venue 固有ではなく venue 横断の抽象契約に属するため、docs/specs/live-strategy.md(tachibana エージェント担当)への統合候補。具体本文は docs/roadmap/kabusapi/_live-strategy-additions.md に切り出し済み。
- IPC venue キー文字列の命名規則(
"kabu_station"等、Rust enum との整合) RequestVenueLogin/VenueLoginStarted/VenueLoginCancelled/VenueReady/VenueErrorのライフサイクルVenueError.code共通予約値("token_expired"/"local_app_down")の意味と再ログイン誘導フロー- venue 横断の credential 取り扱い原則(Python メモリのみ、Rust 経路に流さない、ファイル永続化禁止)
- ログイン UI は Python tkinter subprocess に統一(Rust にダイアログコード非搭載)
Ready.capabilities.venue_capabilities[<venue>]への capability キー追加プロトコルSubscriptionEvicted{symbol}通知の汎用契約(PUSH 上限ある venue の共通インターフェース)
Phase 1 完了ノート(2026-05-09 時点)¶
§4 の受け入れ条件はすべて満たされています。完了後に以下の post-fix バグが修正されました:
- Issue #35 (
kabusapi_rest.py/kabusapi_ws.py/server.py): kabu ログイン済みでもラダーが "Waiting for data..." のまま — 3 層のサイレント障害を修正 - Issue #36 (
handlers/dashboard.rs/handlers/venue.rs): VenueReady 受信時にGetBuyingPower/GetPositionsコマンドが送信されなかった - Issue #37 (
handlers/dashboard.rs/handlers/venue.rs/main.rs): kabu ログイン中に BuyingPower / Positions ペインを後から追加しても auto-fetch が発火しなかった
Phase 2 状況(2026-05-09 着手)¶
§2.2「含めないもの」に列挙した「発注・取消」のうち、以下が Issue #25/#33/#34 で着手されました:
- 注文パネル venue トグル(Rust フロントエンド): OrderEntry / OrderList / BuyingPower / Positions タイトルバーに 立花 / kabu トグルボタンを実装。両 venue が Ready のときのみ表示
- 注文 venue ルーティング(Python バックエンド):
server.pyが選択 venue に応じて注文を振り分け
実弾発注(
POST /sendorder)・取引パスワード収集 UI 等の残スコープは引き続き Phase 2 完了待ち。