【初心者向け】Zaif API×Pythonでプチフィンテック21 仮想通貨自動取引botの作成(メイン処理の実装1)

前回までの記事で、ようやくbotの事前準備の実装が終わりました。

残るはメイン処理のみですが、今回と次回の2回に分けて処理を実装していきます。

<スポンサーリンク>

メイン処理の実装

繰り返し処理とエラー処理の枠組み実装

さて、メイン処理は一定時間間隔での繰り返し処理として実装します。また、当然ながら、その処理の過程で異常が発生する場合がありますので、異常が発生しても継続的に処理を行えるよう、エラー処理も実装する必要があります。

そこで、まずは繰り返し処理とエラー処理の枠組みだけ実装してしまいます。

#③メイン処理(ループ)
while True:
    try:

        #この中にメイン処理を記述

    except Exception as e:
        logger.warning('取引ループ中にエラー発生、60秒待機: %r\n' %e)
        sleep(60)

冒頭のwhileという箇所ですが、「while 条件式」という記述で、以降の処理を条件式の値がTrueとなる限り、永遠に繰り返すことができます。今回条件式の部分には直接「True」を入れていますので、以降の処理を無条件に繰り返すことになります

次に、except以降の例外処理の箇所について、2点補足します。

まず、「sleep(60)」という記述がありますが、これは指定された数字の秒数だけ何も処理をせずにただ待つだけのメソッドです。前処理にてインポートすることにより、このメソッドを使用することができます。

次に、ログメッセージの中にある「\n」ですが、これは改行を意味します。したがって、エラーメッセージは改行付きで出力されることになります。

ループ開始処理の実装

次に、繰り返し毎に行うべき、ループ開始処理を実装します。なお、ここからはwhileとtryの中に記述することになりますので、各行に2つ分のインデントを入れる必要があることに注意下さい。

        #ループ開始処理
        counter += 1
        logger.info('ラウンド{}開始'.format(counter))
        previous_timestamp = current_timestamp
        current_timestamp = getTimestamp(KEY, SECRET)
        last_price = getLastPrice()
        logger.info('現在価格: {}'.format(last_price))

まず2行目で、何回目かのループであるかを表すカウンタに1を加算しています。前処理の実装の中で、このカウンタを0で初期化しましたので、最初にループを回すときにはこのカウンタは1となり、以降、ループを回すごとに1ずつ増えていくことになります。

また、3行目で何回目のループであるかを、ログとして出力しています。

出力する文字列の中に「{}」を入れ、文字列の後に「.format(変数)」と記述することにより、文字列中の「{}」の部分に指定した変数を埋め込んで出力することができます

4、5行目では、過去の取引履歴を参照する際に必要な、前回参照時刻(previous_timestamp)と今回参照時刻(current_timestamp)を設定しています。

今回参照時刻については、ループを回す都度、前処理で定義したgetTimestampメソッドを利用してサーバから現在時刻を取得しています。

前回参照時刻については1回目のループ実行時と2回目のループ実行時で処理が異なるため、注意が必要です

1回目ループ実行時には、current_timestampには初期値であるNoneが設定されていますので、前回参照時刻にもNoneが設定されます。ただし、次に実装する取引履歴の参照処理では、2回目以降のループから履歴を参照しますので、このNoneは意味を持ちません。

そして、2回目のループ実行時からは、その前の回に設定されたcurrent_timestampの時刻bが設定されることにより、previous_timestampには前回参照時刻が代入されます。

さらに、続く6、7行目で、参考情報として現時点の価格をログ出力するようにしています。

約定/決済状態の確認処理実装

続いて、発注したポジションの約定/決済情報を取引履歴から参照し、その情報のログ出力や必要に応じてポジションリストを更新する処理を実装します。

##③-1約定/決済状態の確認(2回目以降のループ処理時のみ)
        if counter >= 2:
            params = {
                'method': 'trade_history',
                'nonce': time(),
                'since': previous_timestamp,
                'currency_pair': CURRENCY_PAIR
            }

            response_dict = tradeRequester(params, KEY, SECRET)

            #前回ループ処理実行時以降に発生した約定/決済データを1つ1つ確認
            order_numbers = response_dict['return'].keys()
            for order_number in order_numbers:
                price = int(response_dict['return'][order_number]['price'])

                #買い約定がある場合の処理
                if response_dict['return'][order_number]['your_action'] == 'bid':
                    logger.info('買い約定({})'.format(price))
                    logger.info('売り注文({})'.format(price + LIMIT))

                #決済がある場合の処理
                elif response_dict['return'][order_number]['your_action'] == 'ask':
                    logger.info('売り約定({})'.format(price))
                    position_list[price - LIMIT] = False

やっていることは、以下の通りです。

  • ループが2回目以降の場合、前回参照時刻以降の取引履歴を参照する
  • 買い注文の約定履歴がある(=売り注文の発注も自動的に行われている)場合にはその事実をログ出力する
  • 逆に売り注文の約定履歴がある場合にはそれをログ出力するとともに、再度買い注文を発注できるようにポジションリスト中の該当するポジションのステータスをFalseにする

丁寧にコードを読み解いていけば、それほど難しい処理はないと思いますが、1点だけ補足します。

取引履歴を参照するAPIは「trade_history」というものです。これの戻り値に含まれる情報は多々ありますが、その中には「action」と「your_action」という似た項目があります。

約定状態を確認するためには、このうち「your_action」を見る必要がありますので、コード中にもこの項目を指定しています。

終わりに

今回の記事は以上です。

残るは、メイン処理中のメインとも言える発注処理ですが、次回、この発注処理の実装を行って、本シリーズを締めくくりたいと思います。

カテゴリ:フィンテック
<スポンサーリンク>

シェアする

フォローする