kabusapiを使った仮想証券会社を作る
売買機能を持ってる投資ツールを作ってると、絶対に仮想証券会社が必要になる。
これを毎回ツールに組み込んで開発すると割とコストが高いから、
自前で仮想証券会社を作って建てちゃうのが良い。
ただkabusapiを利用する場合はちょっと難しくて、
pushで取れる価格は50銘柄とか、
restで価格を取ろうとしても1銘柄当たり最悪数秒かかるとか、
大量の銘柄を自由に扱うのは困難。
しかも、複数ツールが同時に立ち上げる場合は、
tokenを共有して使わないといけないとか、認証の制約も少なくない。
ってことで、その辺を解決しながら、kabusapiを使った仮想証券会社を作る。
複数のツールを同時に動かす際の問題
kabusapiには複数ツールを動かすうえでの問題がいくつかある
アクセストークンを同時に1つしか発行できない
複数ツールからアクセストークンを発行すると古いものは破棄されるため、常に1つのツールしかアクセスできない
websocketが同時に1つしか接続を作れない
これは試してないけど、そうらしい。pushで価格を得たい場合、ツールは1つしか使えない
登録銘柄一覧が取得できない
銘柄登録一覧が取得できないため、今どの銘柄が登録されているか、他のツールが登録したのか自分で登録したのかなどが把握できず、複数ツールを動かした際に追加すべきか消していいかが分からない
銘柄の価格情報をRESTで取ろうとすると、登録銘柄に登録すべき
登録銘柄に登録されている銘柄についてはkabuステーションで価格を取得する仕組みになっているので、価格情報が欲しければ銘柄登録に追加するしかない
が、上記の銘柄登録一覧が取得できない問題にぶつかる
などなど。
ってことで、これらをまとめて管理する何かが必要になります。
Go + gRPCで作ったサーバを建てて、そこからkabusapiを叩くようにしようと思います。
これが無いことには複数ツールを同時に動かすのが難しいので、仮想証券会社に着手するのは後回し。
仮想証券会社で必要な機能
価格情報の登録
注文の登録
注文一覧
建玉一覧
注文取消
登録した価格情報をもって仮想証券会社は約定確認し、注文の状態やポジションの状態を更新していく。
基本的に受け取る情報はkabusapiで指定できるものと一致させる。
ただ、口座とか、財布に依存するものは確認のしようがないからしない。
他にも価格とか数量のバリデーションもしない。
DBを使ってもいいけど、まずはメモリ上に展開する程度にとどめるつもり。
main関数を持たないライブラリとして開発する。
仮想証券会社の一部を別のコンテキストとして開発するって思想。
これらを現物、信用、先物、オプションと作る。
とりあえず現物、信用からでいいかな。次に先物。オプションは触ったことないからそこまで作るか分からない。
約定
約定処理はいくつかのステップからできている。
約定可能かのチェック
約定価格の決定
注文状態の更新
約定可能かのチェック
約定にはいくつもの要素が絡む。
執行条件
時刻(タイミング)
現値や気配値
スタンダードな成行だけを表にする
table:成行の約定チェック
執行条件 タイミング 現値 気配値 約定可能
成行 寄り あり あり 可能
あり なし 可能
なし あり 可能
なし なし 不可能
ザラバ あり あり 可能
あり なし 不可能
なし あり 可能
なし なし 不可能
引け あり あり 可能
あり なし 不可能
なし あり 可能
なし なし 不可能
寄りや引けでは全ての注文が同じ価格で約定する。
つまり、価格が1つであるということなので、気配値ではなく現在値が必要。
ただし、実際の市場では寄り引けで約定しないこともあるので、その場合は板で約定する。
ザラバでは基本的に気配値があれば約定できる。
現在値があっても気配値がなければ、板に反対の売買がないということなので、約定できない。
タイミングの話になると、寄り、ザラバ、引けをどう判断するのか。
寄りはそのセッションで最初の現在値が寄り付きの価格になる。
9時丁度に寄りが発生する可能性もあるし、11時に最初の約定が発生して寄りが発生する可能性もある。薄い板なやつですね。
ってことで、寄りは最初の現在値。
じゃあ引けは?というと、前場の引けは11:30。実際に引け価格がくるのはそっから2, 3秒後。
11:30直前のザラバと11:30直後の引けの違いって判断が難しい。
もう仕方がないから現在値時刻が11:30以降のものを採用しようとする。
ただ、実市場では約定しないこともある。となると、それっぽい処理をするしかない。
とまあ、比較的単純な成行でもこれ。
指値とかIOCとか不成とか、より複雑なものはいっぱいある。
約定価格の決定
約定価格の決定には下記パターンを分けて考えないといけない
執行条件
タイミング
初回約定確認か、そうでないか
執行条件は言わずもがな、タイミングは寄りザラバ引け。
初回約定確認かどうかは、指値の場合に関わってくる。
指値は注文すると同時にまず板と突き合わせる。
その時点で約定可能なら、成行のように約定する。
すぐに約定しないなら、板に並ぶことになる。
また板に並んだ指値は、楽観的約定と悲観的約定がある。
楽観的約定は板の中で先頭に並んでいると考えるもので、現在値が指値と重なった瞬間に約定する。
悲観的約定は板の中で最後尾に並んでいると考えるもので、最良気配が指値を通り過ぎて初めて約定する。
どちらが良いというのはないが、楽観的の場合デモより実売買の成績が悪くなり、悲観的の場合デモより実売買の成績が良くなる。
楽観的だと誤った戦略のまま実売買を始める恐れがあり、悲観的だと有効な戦略を捨てる恐れがある。
僕は基本的に悲観的約定を採用する。
注文状態の更新
注文状態として更新されるのは下記
状態
初回約定確認済みか
約定一覧
仮想証券会社は実板を持っているわけじゃないので、約定するときは必ず全約定になってしまう。
なので部分約定を懸念する必要がないが、それでも状態遷移は発生する。
状態は、新規、注文中、全約定、取消中、取消済み、など。
初回約定確認済みかは指値の動きに必要なため。
約定一覧は基本的に全約定なのであまり重要ではないが、約定した際にその約定でどんなポジションが発生したのかを保持する。
これらは状態の更新が発生するため、約定確認とは別処理にしておくべき。
ただし、初回約定確認済みかどうかだけは、約定確認のタイミングで行なわれることになる。
とまあ、ここまで約定確認、約定価格、約定状態更新と書いたけど、
どれも全力で取り組むとかなり大きな仕組みになってしまう。
簡素化できるところは簡素化しなくてはいけないし、
手を抜いてはいけないところは手を抜かないようにしなくてはいけない。
うん、難しい。
どう実装するか
オブジェクト指向でプログラミングしていると再利用したくなるけど、
まずは泥臭く重複など気にせずごりごり実装していく。
テスト駆動でも登場するけど、まずは動くもの、リファクタリングは後回し。
執行条件ごと、タイミングごと、価格情報など、
とにかく地道に約定する条件をコーディングしていく。
複雑度の高いものは頭で考えて最初からきれいに書こうとするとどこかで失敗するか動くものが作れないかになる。
大まかには完成
まだ修正すべき点はあるし、信用とか先物取引に対応できていないけど、
最低限の機能は実装できたと思う。
これからこの機能をapiとの中継器に実装し、動作させていく。
更新履歴