今回は「自動売買BOTの実装の練習」として、酒田五法の赤三兵と黒三兵(三羽鳥)を、自動売買ロジックとして実装するための手順を説明していきます。
三兵の売買ロジックを定義する
酒田五法の三兵とは、以下のように陽線・または陰線が3本連続で続くローソク足パターンのことをいいます。陽線が3本連続で続いた場合は、上昇トレンドなので買いのサイン、陰線が3本連続で続いた場合は、下降トレンドなので売りのサイン、と判断します。
ここでは単純に以下のように定義してpythonでプログラムしてみます。
赤三兵
1.3足連続で(終値>始値)の足が続いている
2.3回連続で始値と終値が前の足より上昇している
黒三兵
1.3足連続で(終値<始値)の足が続いている
2.3回連続で始値と終値が前の足より下落している
1と2のルールは両方必要です。
「3足連続で 終値>始値 」「3足連続で 終値<始値」のルールだけだと、必ずしも赤三兵や黒三兵の形にならないので注意してください。
ルール1で「陽線」であることは保証されますが、それが右肩上がり(または右肩下がり)かどうかは、ルール2を加えなければ判定できません。陽線が連続で続いていても、その始値や終値が前の足より低い、ということは十分あり得るからです。
追加ルール
このままでも練習としては問題ないのですが、上記のロジックだけだと以下のようなローソク足パターンも検出してしまいます。
なので、ローソク足の実体がある程度の大きさである、ヒゲの割合よりも実体の割合の方が大きい、という2つの条件を加えてみましょう。今回は以下のような条件にします。
1.実体の大きさ(上昇率)が始値の0.05%以上
2.ヒゲを含む値幅のうち実体の割合が50%以上
どちらも明確に、OHLCの価格データから数字で定義できます。
1)の条件は、「終値/始値 ― 1」の計算結果のことです。今回はテストで1分足を見てるので、「0.05%」に設定していますが、いくつが最適なのかは見ている時間軸によって違います。実際に動かす予定の5分足では「0.2%」くらいはあった方がいいかもしれません。自分で色々調整してみてください。
2)の条件は、「(始値 ― 終値)の絶対値 / (高値 ― 安値)」で計算できます。これも50%が最適かどうかはわかりませんが、今回は50%にします。
注意
「ローソク足パターンの傾向分析」などの本を読めばわかりますが、酒田五法の「赤三兵」「黒三兵」は、それだけを単独のシグナルとして用いても、統計上の勝率がそれほど良くないことがわかっています。
赤三兵を買いのシグナルとして使うなら、本来は、底値圏で捉えなければ意味がないので、各テクニカル指標やオシレーターと組み合わせて使うべきです。ですが、今回ははじめてのBOT作成の練習なので、シンプルに上のロジックだけで定義します。
また人によっては、三兵は陽線・陰線が「窓を開けずに」3本連続で続くことを条件として定義するようですが、今回は窓があるかどうかは考慮しません。
「赤三兵」のPythonコード
まずは赤三兵(3本連続で陽線が続く買いシグナル)を実装してみましょう。1)3足連続で(終値>始値)の足が続いている、2)3回連続で始値と終値が前の足より上昇している、の条件を満たす場合に、買いシグナルを出すコードを作ります。
なお、前回までの記事(「10秒おきにBitflyerのローソク足を取得するプログラム」)までの内容は、書けることを前提として進めます。
以下がpythonコードになります。
import requests from datetime import datetime import time def get_price(min): response = requests.get("https://api.cryptowat.ch/markets/bitflyer/btcfxjpy/ohlc",params = { "periods" : min }) data = response.json() last_data = data["result"][str(min)][-2] return { "close_time" : last_data[0], "open_price" : last_data[1], "high_price" : last_data[2], "low_price" : last_data[3], "close_price":last_data[4] } def print_price( data ): print( "時間: " + datetime.fromtimestamp(data["close_time"]).strftime('%Y/%m/%d %H:%M') + " 始値: " + str(data["open_price"]) + " 終値: " + str(data["close_price"]) ) def check_candle( data ): realbody_rate = abs(data["close_price"] - data["open_price"]) / (data["high_price"]-data["low_price"]) increase_rate = data["close_price"] / data["open_price"] - 1 if data["close_price"] < data["open_price"] : return False elif increase_rate < 0.0005 : return False elif realbody_rate < 0.5 : return False else : return True def check_ascend( data,last_data ): if data["open_price"] > last_data["open_price"] and data["close_price"] > last_data["close_price"]: return True else: return False last_data = get_price(60) print_price( last_data ) flag = 0 while True: data = get_price(60) if data["close_time"] != last_data["close_time"]: print_price( data ) if flag == 0 and check_candle( data ): flag = 1 elif flag == 1 and check_candle( data ) and check_ascend( data,last_data ): print("2本連続で陽線") flag = 2 elif flag == 2 and check_candle( data ) and check_ascend( data,last_data ): print("3本連続で陽線 なので 買い!") flag = 3 else: flag = 0 last_data["close_time"] = data["close_time"] last_data["open_price"] = data["open_price"] last_data["close_price"] = data["close_price"] time.sleep(10)
今回は少し長いので、コードの解説記事は、別の記事にしておきます。
先に実行結果の方を見ておきましょう。
実行結果
このpythonプログラムを実行すると、以下のようになります。
これを見ると、例えば、3月21日の夜中2時45分にシグナルが点灯してるのがわかります。実際に、BitflyerFXのチャートを見てみると、以下のようになっていました。
….これは、明らかに「買い」で入ってはいけなそうな局面ですね。
もし改良したい場合
このように、赤三兵は、上昇トレンドの終わりで現れた場合は天井(バイイングクライマックス)のシグナルとも言われています。繰り返しますが、赤三兵だけをシグナルに買いエントリーするのはお勧めできません。
実際に動かすBOTでは、RSIなどのオシレーターなどと組み合わせて、「売られ過ぎ」のときにエントリーするよう改良すべきでしょう。pythonでテクニカル指標を実装する方法は、今後、解説していきます。
またよく言われるように、赤三兵の3本目の足に上ヒゲが付いている場合は、弱気のシグナルです。上記の、check_candle()関数を自分で調整して、実体の割合ではなく、上ヒゲの割合でフィルターをかけてもいいかもしれません。
今回はとりあえず「テストBOTを作れるようになる」ことが目標なので、このまま話を進めます。
もっと効率的にテストする方法
上記のプログラムを実際に動かしてみるとわかりますが、実際のリアルタイムのチャートで検証しようとすると、シグナルが点灯するまで何十分・何時間もパソコンの前で待機しなければなりません。
例えば、上記のシグナルの条件に『3本目の足に上ヒゲがついてない場合』という条件を付け加えたとしましょう。その売買シグナルが、理想のタイミングで点灯するかどうかをテストするために、また何時間も待つのはあまりに非効率です。
なので、シグナルの条件のテストに、直近の過去データを使う方法を紹介しておきます。過去データでテストできれば、以下のようにどのくらいの頻度でシグナルが点灯するか、すぐに確認できます。
以下の記事では、その方法を解説しておきます!
練習問題
今回のpythonコードを改良して、黒三兵による売りシグナルと赤三兵による買いシグナルの両方が点灯するようにしてみましょう!
ポイントとして、赤三兵のシグナル(買い)と黒三兵のシグナル(売り)をそれぞれ関数にしてしまい、While文の外に出すと見やすくなります。またflagという変数を、買いエントリー用と売りエントリー用の2つ用意するといいです。
・練習問題の解答例
1:3足連続で(終値>始値)の足が続いている
2:3回連続で始値と終値が前の足より上昇している
の2つの条件が必要とのことですが
1を満たした時点で2は満たされるのではないですか?
一つ前の分足の終値=現在の分足の始値という認識だったのですが違うのでしょうか?
ありがとうございます!…たしかに、気づかなかったですw
多分、その通りだと思います。
厳密には、始値は前足の終値を参照してるわけではなく、範囲時間の中で最初に約定した注文の価格のことだと思うので、価格が少し飛ぶことはあると思います。ただ、おっしゃるように、1を満たしてかつ2を満たさないようなケースは現実にはないかもしれないですね。実際に検証してないので確実なことは言えないですが。