hubotとSlackで株取引をちょっと助ける

# **はじめに**

株をやっていて、ある程度自分の見方が決まってくると株のチェック行為が **ルーチン化** してくるわけですが、そんなことがあると途端に湧いてくる **自動化 / 省力化** の欲求。

![hubot_icon.png](https://qiita-image-store.s3.amazonaws.com/0/45253/cb6e5b0e-ced2-34e2-bc6d-e707dfc80171.png)

今回はそんなモチベーションから生まれた、ウチのSlackに生息する **money-botくん** の

- **株価サマリ表示機能**
- **株価チャート表示機能**
- **(おまけ) 株取引格言アドバイス機能**

について紹介します。
自分と親しい友人用に作っているだけなので全然綺麗ではないんですが、 **新たなbot機能のアイデア** や **汚く作ってしまったところの改善アイデア** なんかをもらえたら嬉しいなぁなんて気持ちで書いてます。

# **機能イメージ**

株のことを調べる際には有名どころでいけば **[Yahoo!ファイナンス](https://finance.yahoo.co.jp/)** だったり **[モーニングスター](https://www.morningstar.co.jp/)** だったりするかと思いますが、日頃のルーチンを通じて僕は **[株探](https://kabutan.jp/)** を日常的に使うようになりました。
割と各株についてコンパクトにまとまっているところが好きで愛用(?)しています。

とはいえ、そうやって愛用しているサイトであっても、自然と自分の動線は決まっていくものなので、その動線の部分だけをサマれないかなと思ったりしたわけです。

こういうのは見たほうが早いので、先に実際のやりとり画像で説明します。

## **株価サマリ表示機能**

チャット中で **4桁の数字** をつぶやくと、それを銘柄コードとして **該当する銘柄のサマリ** を表示します。当然タイトルは株探ページへのリンクになっています。

|![WS000127.png](https://qiita-image-store.s3.amazonaws.com/0/45253/fd71efb8-7421-d593-abeb-203f9ed56e6c.png)|
|:-:|

正確には、通常の文脈で喋った4桁数字(株価とか)も銘柄コードとして拾われると困るので前後空白の場合に反応するよう調整しています。

サマリの内容としては基本的に株探の数値をそのまま表示していますが、唯一 **Q成長率** というやつだけ自分で導入しています。
自分の取引はテクニカル寄りなのでチャートの形をよく見るんですが、チャートの高さが値動きによらず1画面へ **いい感じ** に表示される都合で、 **一見同じように見える** チャートであっても、実際の成長度合いって結構違っていたりします。

例えば以下のグラフそれぞれで、左端の終値と右端の終値を比較すると上昇率に2倍以上の開きがあったりします。

|![WS000137.png](https://qiita-image-store.s3.amazonaws.com/0/45253/c03bb0a6-d313-4384-674a-d0e3ec5eee8d.png)|![WS000138.png](https://qiita-image-store.s3.amazonaws.com/0/45253/7573d01e-e1b9-6769-7bf9-cd33d0c1681f.png)|
|:-:|:-:|
|**+77%**|**+29%**|

そうした意味で、サマリを作る過程で **60営業日前** の株価と現在株価を比較して、その成長率を **Q成長率** として出しています。QはQuaterのつもりです。

あと、株探ってその企業の業績が上向きか下向きかっていうのをページに出してくれますが、それをAttachmentsの色に翻訳して表示したりしています。

|未定|急上昇|上昇|停滞|下降|急下降|情報なし|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|![未定](https://kabutan.jp/images/cmn/gyouseki_0.gif)|![急上昇](https://kabutan.jp/images/cmn/gyouseki_1.gif)|![上昇](https://kabutan.jp/images/cmn/gyouseki_2.gif)|![停滞](https://kabutan.jp/images/cmn/gyouseki_3.gif)|![下落](https://kabutan.jp/images/cmn/gyouseki_4.gif)|![急下降](https://kabutan.jp/images/cmn/gyouseki_5.gif)|―|
|<font color="#BDBDBD">■</font>|<font color="#FF0000">■</font>|<font color="#FE9A2E">■</font>|<font color="#01DF01">■</font>|<font color="#0000FF">■</font>|<font color="#8904B1">■</font>|<font color="#FFFFFF">■</font>|

なので先ほどのソニーは **業績急上昇(株探調べ)** ということが一目でわかります。

他には地味に大事な機能として **決算日表示機能** があります。
株探は決算日が近づくと決算予定日をページに書いてくれるんですが、ある場合はメッセージ本文として拾ってきてくれます。
基本的に決算ギャンブルしない人なので、これで気付けるのは非常にありがたい。

|![WS000131.png](https://qiita-image-store.s3.amazonaws.com/0/45253/f4b6b0ac-f8f5-6283-ae87-dcd1bc170355.png)|
|:-:|

というのがサマリ機能でした。

ちなみに複数銘柄の一括表示にも対応してます。中では非同期なのでつぶやいた順序にはならない仕様。

|![WS000129.png](https://qiita-image-store.s3.amazonaws.com/0/45253/ce2d6dc3-b479-c97a-6323-d6690145d113.png)|
|:-:|

家電業界並べてみましたけど、どこも業績よくて業績ラベルの例にもならん...。まぁいいか。

## **株価チャート表示機能**

サマリ機能があるだけで大分よくなったんですが、同じく株やってて情報交換する友人と銘柄の話をする際、当然 **チャートのスクショ** を貼ったりするわけです。何度も。
というわけで作りました。

|![WS000132.png](https://qiita-image-store.s3.amazonaws.com/0/45253/51528a9f-4294-4f5c-75cb-f5bdff12770a.png)|
|:-:|

銘柄コードのみをつぶやいた場合は、サマリに加え **日足のチャート** も出してくれます。
このチャートは株探で日足チャートを表示させた場合のものを **[PhantomJS](https://www.npmjs.com/package/phantomjs-prebuilt)** で切り取ってSlackへアップロードさせています。

## **(おまけ) 格言アドバイス機能**

あとは個人的にお気に入りの機能です。
株って戦略それ自体もそうですが、本人の精神性もすごく大事だと思うので、先人の格言みたいなものをちょいちょい取り込んでいきたいなと思ったわけです。そこでこれ。
「悩」という文字に反応して **株の格言** をもたらす機能。

|![WS000133.png](https://qiita-image-store.s3.amazonaws.com/0/45253/5dcdd342-8a42-f097-5d21-a6cf5f43c13e.png)|
|:-:|

|![WS000134.png](https://qiita-image-store.s3.amazonaws.com/0/45253/439f5ba6-9f25-aa06-bc7e-07ac27e5b3d2.png)|
|:-:|

これらの格言は **[相場格言集 | FX比較マネー](https://www.mo-ney.net/about/proverb/)** からランダムで選んでくるようになっています。
botがちょっとだけ喋ってるのはただの遊び心です。これも決まった単語リストからランダムです。

「悩」一文字にしか反応してないので、支離滅裂もない返しではあるんですが、含蓄の深い言葉が返ってくるので大体「 **なるほど...** 」ってなったりするのが面白いところ。

# **実装**

それでは実装の話をします。コード自体は全然美しくないので処理上のポイントだけを解説します。
綺麗な実装PRをお待ちしております...！

**[GitHub: t-nakayama0714/money-bot](https://github.com/t-nakayama0714/money-bot)**

## **実行環境**

Bluemix上のコンテナで動いてます。以前の記事で

**[無料で整える趣味チームの開発環境](https://qiita.com/t_nakayama0714/items/c0eb5e298524c127bccd)**

なんてのを書きましたが、ここのhubotがだいたいこいつです。記事でも触れている通り、他にはAWS系機能があります。
この記事用にスクリプトを分離する際、なんのミスもなければ多分そのまま動くはず...。

## **株価サマリ表示機能**

コード的にはダラダラ書かれていますが、やってること自体はそんなに難しくないです。

**1. hearで銘柄コードを捕まえる**
**2. 銘柄コードたちをforでまわす**
**3. 各銘柄コードごとに対応する株探ページのURLから情報をひたすら抜き出す**
**4. 抜き出した情報をAttachmentsにまとめて送る**

って感じでしょうか。

初っ端の銘柄コードを捕まえるところで、割と意味不明なことになっています。
これはメッセージをShareしたとき、暗黙に含まれる

```
[November 5th, 2017 5:53 PM] nakayama.takahiro: hoge message
```

というタイムスタンプが厄介なためでした。
ここの記述は前後空白になっているため `2017` を銘柄コードとしてとらえてしまい、それを避けるべく非常にまわりくどい格好で銘柄コードを捕まえています。

あとはHTTPリクエストで帰ってくるbody全体から、 **正規表現** でほしい値をひたすら抜いてきます。
当然ガチガチのフォーマットで引き抜いてるので、株探が少しでもサイトリニューアルしたら値が取れなくなる可能性が高いです。
が、今のところは「その時は直せばいいや」くらいの感覚です。

で、最後にAttachmentsにして色付けなんかをしながらメッセージを送っています。

```scripts/trade-util.coffee
# Attachmentsの構成
data =
  attachments: [
    color: perf_color[perf_index]
    title: "#{title} : #{price} (#{priceup}, #{pctup}%)"
    title_link: "https://kabutan.jp#{fullpath}"
    pretext: settle
    text: msg_body
    mrkdwn_in: [
      "text",
      "pretext"
    ]
  ]

# レスポンス
# hubot-slack4系からこの送り方でよくなった
msg.send data
```

コメントにも書いてありますが、 hubot-slack4系と3系でAttachmentsの添え方が違うことに注意してください。
**[hubot-slack v4移行時のハマりどころ(p.11)](https://www.slideshare.net/knjcode/hubotslack-v4-hubotchatops)**

## **株価チャート表示機能**

こちらも動かすまでは難儀しましたが、できてしえば処理は簡単です。

**1. hearで銘柄コードを捕まえる**
**2. 銘柄コードに対応する株探ページから日足チャートをPhantomJSで抜き出す**
**3. 取得した画像をSlackの添付ファイルとして送る**

PhantomJSをドキュメント通りに使おうとしてなんだかよくわからなくなって挫折した結果、

**[家庭用にHubotスクリプトを書いてみた話](https://qiita.com/k-ysd/items/c7580a5febba82e7a802)**

の該当部分をほぼ丸パクするに至りましたm(_ _)m

スクショ用JSのところには、株探の日足チャートをぴったり抜き出すべく座標情報を驚くほど **ハードコード** しています。
こちらもやはり株探のリニューアルで即死すると思われます。

```scripts/lib/kabutan_chart.js
// 切り抜き位置(株探チャート用)
page.clipRect = {
  top: 643,
  left: 475,
  width: 640,
  height: 402
};
```

あとは取得した画像をどうやって見せるかなんですが、サマリ同様にAttachmentsの `image_url` を使う手があります。
が、これはSlackから見てReachableな画像でないといけないので、コンテナ内に生成した画像をどうにかするのは大変です。多分同一コンテナにWebサーバ立てるとかやS3なんかにファイルを置くとかすればいいんでしょうけど、中々面倒なのが素直な印象です。

そこで素直にファイルをアップロードすることにしています。
アップロードはお馴染み `curl` でできてしまうので、

```scripts/trade-util.coffee
# 画像をアップロードする
cmd = "curl -F filename=#{filetitle} -F file=@stock_image/#{code}.png -F channels=#{channel} -F token=#{process.env.HUBOT_SLACK_TOKEN} https://slack.com/api/files.upload"
childProcess.exec cmd, (err, stdout, stderr) ->
```

という感じになりました。

### **残課題**

よーく見るとわかるのですが、こうして取得できた画像には日本語が表示できていなかったりします。

|![original.png](https://qiita-image-store.s3.amazonaws.com/0/45253/05f83343-41ec-3663-de6a-7ac15476123e.png)|
|:-:|

↑　株探の元チャート
↓　PhantomJSで生成したチャート

|![phantomjs.png](https://qiita-image-store.s3.amazonaws.com/0/45253/d435759c-ffcf-edf1-c579-a9aafd7811bc.png)|
|:-:|

**[PhantomJSで日本語が文字化けして辛い](http://t-cyrill.hatenablog.jp/entry/2014/10/05/123803)** をやったら直るのはわかっているんですが、今のままでも困ってないので別にいいかなと思って放置しています。



## **(おまけ) 株取引格言アドバイス機能**

これ自体に特段の技術トピックはありません。
既にサマリを出すためにやった内容で大体できています。配列からランダムに値を取り出すくらいのところでしょうか。

格言を選ぶまでがまどろっこしいのは取得元のソースがそんな感じになっていたからでした。一度見てみてください。

# **おわりに**

日々のルーチンワークにhubotは絶大な力を発揮しますね。
このbotを作るにあたり、AttachmentsやPhantomJSなど、それまで触ったことのない要素に触れられたため、さらにbotの自由度が上がりそうです。