ライブ戦略 venue 横断契約¶
status: proposed — 本ドキュメントは venue 横断の抽象契約をまとめる新規スケルトンであり、内容は各 venue spec から抽象化される過程にある。tachibana / kabusapi / 暗号資産 venue のいずれもこの契約に従う前提で実装されているが、文書としての整合化は移送後の継続課題。
1. 目的¶
「ライブ戦略 = 実 venue(broker / 取引所)に対して subscribe / fetch / 認証を行うモード」全般に共通する抽象契約を、venue 固有 spec から切り出して 1 箇所に集約する。venue 固有事情は各 docs/specs/venues/<venue>.md 側に置き、本書はそこからの参照のみを持つ。
2. 契約の構成要素(スケルトン)¶
2.1 VenueState FSM¶
Idle / LoginInFlight / Ready / Error の 4 状態を持つ単一 enum。venue ごとの実 state 機械は src/venue_state.rs::VenueState を共通利用する。
- 状態遷移の DTO 名は
VenueLoginStarted/VenueLoginCancelled/VenueReady/VenueError(Python engine event)。 - UI 側の状態管理は
VenueState::{Idle/LoginInFlight/Ready/Error}1 本化。 - 詳細な遷移表と冪等性の規約は各 venue spec の「セッション寿命と復旧」節に記載。
2.2 venue-ready ゲート¶
- venue の業務リクエスト(
ListTickers/GetTickerMetadata/FetchTickerStats/Subscribe)はVenueReady受信後にのみ送ってよい。 VenueReadyは冪等イベント。Python サブプロセス再起動検知時のみ Rust 側が状態をリセットし、active subscriptions を 1 度だけ resubscribe する。- 詳細な timeout / cache / bridge 規約は
engine-client/src/process.rs::ProcessManagerを一次ソースとする。
2.3 VenueError DTO 形状¶
codeは UI 側の severity 判定とアクションボタン出し分けにのみ使う。messageは Python 側 venue コードが詰めた user-facing 文言を Rust UI がそのまま描画する。- venue 固有
code一覧と severity マッピングは各 venue spec の「失敗モードと UI 表現」節を参照。
2.4 認証ライフサイクル¶
- runtime 中の自動再ログインは禁止(再ログインは「ユーザー明示」操作が起点のときだけ許可)。
- アプリ起動直後の session 復元フェーズに限り、復元 session の validate が失敗した場合の再ログインを 1 回だけ許可する。
- 「自動」と「手動(ユーザー明示)」の境界判別基準は
Command::RequestVenueLoginの受信を起点とするか否かで分ける。
2.5 Strategy SDK 接点¶
ユーザー戦略(Strategy)が live モードで venue とやり取りする際の境界。本節は別 spec(docs/specs/strategy-sdk.md)と相互参照。
3. venue 固有 hook¶
3.1 tachibana¶
venue 固有の契約は docs/specs/venues/tachibana.md を参照。本書の 2.1〜2.4 はすべて tachibana の旧 spec.md の決定事項を venue 横断に抽象化したものであり、tachibana 側の実装規約(FD frame quote rule / p_errno=2 検知 / dead-frame timeout / banner code 一覧)はそちらで完結する。
3.2 kabusapi¶
kabusapi 共通 hook(docs/specs/live-strategy.md 追記断片)¶
本ファイルは tachibana エージェントが Wave 4 で作成する docs/specs/live-strategy.md に append すべき、kabusapi venue 由来の venue 横断抽象契約 を切り出したもの。本ファイル単独では参照されず、Wave 4 で統合された後は内容が docs/specs/live-strategy.md 側に同化する。
A. IPC venue キー命名規則¶
- IPC
venueフィールド文字列は RustVenue::*enum と 1:1 対応するsnake_case。 - kabuステーション venue の場合: Rust
Venue::KabuStation↔ IPC"kabu_station"。 - 立花 venue 同様、
Venue::from_strで受理し、未知 venue は明示的に reject する。 - venue 文字列追加時は SCHEMA_MINOR bump が必要。
B. venue ログイン共通ライフサイクル¶
| IPC メッセージ | 方向 | 発火タイミング |
|---|---|---|
RequestVenueLogin{venue} |
Rust → Python | GUI から「ログイン」ボタン押下 |
VenueLoginStarted{venue} |
Python → Rust | startup_login 開始時 |
VenueLoginCancelled{venue} |
Python → Rust | ユーザーがダイアログをキャンセル |
VenueReady{venue} |
Python → Rust | 認証完了(トークン取得など) |
VenueError{venue, code, message} |
Python → Rust | エラー検出時 |
すべての venue でこの遷移を満たすこと。
C. VenueError.code 共通予約値¶
| code | 意味 | 期待挙動 |
|---|---|---|
"token_expired" |
トークン失効。retry 失敗時にこの code を発火 | tkinter 再ログインダイアログへ誘導。自動再ログインは禁止(ユーザー入力を伴う) |
"local_app_down" |
venue 提供アプリ(kabuステーション本体等)が落ちている / 接続不可 | 5s × N 回のバックオフ retry 後に発火。早朝強制ログアウト窓では INFO 扱い |
新 venue 追加時はこの命名空間衝突を test_schema_compat.py で検証する。
D. credential 取り扱い原則¶
- API パスワード / トークン / 取引パスワードは Python メモリのみ に保持し、Rust 経路に流さない。
- ファイル永続化禁止(kabusapi はトークン短命、立花は session cache あり等、venue 毎に差異)。
caplogに credential が出ないことをテストで確認(venue ごとにtest_*_logging.pyを持つ)。- debug env は venue prefix 付き:
DEV_TACHIBANA_*/DEV_KABU_*。
E. ログイン UI は Python tkinter subprocess に統一¶
- Rust にダイアログコードを書かない。
- subprocess 隔離(メイン engine プロセスをフリーズさせない)。
- 取引パスワード(取消/発注時)の収集 UI も同じ方式に揃える。
F. capabilities キー追加プロトコル¶
Ready.capabilities.venue_capabilities[<venue>]に venue 別 capability dict を追加する。- 必須キー候補:
requires_local_app: bool/max_push_symbols: int|null/supports_amend: bool/requires_trade_password_for_cancel: bool/is_production: bool。 - 数値の一次ソース(例: PUSH 上限)は venue spec ファイルに置き、Rust 定数 / Python 定数と 1:1 一致を invariant test で保証する。
G. SubscriptionEvicted{symbol} 共通通知¶
- PUSH 銘柄上限のある venue(kabuステーション = 50 上限)で LRU evict が発生したとき、
SubscriptionEvicted{symbol}を IPC で送出する。 - UI は当該 symbol のチャートに「再登録が必要」バナーを表示する。
- 立花 venue は現状上限なしのため発火しないが、将来 venue 追加時の共通契約として定義する。
H. URL リテラル所在原則¶
- 各 venue の API URL リテラルは Python 側 1 ファイル(kabusapi なら
kabusapi_url.py、立花ならtachibana_url.py)に集約。 - Rust / engine-client / その他 Python ファイルへの URL リテラル漏出は CI lint で阻止。
localhost:18080本番 /localhost:18081検証など環境別 base URL もこのファイルでのみ定義。
4. 出典¶
docs/specs/venues/tachibana.md(旧docs/specs/venues/tachibana/spec.md、source_commit: 236c0d2)src/venue_state.rsengine-client/src/process.rs::ProcessManagerengine-client/src/dto.rs::EngineEvent::{VenueReady, VenueLoginStarted, VenueLoginCancelled, VenueError}