名称未設定-23

IFTTTなんて要らなかったんや… TradingView WebhookとGoogle Apps Scriptだけでお手軽bitFlyer自動取引BOT

前置き

やあ (´・ω・`)
うん、「また」なんだ。済まない。

…というわけで、最早IFTTTすら要らない子になり、速度も向上した
TradingView Webhook → Google Apps Script → bitFlyer
のBOTの作り方を解説していきます!

↓これまでの記事はこちらから


前提条件

この記事は全文無料で読めます。(有料設定は投げ銭用です)
しかし、TradingViewのWebhookアラートを使用するにはTradingViewの有料会員登録が必要ですので、その点はご理解ください。

↓TradingViewの有料登録はこちらから(アフィリエイトリンクです)

bitFlyerでBOT取引を行う際、API KeyとAPI Secretが必要になります。
bitFlyerでの口座開設はもちろんですが、API Key等を使用する際の注意事項についても各々で充分に理解した上でご利用ください。
当note及びプログラムコードの利用したことにより利用者が被る損失や被害について、筆者は一切の責任を負うことはできません。


仕様(ざっくり)

TradingView → Google Apps Script → bitFlyer

画像1


準備

・TradingView有料会員になる
・bitFlyerのAPI KeyとAPI Secretを取得


Google Apps Scriptの設定

⭐️Google Driveにアクセス

⭐️+新規をクリック

画像2

⭐️Google スプレッドシートをクリック

画像3

⭐️任意の名前(ここでは「tradingview_bf」)を入力

画像4

⭐️ツール > スクリプトエディタをクリック

画像5

⭐️無題のプロジェクトをクリックし任意のプロジェクト名(ここでは「tradingview_bf」)を入力しOKをクリック

画像6

⭐️以下のコードを貼り付け

//=========================================================
// TradingViewのアラートに入力するメッセージ
// 買い... BUY
// 売り... SELL
//=========================================================

//=========================================================
// ↓入力部分↓
//=========================================================
// API Key等を設定
var key = 'API Key';
var secret = 'API Secret';

// 注文量(FXBTC)
ORDER_SIZE = 0.01;

// Discord Webhook URL
DISCORD_WEBHOOK_URL = "Discord Webhook URL";

//=========================================================
// ↓コード本体↓
//=========================================================
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();

function doPost(p){
var order_side = p.postData.contents;
sheet.getRange("A1").setValue(order_side);
var ucs = order_side.toUpperCase();


try{
  // bitFlyerに注文
  bitflyer(ucs);
  
  // Discord投稿
  var message = "@here "+ucs+" FXBTCJPY "+ORDER_SIZE+"₿FX"
  discord(message);
  
  // A1を空欄に戻し、各種情報を取得するためのフラグを立てる
  sheet.getRange("A1").setValue("");
  sheet.getRange("A2").setValue("TRUE");
}catch(e){
  Logger.log(e);
  
  // A1を空欄に戻し、各種情報を取得するためのフラグを立てる
  sheet.getRange("A1").setValue("");
  sheet.getRange("A2").setValue("TRUE");
      
  // Discord投稿
  var message = "@here 注文エラーが発生しました"
  discord(message);
}  
}

// 注文後に各種情報を取得
function get_info(){
var pub = sheet.getRange("A2").getValue();
Logger.log(pub);
if(pub==true){
  var bal = getBalance();
  var pos = getPositions();
  var message = "@here \n預入証拠金: "+bal[0]+"\n必要証拠金: "+bal[1]+"\n評価損益: "+bal[2]+"\n評価証拠金: "+bal[3]+"\n証拠金維持率: "+bal[4] +"\n--------------------"+ "\n合計建玉: "+pos[0]+ "\n平均約定価格: "+pos[1]+ "\n売買: "+pos[2];
  discord(message);
  sheet.getRange("A2").setValue("");
}
}

//Discordの処理
function discord(message) {  
var discordUrl = DISCORD_WEBHOOK_URL;
var payload = JSON.stringify({content: message});
var params = {
  headers: {
    'Content-Type': 'application/json'
  },
  method: "POST",
  payload: payload,
  muteHttpExceptions: true
};
try {
  var response = UrlFetchApp.fetch(discordUrl, params);
  Logger.log(response.getContentText());
}
catch(e){
  Logger.log(e);
}
}

// bitFlyer注文   
function bitflyer(ucs) {  
var timestamp = Date.now().toString();
var method = 'POST';
var path = '/v1/me/sendchildorder';
var body = JSON.stringify({
  product_code: "FX_BTC_JPY",
  child_order_type: "MARKET",
  side: ucs,
  size: ORDER_SIZE
});
var text = timestamp + method + path + body;
var signature = Utilities.computeHmacSha256Signature(text, secret);
var sign = signature.reduce(function(str,chr){
  chr = (chr < 0 ? chr + 256 : chr).toString(16);
  return str + (chr.length==1?'0':'') + chr;
},'');
var url = 'https://api.bitflyer.com' + path;
var options = {
  method: method,
  payload: body,
  headers: {
    'ACCESS-KEY': key,
    'ACCESS-TIMESTAMP': timestamp,
    'ACCESS-SIGN': sign,
    'Content-Type': 'application/json'
  }
};
var response = UrlFetchApp.fetch(url, options);
if( response != null ){
  var obj = JSON.parse(response.getContentText());
  Logger.log("child_order_acceptance_id(APIの受付ID): "+ obj.child_order_acceptance_id);
}
}

// 証拠金や損益関係の情報を取得
function getBalance(){
var timestamp = Date.now().toString();
var method = 'GET';
var path = '/v1/me/getcollateral';
var text = timestamp + method + path;
var signature = Utilities.computeHmacSha256Signature(text, secret);
var sign = signature.reduce(function(str,chr){
  chr = (chr < 0 ? chr + 256 : chr).toString(16);
  return str + (chr.length==1?'0':'') + chr;
},'');
var url = 'https://api.bitflyer.com' + path;
var options = {
    method: method,
    headers: {
      'ACCESS-KEY': key,
      'ACCESS-TIMESTAMP': timestamp,
      'ACCESS-SIGN': sign,
      'Content-Type': 'application/json'
    }
};
var strRespons = UrlFetchApp.fetch(url, options);
if( strRespons == null ){ return false; }
var json = JSON.parse(strRespons.getContentText());
var open_collateral = parseInt(json.collateral, 10) + parseInt(json.open_position_pnl, 10); 
var keep_rate_par = parseInt(json.keep_rate * 100, 10);
return [json.collateral, json.require_collateral, json.open_position_pnl, open_collateral, keep_rate_par]
}

// 建玉に関する情報を取得
function getPositions(){
var timestamp = Date.now().toString();
var method = 'GET';
var path = '/v1/me/getpositions?product_code=FX_BTC_JPY';
var text = timestamp + method + path;
var signature = Utilities.computeHmacSha256Signature(text, secret);
var sign = signature.reduce(function(str,chr){
  chr = (chr < 0 ? chr + 256 : chr).toString(16);
  return str + (chr.length==1?'0':'') + chr;
},'');
var url = 'https://api.bitflyer.com' + path;
var options = {
  method: method,
  headers: {
    'ACCESS-KEY': key,
    'ACCESS-TIMESTAMP': timestamp,
    'ACCESS-SIGN': sign,
    'Content-Type': 'application/json'
  }
};
var strRespons = UrlFetchApp.fetch(url, options);
if( strRespons == null ){ return false; }
var json = JSON.parse(strRespons.getContentText());
Logger.log(json);
var size_sum = 0.0;
var ave_pri = 0;
var last_side;
for each(var obj in json){
  size_sum += obj.size;
  ave_pri += obj.price * obj.size;
  last_side = obj.side;
}
var ave_con = ave_pri/size_sum;
return [size_sum, ave_con, last_side]
}

⭐️以下の部分に関しては各自で編集してください

//=========================================================
// ↓入力部分↓
//=========================================================
// API Key等を設定
var key = 'API Key';
var secret = 'API Secret';

// 注文量(BTC)
ORDER_SIZE = 0.01;

// Discord Webhook URL
DISCORD_WEBHOOK_URL = "Discord Webhook URL";

↓ こんな感じ。「'」と「;」は消さないように注意。
(「;」は消しても問題はないですが念の為)

//=========================================================
// ↓入力部分↓
//=========================================================
// API Key等を設定
var key = 'aaaabbbbccccdddd';
var secret = 'eeeeffffgggghhhh';

// 注文量(BTC)
ORDER_SIZE = 0.01;

// Discord Webhook URL
DISCORD_WEBHOOK_URL = "https://discordapp.com/api/webhooks/iiiiijjjjjjkkkkk";
※ 注文量は必ず最小である0.01から試してください!!
Discord Webhook URLの取得方法は、以下の記事の「DiscordのWebhook URLを取得」を参考にしてください。

⭐️ファイル > 保存をクリック

画像7

⭐️公開 > ウェブアプリケーションとして導入をクリック

画像8

・プロジェクト バージョン:New
・次のユーザーとしてアプリケーションを実行:自分
・アプリケーションにアクセスできるユーザー:Anyone, even anonymous 
⭐️以上になっていることを確認し導入をクリック

画像9

⭐️許可を確認をクリック

画像10

⭐️自分のGoogleアカウントをクリック

画像11

⭐️詳細をクリック
⭐️tradingview_bf(安全ではないページ)に移動をクリック

画像12

⭐️許可をクリック

画像13

⭐️現在のウェブアプリケーションのURLコピーしてOKをクリック

画像14

※このURLは厳重に管理してください
※今後、スクリプトを編集し更新する際は[ファイル]>[保存]で保存した後、[公開]>[ウェブアプリケーションとして導入]でアップデートする必要があります。その際、プロジェクトバージョンNewにするのをお忘れなく!

⭐️🕑をクリック

画像15

⭐️+トリガーを追加をクリック

画像16

・実行する関数を選択:get_info
・実行するデプロイを選択:Head
・イベントのソースを選択:時間主導型
・時間ベースのトリガーのタイプを選択:分ベースのタイマー
・時間の間隔を選択(分):1分おき
⭐️以上を選択し保存をクリック

画像17


TradingViewの設定

⭐️TradingViewのテストアラートを送ってみます。
⭐️Webhook URLのチェックボックスにチェックを入れ、先ほどコピーしたURLをペースト
⭐️メッセージに「TEST」と入力

画像18

⭐️Discordの方を見てみると、まず先に注文についての投稿がきます。
⭐️その1分程度後に、証拠金関係と建玉関係の投稿がきます。

画像19

本番のアラートでは、
⭐️買いアラートのメッセージには「BUY
⭐️売りアラートのメッセージには「SELL
と入力してください

画像20

⭐️注文が通った際は以下のようなメッセージがきます。

画像21


終わりに

いかがでしたでしょうか?

とうとうIFTTTすら不必要になりシンプルになったため、注文完了までの速度もだいぶ早くなりました。
具体的にどれくらいの速さになったかは後日検証して公開しようと思っています。

細かいことですが、注文はリアルタイムに処理している一方で、証拠金や建玉についての情報投稿は1分毎と時間を決めて動作させています。
(注文直後に情報を取得しても、注文による建玉の変化が反映されないためです)

現在、BitMEX版の制作も進めており、注文周りは完成したため、証拠金等の情報取得部分を完成させたら公開しようと思っています。


以上です。お付き合いいただきありがとうございました。

有用でしたら是非投げ銭として、記事の購入をよろしくお願いします!!
(有料部分は投げ銭用なので何もありません。)


ここから先は

1字

¥ 2,000

サポートしていただいたお金は全てがん闘病生活の資金に充てさせて頂きます。 BTC: 3679CqD4SnZtTgeMTVPjCefCMkrHu3nmjb