はじめに
前回は、約定内容をスプレッドシートに追記するライブラリ「libAddStockOrderToList」を作成しました。
今回は、このライブラリを使用してGmailで楽天証券から米国株式の約定通知を受信したら、約定内容をスプレッドシートに追記する仕組みを作ります。
Google App Scriptを使いますので、概要は以下の記事を参照してください。
対象読者
ここで紹介する内容は、以下の条件を満たす方が対象となります。
対象読者
- 楽天証券の口座を保有している
- 楽天証券の米国株式約定通知メール設定において「配信希望」としている
- 楽天証券からの配信メールにGmailを指定している
- 米国株式約定内容をスプレッドシートに自動登録させたい
では、どのように構築するのか見ていきましょう。
約定内容をスプレッドシートに自動追記
今回は、以前作成した「約定内容カレンダー登録」処理を改造して実現します。
変更点は以下の通りです。
- スプレッドシート追記用の情報抽出を追加(銘柄名、講座・売買、決済方法、約定単価)
- スプレッドシートに約定情報を追加する関数呼び出しを追加
約定内容抽出
楽天証券から送られてくる米国株式の約定通知から、以下の赤字に示す部分を抽出します。
米国株式約定通知
関谷 様
米国株式の注文が約定しました。
注文番号:0000
銘柄名(銘柄コード):プルデンシャル・ファイナンシャル(PRU)
口座・売買:特定・買付
決済方法:外貨
約定単価:105.14米ドル
約定数量:2株(口)
約定日時:2021/12/14 23:30
約定は一部約定の場合があります。
詳細は約定照会画面でご確認ください。
■米国株式取引の約定照会
<ウェブ>
PCサイトにログイン後、「注文」→「米国株式」→「注文照会・訂正・取消」
<マーケットスピード>
ログイン後、「注文約定」→「米国株式」→「約定照会」
<iSPEED for iPhone/Android>
ログイン後、「注文」→「米国株式取引」→「約定照会」
■本メールの設定の確認・変更(配信・停止)
PCサイトにログイン後、「マイメニュー」→お客様情報の設定・変更「メールサービス」→通知メール「約定通知メール」
http://www.rakuten-sec.co.jp/cgi-bin/CTS/Direct_Login.cgi?homeid=USER&type=account&sub_type=&local=acc_mail_select&eventType=init
────────────────────────
このメールについてのご質問等は、楽天証券カスタマーサービスセンターまでお気軽にお問い合わせください。
楽天証券カスタマーサービスセンター
フリーダイヤル:0120-41-1004
携帯電話から:03-6739-3333(通話料有料)
受付時間 平日8:30-17:00 (土日祝・年末年始を除く)
https://www.rakuten-sec.co.jp/web/support/
────────────────────────
楽天証券株式会社
メール本文中に現れる「注文番号」から、「約定は一部約定の場合があります」までの間の情報が抽出する対象となります。
そのため、以下に示すようにCUT_START、CUT_ENDで抽出の先頭と終了を識別するための文字を定義しておきます。
// 検索文字列
var CUT_START = '注文番号';
var CUT_END = '約定は一部約定の場合があります。';
以下に示すコードが約定内容の抽出部分です。
// 楽天証券からの約定メールの内容確認
var rows = body.split("\n");
for (var i in rows) {
var row = rows[i];
if(row.indexOf(CUT_START) >= 0){
cutting = true;
}
if(cutting){
if(row.indexOf(CUT_END) >= 0){
cutting = false;
}
else{
contents += row + '\n';
if(row.indexOf('銘柄名(銘柄コード):') >= 0){
ticker = row.match(/([A-Z]*)/);
ticker_name = row.replace('銘柄名(銘柄コード):', '');
}
else if(row.indexOf('口座・売買:') >= 0){
type = row.replace('口座・売買:', '');
}
else if(row.indexOf('決済方法:') >= 0){
pay_type = row.replace('決済方法:', '');
}
else if(row.indexOf('約定単価:') >= 0){
unit_price = row.replace('約定単価:', '');
unit_price = unit_price.replace('米ドル', '');
}
else if(row.indexOf('約定数量:') >= 0){
amount = row.match(/\d{1,2}/);
}
else if(row.indexOf('約定日時:') >= 0){
tmp = row.match(/\d{4}\/\d{1,2}\/\d{1,2} \d{1,2}:\d{1,2}/)
Logger.log(tmp[0]);
startTime = new Date(tmp[0]);
endTime = new Date(startTime.getTime() + 10 * 60000); // 終了時刻取得
}
}
}
}
CUT_STARTからCUT_ENDまでの間に出現した、以下の文字にマッチした場合に必要な情報を抽出します。
文字列の検索には「indexOf()」関数を使用します。
- 検索文字「銘柄名(銘柄コード):」→ 抽出結果を銘柄コードを「ticker_name」に格納
- 検索文字「口座・売買:」→ 抽出結果を結果を「type」に格納
- 検索文字「決済方法:」→ 抽出結果を「pay_type」に格納
- 検索文字「約定単価:」→ 抽出結果を「unit_price」に格納
- 検索文字「約定数量:」→ 抽出結果を「amount」に格納
- 検索文字「約定日時:」→ 抽出結果を「startTime」に格納
スプレッドシート登録
抽出した約定内容をスプレッドシートに登録します。
登録には前回作成したライブラリ「 libAddStockOrderToList 」に定義した「registToSpreadSheet()」を使用します。
まずは、ライブラリを使用できるようにするために、ライブラリ「 libAddStockOrderToList 」のスクリプトIDを確認しコピーします。
次に、ライブラリとして追加します。
ライブラリの「+」ボタンを押し、表示された画面にコピーした「 libAddStockOrderToList」 のスクリプトIDを貼り付けます。
すると、ライブラリとして「 libAddStockOrderToList 」が追加されて使えるようになります。
スプレッドシートに追加する関数は、「registToSpreadSheet()」です。
ライブラリ内の関数呼び出しは、
ライブラリ名.関数名
となるので、以下のように指定します。
// スプレッドシートに追記
libAddStockOrderToList.registToSpreadSheet('StockOrderList', '',
ticker_name, type, pay_type, unit_price, amount, startTime);
スプレッドシート名は「StockOrderList」となります。※お好みで変更してください。
libAddStockOrderToList については以下の記事を参照ください。
全てのコード
Googleカレンダーに追加するコードを改造しています。
/*
* 楽天証券からの約定メールの内容をGoogle Calendarに登録する
*
* 1.Google Calenderに以下のフォーマットで終日イベントが作成される。
* 「約定(code)x株」
* 2.スプレッドシート「StockOrderList」に約定内容が追加される。
*
* 2022/01/06 Created by N.Sekiya
*/
// 処理済み後に付けるラベル名(ラベルが存在しなければ自動的に作られる)
var LABEL = '自動処理済';
// GMail検索文字列(楽天カードからの請求予定金額情報)
var SEARCH_QUERY = 'is:unread -label:' + LABEL + ' from:tradesys@rakuten-sec.co.jp subject:米国株式の注文が約定しました';
// 検索文字列
var CUT_START = '注文番号';
var CUT_END = '約定は一部約定の場合があります。';
function registStockContractInfoToCalendar() {
// デフォルトカレンダーを取得
var calendar = CalendarApp.getDefaultCalendar();
var threads = GmailApp.search(SEARCH_QUERY, 0, 1);
if (threads.length === 0) {
Logger.log("メールが見つかりません");
return;
}
for(var k in threads){
var thread = threads[k]
var messages = thread.getMessages();
for (var j in messages){
var message = messages[j];
var body = message.getPlainBody(); // HtmlメールからPlain textの本文を取得する
var cutting = false;
var ticker = null;
var amount = null;
var startTime = null;
var endTime = null;
var contents = '';
// スプレッドシート追記用
var ticker_name = null;
var type = null;
var pay_type = null;
var unit_price = null;
// 楽天証券からの約定メールの内容確認
var rows = body.split("\n");
for (var i in rows) {
var row = rows[i];
if(row.indexOf(CUT_START) >= 0){
cutting = true;
}
if(cutting){
if(row.indexOf(CUT_END) >= 0){
cutting = false;
}
else{
contents += row + '\n';
if(row.indexOf('銘柄名(銘柄コード):') >= 0){
ticker = row.match(/([A-Z]*)/);
ticker_name = row.replace('銘柄名(銘柄コード):', '');
}
else if(row.indexOf('口座・売買:') >= 0){
type = row.replace('口座・売買:', '');
}
else if(row.indexOf('決済方法:') >= 0){
pay_type = row.replace('決済方法:', '');
}
else if(row.indexOf('約定単価:') >= 0){
unit_price = row.replace('約定単価:', '');
unit_price = unit_price.replace('米ドル', '');
}
else if(row.indexOf('約定数量:') >= 0){
amount = row.match(/\d{1,2}/);
}
else if(row.indexOf('約定日時:') >= 0){
tmp = row.match(/\d{4}\/\d{1,2}\/\d{1,2} \d{1,2}:\d{1,2}/)
Logger.log(tmp[0]);
startTime = new Date(tmp[0]);
endTime = new Date(startTime.getTime() + 10 * 60000); // 終了時刻取得
}
}
}
}
Logger.log('ticker_name:' + ticker_name);
Logger.log('type:' + type);
Logger.log('pay_type:' + pay_type);
Logger.log('unit_price:' + unit_price);
Logger.log('amount:' + amount);
Logger.log('date time:' + startTime);
// スプレッドシートに追記
libAddStockOrderToList.registToSpreadSheet('StockOrderList', '',
ticker_name, type, pay_type, unit_price, amount, startTime);
// Googleカレンダーに登録
if(ticker && amount && startTime && endTime){
var title = '約定' + ticker + amount + '株';
Logger.log(title);
Logger.log(contents);
if(checkExist(calendar, startTime, endTime, title) == false){
var options = {
description : contents
}
var event = calendar.createEvent(title, startTime, endTime, options);
event.setColor(CalendarApp.EventColor.GREEN);
event.removeAllReminders(); // 結果なので通知は無し
}
}
// 処理済みメールとしてラベルを付ける
putLabel(thread);
}
}
}
/*
* 登録済み情報があるかチェック
*
*/
function checkExist(calendar, registStart, registEnd, registTitle){
// イベントリスト取得
var events = calendar.getEvents(registStart, registEnd);
for(const event of events){
var title = event.getTitle();
//Logger.log('title:' + title);
if(title.indexOf(registTitle) >= 0){
return true; // イベント登録済み
}
}
// イベント未登録
return false;
}
/*
* 処理済みとしてスレッドにラベルを付ける
*
* LABELで指定されるラベルが存在しない場合は作成する
*/
function putLabel(thread){
var label = GmailApp.getUserLabelByName(LABEL);
if(label){
thread.addLabel(label);
Logger.log('既存ラベル使用');
}
else{
var newlabel = GmailApp.createLabel(LABEL);
thread.addLabel(newlabel);
Logger.log('新規ラベル追加');
}
}
Googleカレンダーの登録が残っていますが、必要なければcalendar.createEventからの3行を削除してください。
繰返し実行
正しく動作することを確認したら、繰り返し実行できるよう設定します。
トリガーを設定し、registStockContractInfoToCalendar()を定期的に呼び出すようにします。
トリガーの設定方法については、以下の記事を参照ください。
繰り返し実行する間隔は、急ぐ必要のない処理なので5分おきにします。
まとめ
いかがでしたでしょうか。
これで楽天証券からの米国株式約定通知メールを受信すると、カレンダーに追加し、スプレッドシートに追加されるようになりました。
自分が必要な情報を、自動的に必要な場所に必要な形にすることで、ほんの少しストレスが解消されて、生きやすくなると思います。
それを積み重ねることで、積みあがった自由時間を使い、もっと自由な発想で面白いことに取り組めるようになるはずです。
技術は人を自由にすると思うのです。
では、今日も良い一日を。