前回の記事に引き続き、今回も仮想通貨botの開発状況をまとめていきます。
前回の記事で作ったBotの問題点を解消したコードを作りました。
簡単に言うと「価格が20%以上変動したタイミングを見て注文を出す」ように条件付けしています。
また、「すでに注文を出している時には新たに注文を出さない」ようにしています。
サーキットブレーカーBot2
ChatGPTに出した指示は以下の3つ。
![](http://yodakaart.tech/wp-content/uploads/2023/11/girl-300x300.png)
上記のコードでは、現在の価格に反応して注文を発生させてしまうのではないか。 価格が20%変動した時に買い注文や売り注文を出すコードにするにはどうすれば良いか。
![](http://yodakaart.tech/wp-content/uploads/2023/11/girl-300x300.png)
「price_change_ratioが20%以上の時」に条件変更しなさい。
![](http://yodakaart.tech/wp-content/uploads/2023/11/girl-300x300.png)
上記のコードで買い注文か売り注文を持っている時は、新たに買いと売りの注文を出さないようにしたい。どうすれば良いか。
作成されたのが以下のコードです。
import ccxt import datetime import time # APIキーとAPIシークレットを直接設定 api_key = 'Your API KEY' api_secret = 'Your API SECRET' bitflyer = ccxt.bitflyer({ 'apiKey': api_key, 'secret': api_secret, }) symbol = 'FX_BTC_JPY' def get_current_price(): ticker = bitflyer.fetch_ticker(symbol) return ticker['last'] def close_order(order_id): try: bitflyer.cancel_order(order_id, symbol) print(f"注文 {order_id} が手仕舞いされました。") except ccxt.NetworkError as e: print(f"手仕舞いエラー(ネットワークエラー): {str(e)}") except ccxt.ExchangeError as e: print(f"手仕舞いエラー(取引所エラー): {str(e)}") except Exception as e: print(f"手仕舞いエラー(その他のエラー): {str(e)}") # メインのループ処理 buy_order = None sell_order = None while True: try: closest_diff = 1000000000 closest_num = 0 # 現在のUNIXタイムスタンプを取得 current_time = datetime.datetime.now().timestamp() # 10分前のUNIXタイムスタンプを計算 ten_minutes_ago = current_time - 600 # 約定履歴を取得 trades = bitflyer.fetch_trades(symbol, limit=500) for i in range(len(trades)): time_diff = (trades[i]["timestamp"] - ten_minutes_ago * 1000) / 1000 if abs(time_diff) < closest_diff: closest_diff = abs(time_diff) closest_num = i past_price = trades[closest_num]["price"] current_price = get_current_price() # 注文を作成する条件: 過去の価格と現在の価格が20%以上の変動率を超えた場合に注文を作成する price_change_ratio = (current_price - past_price) / past_price if abs(price_change_ratio) > 0.2: # 例: 価格変動率が20%以上の場合 # 既に買い注文が存在しない場合に注文を作成 if buy_order is None: buy_price = int(current_price * 0.8) buy_order = bitflyer.create_order(symbol, "limit", "buy", 0.01, buy_price) print("買い注文が発注されました.") # 既に売り注文が存在しない場合に注文を作成 if sell_order is None: sell_price = int(current_price * 1.2) sell_order = bitflyer.create_order(symbol, "limit", "sell", 0.01, sell_price) print("売り注文が発注されました.") while True: time.sleep(5) # 注文が発注されてから手仕舞いを試みるまでの待機時間 current_price = get_current_price() # 利益率が一定の閾値を超えた場合に手仕舞いを試みる if (current_price - past_price) / past_price > 0.15: # 例: 利益率がX%以上の場合 close_order(buy_order['id']) close_order(sell_order['id']) break # 手仕舞いが成功したらループを抜ける except ccxt.NetworkError as e: print(f"ネットワークエラーが発生しました: {str(e)}") time.sleep(5) except ccxt.ExchangeError as e: print(f"取引所エラーが発生しました: {str(e)}") # 取引所エラーの場合、エラーメッセージを表示 print(f"取引所エラーメッセージ: {e}") time.sleep(5) except Exception as e: print(f"予期せぬエラーが発生しました: {str(e)}") time.sleep(5)
このコードを実行しても、現在の相場では直ちに注文が出ることはありませんでした。
ひとまず、条件分岐については成功したと言って良いでしょう。
ただ、実際に稼働させる際は、変動率20%まで粘らなくても良いのかもしれません。
設定してある数値price_change_ratioを19%程度に設定しておくことで、早めの注文を出すということもできそうです。
また、手仕舞いの条件も20%全てが戻った時ではなく、15%に設定して利益を出しやすくしています。
サーキットブレーカーは発生タイミングが読めないため、手仕舞いまで確実にBotに行わせるのが良いと思います。
この辺りはリスク要因にもなるため、慎重に試していこうと思います。
まとめ
注文を出す時と手仕舞いの条件分岐を設定しました。
実際に稼働させて、効果を検証していきます。
この調子でコツコツと学習を進めていきます。