Pythonで日本株の投資支援・自動売買ツールを自作しています。
前回は、三菱UFJ eスマート証券のAPIから取得した市場データを実際の売買へ使うことを想定し、
- 二重注文を防ぐ
- 古い株価では注文しない
- 注文結果が分からない場合は再送しない
- 証券会社と自分の記録が違えば止める
- 人間が承認した注文にも有効期限を付ける
といった安全対策を実装しました。(前回記事:株の自動売買を実運用する前に安全対策を実装|二重注文・異常データをどう防ぐ?)
しかし、これだけではPaper Tradingを始めるには不十分です。
次に考える必要があったのが、
「いくらまで注文してよいのか」
という資金管理でした。
100万円の仮想資金があるからといって、100万円すべてを1銘柄に投入してよいわけではありません。
さらに、
- 未約定の注文をどう扱うか
- 1日の損失が大きくなったらどうするか
- システムに異常が起きたらどう止めるか
といったルールも必要です。
そこで今回は、実際のお金を使わないPaper Tradingへ進む前に、
資金管理・損失上限・緊急停止
の仕組みを作りました。
Paper Tradingは100万円から始める
最初のPaper Tradingでは、仮想資金を
100万円
に設定しました。
実際に運用するときの条件も、かなりシンプルにしています。
- 仮想資金:100万円
- 現物取引のみ
- 100株単位
- 1銘柄への投資は資金の50%まで
- 総投資額は資金の90%まで
- 現金を10%以上残す
- 同時保有は最大2銘柄
- 1日の損失が2万円に達したら新規BUY停止

まだ利益を最大化するための設定ではありません。
まずは、
「システムが資金を正しく管理できるか」
を確認するためのルールです。
100万円あるからといって100万円使えるわけではない
資金管理を作る中で、最初に問題になったのが未約定注文です。
例えば、口座に100万円あるとします。
ここで40万円分の買い注文を出しました。
しかし、まだ約定していなければ、実際の現金残高は100万円のままです。
単純に現金だけを見ていると、
「まだ100万円使える」
と判断できてしまいます。
その状態で別の40万円、さらに40万円の注文まで許せば、
40万円+40万円+40万円=120万円
となり、実際に持っている資金を超える注文を作れてしまいます。
そこで、まだ約定していないBUY注文についても、
すでに使う予定の資金
として予約する仕組みを追加しました。
50万円のBUY注文を出した時点で、その50万円は別の注文には使えません。
注文が約定する、キャンセルされるなどして状態が確定したときに、予約された資金も更新します。
資金チェックと注文処理の間にも事故は起こる
もう一つ考える必要があったのが、同時処理です。
例えば、
- 資金が足りているか確認
- 注文用の資金を確保
- 注文処理へ進む
という流れがあったとします。
2つの処理がほぼ同時に動くと、
両方が①の時点で、
「資金は十分ある」
と判断してしまう可能性があります。
そこで、
資金チェック → 資金予約 → 注文処理の確定
を途中で別の処理が割り込めない形で扱うようにしました。
単に「残高が足りているか」を確認するだけではなく、
その資金を本当にこの注文へ割り当てられるか
まで管理する仕組みです。
1日2万円負けたら新しいBUYを止める
資金管理と合わせて、1日の損失上限も設定しました。
今回のPaper Tradingでは、
1日 -20,000円
を基準にしています。
100万円に対して2%です。
判定に使うのは、売却して確定した損失だけではありません。
当日の実現損益+現在保有している株の含み損益
で判断します。
例えば、
- 実現損益:-10,000円
- 含み損益:-10,000円
なら、合計は
-20,000円
です。
この時点で、その日の新しいBUYを停止します。
株価が戻っても、その日は取引を再開しない
ここで少し悩んだのが、
損失が一度2万円に達したあと、株価が戻ったらどうするか
です。
例えば、
- -19,999円 → BUY可能
- -20,000円 → BUY停止
- その後 -10,000円まで回復
となった場合です。
現在の設計では、
-10,000円まで戻っても、その日はBUYを再開しません。
一度その日の損失上限に到達したという事実を保持します。
これは、損失ライン付近で、
停止 → 再開 → 停止 → 再開
を繰り返さないためです。
大きく負けた日に、取り返そうとしてさらに取引を増やすことも避けられます。
翌営業日になれば、改めてその日の取引として判断します。
損失上限に達しても「何もできない」わけではない
ただし、-20,000円に到達した瞬間にすべての操作を禁止するわけではありません。
止めるのは、
新しいリスクを増やす操作
です。
例えば新規BUYは停止します。
一方で、
- 保有株のSELL
- 未約定注文のキャンセル
- 証券会社との状態確認
など、リスクを減らしたり状態を確認したりする処理は継続できます。
損失が大きくなったからといって、保有株を売ることまで禁止してしまえば、逆にリスクを増やす可能性があるためです。
Kill Switchも実装した
Daily Lossとは別に、
システムそのものに異常が発生した場合の停止機能
も作りました。
いわゆるKill Switchです。
例えば、
- 注文を送信できたか分からない
- キャンセルできたか分からない
- 証券会社と自分の記録が一致しない
- 認証で異常が発生した
- 保存している状態に問題がある
といった場合です。
こうした状態で新しい注文を続けると、二重注文や想定外のポジションにつながる可能性があります。
そのため異常を検知した場合は、
新しいリスクを取る処理を停止
します。
Kill Switchだからといって全株売却はしない
最初は、
「異常が起きたら全部売れば安全なのでは?」
とも考えられます。
しかし、実際にはそう単純ではありません。
例えば、
証券会社へ注文が届いたか分からない
という異常が起きているとします。
この状態で自動的に保有株を成行売却しようとしても、その売却注文自体が正常に処理される保証はありません。
むしろ状態が分からないまま新しい注文を追加することになります。
そこで今回のKill Switchでは、
異常発生=全株を自動的に成行売却
にはしていません。
まず、
新しいリスクを増やさない。
そして状態を確認する。
前回の安全対策から続いている、
「分からない状態を推測で処理しない」
という考え方です。
再起動しても勝手に復旧しない
もう一つ重要なのが再起動です。
システムで異常が発生したあと、
「とりあえず再起動すれば元通り」
では困ります。
異常の原因が解決していないのに再起動だけで取引可能になれば、Kill Switchの意味がありません。
そこで停止状態も保存するようにしました。
異常によって取引が停止した場合、PCやプログラムを再起動しても自動的には解除されません。
状態を確認したうえで、
人間が明示的に再開する
必要があります。
日本株用のPaper取引も見直した
資金管理とSafetyを作る中で、Paper Trading側にも一つ問題がありました。
これまで使っていた汎用的なテストでは、
100株注文 → 40株約定 → 残り60株
のような状態も再現できました。
注文管理のテストとしては便利です。
しかし、今回想定している日本株の運用は100株単位です。
そこで日本株向けのPaper取引では、
100株注文なら100株
200株注文なら、
100株+100株
という単元株単位で扱うようにしました。
汎用的なテスト機能は残したまま、
日本株Paper Trading用の仕組みを別に用意する
形にしています。
再起動してもPaper口座を復元できるようにした
Paper Tradingだからといって、プログラムを終了するたびに100万円へ戻ってしまっては検証になりません。
そこでPaper側でも、
- 現金
- 保有株
- 平均取得価格
- 実現損益
- 含み損益
- 注文のために予約している資金
などを保存します。
プログラムを再起動しても、前回の状態から続けられるようにしました。
さらに、同じ約定情報を誤ってもう一度処理しても、
現金や保有株が二重に更新されない
仕組みも追加しています。
正常系だけでなく「壊れ方」もテストした
今回も、正常にBUYしてSELLできることだけを確認したわけではありません。
例えば、
- 未約定注文が残っている
- 200株が100株ずつ約定する
- 同じ約定情報がもう一度届く
- 注文結果が分からない
- キャンセル結果が分からない
- 再起動する
- 証券会社との状態が一致しない
- 古い市場データが渡される
- 損益情報が欠けている
- 1日の損失上限ちょうどに到達する
- 資金上限に達する
- 緊急停止状態になる
- 承認の有効期限が切れる
- 日本株なのに40株だけ約定する
といったケースも確認しました。
最終的な回帰テストでは、
656 tests PASS
まで到達しています。
単純にテスト件数を増やすことが目的ではなく、
正常に動くかではなく、異常が起きたときに危険な方向へ進まないか
を確認するためのテストです。
これでPaper Tradingを開始できる……わけではなかった
ここまでで、
- 仮想資金100万円
- 1銘柄50%まで
- 総エクスポージャー90%まで
- 現金10%以上
- 最大2銘柄
- 未約定BUYの資金予約
- 1日-20,000円で新規BUY停止
- Kill Switch
- 再起動後の状態復元
- 日本株100株単位のPaper取引
まで作りました。
資金管理と安全装置という意味では、かなり形になってきました。
しかし、ここでもう一度全体を確認すると、
まだ正式なPaper Tradingを開始する段階ではありませんでした。
個々の部品は揃ってきましたが、
日足データ → AIの売買判断 → 人間による確認 → 仮想注文
という一連の流れを、正式なPaper Tradingとして一本につなぐ必要があります。
さらに調べていくと、
バックテストでAIが見ていた株価と、実際の注文金額を計算する株価を同じように扱ってよいのか
という新しい問題も見つかりました。
次回は、
AIの判断から仮想注文までをつなぐPaper Runner
を作ります。
そこで、
- 日本市場の営業日判定
- 完成した日足だけをAIへ渡す仕組み
- 分析用株価と実際の注文価格の使い分け
- 市場データの有効期限
- Human Approval
- 注文直前のSafety再確認
を一つにつなぎ、
AIが出した候補を、人間が確認して仮想注文として送信できるところ
まで進めます。
まとめ
前回までは、
「異常な状態で注文しない」
ためのSafetyを中心に作ってきました。
今回はその上に、
「そもそも、いくらまで注文してよいのか」
という資金管理を追加しました。
Paper Tradingの初期条件は、
- 仮想資金100万円
- 現物・100株単位
- 1銘柄50%まで
- 総エクスポージャー90%まで
- 現金10%以上
- 最大2銘柄
- 1日-20,000円で新規BUY停止
です。
さらに、未約定注文にも資金を予約し、損失上限へ一度到達した日は新規BUYを再開しないようにしました。
システム異常時についても、
「何かあったら全部売る」
のではなく、
「状態が分からないなら、まず新しいリスクを止める」
設計にしています。
自動売買ツールを作り始めたころは、売買シグナルを出すことが中心でした。
しかし実運用へ近づくほど、
何を買うかより先に、いくらまで買ってよいか、そしていつ止まるべきか
を決める必要があることが分かってきました。
次は、ここまで作った安全装置の上にPaper Runnerを構築し、AIの売買判断から仮想注文までを一本につなげます。(続編記事:AIの売買判断から仮想注文まで。日本株Paper Tradingの仕組みをつないでみた)
自動売買ツール開発の現在地
バックテスト・売買ルールの検証
✓ 完了
↓
証券会社API・実際の市場データ取得
✓ 完了
↓
誤発注・異常データ・セキュリティ対策
✓ 完了
↓
資金管理・損失上限・緊急停止機能
✓ 今回ここまで
↓
AI判断から仮想注文までのPaper Runner構築
→ 次回
↓
実市場データを使った仮想約定
↓
正式なPaper Trading
↓
少額で、注文前に自分で確認する実運用
↓
実運用の結果を確認しながら段階的に自動化



コメント