BitflyerのBTCFXで自動売買ができる試作版のBOTを作る!前回の記事の続きです。エントリーの条件・手仕舞いの条件などの売買ロジックが完成したので、ここに実際にBitflyerにオーダーを出すコードを入れてみましょう。ついでに今回の記事から「売りシグナルの判定」と「売りからのエントリー」にも対応できるようコードを改良します。(こちらの記事の答え合わせです)暫定的な完成版のpythonコードが以下になります。data["close_price"]time.sleep(10)こちらのコードをそのまま書き写せば、とりあえず動きます。安定的に(エラーで止まったりせずに)何日も連続で動かし続けるためには、あともう一工夫だけ必要です。これについては、この次の記事で解説します。前回の記事からの変更点で、重要な部分について解説しておきます。flag前回の記事でも、「買いシグナルの状況」「サーバーに出した注文状況」「ポジションの保有有無」などの情報を管理するために、flagという変数を作りました。今回は、売りシグナル・売りエントリーも考えないといけないので、以下のように変数flagを改造しましょう。""}}buy_signalとsell_signalは、それぞれ「何本連続で陽線が続いているか?」「何本連続で陰線が続いているか?」を管理するフラッグです。この値が「3」になったらその方向(BUY/SELL)でエントリーします。orderは「現在、サーバーに未約定の注文があるか?」を管理するためのフラッグです。今回は、ロング・ショートの両側を考えるため、orderというフラッグの中に、さらにexistとsideという2つの要素を作ります。existが注文の有無、sideが買いか売りか、を管理するための要素です。countは「一定時間で注文が約定しなければキャンセルする」というロジックのために使います。メイン処理では全体のループを10秒間隔で回すため、例えば、「1分間(60秒)約定しなければキャンセルする」というロジックを組むために、このcountをループごとに1ずつ増やし、6を超えたらオーダーキャンセルを出すようにします。positionは、「現在、ポジション(建玉)があるかどうか?」を管理するためのフラッグです。こちらも「買いポジション」「売りポジション」の両方があることを考慮して、「side」という要素を持つ入れ子構造に修正しておきます。True買いシグナルと売りシグナルの両方に対応できるように、「side」という引数を受けとり、それによってシグナルを出し分けるように改良しました。"BUY"前回の記事で「#ここに買い注文のコードを入れる」と書いておいた部分に上記のコードを入れます。bitflyer.create_order()と書けば、CCXT経由で簡単にbitflyerに注文を出すことができます。このコードの書き方は、「CCXTでBitflyerに注文を出す方法」の記事ですでに解説しましたので、そちらを参考にしてください。同じように売りシグナルを判断して売り注文を出す関数も作っています。こちらは買い注文を単に反対にしただけなので、解説は省略します。一定時間で注文が通っていなければキャンセルする」と書いておいた部分に、上記のコードを入れていきます。get_getpositions()で建玉の一覧を取得し、さらにfetch_open_orders()で未約定の注文一覧を取得します。建玉があれば、指値注文が通ったと判断できますので「注文が約定しました!」と表示します。flag["order"]["exist"](未約定の注文の有無を管理するflag)をFalseに更新し、flag["orders"]["exist"](ポジションの有無を管理するflag)をTrueに更新します。flag["order"]["side"]もしまだ建玉がなければ、orders(未約定の注文一覧)を確認します。未約定の注文があれば、「まだ未約定の注文があります」と表示します。先ほど説明したように、flag["order"]["count"]というフラッグにカウント1を追加します。全体の処理はWhile文で10秒おきに回っているので、このフラッグのカウントが「6」以上になれば、「1分間約定しなかった」と判断して注文をキャンセルします。いうのは、今回の記事で新たに作成した注文キャンセルのための関数です。ここにキャンセル処理をそのまま書いてもいいのですが、少しだけ長い処理になるので、読みやすいように別の関数として外に出すことにしました。内容は後ほど説明します。最後のelse:の部分は、エントリー注文を出したものの、「建玉の一覧」にも「未約定注文の一覧」にも、どちらにも情報が存在しないパターンを捕まえています。else:print("注文が遅延しているようです")これは注文のリクエスト(通信)は正常に受理されたものの、サーバー側への注文の反映が「遅延」しているときにおこる現象です。両方を取得しなければ、現在がどういう状態にあるのか判別することができません。「遅延」はまだサーバー側に注文が認識(反映)されていない状態。「未約定」は注文が反映されてまだ約定していない状態。Falseさきほどの続きで、「未約定の注文一覧」をキャンセルするための関数です。CCXTライブラリを使えば、bitflyer.cancel_order()で未約定の注文をキャンセルすることができます。注文のキャンセルを出した時点で、「約定しない注文をキャンセルしました」と表示し、flag["order"]["exist"](未約定の注文を管理するフラッグ)をFalseに戻します。カウント用のフラッグも0に戻しておきます。Bitflyerの注文キャンセルのAPIを使った場合でも、通信のすれ違いで注文が約定してしまうことがあります。そのため、未約定の注文をキャンセルした後に、20秒間待機し、続けて「ポジションが残ってないかどうか?」を念のために確認します。それが以下の部分です。flagbitflyer.private_get_getpositions()で、現在のポジション(建玉)の状況を確認します。空のデータが返ってきたら、未約定の注文のキャンセルに成功したということです。この場合は、「現在、未決済の建玉はありません」と表示します。1つでもデータが返ってきた場合は、「未約定の注文をキャンセルするつもり」だったものの、「スレ違いで注文が約定してしまいポジションを持ってしまった」という状況になります。そのため、flag["position"]["exist"](ポジションの有無を管理するフラッグ)をTrueに更新します。flagflag["position"](ポジションの保有の有無を管理するフラッグ)を使って、買いポジションであれば売り決済、売りポジションであれば買い決済の成行注文を出します。成行注文を出した後は、flag["position"]["exist"]をFlaseに更新しておきます。これでまたエントリーができるようになります。data["close_price"]time.sleep(10)ここがメインのループ処理の部分です。長くなりそうなコードはすべて関数にして外に出しておいたので、メイン処理自体は、かなりすっきりと書くことができました。このように全体のロジック部分をシンプルにしておくと、後で(何をやってるのか?)が見やすくなり、管理もしやすくなります。一応、1つずつ確認しておきます。)まず最初に最優先で「未約定の注文がないか?」をフラッグで確認します。あれば、先ほどの「未約定の注文を管理する関数」を呼びます。メイン処理のWhile文は10秒間隔で回しているので、10秒おきに「注文が実行されたかどうか?」を確認することになります。データを取得するのは10秒おきですが、ローソク足に更新があるのは(1分足ベースであれば)1分おきです。日時データに更新があった場合のみ、その始値・終値などのデータを表示し、次の処理に進むようにします。)ポジション(建玉)の有無を確認し、もしポジションがあれば、さきほどのclose_position()関数を呼んで、手仕舞いの条件を満たしているかどうかを確認します。ポジションを持っていない場合は、買いシグナル(buy_signal)、売りシグナル(sell_signal)を順番に確認します。今回の自動売買ロジックでは、売りシグナルと買いシグナルが両方点灯することはありえないので、単に順番に実行するだけで構いません。実行結果こちらを実行すると以下のような感じになります。20時14分頃に3本連続で陰線のシグナルが出たのでショートでエントリーし、次の足ですぐに終値が上がってしまったので損切の決済をしたようです。実際にBitflyerの管理画面にも売買の履歴が入っています。チャート上では以下のタイミングでエントリーしています。条件)は緩和し、単純に陰線/陽線が3本続いたらそれを売り/買いのシグナルとして動かしました。左の矢印で3本連続の陰線による売りシグナルが点灯し「売り注文」、右の矢印で前回の終値を上回って引けたので「決済」しています。意図した通りの挙動はしているようです。例外処理について今回の記事で、ようやく自動で売買判断をしながら動き続けるBOTを作ることができました!しかし実はあと1つだけ学ばなければならないことがあります。上記の自動売買BOTは、そのままでも動くことは動きます。pythonのプログラムコードや構文には問題はありません。このままだと、1度でもBitflyerやCryptowatchのサーバーからエラーが返ってきたら、そこで止まってしまいます。Error」を返します。これに対する処理を入れておかないと、そこでBOTがエラーを吐いて中断してしまいます。このような対策のことを「例外処理」といいます。コメントをキャンセルメールアドレスが公開されることはありません。