メタラーまとんがハイソにやらかすようです

東大理系修士卒JTBCエンジニアのハイソサイエティ(上流階級)な日常

Suicaの電車賃でポイントが貯まるサービスが10月1日からスタート!やらない理由が無いから、今すぐ登録!

ども!まとんです。

お得なポイント情報をみんなに知らせることに、生きがいを感じている者です。

10月1日から電車賃でポイントが貯まるサービスが始まっているので、知らなかった人は、是非やりましょう!

10月1日から電車賃でJREポイントが貯まる!!

www.jrepoint.jp

消費税が10%に増税した10月1日から、Suicaで電車利用した分に対してポイントが貯まるサービスが開始しました!!

これまで、電車賃でポイントを発生させることは不可能でした。画期的なサービスが開始したと思っています。

プライベートで電車を使ったときはもちろん、会社の出張旅費を自分のSuicaで立て替え払いしている人は、出張に行けば行くほどポイントを溜められることになります。最高ですね!!!

利用するためにはWeb上でSuicaの登録が必要

このサービスの大事なのは、Web登録しないとポイントが貯まらないことです。

具体的には、JRE POINT WEBサイトで会員登録をして、自分のSuicaの番号を登録する必要があります。

登録しないとポイントが貯まりません。

やらない理由が全くないので、この記事を読んだ人は今すぐ登録した方が良いと思います。

貯まったポイントは、1ポイント=1円でSuicaへのチャージや、駅ビルのお店での買い物に使えます。

また、JRE POINTのポイントカード(駅ビルのお店で使えるポイントカード)を持っている人は、それも紐づけることができるので、ポイントが一括管理できてよいです。

ポイント還元率は0.5%、チャージ時の二重取りも可

気になるポイントの還元率は、0.5%です。

例えば200円乗ったら1ポイント(=1円)です。

片道1000円の出張に行けば、往復で10ポイントが貯まります。

199円以下でも、切り上げで1ポイントが貰えます。さすがJR、太っぱら!

モバイルsuicaなら4倍の2%貯まる!!

さらに、モバイルSuicaを使っている人は、電車賃のポイントが0.5%の4倍の2%になります!

2%はヤバいですね!!

片道1000円の出張で40円もたまります。なかなか無視できない金額ですよね!

モバイルsuicaというのは、スマホやスマートウォッチにSuicaを登録するサービスです。

Suicaを取り出さず、スマホ1台で決済が完了できるので、是非登録しましょう。

Suicaチャージでもクレカポイントは貯まる。VIEWカードオートチャージが最強

Suicaにクレカでチャージすれば、チャージにかかる代金でクレカのポイントも貯まるので、ポイントの二重取りができます。

例えば1%分のポイントが貯まるクレカを使っている人は、1000円チャージして1000円分電車に乗れば、1% + 0.5% = 1.5%分がたまることになります。

JRE POINTに特化した現状の最強のクレカは、JR系列が発行しているクレカVIEWカードシリーズだと思います。

VIEWカードは通常は0.5%ですが、Suicaチャージ時は1.5%です。

なので、例えばモバイルsuicaと組み合わせると、

(1)1000円チャージ時に1.5%たまる

(2)1000円電車に乗って、モバイルSuicaで2%たまる

で、合計3.5%貯まることになります。1000円使えば35円です!

VIEWカードなので、suicaへのオートチャージ設定も可能です。

ANA VISA suicaだとシナジー効果無し・・・。

僕はメインのクレカでANA VISA suicaカードを使っていますが、残念ながらANA VISA suicaと今回のサービスはシナジー効果が無いです。

ANA VISA suicaVIEWカードなのでオートチャージができて、ANAマイルが貯まるカードなのですが、

実はVIEWカードには2段階あって、JRE POINTが貯まる正規(?)VIEWカードと、他社ポイントが貯まる非正規(?)VIEWカードがあります。

僕のANA VISA suica三井住友カードのポイントが貯まる非正規VIEWなので、チャージ時のボーナスはありません。(とはいえ、普通の倍率でマイルは貯まる)

今すぐ登録しよう!!

とにかく、この記事を見た人は、今すぐ登録しましょう。

登録しないで電車に乗るのがもったいないです!

www.jrepoint.jp

以上、メタラーまとんでした。

ではでは。

「日本一長いすべり台」を時速30kmで滑ってきた!奥日立きららの里

ども!まとんです。

我々オタク仲間で毎年秋に開催している恒例行事、「ふれっしゅツアー」

今年は24人ものオタク達が集結し、「日本一長いすべり台」で有名な奥日立きららの里@茨城に行ってきました!

f:id:highso:20191005194427j:image

パリピの皮をかぶった陰キャたちの図。ちゃんと全員オタク。

奥日立きららの里

奥日立きららの里は、東京ドーム10個分の敷地を活用し、全長1188メートルの日本一長いすべり台「わくわくスライダー」や宿泊施設 「ケビン」 ・ 「オートキャンプ場」 ・ 「バーベキュー]など、ご家族で
楽しめる 宿泊体験型のレクリエーション施設です。また自然豊かで、四季折々の風景も楽しめます。

東京からのアクセスは、車が良いでしょう。

我々は貸切バスで10:00に新宿駅を出発し、12:30頃に到着しました。(バスをチャーターしてくれた、ふれっしゅ氏に感謝!)

まず、手ぶらバーベキューで腹を満たしてから、いざすべり台へ!!

わくわくスライダー

きららの里のメインアトラクションです。

全長1188mのすべり台

僕の第一印象は「お尻が痛くなりそう・・・」でしたが、現地に行ってみると、思っていたのと違いました。

f:id:highso:20191005194415j:image

f:id:highso:20191005185230p:image

すべり台とは名ばかりで、本格的なスライダーでした!!

カート(スレッドと言うらしい)には大人は1人乗り、子供(4歳〜小2)は大人との2人乗りです。

カートはタイヤがついていて、摩擦がほぼ無く、滑らかに進みます。

搭乗者はブレーキのバーを操作できて、怖くなったらブレーキをかけられます。

注意書きには「急カーブではブレーキをかけてください」「前の人にぶつからないようにしてください」「ノーブレーキ走行はやめてください」などと書いてありますが、要するに、搭乗者の運転技術に委ねられている。

急カーブで速度を出しすぎたり、体のバランスを崩すと、コースアウトも普通にありえます。かなりスリリングですね。

いちおう、30km/hを超えると自動ブレーキがかかるようです。

乗ってみた感想!

めっちゃ楽しかったです!

遊園地のアトラクションのように決められた速度が出る仕組みではなく、ウォータースライダーのように自分でスピードを調整できるのが楽しいです。

急カーブではちゃんとブレーキをかけないと、本当にコースアウトしてしまいそうで、「まだ死にたくない」とか頭をよぎっていました。

スキー用アプリで速度を測ってみた!

せっかくなので、スキーやスノボで滑走記録をつけるアプリ「Ski Tracks」を使って、実際にどの程度の速度が出ているのか測定してみました。

f:id:highso:20191005190008p:image

こちらが結果。滑り降りたあとに、ワイヤーで元の高さまで戻るところまで計測しました。

最大速度は時速30.8kmとでていますね。

このアプリは誤差が大きいので正確な数字は分かりませんが、最大速度の30km/h近くを出せていたようです。
f:id:highso:20191005190012p:image

速度と高度の変遷。

滑っている間は概ね30km/h出ていたようです。

料金

奥日立きららの里の入場料は、大人260円、子供80円。

わくわくスライダーの1回券は、大人530円、320円。

ただし、3人以上いるのなら、3回券の大人1280円、子供740円を買って、シェアするのがオススメです。

土曜日のお昼に行きましたが、かなり人気で混んでおり、搭乗までに約30待ちでした。

その他

きららの里には、すべり台の他にも色々と遊ぶところがあります。

一番のオススメはポニーですね。

f:id:highso:20191005185236j:image

ポニーかわいい!触れる!顔デカイ!

100円でエサを買ってあげることもできます。

f:id:highso:20191005185238j:image

手のひらにモナカを乗せて差し出すと

f:id:highso:20191005185241j:image

パクッ

f:id:highso:20191005185243j:image

モシャモシャ

 

良い・・・。

動物に触れ合えるのは、とても良い。

他にも羊とかウサギとかニワトリとかいました。

f:id:highso:20191005185247j:image

ちなみに、わくわくスライダーは飲酒していると乗れません。

なので、バーベキューではノンアルコールで我慢して、スライダーが終わった後に乾杯するのがオススメです!

なお、僕は飲めないのでQooで乾杯。運動した後のQooは、めっちゃ美味い。

 

日本一長いすべり台、みなさんも体験してみてください!

以上、メタラーまとんでした。

ではでは。

過去のふれっしゅツアー関連記事

2018年

フライボード

流しそうめん

2017年

ラフティング

キャンプファイヤー

【育児応援bot】赤ん坊の写真を送るとAmazon Rekognitionで画像解析して褒めてくれるLINEボットを作った!

ども!AWS認定SAアソシエイトのまとんです。

最近、LINEボットを作るのにハマっています。

今回、赤ん坊の画像を送ると「育児してて偉い!」と返してくれる「育児応援LINEボット」を作ったので紹介します!

【使ったもの】

AWS関連:Amazon Rekognition、Lambda、API Gateway

・LINE関連:Messaging API

・開発環境:Windows10、Python 3.7

Amazon Rekognitionを使うと、めちゃくちゃ簡単に画像解析ができました。AI楽しい!!

経緯

うちには0歳の娘がいます。

平日、僕が働いていると、嫁が娘のカワイイ写真をLINEでたくさん送ってくれます。

僕はそれを、トイレ休憩の合間なんかに見てホッコリして、「今日も育児してくれてありがとう!偉い!」と返事をするわけです。

しかし、仕事中なので、すぐに返事をすることはできません。

嫁が写真を送ってから僕が返事をするまでに、若干のタイムラグが生じてしまうのが課題でした。

そこで、娘の写真を送ったら、すぐに「育児してて偉い!」と僕の代わりに返事をしてくれるbotを作れば、嫁はタイムリーに返事が貰えて良いのでは!?と考えました。

(旦那の仕事を、クラウドにアウトソース!これが俺の""働き方改革""

作りたいもの

f:id:highso:20190929192530p:image

作りたいものの要求仕様は下記です。

(1)LINEで写真を送ったら、すぐに返事をしてくれるLINEボット。

(2)写真が娘の写真だったら「偉い!」と褒める。関係の無い写真だったら、褒めない。

(1)については前回の記事で同等のものを実装したので、この記事では(2)について解説します。

highso.hatenablog.com

実装

アーキテクチャ

f:id:highso:20190929152858p:plain

< 前回の記事での実装分>

僕と嫁とbotの三人が入っているLINEのトークルームを用意します。

LINEのbotはMessagingAPIというサービスで簡単に作ることができます。

LINEのトークルームで誰かが発言すると、botはwebhookで他サービスのAPIを叩くことができます。

他サービスとして、AWSAPI GatewayAPIを叩くように設定します。

API Gatewayは、Lambdaを叩くように設定します。

LambdaでMessagint APIのPOSTを捌いて返事をする処理を行います。

<この記事での実装分>

Lambdaでは、まずbotが受け取った画像のデータを、MessagingAPIから受け取ります。

受け取った画像データを、Amazon Rekognitionという分析APIに投げます。

Rekognitionは、AWSによって学習済みの画像解析モデルを使って、識別だけを行ってくれるサービスです。(他にも機能はいっぱいあるかも)

Rekognitionが、画像に含まれるラベル(赤ん坊が含まれている確率90%、など)と、顔認識(推定年齢0~5歳、など)を行って、結果を返してくれます。

結果に応じて、赤ん坊だったら「偉い!」というメッセージをMessaging APIに返します。

botがメッセージを応答します。

赤ん坊の写真と判定する仕組み

Amazon Rekognitionには画像と動画を分類する様々な機能があるのですが、今回はラベル検出の「DetectLabels」と、顔検出と顔分析の「DetectFaces」の二つを使います。

これらを使って、「赤ん坊の画像化かどうか?」を判定します。

まず、DetectLabelsで、画像に含まれるラベルを検出します。

ドンピシャの「Baby」ラベルが信頼度50%以上で検出されれば、OKです。

しかし、画像によっては、うまく「Baby」が検出されず、類似の「Human」「Person」「Newborn」が検出されることもあります。

この場合には、さらにDetectFacesを使って、年齢を推定します。

DetectFacesでは、顔の画像から、「性別」や「感情」など色々な情報を推定します。

この中から「年齢レンジ」だけを使います。

年齢レンジの最大値が「4歳以下」だった場合には、赤ん坊と判定することにしました。

 

以上の方式をまとめると、

・画像にBaby画像があるか?

・画像に人がいる場合、年齢は4歳以下か?

で判定するようにしました。

この仕組みでうまく判定できない場合は、「赤ん坊が後ろ向きの写真」です。

顔が映っていないと、顔検出で年齢推定ができないので、上手く判定できません。

Lambdaコード

LINE bot~Lambdaまでの通信部分については、前回の記事に書いたので、そちらをご覧ください。(LINEボットライブラリをpipでローカルにインストールして、zipに固めてlambdaにアップロードする必要があります)

ソースコードGitHubに公開しています。

github.com

以下では、Lambdaコードの部分だけを開設します。

コードは最終的に以下のようになりました。

import json
import sys
import os
import random
from datetime import datetime as dt
from datetime import timedelta
import boto3
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
from linebot.exceptions import (
LineBotApiError, InvalidSignatureError
)

#(1)Amazon REKOGNITION
rekognition_label = boto3.client('rekognition')
rekognition_face = boto3.client('rekognition')

#(2)LINE Messaging API
LINE_CHANNEL_SECRET = os.getenv('LINE_CHANNEL_SECRET', None)
LINE_CHANNEL_ACCESS_TOKEN = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
if LINE_CHANNEL_SECRET is None:
    print('Specify LINE_CHANNEL_SECRET as environment variable.')
    sys.exit(1)
if LINE_CHANNEL_ACCESS_TOKEN is None:
    print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
    sys.exit(1)
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)

#(3)Messaging API Handler
@handler.add(MessageEvent)
def message(event):
    #(4)LINE message information
    event_type = event.type
    message_type = event.message.type
    message_id = event.message.id
    #msg = 'event_type: ' + event_type + ', user_id: ' + user_id + ', message_type: ' + message_type + ', message_id:' + message_id

    if message_type == 'image':
        #(5)Get image data from LINE
        message_content = line_bot_api.get_message_content(message_id)
        content = bytes()
        for chunk in message_content.iter_content():
            content += chunk

        #(6)Recognize image by Rekognition
        labels = detect_labels(content)
        print(labels)
        msg_label = ''
        baby_flag = False
        human_flag = False
        for label in labels['Labels']:
            msg_label += label['Name'] + ':' + str(round(label['Confidence'],1)) + '% '
            if label['Name'] == 'Baby':
                baby_flag = True
                print('Here is a baby.')
            if label['Name'] == 'Baby' or label['Name'] == 'Person' or label['Name'] == 'Human' or label['Name'] == 'Newborn':
                human_flag = True
                print('Here is a Human.')
        msg_label = msg_label[:-1]

        #(7)Detect face in image by Rekognition
        if human_flag == True: #When a human is detected
            FaceDetails = detect_faces(content)
            print(FaceDetails)
            if len(FaceDetails['FaceDetails']) == 0: #When a face is not detected
                human_flag = False
            else:
                age_min = FaceDetails['FaceDetails'][0]['AgeRange']['Low']
                age_max = FaceDetails['FaceDetails'][0]['AgeRange']['High']
                msg_face = 'Age:' + str(age_min) + '-' + str(age_max) + 'years old'
                if age_max < 5:
                    baby_flag = True

        #(8)Ask LINE bot to reply messages
        text = []
        if baby_flag == True: #There is a baby
            msg_approval = ['可愛い!', '天使!', '偉い!', '育児して偉い!', '最高!', 'すごい!', 'キャワワ!', '天才!', '【大当たり】おめでとうございます!']
            text.append(TextSendMessage(text=random.choice(msg_approval)))
        else: #There is no baby
            text.append(TextSendMessage(text='No baby.'))
            text.append(TextSendMessage(text=msg_label))
        if human_flag == True: #There is a face
            text.append(TextSendMessage(text=msg_face))
        line_bot_api.reply_message(event.reply_token, text)

def detect_labels(image_bytes):
    try:
        res = rekognition_label.detect_labels(
            Image={
                'Bytes': image_bytes
                },
            MaxLabels=6,
            MinConfidence=50
        )
    return res
    except Exception as ex:
        print("fail to detect labels. error = " + ex.message)

def detect_faces(image_bytes):
    try:
        res = rekognition_face.detect_faces(
            Image={
               'Bytes': image_bytes
            },
            Attributes=[
                'ALL',
            ]
        )
        return res
    except Exception as ex:
        print("fail to detect faces. error = " + ex.message)


def send_line_bot(signature, body):
    ok_json = {"isBase64Encoded": False,
        "statusCode": 200,
        "headers": {},
        "body": ""}
    error_json = {"isBase64Encoded": False,
        "statusCode": 403,
        "headers": {},
        "body": "Error"}

    try:
        handler.handle(body, signature)
    except LineBotApiError as e:
        print("Got exception from LINE Messaging API: %s " % e.message)
        for m in e.error.details:
            print(" %s: %s" % (m.property, m.message))
        return error_json
    except InvalidSignatureError:
        return error_json

    return ok_json

def lambda_handler(event, context):
    signature = event["headers"]["x-line-signature"]
    body = event["body"]
    res = send_line_bot(signature, body)
    print(res)

    return res

(1)Amazon REKOGNITIONのインスタンス生成

Pythonの場合、AWSの公式ライブラリboto3を使って、APIを叩くためのインスタンスを簡単に作れます。

(2)LINE Messaging APIインスタンス生成

Messaging APIのアクセストークン(環境変数に登録)を使って、Messaging APIインスタンスとハンドラーを作ります。

(3)Messaging APのHandler関数

@handler.add(MessageEvent)
def message(event):

    (処理内容)

で、「LINE botがメッセージイベントを受信したとき」に起動する関数を作れます。

「メッセージイベント」とは、テキストや、スタンプ、画像などを含みます。

テキストだけに反応させたいときは、「@handler.add(MessageEvent, message=TextMessage)」とすればよいです。

参考:

GitHub - line/line-bot-sdk-python: LINE Messaging API SDK for Python

Messaging APIリファレンス

(4)LINEのメッセージ情報を取得

eventオブジェクトの中に、メッセージの様々な情報が含まれています。

今回は、event.message.typeで「画像メッセージかどうか」の情報を取得するのと、event.message.idで「メッセージごとに一意に付けられるid」を取得します。

(5)LINEから画像データを取得

画像メッセージだったときに、get_message_content()メソッドを使って、(4)で取得したidに紐づく画像データのバイナリを取得します。

バイナリはfor文でイテレーションできるので、結合して、content変数に画像データの全体を格納します。

(6)Rekognitionで画像のラベル検出

いよいよ、Rekognitionを使って画像を分析していきます。

自前で作ったdetect_labels()では、Rekognitionインスタンスのdetect_labels()メソッドを起動して、RekognitionのAPIに画像を受け渡して、結果をresに取得します。

Rekognitionへの画像データの受け渡し方は2通りあります。

(1)S3に保存済みの画像を使う。S3のキーを渡す。

(2)バイナリを直接送る。

どちらの実装でもよいのですが、(1)の場合には、「S3に画像を一時的に保存→Rekognitionに画像を送る→S3から画像を削除」という手続きを踏む必要があり、めんどうでした。

今回、LINEから画像データをバイナリで受け取っているので、ストレージを経由せず、直接渡す(2)の方式を選びました。

参考:DetectLabels - Amazon Rekognition

detect_labels()では、「最大ラベル取得数」と「信頼度の下限」をJSONで設定できます。

今回は、「最大ラベル数6、信頼度50%」と設定しました。

信頼度が50%以上のラベルの上位6個を返してくれます。

 

ラベルの識別結果は、labels['Labels']に格納されます。

これをfor文でイテレートすると、['Name']にラベル名が、['Confidence']に信頼度が入っています。

今回、'Baby'ラベルの有る無し、などを調べています。

(7)Rekognitionで顔検出と顔認識

人間のラベル(Baby, Human, Person, Newborn)が含まれていた場合には、さらにdetect_faces()のAPIを叩きます。

APIの使い方はdetect_labels()と同様に、JSONで画像のバイナリデータを送るだけです。カンタン!

結果は['FaceDetails']に格納されますが、注意として、顔が検出されなかった場合には['FaceDetails']に何も格納されません。

なので、「if len(FaceDetails['FaceDetails']) == 0:」でエラー処理を入れています。(他に良い方法をご存知の方は、教えて欲しいです)

 

顔の検出結果は、様々な属性がありますが、

今回は最大年齢['FaceDetails'][0]['AgeRange']['High']を使って、「4歳以下かどうか」を調べています。

参考:DetectFaces - Amazon Rekognition

(8)結果をLINE botに返す

line_bot_api.reply_message(event.reply_token, text)で、textの内容をLINE botに返事させることができます。

textには、TextSendMessage(text=<文章>)で定義したTextSendMessageオブジェクトを入れます。

textをTextSendMessageのリストにすると、リストの個数分のメッセージをbotが返事することになります。

今回は、

・赤ん坊だったら褒めるメッセージをランダムに1個返す。赤ん坊でなかったら「No baby.」と返す

・detect_labelsで識別したラベルを返す。

・detect_facesで識別した推定年齢を返す。ただし、顔が検出できなかったらナシ。

と返事をするよう実装しました。

 

ここで、LINE botではテキストを返すのは簡単ですが、画像を返すの難しいです。

画像を返す場合、画像を何らかの形でインターネット公開して、アドレスを渡す必要があります。

例えば、一旦S3に格納して、静的webホスティングでアドレスを与える、などすれば可能かと思います。

本当は、画像に対して「ここが赤ん坊と識別されました」のバウンディングボックスをつけた画像を返したかったのですが、今回は見送りました。

環境変数

Lambdaの環境変数に、Messaging APIのアクセストークンを2個、登録する必要があります。

LINE_CHANNEL_SECRETとLINE_CHANNEL_ACCESS_TOKENです。

IAMロール

Lambdaには、Rekognitionを使うためのIAMポリシーをアタッチする必要があります。

f:id:highso:20190929152829p:plain

 AmazonRekognitionFullAccessと、CloudWatchLogsFullAccessのポリシーをアタッチしたIAMロールを作成し、このIAMロールをLambdaにアタッチします。

f:id:highso:20190929152848p:plain

IAMロールが正しく機能していれば、LambdaのDesinger画面ではこのように、アクセス先のリソースにCloudWatchとRekognitionが表示されるはずです。

タイムアウト設定

Lambdaのタイムアウトはデフォルトで3秒に設定されています。

Lambdaは使用した時間単位で課金されます。例えば無限ループに入ってしまうと、無限に課金されてしまうので、タイムアウトの設定は必須です。

今回、Rekognitionの応答に若干の時間がかかるので(特にdetect_facesに数秒かかる)、3秒だとタイムアウトしてしまいます。

10秒に設定すれば、タイムアウトを回避できました。

f:id:highso:20190929152818p:plain

デモ

無事に、赤ん坊の画像を送ると褒めてくれる「育児応援botができました!!

感想

AI楽しい!!!この一言に尽きます。

Rekognitionを使えば、学習とかめんどくさいステップを全て吹っ飛ばして、結果だけ返してくれるので、ラクチンでした。

最初は「LambdaにTensorFlowをインストールする必要があるのか・・・?」とか思っていましたが、そんな必要はなかったんや。

Rekognitionの精度は、AWSさんに委ねられているので、今後も頑張って精度を上げていってほしいです。

 

LINEbotを使い始めると、嫁も楽しんで写真を送ってくれるようになりました。

作ったオモチャを家族に使ってもらえるのは楽しいですね。

クラウドアプリなので、モノを管理する必要も無いので、運用が簡単なのもいいです。

 

みなさんも是非、Rekognitionで遊んでみてください!

以上、メタラーまとんでした。

ではでは。

株主優待目当ての投資を始めていくぞ!

ども!ファイナンシャルプランナー2級のまとんです。

そろそろ、株式投資にチャレンジしていこうかと思います。

僕の投資履歴

社会人を3年ほどやって、まず、現金を貯めました。

社会人になる前からファイナンシャルプランナーの勉強を始めたので、無駄な保険に毎月お金を落とさないよう工夫して、手取り(可処分所得)を最大化しました。

僕は酒もタバコもギャンブルも風俗も車もやらないので、我ながら低燃費男子だと思っています。

趣味はブログ、資格取得、水彩画、電子工作、ボードゲームなど、低コストなものばかりです。

ボーナスが出ても、特に欲しいものもないし、ほとんど貯金しています。

散財は、たまに夫婦でハイソディナー(高級ホテルのビュッフェとか、アフアヌーンティーとか)に行くことくらいです。

結婚式と新婚旅行と第一子の出産を済ませたので、しばらく大きな出費は無い見込みです。

医療保険だけは掛け捨ての安いものに加入していて、入院費用はリスク管理しています。

奨学金の返済は毎月続けています。42歳くらいまで続く予定です。

まずは積立NISA

で、銀行の預金が「いざというときに対応できる程度の額」たまったので、投資を始めました。

まずは、積立NISA投資信託を月3万始めました。

積立NISAは20年間の制限があるので、20年後に引き下ろして、子供の大学の学費に充てる予定です。

積立NISAを始めるために、楽天証券で口座を作ったり、投資信託の仕組みを勉強しました。

はじめての投資だったのでドキドキでしたが、NISA制度に後押ししてもらえました。

ドル建て生命保険

次に、ドル建ての生命保険に加入しました。

子供が産まれたので、僕が急死した時に家族が路頭に迷わないためのリスク管理としての生命保険です。

さらに、この生命保険はドル国債ベースの保険商品で、毎年固定金利で運用されます。

30年後にざっくり2倍になるというプランです。

解約時のドル円為替レートも関係するので、外為の商品でもあります。

僕が定年まで死ななければ、30年後に引き出して、老後資金に充てるつもりです。

iDeCoはやっていない

今の時代は「とりあえずiDeCoとNISAがお得だからやっておけ」と言われていますが、iDeCoはまだやっていません。

iDeCoは60歳になるまで引き出せないので、使い道は老後資金になります。

僕の場合は、ドル建て生命保険と役割が被っているので、二重になるのはもったいないなぁと思う気持ちと、

iDeCoで買う商品は投資信託なので、積立NISAと被っており、つまらないなぁと思う気持ちがあります。

なので、iDeCoはまだ始めていません。そのうち始めるかも。

国内株式を始めるぞ!

さて、これまでに

・銀行の預金(最低リスク)

・ドル国債の生命保険(小〜中リスク)

・NISA枠で投資信託(中リスク)

とやってきました。そろそろ、高リスクの資産をポートフォリオに加えてもよいかなと思い、

・国内株式(高リスク)

にチャレンジしようかと思います!

 

株式のやり方としては、

・配当金、株主優待券などのインカムゲイン目的

・長期のキャピタルゲイン目的

・短期のキャピタルゲイン目的

があります。

まずは最も気軽に始められる、株主優待券目的の投資からスタートしていきます。

株主優待を調べるの楽しいぞ!

まずは、株主優待の情報を見渡せるこの本を買ってみました。

何月にどの企業の株を所有していれば、どんな優待が貰えるか、がリストになっています。

例えば、9月末にさくらインターネットを100株所有していれば、500円のQUOカードが貰える、など分かります。

ネットでも同等の情報は調べられるのですが、嫁と2人で、るるぶを読む感覚で読めるのが楽しいです。

 

で、株主優待は主に3月の月末に権利確定する銘柄が多いのですが、次に多いのは9月です。

というわけで、まずは練習として9月権利確定の株を少し、指値注文してみました。

 

株式は高リスクなので、どうなるかわかりませんが、

まずは色々とトライしてみようと思います。

 

以上、メタラーまとんでした。

ではでは。

投資の現況記事

1. 株主優待目当ての投資を始めていくぞ!

2. 投資の近況報告!!積み立てNISA、ドル建て生命保険、国内株式

3. JTBC社員が投資に走るワケ

4.【国内株式】なんとかコロナを生き延びてます。3ヶ月を振り返る

5. 資産運用の現況!第二次コロナショックに備えてどうする!?

6. 父の日なので100万円を入金しました!ポートフォリオを見直して17年後の2000万円を目指す!

7. 素人投資家のリアルな現実をお伝えします。300万円が1年半で何円になった?

LINE Botに生命保険の解約返戻金を教えてもらえるようにした!Messaging API, Amazon API Gateway, Lambda

ども!AWS認定SAアソシエイトのまとんです。

LINE botに話しかけると、生命保険の金額を教えてくれる仕組みをで作ったので紹介します!

使ったもの:AWSを使ってサーバーレス実装しました。

経緯

先日、ドル建て生命保険の解約返戻金をLINEに通知してくれる仕組みを作りました。

highso.hatenablog.com

SORACOMのボタンを押すと、LINEのトークルームに金額を通知してくれるという仕組みです。

SORACOM LTE-M Button powered by AWS

SORACOM LTE-M Button powered by AWS

 

f:id:highso:20190916232950j:plain

このボタンをダイニングテーブルの上に置いておきました。

嫁には「好きな時にボタンを押していいよ!」と言っておいたのですが・・・

f:id:highso:20190922154821p:plain

嫁いわく、「ボタンを押すのがめんどくさい。LINEで反応させてくれ」とのこと。

ボタンを押すことさえ、手間。LINE上で完結させないとダメのようです。

となると、実装がガラリと変わるので、大変なのですが。。。

 

しかし、顧客(嫁)が本当に求めているものを、何としてでも作って提供するのがエンジニア冥利というものです。

というわけで、LINE Botで返事をする仕組みを作りました。

作りたいもの

今回の要求仕様は以下の通りです。

完成形のイメージ:

f:id:highso:20190922161659j:plain

実装

アーキテクチャ

f:id:highso:20190922154840p:plain

LINEはMessaging APIなるサービスで、独自のbotを作る仕組みを提供しています。

Messaging APIで作った自分専用のbotを、僕と嫁のトークルームに参加させます。

トークルームで話しかけると、botのMessaging APIが反応し、webhookで別システムのAPIを叩くことができます。

別システムとして、AWSを使用します。

AWSではAPI Gatewayを使って、自分のAPI(アドレス)を簡単にインターネット公開することができます。

Messaging APIのwebhookでAPI Gatewayのアドレスを叩くように設定することで、LINEとAWSを連結させることができます。

API Gatewayは、後段のLambdaを起動して、POSTメッセージを捌く処理を実装します。

POSTの応答で、botに生命保険金額を発言するように返せばOKです。

生命保険金額の複利計算と、ドル円為替レートの取得については、前回の記事で詳細に説明したので、この記事では省略します。

Messaging API

LINE botを作っていきます。以下の記事を参考にさせていただきました。

LambdaではじめてのLINE Botを作る | DevelopersIO

LINE Developersに登録して、bot用チャネルを作成

まず、LINE Developersコンソールに、自分のLINEアカウントでログインします。

新規プロバイダーを作成します。プロバイダーとは、開発者(企業・個人)の名前です。

プロバイダー名「メタラーまとん」で作成しました。

次に、Messaging APIのチャネルを作成します。チャネルは、botことだと理解しています。

チャネル名「メタラーまとん」で作成しました。

チャネルの設定

メタラーまとんチャネルの「チャネル基本設定」カラムで、色々と設定します。

・Channel Secretの文字列をコピー

・アクセストークン(ロングターム)を発行→文字列をコピー

Botグループトーク参加→設定はこちら

 「グループ・複数人チャットへの参加を許可する」にチェック。自分と嫁のグループチャットを使うため。

f:id:highso:20190922154846p:plain

・LINE@機能の利用→自動応答メッセージ→設定はこちら

 「応答メッセージ」をオフ。デフォルト(オン)では、話しかけたときに毎回返信をするようになっている。今回は不要なのでオフにする。

AWS

必要なライブラリをzipで固めてLambdaにアップロードする

今回の実装では、LambdaのPython3.7ランタイムを使います。

Lambdaでサードパーティのライブラリを使いたいときは、直接pip installすることができず、一旦ローカルでpipをして、zipで固めてアップロードする必要があります。

今回必要なライブラリは、line-bot-sdk、oandapyV20、requestsです。これらをzipで固めていきます。

 

僕は開発環境でWindows 10を使っていて、pipするのが難しいです。

そこで、Windows Subsystem for Linux (WSL)でUbuntuを走らせて、この上でpipしていきます。WSLへのPythonインストール手順は割愛します。

作業用ディレクトリ作成、移動

$ mkdir HighsoButton

$ cd HighsoButton

ライブラリを作業用ディレクトリにインストール

$ sudo pip3 install oandapyV20 -t ./

$ sudo pip3 install requests -t ./

$ sudo pip3 install line-bot-sdk -t ./

不要ファイルを削除

$ rm *.dist-info -r

フォルダごとzipに固める

$ sudo zip -r HighsoLineBot.zip ./*

f:id:highso:20190922154836p:plain

「HighsoLineBot.zip」ができればOKです。

WSLを使っている人は、下記コマンドでzipをWindows環境にコピーしましょう。

$ cp HighsoLineBot.zip /mnt/c/Users/<ユーザー名>/Desktop/

 

次に、AWS Lambdaで、新しいLambda関数を作成します。

関数名:HighsoLineBot

リージョン:オレゴン

ランタイム:Python 3.7

コードエントリタイプ→「.zipファイルをアップロード」で、先ほど作成したzipをアップロードし、画面右上の「保存」ボタンを押します。

f:id:highso:20190922154809p:plain

./HighsoLineBot/ 以下に、各種ライブラリのフォルダが出現すればOKです。

./HighsoLineBot/に、新しいPython「lambda_function.py」を作成して、保存します。

AWS LambdaでPOST処理を書く

lambda_function.pyに、POSTを捌く処理を書いていきます。

line-sdk-botの使い方について、以下の記事を参考にさせていただきました。

Lambdaでline-bot-sdk-pythonを使用してオウム返しBOTを作成する - Qiita

Lambdaでやることは以下の通りです。太字以外の部分は、前回の記事実装済みです。

  1. OANDA APIドル円為替レートを取得
  2. 生命保険金の複利運用額を計算し、ドル円換金額を計算
  3. LINE-botハンドラーを作成。
  4. botからイベントを受け取り、X-Line-Signatureで認証
  5. メッセージ内に「円」「いくら」等特定の文字列があったら、2で計算したドル円換金額を答えるよう、botに指示
  6. POSTのステータスコードjsonで返す

具体的には、以下のコードをlambda_function.pyに書きました。(太字が今回実装した部分)

import json
import sys
import urllib.parse
import urllib.request
import datetime
import os
from oandapyV20 import API
import oandapyV20.endpoints.instruments as instruments
from datetime import datetime as dt
from datetime import timedelta
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,
)
from linebot.exceptions import (
LineBotApiError, InvalidSignatureError
)

# LINE Messaging API
LINE_CHANNEL_SECRET = os.getenv('LINE_CHANNEL_SECRET', None)
LINE_CHANNEL_ACCESS_TOKEN = os.getenv('LINE_CHANNEL_ACCESS_TOKEN', None)
if LINE_CHANNEL_SECRET is None:
    print('Specify LINE_CHANNEL_SECRET as environment variable.')
    sys.exit(1)
if LINE_CHANNEL_ACCESS_TOKEN is None:
    print('Specify LINE_CHANNEL_ACCESS_TOKEN as environment variable.')
    sys.exit(1)
line_bot_api = LineBotApi(LINE_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(LINE_CHANNEL_SECRET)

#OANDA API
OANDA_ACCESS_TOKEN = os.environ.get('OANDA_ACCESS_TOKEN')
api = API(access_token=OANDA_ACCESS_TOKEN)


def get_USDJPY():
    params = {
        'count': 1,
        'granularity': 'D'
    }
    r = instruments.InstrumentsCandles(instrument="USD_JPY", params=params)
    api.request(r)

    data = []
    for raw in r.response['candles']:
        data.append({
        'time': raw['time'],
        'volume': raw['volume'],
        'o': raw['mid']['o'], #始値
        'h': raw['mid']['h'], #高値
        'l': raw['mid']['l'], #安値
        'c': raw['mid']['c'], #終値
    })
    print(data)

    #前日の終値
    date = dt.strptime(data[0]['time'][:19], '%Y-%m-%dT%H:%M:%S')
    date = date + timedelta(hours = 9)
    #print(date)
    exchange_rate = float(data[0]['c']) #USD-JPYレート
    msg1 = str(date.year) + '年' + str(date.month) + '月' + str(date.day) + '日'
    msg2 = 'USD-JPY終値: ' + str(exchange_rate) + '円'
    print(msg1)
    print(msg2)

    #日ごとの複利計算
    start_date = dt(year=2019, month=8, day=20) #保険開始日
    elapsed_time = date - start_date
    elapsed_day = elapsed_time.days
    msg3 = '経過日数: ' + str(elapsed_day) + '日'
    print(msg3)

    ## Y = a*b^X
    ## 解約返戻金(USD) = a*b^(経過日数)
    a = 8457.28972
    b = 1.00007929
    refund_USD = a * b ** elapsed_day
    #refund_USD = refund/5
    exchange_fee = 0.5 #USDからJPYへの為替手数料(円)

    refund_JPY = refund_USD * (exchange_rate - exchange_fee)
    msg4 = '複利運用額: ' + str(round(refund_USD, 1)) +'ドル'
    msg5 = '解約返戻金: ' + str(round(refund_JPY, 1)) + '円'

    msgs = '\n'.join([msg1, msg2, msg3, msg4, msg5])
    print(msgs)
    return msgs


def send_line_bot(signature, body, msg_refund):
    ok_json = {"isBase64Encoded": False,
        "statusCode": 200,
        "headers": {},
        "body": ""}
    error_json = {"isBase64Encoded": False,
        "statusCode": 403,
        "headers": {},
        "body": "Error"}

    @handler.add(MessageEvent, message=TextMessage)
    def message(line_event):
        text = line_event.message.text
        if '円' in text or 'いくら' in text:
            rep = msg_refund
            line_bot_api.reply_message(line_event.reply_token, TextSendMessage(text=rep))
        elif 'まとん' in text:
            rep = 'いじめないで・・・'
            line_bot_api.reply_message(line_event.reply_token, TextSendMessage(text=rep))

    try:
        handler.handle(body, signature)
        except LineBotApiError as e:
        print("Got exception from LINE Messaging API: %s\n" % e.message)
        for m in e.error.details:
            print(" %s: %s" % (m.property, m.message))
            return error_json
    except InvalidSignatureError:
        return error_json

    return ok_json

def lambda_handler(event, context):
    msg_refund = get_USDJPY()

    signature = event["headers"]["X-Line-Signature"]
    body = event["body"]
    res = send_line_bot(signature, body, msg_refund)
    print(res)

    return res

アクセストークンなどのクレデンシャルをコードにハード埋め込みしないよう、Lambdaの環境変数に、以下を登録します。

・Messaging APIのChannel Secret 

・Messaging APIのアクセストークン(ロングターム)

・OANDA APIのアクセストーク

f:id:highso:20190922154815p:plain

以上の設定が終わったら、Lambdaを保存します。

Amazon API GatewayでMessaging APIのwebhookをLambdaに投げる

API Gatewayを開き、新規作成をします。

プロトコル:REST

新しいAPI

API名:HighsoInvestment

エンドポイントタイプ:リージョン

f:id:highso:20190922154750p:plain

リソース→アクション→メソッドの作成→POSTを選択

統合タイプ:Lambda関数

Lambdaプロキシ統合の使用:チェック

Lambdaリージョン:us-west-2 (オレゴン)

Lambda関数:HighsoLineBot

f:id:highso:20190922154754p:plain

メソッドリクエストを設定

・HTTPリクエストヘッダーに名前「X-Line-Signature」を追加

POSTが以下のようになっていればOK

f:id:highso:20190922154826p:plain

アクション→APIのデプロイ

新しいステージを選択。

ステージ名「beta」でデプロイ

デプロイが完了すると、URLが表示されるのでコピーする。

API GatewayとLambdaの連携に成功すると、Lambdaの画面で以下のようにAPI Gatewayトリガーが追加されたことが分かる。

f:id:highso:20190922154801p:plain

最後に、Messaging APIの設定画面に戻り、以下の設定をすれば完了。

・Webhook送信:利用する

・Webhook URL:先ほどデプロイしたAPI Gatewayのアドレス

f:id:highso:20190922154831p:plain

botを友達登録して、トークルームにbotを招待

Messaging APIの「LINEアプリへのQRコード」を、LINEの友達追加で読み取り、botメタラーまとん」を友達登録。

僕と嫁が参加しているトークルームに、メタラーまとんを招待。botなので一瞬で承認して入ってきます。

トークルームで何か発言して、botが反応すればOK。

上のLambda関数だと、「円」「いくら」を含む発言をすると、解約返戻金を教えてくれて、「まとん」を含む発言をすると「いじめないで・・・」と返事をします!

デモ動画

感想

LINE Botを作るのはめちゃくちゃ簡単でした!

親切な解説記事があったおかげとはいえ、わずか2.5時間でLINE botを作れました。

botを作ると、さっそく嫁が色々と遊んでくれたので、満足です。

みなさんもLINE Botを作って遊んでみてください。

 

以上、メタラーまとんでした。

ではでは。

ファイナンシャル × IoT記事まとめ

1. ドル円為替レートをLINEに通知するハイソ投資ボタンを作った! Lambda, LINE Notify, OANDA, SORACOM

2. ドル建て生命保険の解約返戻金を計算してLINEに通知する仕組みを作った!

3. LINE Botに生命保険の解約返戻金を教えてもらえるようにした!Messaging API, Amazon API Gateway, Lambda

4. 投資の近況報告!!積み立てNISA、ドル建て生命保険、国内株式

ブログで履歴書

ども!メタラーまとんです。

自己紹介を書きます!

僕は自称ハイソの貧乏サラリーマンです。

エンジニアで、ファイナンシャルプランナーで、一児の父です。

年収を上げるためにGAFAへの転職を狙っています。

僕は「背中より、ブログで語れ」をモットーにしているので、今まで書いてきた記事の中で、特に思い入れのある記事をまとめました。

SNS

Twitter: @Highso_ciety

GitHubmaton456 (メタラーまとん)

趣味の資格取得

ファイナンシャルプランナー3級で資格取得にハマり、最近ではエンジニア系の資格を中心に集めています。

AWS 認定ソリューションアーキテクトアソシエイト

AWS認定に合格しました!ソリューションアーキテクト - アソシエイト、感想・所感・勉強法

・G検定

【2019年第2回】G検定を受けた!試験中に圧倒的成長!!

ネットワークスペシャリスト

【平成30年度】ネットワークスペシャリスト受けてきた!!!午前は突破!!!所感・解答速報・感想・講評・攻略・難易度

技術士一次試験

【2018年】技術士受けて来た!感想・講評・速報!第一次試験(技術士補)電気電子部門

応用情報技術者

【18年春】応用情報技術者試験の速報・所感

ファイナンシャルプランナー2級

【資格】FP2級受験の結果

TOEIC 800点

ファイナンシャルプランナー3級

エンジニア作品

ファイナンシャル×IoT

ドル建て生命保険の解約返戻金をLINEに通知するIoT作品を作りました。

f:id:highso:20190916232950j:plain

1. ドル円為替レートをLINEに通知するハイソ投資ボタンを作った! Lambda, LINE Notify, OANDA, SORACOM

2. ドル建て生命保険の解約返戻金を計算してLINEに通知する仕組みを作った!

3. LINE Botに生命保険の解約返戻金を教えてもらえるようにした!Messaging API, Amazon API Gateway, Lambda

マウスDJ

マウスを動かすとドゥイドゥイ鳴るおもちゃを作りました。


マウスDJ - MouseDJ

1. 【マウスDJ】デビューしました。

2. 【マウスDJ】プロ―モーションムービーを作りました!

ソレノイドで奏でる

1. 【JAWS DAYS 2019参加レポ】「あのボタン」SORACOMの薄い本を買ってみた! - メタラーまとんがハイソにやらかすようです

2. ソレノイド(ZHO-0420S-05A4.5)をArduinoとMOSFETで動かしてみた! - メタラーまとんがハイソにやらかすようです

3. AWS IoTをWSL(Windows Subsystem for Linux)のUbuntuで動かしてみた! - メタラーまとんがハイソにやらかすようです

4. ソラコムのボタンでUbuntuとサーバーレス通信してみた!(AWS IoT 1-click / Lambda / AWS IoT / Windows Subsystem for Linux: WSL) - メタラーまとんがハイソにやらかすようです

5. ソラコムのボタンとESP32を繋いでソレノイドを演奏してみた!(AWS IoT 1-click / Lambda / AWS IoT / ESP32)

無料版はてなブログCSS編集

実はこのブログで最もスターを得ている記事はこちらです。

1. 【2018年版】無料はてなブログでスマホ画面のCSSを編集する方法

2. 【2018年版】無料はてなブログでスマホ画面のフォントを16pxに大きくする方法

財テク

積み立てNISA

僕にとっての初めての投資は、月3万円の積み立てNISAでスタートしました。

f:id:highso:20181113021256p:plain

1. 楽天証券で「積み立てNISA」始めました。投資に興味無いエンジニアにオススメ!

2. 【積み立てNISA】税務署審査などモロモロで1ヵ月もかかった件

3. 【楽天証券】積立NISAで「eMAXIS Slim 先進国株式インデックス」発射!!「楽天・全米株式」との比較と、20年間の試算してみた

4. 初めての投資の運用報告が「-3%」で激おこ

5. 【つみたてNISA】年末の阿鼻叫喚から回復し、ついに黒字に転じました!!

節税

僕は節税オタクです。みんなにお得な節税制度を紹介することを生業としています。

f:id:highso:20181107003342j:plain

1. 「節税」をはじめからていねいに - サラリーマンができる税金対策の種類をまとめてみた

2. 今年のふるさと納税は「豚肉・明太子・ハンバーグ」の布陣で決めた!!(初心者向けに解説します)

3. ふるさと納税で冷子が喜んでいるよ

マイル

僕はANAマイラーです。僕の知見を凝縮したこの記事は、わりとアクセス数を集めています。

1. ANAカードで10マイルコースにするとお得になる基準を計算してみた

資産形成

老後、保険、教育資金、持ち家についての持論を展開しています。

どの記事もめちゃくちゃ長いですが、僕の全てを出し尽くしました。

f:id:highso:20180921014751j:plain

1. 「老後の月8万円」を、エンジニアの君はどうやって稼ぐか

2. 新社会人に読んで欲しい。その保険、本当に必要ですか? (新社会人は是非読んでほしい!)

3. 平成最後に教育資金を考える。つみたてNISAで資産を形成! (娘の教育資金2000万円を貯める具体的な作戦)

4. 令和時代に家を買うべきかどうか問題 (アラサーに是非読んでほしい!)

その他の興味

育児・教育

娘が産まれて父親になってから、育児について考えるようになりました。

僕の持論を語ります。

1. 教育の機会均等を実現するのは親の努力

2. 親として、考えることをやめない、諦めない。

3. 新しい家族の在り方「S.A.C.家族」を提案します

4. 【令和元年】0歳児の教育コンテンツを比較します

働き方改革

僕は働き方改革アンバサダーを自称しています。口だけにならず、成果を残すタイプの働き方改革を実践していきます。

1. 忘年会を””働き方改革””していけ

 

一つでも、興味のある記事を読んでいただければ幸いです!

以上、メタラーまとんでした。

ではでは。

ドル建て生命保険の解約返戻金を計算してLINEに通知する仕組みを作った!

ども!ファイナンシャルプランナー2級兼、AWS認定SAアソシエイトのまとんです。

最近、ドル建ての生命保険に加入したのですが、解約返戻金がよく分からないという課題がありました。

そこで、現在の解約返戻金を計算し、LINEに通知してくれる仕組みAWSを使って構築したので紹介します。

経緯:ドル建ての生命保険に入った

まとまったお金を銀行口座に預けておくのはもったいないと思い、思い切って生命保険に加入しました。

この生命保険には機能が二つあって、(1)終身生命保険の機能と、(2)資産運用の機能があります。

具体的には、

(1)僕が死んだときに嫁に死亡保険金が下りる。不慮の事故などの死亡リスクに備えられる。

(2)30年間、固定金利で運用される。ざっくり、30年後に2倍になり、老後資金に備えられる。

この生命保険は、毎月お金をコツコツと振り込むタイプではなく、最初に一気にドカンとお金を預けるタイプ(一時支払い)の生命保険です。

一時支払いを選んだ理由は、最初からまとまったお金で運用を始めた方が、運用のパフォーマンスが高くなるからです。

この保険は終身保険です。つまり、僕が死ぬまで、何歳でも保険が適用されます。

とはいえ、仮に僕が100歳まで生きていても、100歳で嫁が死亡保険金を受け取っても面白くないので、60歳くらいまで生きていたら、解約します。

そのとき、解約返戻金を受け取ることができます。

30年度に解約すれば、最初に預けたお金が、約2倍になって戻ってくるという保険です。老後の備えになりますね。

課題:運用益と為替の影響で難しい!

この保険の難しいところは、解約返戻金の計算です。

まず、この保険はドル建てです。

最初にお金を預ける際に、僕の円はドルに換金されて、保険会社がドルで運用します。

というのも、保険会社はドル国債をベースに運用するからです。(ドル国債金利が高いことから、この保険の固定金利が担保されています)

僕が保険に加入した日のドル円レートは、約106円でした。

なので、30年度に解約する際に円安になっていれば、例えば120円になっていれば、さらに13%ほど運用益を得られます。

逆に、30年後にガチの円高で、例えば70円になっていると、34%ほど減少してしまいます。ここにはリスクがあります。

 

要するに、この保険の解約返戻金は、

・固定金利で少しずつ増えていく分

・為替レートで変動する分

の二つが絡み合っているため、「解約返戻金は何円なの?」を見積もるのが難しいです。

さらに、保険会社は「今の返戻金額を知りたかったら電話でお問い合わせください」というスタンスです。

電話で聞くのはめんどくさい!自分で好きな時に調べたい!

というわけで、今回、解約返戻金をLINEに通知してくれるシステムを作りました。

作りたいもの

要件定義は以下の通り。

・現在の解約返戻金を、好きな時にLINEに通知してくれる

複利運用額を1日単位で計算する

今日のドル円為替レート終値)を反映する

こんな感じでLINEに通知させます。

f:id:highso:20190916232950j:plain

実装

アーキテクチャ

前回の記事で作った、「SORACOMのボタンを押したらLINEに通知する」仕組みをベースに使います。

為替レートはOANDA APIを使って取得します。

f:id:highso:20190908015747p:plain

詳細はこちらの記事からどうぞ。

highso.hatenablog.com

複利運用の近似曲線を算出

まず、複利運用額を計算します。

保険会社は、ざっくり「1年後には〇〇円、2年後には〇〇円、・・・、30年後には〇〇円」だけを教えてくれました。

このサンプル点を元に、近似曲線をPythonで算出しました。

f:id:highso:20190917000221p:plain

※これは、最初に約100万円を入金した場合の例。実際に入金した額とは異なります。

※※106円の日に入金しましたが、最初に手数料などで引かれるので、5~6年以内に解約するとマイナスとなります。

複利運用なので、指数関数(y = a * b ^ 年)で近似できると考えました。

近似曲線を求めるスクリプトはこちら。curve_fit()で簡単に近似できます。

import numpy as np

year = np.arange(1,31)

day = year * 365

henreikin = np.array([1年目の返戻金額, 2年目の返戻金額, ... , 30年目の返戻金額])

array_x = year

#array_x = day

array_y = henreikin

def nonlinear_fit(x,a,b):

    return a * np.power(b, x)

param, cov = curve_fit(nonlinear_fit, array_x, array_y)

param[0]にaの近似値が、param[1]にbの近似値が格納されます。

具体的には、

a = 8457.29004

b = 1.02936377

となりました。

これは単位を年とした場合なので、array_x = dayのコメントアウトを外して実行すると、一日単位での近似式が得られます。

一日単位で計算すると、

a = 8457.28972

b = 1.00007929

となりました。つまり、近似式は以下の通りです。

運用投資額(米ドル) = 8457.28972 * 1.00007929 ^ 運用期間(日)

これで、一日単位で運用額を計算することができるようになりました。

為替レートを計算してLINE通知するAWS Lambda関数

Lambda関数では以下のことをします。

  1. OANDA APIで今日のドル円為替レートを取得
  2. 保険を開始した日から現在日時までの日数を計算
  3. 近似曲線を使って、複利運用額のドルを計算
  4. ドルに、為替レートをかけて、円に換算
  5. LINE Notify APIを使って、LINEに通知
  6. このLambda関数を、SORACOMボタンを押したときに起動するよう設定

このうち、(1),(5),(6)は前回の記事で説明しているので、気になる方はそちらをご覧ください。

具体的には、以下のコードを書きました。太字の部分が、今回新たに加えた部分です。

import json
import sys
import urllib.parse
import urllib.request
import datetime
import os
from oandapyV20 import API
import oandapyV20.endpoints.instruments as instruments
from datetime import datetime as dt
from datetime import timedelta


# LINE notify API
LINE_TOKEN= '自分のアクセストークン'
LINE_NOTIFY_URL='https://notify-api.line.me/api/notify'

#OANDA API
access_token = '自分のアクセストークン'
api = API(access_token=access_token)

def get_USDJPY():
    params = {
        'count': 1,
        'granularity': 'D'
    }
    r = instruments.InstrumentsCandles(instrument="USD_JPY", params=params)
    api.request(r)

    data = []
    for raw in r.response['candles']:
        data.append({
            'time': raw['time'],
            'volume': raw['volume'],
            'o': raw['mid']['o'], #始値
            'h': raw['mid']['h'], #高値
            'l': raw['mid']['l'], #安値
            'c': raw['mid']['c'], #終値
        })
    print(data)

    #前日の終値
    date = dt.strptime(data[0]['time'][:19], '%Y-%m-%dT%H:%M:%S')
    date = date + timedelta(hours = 9)
    #print(date)
    exchange_rate = float(data[0]['c']) #USD-JPYレート
    msg1 = str(date.year) + '年' + str(date.month) + '月' + str(date.day) + '日'
    msg2 = 'USD-JPY終値: ' + str(exchange_rate) + '円'
    print(msg1)
    print(msg2)

    #日ごとの複利計算
    start_date = dt(year=2019, month=8, day=20) #保険開始日
    elapsed_time = date - start_date
    elapsed_day = elapsed_time.days
    msg3 = '経過日数: ' + str(elapsed_day) + '日'
    print(msg3)

    ## Y = a*b^X
    ## 解約返戻金(USD) = a*b^(経過日数)
    a = 8457.28972
    b = 1.00007929
    refund_USD = a * b ** elapsed_day
    exchange_fee = 0.5 #USDからJPYへの為替手数料(円)

    refund_JPY = refund_USD * (exchange_rate - exchange_fee)
    msg4 = '複利運用額: ' + str(round(refund_USD, 1)) +'ドル'
    msg5 = '解約返戻金: ' + str(round(refund_JPY, 1)) + '円'

    msgs = ' '.join([msg1, msg2, msg3, msg4, msg5])
    print(msgs)
    return msgs


    def send_line(msg):
        method = "POST"
        headers = {"Authorization": "Bearer %s" % LINE_TOKEN}
        payload = {"message": msg}
        try:
            payload = urllib.parse.urlencode(payload).encode("utf-8")
            req = urllib.request.Request(
            url=LINE_NOTIFY_URL, data=payload, method=method, headers=headers)
            urllib.request.urlopen(req)
        except Exception as e:
            print ("Exception Error: ", e)
            sys.exit(1)

def lambda_handler(event, context):
    msg = get_USDJPY()
    send_line(msg)

デモ

f:id:highso:20190916233000j:plain

こんな感じで、僕と嫁とLINE Notifyのbotが入っているトークルーム「生命保険は今何円?」に、botが解約返戻金を通知してくれます。

今回は「SORACOMのボタンを押したときに通知する」という仕組みにしましたが、例えば「毎朝6時に通知」などとトリガーをかけても良いと思います。

今後

解約返戻金額をDynamoDBに毎日格納して、たまにグラフ化して振り返る仕組みを実装しようかなと思っています。

 

以上、メタラーまとんでした。

ではでは。

生命保険にまつわるファイナンシャル × IoT記事

1. ドル円為替レートをLINEに通知するハイソ投資ボタンを作った! Lambda, LINE Notify, OANDA, SORACOM

2. ドル建て生命保険の解約返戻金を計算してLINEに通知する仕組みを作った!

3. LINE Botに生命保険の解約返戻金を教えてもらえるようにした!Messaging API, Amazon API Gateway, Lambda

4. 投資の近況報告!!積み立てNISA、ドル建て生命保険、国内株式