実際に売買BOTを稼働させたり、バックテストを行う際には、以下の売買注文をしなければなりません。
・注文のシグナルが出たら「買いor売りの注文を出す」
・手仕舞いのシグナルが出たら「ポジションを決済する」
この売買ができなければ、手動操作をシュミレートしてBOTに売買をしてもらう事はできませんからね。
実際にこれらの操作をプログラムに行ってもらうために、どの様に実装をしていけば良いのかについて解説します。
コンテンツ
注文と手仕舞いの考え方
売買注文や手仕舞いを実装する時には、なるべくシンプルで分かりやすい形でプログラムに落とし込んでいく必要があります。
そのために、最低限のルールを決めておきましょう。
シグナル判定・注文・手仕舞いは関数化する
さて、関数化の方法は覚えているでしょうか^^
■Pythonで作る関数のサンプル
1 2 3 4 5 6 7 |
#関数「test_func」を定義 def test_func(a,b): ret = a + b return ret print(test_func(1,2)) #3が返り値 |
サンプルコードでも何度も使用しているので大丈夫だと思いますが、シグナルを判定したり売買注文は全てmainの中で行うのではなく専用の関数を作りましょう。
ざっくりと売買に必要な関数を挙げると、
・買い注文を入れる関数
・売り注文を入れる関数
・注文一覧を取得する関数
・約定したかを確認する関数
・買い注文を手仕舞いする関数
・売り注文を手仕舞いする関数
・その他(注文をキャンセルする関数など)
買い注文と売り注文の関数は同じにしてしまってもOKです。ただし、売買ロジックが、買いと売りで少しでも異なる場合は関数を分けるか、関数に渡す引数で明確な処理の切り分けができる様にしましょう。
これらの関数をmain処理から何度も呼び出し、それぞれの関数を通りながら、現在やるべき事をプログラムに実行してもらう。という流れになります。
状態を管理する変数を設定
上記で紹介しただけでも、通過しなければならない関数がいくつもある事が分かります。しかし、各関数の中で行う処理&処理結果は、main処理の中で把握しておかなければなりません。
その情報を保持しておく変数を作成しましょう。例えば、以下の様に変数を定義しておきます。
■変数の定義
変数名 | 論理名 ※プログラム中の名称 |
変数の値 |
買い注文フラグ | order_buy_flag | 初期値、買いポジション保持中:0 買い注文のシグナルが出た:1 |
売り注文フラグ | order_sell_flag | 初期値、売りポジション保持中:0 売り注文のシグナルが出た:1 |
買いポジションフラグ | position_buy_flag | 買いポジションを保持していない:0 買いポジション保持中:1 |
売りポジションフラグ | position_sell_flag | 売りポジションを保持していない:0 売りポジション保持中:1 |
買いポジション手仕舞いフラグ | close_buy_flag | 買いポジションの手仕舞いシグナルが出ていない:0 買いポジションの手仕舞いシグナルが出た:1 |
売りポジション手仕舞いフラグ | close_sell_flag | 売りポジションの手仕舞いシグナルが出ていない:0 売りポジションの手仕舞いシグナルが出た:1 |
未約定注文フラグ | no_order_flag | 未約定の注文が存在しない:0 未約定の注文が存在する:1 |
変数は必要に応じて追加・削除してOKです。また、当然ですが変数名は好きな名前を付けてOKです。
Python上では以下の様にして変数を定義すればOKです。
※trade_infoという変数に各フラグの内容を詰め込んでいます。
■Pythonコード
1 2 3 4 5 6 7 8 9 |
trade_info = { "order_buy_flag": 0, "order_sell_flag": 0, "position_buy_flag": 0, "position_sell_flag": 0, "close_buy_flag": 0, "close_sell_flag": 0, "no_order_flag": 0 } |
なぜ買いと売りを分けるのか?
サンプルの変数では、わざわざ買いと売りのフラグを使い分けています。
買い注文と売り注文は結局同じ注文なのだから、同じフラグにしても良さそうなものです。
しかし、トレードのアルゴリズムによっては買いと売りではルールが異なる事があるのです。
※上昇トレンドなのか?下降トレンドなのか?による違いが一番分かりやすいと思います。
ですから、ここでも買いと売りで変数名を分けています。アルゴリズム上、一緒の変数にしても問題ないな~という事であれば、一緒にしてしまってもOKです。逆に使わないけど、後々のために分けておくか~というのもOKです。
売買ロジック
次に、具体的に売買する関数の中身を考えておきましょう。
売買注文
まずは売買注文に関する関数や処理を解説します。
注文をする
当然ですが、トレードを行うためにはまずは注文をしなければなりません。
上述した様に、
・買い注文を入れる関数
・売り注文を入れる関数
の関数を作成しましょう。
注文を行うための関数を呼び出す際には条件を作っておく必要があります。それがシグナルを判定する関数の結果判定です。
買い注文を入れる関数を呼ぶ際には、「買い注文が出たら」を条件にする必要があります。
※ccxtの場合は「create_order」関数で注文できます
注文が通った事を確認する
注文をしたら、注文が通った事を確認しましょう。
もしも一定時間経過しても注文が通っていない場合は、サーバーのリクエストエラーになっているケースもありますので、エラー判定ができる様にします。
注文が通っているかどうかは「注文一覧の取得」で確認可能です。「注文一覧の取得」はAPIを公開している取引所であれば、専用の関数を用意しているはずですので、それを活用しましょう。
※ccxtの場合は「fetch_open_orders」関数で未約定の注文の一覧を取得できます。
約定確認
実際に注文が通ったら、「約定」している事を確認する必要があります。
注文=約定という前提でその後の処理を行うと、処理の整合性が取れなくなってしまいます。
なので、約定しているかどうかを確認して、
⇒約定していたら「現在ポジションを持っている」
⇒未約定であれば「まだポジションを持っていない」
というステータスである事を、プログラム内の変数で管理しておきましょう。
手仕舞い処理
現在ポジションを持っている場合、手仕舞いをしなければなりません。
その手仕舞いのタイミングでトレード1回分の、
・利益が出る(勝ち)
・損失が出る(負け)
のいずれかが確定します。
手仕舞いと言っても、実際には注文処理と同じ事をしています。
・買いポジションを持っていたら、売りで手仕舞いする
・売りポジションを持っていたら、買いで手仕舞いする
という点だけ注意すればOKです。
その他
売買条件によっては当然これまでにお伝えした以外の処理も必要になります。
現在買いポジションを持っていても、さらに買い増しをするケースなどもあると思います。ただし、まずは基本的な売買ロジックだけをしっかりと身につけておきましょう。
基本の部分が分かっていれば、後から必要な部分だけ柔軟に追加・修正する事はそんなに難しい事ではありません。
注文&手仕舞いの処理イメージ
では、実際のプログラムをイメージしながら、注文&手仕舞いの処理を行ってみましょう。
まだまだ実際の処理とはほど通いのですが、ざっくりとイメージを掴むだけでOKです。
■処理の流れ
1)変数を定義
2)売買判定を行う(シグナルを出す)
3)買い注文を入れる(注文が通ったか、約定したかを確認)
4)手仕舞いの判定
5)手仕舞いをする
というこれだけの処理ですが、簡単なプログラムにするだけで少しイメージが湧きます。
■Pythonコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#変数を定義 trade_info = { "order_buy_flag": 0, "order_sell_flag": 0, "position_buy_flag": 0, "position_sell_flag": 0, "close_buy_flag": 0, "close_sell_flag": 0, "no_order_flag": 0 } #設定 print("売買シグナルの判定") trade_info["order_buy_flag"] = 1 #ロジック if trade_info["order_buy_flag"] == 1: print("買い注文実行") trade_info["no_order_flag"] = 1 print("注文が通った") trade_info["no_order_flag"] = 0 print("注文が約定した") trade_info["position_buy_flag"] = 1 if trade_info["order_sell_flag"] == 1: print("売り注文実行") trade_info["no_order_flag"] = 1 print("注文が通った") trade_info["no_order_flag"] = 0 print("注文が約定した") trade_info["position_sell_flag"] = 1 if trade_info["position_buy_flag"] == 1: print("手仕舞いシグナルの判定") print("買いポジションの手仕舞いシグナルが出た") trade_info["close_buy_flag"] = 1 if trade_info["position_sell_flag"] == 1: print("手仕舞いシグナルの判定") print("売りポジションの手仕舞いシグナルが出た") trade_info["close_sell_flag"] = 1 if trade_info["close_buy_flag"] == 1: print("売り注文(手仕舞い)実行") print("注文が通った") print("注文が約定した") if trade_info["close_sell_flag"] == 1: print("買い注文(手仕舞い)実行") print("注文が通った") print("注文が約定した") |
■実行結果
1 2 3 4 5 6 7 8 9 |
売買シグナルの判定 買い注文実行 注文が通った 注文が約定した 手仕舞いシグナルの判定 買いポジションの手仕舞いシグナルが出た 売り注文(手仕舞い)実行 注文が通った 注文が約定した |
■実行結果(売り注文「trade_info[“order_sell_flag”] = 1」の場合)
1 2 3 4 5 6 7 8 9 |
売買シグナルの判定 売り注文実行 注文が通った 注文が約定した 手仕舞いシグナルの判定 売りポジションの手仕舞いシグナルが出た 買い注文(手仕舞い)実行 注文が通った 注文が約定した |
■簡単な解説
プログラム上はprint文を出力しているだけなので、全然大した事はしていません^^;
ただ、各print文を出力している箇所に、実際の処理(関数)を入れる様にしたら、いかがでしょうか?trade_infoの情報を適切に書き換えながら、注文や手仕舞いなどの処理を繰り返していけます。
まとめ
今回は、手仕舞いと売買状況を管理する変数を中心にお伝えしました。
変数の中で、現在のトレードの状態をコントロールしながら、必要な処理を呼び出していく様な構造にすればOKです。
プログラムを見ていて、本当に変数必要なの?と思ったかもしれませんが、実際には判定処理などはそこそこのコード量になります。main関数で全ての処理の状況を正確に判断するためにはどうしても変数を定義する事が大切なのです。