GMOコインAPIを使ってビットコインの高騰・下落をLINEで通知する

# はじめに
ビットコイン投資をやっている友人からビットコイン価格が高騰か下落した場合にLINE通知するような機能が欲しいと要望があったので、作ってみました。

# できること
定期的にビットコイン価格を自動チェックして騰落率が閾値を超えるとLINEでメッセージが送られます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/28998068-7318-eedb-7083-90cfad9eb8e4.jpeg" width=50%/>
固定メッセージ：ビットコイン（購入 or 売却）価格が急変しました
騰落率(1時間)：1時間前のレートと比較した騰落率
騰落率(24時間)：24時間前のレートと比較した騰落率
現在の購入価格：現在のビットコイン購入価格

# 構成イメージ
レート取得からLINE通知までの簡単な機能フローのイメージです。（雑ですんません...）
![スクリーンショット 2023-05-14 0.19.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/c0905ad4-e9ed-ba94-8e92-102b83a90cdf.png)


# 開発環境
* MacBookPro（Intel）
* GoogleAppsScript

# 事前準備
### LINE Notifyのアクセストークン発行
LINE NotifyはWebサービスからの通知を、LINEで受信することが出来る便利なサービスです。

#### ① LINE Notifyのマイページにアクセス
* [LINE Notify公式](https://notify-bot.line.me/ja/)にアクセス
* ログイン後にマイページを開く
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/5c5df293-36da-2fcc-98af-9110f5437dc3.png" width=80%/>

#### ② トークンの発行
* ページ下部の「トークンを発行」をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/1c6c027f-1001-f2bf-e7f9-cda61af88869.png" width=80%/>

* トークン名を指定し、通知先を選択して発行
   * トークン名：メッセージの先頭につく名前
   * 通知先：メッセージを受信する通知先（グループor自分）を選択する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/af0445a6-8359-bc6c-40a9-0da601bd5b5f.png" width=80%/>

* 発行されたトークンをメモしておく
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/813b7516-d2a2-2052-817e-1b4de739266a.png" width=80%/>

### LINE Notifyの招待
LINE Notifyを友達追加して、通知先に設定したルームに招待してください。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/17668af7-2b3f-e165-d81b-ada507d07c1e.png" width=50%/>

# 実装
### 準備
* 取得したレートを書き込むためのGoogleスプレッドシートを作成
* スクリプトを書くためのGASシートを追加
    * 作成したGoogleスプレッドシートを開き、「拡張機能 > Apps Script」で作成できます。
![スクリーンショット 2023-05-14 8.39.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/e7059130-3c57-645e-9afe-0c1ccdb86e85.png)

### 接続情報の設定
GMOコインAPIとLINE Notify,Googleスプレッドシートの接続情報を設定します。
LINE Notifyとスプレッドシートの接続情報は適宜変更してください。
```javascript
// GMO APIのエンドポイントとAPIキーを設定
var gmoEndpoint = "https://api.coin.z.com/public";
var gmoApiPath = "/v1/ticker?symbol=BTC"; // 取得銘柄を変更したい場合はsymbolを変える

// LINENotifyのトークンを設定
var lineNotifyToken = "LINE Notifyのトークン";

// スプレッドシートのIDとシート名を設定
var spreadsheetId = "GoogleスプレッドシートのID";
var sheetName = "Googleスプレッドシートのシート名";
```

### レートを取得して騰落率が閾値を超えた場合にLINE通知する
現在のレートを取得し過去のレートと比較して、騰落率が閾値の5%を超えた場合にLINEで通知するスクリプトを追加します。
※GMOコインAPIで取得できるデータは[GMOコインAPIリファレンス](https://api.coin.z.com/docs/?javascript#public-api)を参照してみてください。

```javascript
// レートを取得してスプレッドシートに書き込む
function fetchRateAndWriteToSheet() {
  // レート取得
  var response = parseJSON(gmoEndpoint + gmoApiPath);
  var rateAsk = response.data[0].ask;
  var rateBid = response.data[0].bid;

  // スプレッドシートのデータを取得
  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  var sheet = spreadsheet.getSheetByName(sheetName);
  
  // レートとタイムスタンプをスプレッドシートに書き込む
  var now = new Date();  
  var newRow = [now, rateAsk, rateBid];
  sheet.appendRow(newRow);
  
  // LINE通知
  checkRateThreshold(rateAsk, "ask"); // 売却価格
  checkRateThreshold(rateBid, "bid"); // 購入価格

  // 不要なデータを削除
  var dataRange = sheet.getDataRange();
  var dataValues = dataRange.getValues();
  var oneDayAgo = new Date(now.getTime() - (24 * 60 * 60 * 1000));
  for (var i = dataValues.length - 1; i >= 0; i--) {
    var rowData = dataValues[i];
    var timestamp = rowData[0];

    // タイムスタンプが1日前より前の場合、行を削除
    if (timestamp < oneDayAgo) {
      sheet.deleteRow(i + 1);
    }
  }
}

// レートの変動をチェックして通知する
function checkRateThreshold(currentRate, rateMode) {
  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
  
  var currentRow = sheet.getLastRow();
  var previousHourRow = currentRow - 6; // 1時間前のレート
  var previousDayRow = currentRow - 144; // 24時間前のレート
  var colNum = 2;
  var rateType = "売却";
  if (rateMode == "bid") {
    colNum = 3;
    rateType = "購入";
  }
  
  // 騰落率の算出
  var previousHourRate = sheet.getRange(previousHourRow, colNum).getValue();
  var previousDayRate = sheet.getRange(previousDayRow, colNum).getValue();
  var hourChangePercentage = ((currentRate - previousHourRate) / previousHourRate) * 100;
  var dayChangePercentage = ((currentRate - previousDayRate) / previousDayRate) * 100;
  
  // ここで一定の数値を超えるかチェックし、通知の条件を設定
  var threshold = 5; // 通知する基準となる騰落率の閾値
  var isHourThresholdExceeded = Math.abs(hourChangePercentage) > threshold;
  var isDayThresholdExceeded = Math.abs(dayChangePercentage) > threshold;
  var isSend = isHourThresholdExceeded || isDayThresholdExceeded
  
  if (isSend) {
  // LINE Notifyで送信するメッセージ作成
    var sendMessage = "\nビットコイン" + rateType + "価格が急変しました\n\n";
    sendMessage += "騰落率（1時間）：" + Math.round(hourChangePercentage*100)/100 + "％\n";
    sendMessage += "騰落率(24時間）：" + Math.round(dayChangePercentage*100)/100 + "％\n";
    sendMessage += "現在の" + rateType + "価格：" + currentRate.toString() + "円\n\n";
    sendMessage += "詳細へ\n";
    sendMessage += "https://coin.z.com/jp/corp/information/btc-market/";

    // LINE通知
    sendLineNotification(sendMessage); 
  }
}

// LINE Notifyで通知を送る
function sendLineNotification(message) {
  var url = "https://notify-api.line.me/api/notify";

  const options = {
    "method"  : "post", 
    "payload" : "message=" + message,
    "headers" : {"Authorization" : "Bearer "+ lineNotifyToken}
  };

  //  FetchメソッドでLINEにメッセージを送信
   UrlFetchApp.fetch(url, options);
}

// JSON解析
function parseJSON(URL){
  // JSONを参照
  var response = UrlFetchApp.fetch(URL).getContentText();
  var jsonStr = JSON.parse(response);
  
  return jsonStr;
}
```

### 各関数について
早くスクリプトを動かしたい人は読み飛ばしても結構です。

#### fetchRateAndWriteToSheet
レートの取得、スプレッドシートへの書き込み、LINE通知の処理をまとめているメイン関数です。
まず、GMOコインAPIを使用してレートを取得しています。
次にスプレッドシートに取得したレートを書き込みにいっています。（GMOコインAPIでは過去のレートを取得できないため、現在のレートとの比較用にスプレッドシートに情報を保持するようにしています）
書き込み後は、`checkRateThreshold`関数で騰落率を算出して閾値を超えていればLINE通知しています。
最後に1日より前のレートは不要なデータなのでGoogleスプレッドシートから行削除しています。

#### checkRateThreshold
騰落率が閾値を超えているかを判定する関数です。
まず、スプレッドシートから現在のレートと1時間前のレート、24時間前のレートを取得して騰落率を算出します。
次に算出した騰落率が閾値（5%）を超えた場合に`sendLineNotification`関数を使用してLINEで通知しています。
※送信するメッセージを変更したい場合は`sendMessage`変数を修正してください。

#### sendLineNotification
LINE Notifyを使用してレート情報をLINE通知する関数です。

#### parseJSON
`JSON.parse`を使用して、webデータをJSON解析する関数です。

### 定期実行の設定
作成したスクリプトを定期的に実行する設定をします。
Apps Scriptの左メニューから「トリガー > トリガーの追加」からスクリプトのトリガー追加ができます。
下図は、10分ごとにスクリプトを定期実行する設定です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/434bd79d-f882-5b52-a0c5-9de9e56c1f22.png" width=80%/>

### スクリプト実行時の注意点
定期実行を設定することで設定した頻度でスクリプトが実行されるようになります。
が、過去レートがGoogleスプレッドシートに書き込まれていないとスクリプトエラーになるので、初回実行前はGoogleスプレッドシートに24時間分のデータを行追加（10分おきだと144行）しておいてください。

こんな感じ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1097781/0111a88c-0401-31a5-1220-a6c0fe795dbc.png" width=80%/>

# まとめ
1~2時間で実装できたので、非常に簡単に作成できました。（APIつおい）
GMOコインAPIでは過去のレートが取得できなかったので、Googleスプレッドシートに書き込みに行っていますが過去のレートをAPIから取得できれば更に実装が楽になりそうですね。（PrivateAPIでも取れなさそうでした）
ただ、PrivateAPIだと有効注文の一覧など面白そうな情報が更に取得できそうだったので、また機会があればガチャガチャ遊んでみようと思います。