
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
準備
・TradingView有料会員になる
・bitFlyerのAPI KeyとAPI Secretを取得
Google Apps Scriptの設定
⭐️Google Driveにアクセス
⭐️+新規をクリック
⭐️Google スプレッドシートをクリック
⭐️任意の名前(ここでは「tradingview_bf」)を入力
⭐️ツール > スクリプトエディタをクリック
⭐️無題のプロジェクトをクリックし任意のプロジェクト名(ここでは「tradingview_bf」)を入力しOKをクリック
⭐️以下のコードを貼り付け
//=========================================================
// 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を取得」を参考にしてください。
⭐️ファイル > 保存をクリック
⭐️公開 > ウェブアプリケーションとして導入をクリック
・プロジェクト バージョン:New
・次のユーザーとしてアプリケーションを実行:自分
・アプリケーションにアクセスできるユーザー:Anyone, even anonymous
⭐️以上になっていることを確認し導入をクリック
⭐️許可を確認をクリック
⭐️自分のGoogleアカウントをクリック
⭐️詳細をクリック
⭐️tradingview_bf(安全ではないページ)に移動をクリック
⭐️許可をクリック
⭐️現在のウェブアプリケーションのURLをコピーしてOKをクリック
※このURLは厳重に管理してください
※今後、スクリプトを編集し更新する際は[ファイル]>[保存]で保存した後、[公開]>[ウェブアプリケーションとして導入]でアップデートする必要があります。その際、プロジェクトバージョンをNewにするのをお忘れなく!
⭐️🕑をクリック
⭐️+トリガーを追加をクリック
・実行する関数を選択:get_info
・実行するデプロイを選択:Head
・イベントのソースを選択:時間主導型
・時間ベースのトリガーのタイプを選択:分ベースのタイマー
・時間の間隔を選択(分):1分おき
⭐️以上を選択し保存をクリック
TradingViewの設定
⭐️TradingViewのテストアラートを送ってみます。
⭐️Webhook URLのチェックボックスにチェックを入れ、先ほどコピーしたURLをペースト
⭐️メッセージに「TEST」と入力
⭐️Discordの方を見てみると、まず先に注文についての投稿がきます。
⭐️その1分程度後に、証拠金関係と建玉関係の投稿がきます。
本番のアラートでは、
⭐️買いアラートのメッセージには「BUY」
⭐️売りアラートのメッセージには「SELL」
と入力してください
⭐️注文が通った際は以下のようなメッセージがきます。
終わりに
いかがでしたでしょうか?
とうとうIFTTTすら不必要になりシンプルになったため、注文完了までの速度もだいぶ早くなりました。
具体的にどれくらいの速さになったかは後日検証して公開しようと思っています。
細かいことですが、注文はリアルタイムに処理している一方で、証拠金や建玉についての情報投稿は1分毎と時間を決めて動作させています。
(注文直後に情報を取得しても、注文による建玉の変化が反映されないためです)
現在、BitMEX版の制作も進めており、注文周りは完成したため、証拠金等の情報取得部分を完成させたら公開しようと思っています。
以上です。お付き合いいただきありがとうございました。
有用でしたら是非投げ銭として、記事の購入をよろしくお願いします!!
(有料部分は投げ銭用なので何もありません。)
ここから先は
¥ 2,000
サポートしていただいたお金は全てがん闘病生活の資金に充てさせて頂きます。 BTC: 3679CqD4SnZtTgeMTVPjCefCMkrHu3nmjb