株式投資についての覚え書き

株を買い始めて2週間くらい経ったので、調べたり考えたりして分かったことをメモしておく。

株式に対するリターンの源泉

投資家が株式を購入する際には、以下のリターンを期待しているか、もしくはそのようなリターンを期待している別の投資家に売ることができると期待している。小売と卸売の関係と同じく、後者の形態の投資家はそれ自身を買い手と想定することもできるため、メタ構造を形成する。

  • 配当金が得られる。これは純利益の増大に伴って増加すると考えられるため、企業が小さい(=倒産リスクが高く、株価が安い)時期に買っておくと、購入額に対して大きな割合の配当が受け取れるようになる。
    • 配当金は株価の1%〜3%程度が相場なので、株価が落ちないのであれば銀行に預けておくよりも利回りが良い。
  • 企業が自社株買いをする。自社株買いのモチベーションには次のようなものがある。
    • 必要のない株式を回収し、自社の経営権に対するコントロール度合いを増やす。
    • 新規株式を発行することなく、従業員へのストックオプションを確保する。
    • 株主の利益を保証するため、株価や指標を調整する(これは因果と結果がループしているので、定常状態になったメタ構造に対する説明としては有効だが、源泉としては弱い)。

参考: kabukiso.com www.investopedia.com

インデックスファンド

株式投資の話をすると、大抵の人はすぐインデックスファンドを勧めてくる。インデックスファンドのインデックスとは、複数の銘柄からなんらかの方法で算出される指数(インデックス)である。これは単純な株価の平均でもいいし、S&P社のように株式に対して重み付き和を取ったものでもよい(参考:S&P Dow Jones Indices, Float Adjustment Methodology)。インデックスファンドとは、複数銘柄のセットであり、それらに対する指数が市場に対する指数と同じ動きをするように構成されたものである。市場に対する指数としては、日経平均株価とか、S&P 500といったものがある。

複数の銘柄を束ねているため、市場の指数に追随するようなポートフォリオが一度組めれば、不確定要素によるブレが少なくなる。すなわち、個々の株式は無視して、代表値として指数だけを見て運用すれば良くなる。中心極限定理のような理由だと理解しているが、単一銘柄に対する指数の分布が一定の性質を満たすことや、指数が加法的であることなどの条件が必要だと思われる。

もちろん市場として指数が悪化すれば、インデックスファンドからの利益も低くなる。常に勝てる銀の弾丸ではない。市場の指数が景気をよく表しているのであれば、インデックスファンドを買うことは景気に賭けているのとほぼ同じことになる。

これも大抵の人が勧めてくる「ウォール街のランダム・ウォーカー」を読むと大体の気持ちがわかる。ページ数は多いが、興味のあるところだけ適当に拾って読めばいい類の本だと思う。

株価の妥当性

株を買いたい人に株を売るために株を買うというメタ構造が入ってしまうため、株価の妥当性は今ひとつよく分からない。P/E Ratioという指標を目安にするのがよくある手筋っぽい。これは株価を単位株あたりの純利益で割ったもので、投資家がその企業の株式にどれだけ期待しているかの指標……とされている。一見それっぽい説明だが、そもそも企業の元手は株式だけでなく資本金もあるので、企業に対する指標としてはP/E Ratioがいったい何を示しているのか謎である。

株価の絶対的な妥当性は決めるのが難しそうだが、相対的な妥当性なら、おそらく同じ業種でROE (Return on Equity、自己資本利益率)の近い企業と比較するのが良いのではないかと思う。ROEは純利益を純資産で割ったものなので、純粋にどれだけ金を回すのが上手いかという指標になる。純資産の代わりに総資産を使ったReturn on Assetsや、売上を投資額で割ったReturn on Investmentという亜種ももちろんある。ただし、たぶん効率の上がり方は資産に対して線形ではないので、規模等も適宜揃える必要があると思われるし、株式の発行数も影響してくる。これもう何もわからんな。

追記 2020/02/23:買収などに際して行われる企業価値評価というプロセスが、まさにこの妥当な株価を計算するものだと教えてもらった。評価を行う会社や状況によって算出方法は異なるが、基本的には総資産に将来の成長を加味したものを企業価値と想定して、それを単純に株式発行数で割るものらしい。参考:企業価値評価とは?M&Aで使用される企業価値の算出方法 | FUNDBOOK(ファンドブック )M&A仲介サービス

一つの企業を時間軸で見ると、長期的なスパン(1年〜)で成長した企業は株価が上がっているとは言えそう。その逆が言えるかは謎(偽っぽい印象はある)。短期での動きは完全に謎。

参考: www.investopedia.com www.investopedia.com www.investopedia.com https://fundbook.co.jp/valuation/

戦略

以上を踏まえると、投資戦略はいくつかにに大別される。

  • インデックスファンドを買って、総合的な長期の成長に賭ける。
  • 1年〜数年のスパンで成長しそう&成長の余地がある株を予想して買う。
  • あまり値動きしなさそうな株を配当目当てで買う。

どの戦略を取るにせよ、一度株式を買ったら買値を含めて過去にやったことは覚えておく必要はなく、現在持っている株式だけを見てその都度売り買いを判断すれば良い。買値から10%落ちたら損切りするなどと言っている指南書もそこそこあるので初見だと混乱するが、よく考えると過去の売買には干渉できない条件で総資産を最大化する問題なので、過去を気にしなくて良いのは当たり前。ただし、株価の急落は将来の成長率に影響するような何かが引き金になっている可能性もあるので、アラートとしては監視する価値がある。

2020年の目標 - 1月

目標に関してなんも覚えてなかったけど、1ヶ月に1回くらい振り返るとモチベーション維持に良さそうと思ったのはかろうじて覚えていたので振り返りに来た。

osak.hatenablog.jp

毎月振り返るの目標の1つになってるやんけ。Twitterかなんかで雑につぶやいただけだと思っていた。

ゲームは特にしてない。あっいや、なんか流行ってたのでBacon - The Gameをちょっとだけやった。57面のピサの斜塔で詰まって飽きたのでもう一生やらないと思う。

Bacon – The Game

Bacon – The Game

  • Philipp Stollenmayer
  • Games
  • Free
apps.apple.com

あとゲーム的な話としては、Tax returnして一時的に意識が高まったので、Fidelityに証券口座を開いて株式投資を始めた。株についてちょっと調べたけど値動きする理由とか全然わからんのと、そもそも座学だけだとあんまり理解が深まらないタイプなので、とりあえず何が起きるのか肌で感じてみようという気持ち。人々は資金あるならインデックス投資やれやとか勧めてくるけど、インデックスはブラックボックス部が大きすぎて株式市場で起きる現象の理解には使えなさそう……(そうでないなら教えて頂けると助かります)。まあ安定して儲けるパートは今の所目標ではないので別に資金溶けてもいいやくらいの気持ちではある。知識無しで突っ込むというのはそういうことだし……。


体重は61.5〜62.5kgの間を振動している。標準体重は59.9kgらしいので、特に減らす必要はなく、これを維持できればいいということでいいのかなぁ。食生活をあんまり変えてないのに初期と比べて明らかに下がらなくなったし……。


新しい技術。GoでWebクローラを書いた(多分近いうちにリファクタリングする)。 github.com このフレームワーク上でいくつかクローラを作って、余ってたThinkpadを使った自宅サーバで動かしている。定期的に走らせるためにsystemd.timerを勉強して使った。超便利。

色々なWebサービスMastodonへの自動ポストをしてくれないので、IFTTT経由でAWS Lambdaを叩いてクロスポストするやつを作った。今のところFoursquareのチェックインと読書メーターに対応している。 github.com AWS LambdaはNode.jsとかPythonのようなちょっと長期メンテはしたくないです……という感じの言語で書く印象が強くて敬遠していたけど、Goで書けることを知ったのでこれが未来か……となってサクッと書いた。AWSは神。これをAmazon API Gatewayで適当にREST API化すると一瞬でWebhookになる。AWSは神。

あとこのリポジトリを開発してる過程でGo Modulesの存在を知った。名前はTwitterでよく見てたしIntelliJにもGo Modulesというのがあって何だろうとずっと思っていたけど、要するにGOPATHからリポジトリを切り離して普通の言語っぽいパッケージマネージャを実現するやつだった。これはマジで世界が変わる。

業務では相変わらずKotlinを結構ヘビーに使っており、リフレクションで遊んでJavaと比べてあまりの使いやすさに感動したり、良いプロジェクト構造への知見が溜まったりした。こういうのいつかpublicに書きたいですねえ。そもそも社内ブログ用にまとめろよって話でもあるが……。


中国語。Duolingoは毎日続いている。最初は英語でやっていたけど、日本語でもサポートされてることに気付いて途中から移行した……ところ、日本語はコースが途中までしか作成されてないことに最後まで行ってから気付き、また英語に戻した。中文英訳問題で英文法を間違えて❌判定されるのが地味に精神に来る。基礎能力が上がっている気はするが、運用能力が上がっている感じはあまりしないので、中国語の文章をネットで読むとかしたほうが良さそう。漢字の読みも覚えないとPCで打てないので、会話する気がなくても地味に重要。


本。異種族レビュアーズを読んだ。アニメは観てない(最近アニメを観る気力が出ない)。天原作品の世界観にハマって、Pixivに上がってるイラストを読破して、貞操逆転世界シリーズと33歳独身女騎士隊長を買った。

www.dlsite.com

この人、現実とは違う人の思考ロジックをトレースして出力するのが異常にうまくてすごい。何が世界観に影響するのかをピンポイントで把握して出力している感じがする……。

9月末に日本で買って積んでた「いま世界の哲学者が考えていること」も読んだ。この本はかなり読み口が軽く、何がキーになっているかの最低限の理解を得て、次に読む本を決めるための本という感じ。実在論の話がかなり琴線に触れたので、参照されてた本を4冊ほど買った。


なんかこうやって書くといろいろやってるように見えるな。2月もちゃんと人生できるといいですね。

グリーンカード取得の記録

晴れてグリーンカードを取ったので、今後誰かの参考になればと思って何をやったかの記録を残しておく。自分も他の人のブログで色々調べたりしたので……。

  • 2018年8月頃:会社がスポンサーになってグリーンカード取れるけどどうする?とマネージャーに聞かれたので、とりあえず手続きを進めてもらうようにお願いする。
  • 2018年9月頃:簡単な履歴書、大学の学位証明(日本語のを出したら、アメリカの調査機関でアメリカの学位と同じであることを保証する証明書を作ってもらった)、マネージャーからの推薦状的なもの(中身は自分で書いた)を会社のGlobal Mobilityチームに提出する(あんまり覚えてない)。
  • 2018年11月頃:PERM Labor Certificationを発行できるか確認するため、会社指定のフォームでスキルリストを提出する。
  • 2018年12月頃:I-140アメリカでの雇用に基づいた永住権申請書)作成のため、会社が作った雇用証明書のテンプレートに自分の業務内容を書いて提出する。
  • 2019年1月頃:ETA 9089(PERM Labor Certificationの申請書)ができたという通知が来たので、Work historyや最新のI-94情報が正しいか確認する。
  • 2019/01/18:ETA-9089を提出したという連絡が来る。
  • 2019/04/24:PERMが発行されたという連絡が来る。
  • 2019年5月頃:I-140のために必要な追加書類のスキャンを提出するよう連絡が来る。移民に関係しそうな個人情報は全部要求される。パスポートの出入国スタンプ全部とか、最新のI-94とか、Birth Certificateとか。Birth Certificateは戸籍謄本を翻訳してもらうことで作成可能っぽいが、手元になかったので6月末に日本に行くタイミングで持ってくることにする。
  • 2019/07/19:ヒューストンの日本総領事館で戸籍謄本を翻訳してBirth Certificateにしてもらう。現金で$15くらいを釣り銭無しで払う必要があるので注意が必要。あとで聞いた話によると、自分をTranslatorとして自力翻訳したものでもいいっぽい?(未検証)
  • 2019/07/22:Birth Certificateの取得状況を伝えてなかったので、はよ書類出せやという催促がGlobal Mobilityチームから届く。すみません……。書類は揃ってたので即提出する。
  • 2019/07/24:I-140はできたから、I-485アメリカ在住のステータスを永住権に変換する申請書)とI-131グリーンカード申請中のReentry permit申請書)、I-765(Employment Authorizationの発行申請書)も提出するねということになり、I-485のために両親の出生地を教えてくれと言われる。Reentry permitというのは、ビザの種類によってはI-485を出した時点で失効してしまうので、その状態でもアメリカに入国できるようにするための書類。自分はL-1で入国していたので関係ないっぽいが、万が一のための保障としてでやっとくねとのこと。しかしI-131処理中にアメリカを出国すると却下されることがあるらしく、9月に日本に行く予定があったので、I-131はとりあえずそれまで延期してもらうことにする。
  • 2019/08/23:I-485が受理されたとの連絡が来る。同時にメディカルチェックを受けてI-693(移民用の健康診断+ワクチン接種証明書)をもらっといてねと言われる。これを発行できるのはCivil Surgeonという特殊な資格がある人だけらしい。これを発行できる病院はUSCISのサイトで検索できる
  • 2019/08/28:I-693のための検診を受けに行く。予防接種はTdap(三種混合)、Measles(はしか)、Mumps(おたふくかぜ)、Rubeola(風疹)(これらはアメリカだとMMRという名前で接種するらしい)、Varicella(水疱瘡)が要求される(年齢や時期によって異なる)。母子手帳の予防接種記録を自分で翻訳してもいいっぽいよとTwitterで聞いたので持っていこうとするも、当日忘れる(は?)。内容は覚えていたが、母子手帳に水痘と書いてあったのを水疱瘡だと分からず(は??)、水疱瘡は受けてないと思うと医師に言ったところ、じゃあ接種してCertificate持ってきてねと言われる。それとは別に他の結核や梅毒等の検査のため血液を取られる。結核ツベルクリン注射をするもんだと思っていたら、最近は血液検査で分かるらしい。この検診は$400くらいかかった。
  • 2019/08/30:4月に普通の健康診断を受けたAustin Regional Clinicで相談すると、とりあえず抗体があるか血液検査でチェックしようかという事になる。そしたら全部抗体があった(Tdapは4月に接種してた)。証明書だけもらって提出する。検査は$50くらいだった。
  • 2019/08/27:Biometricsを取るから指定のUSCISオフィスに9/6に行ってねという連絡が来る。これは車で15分くらいの近所だった。
  • 2019/09/06:Biometricsを取りに行く。写真を撮って指紋を取って終わり。
  • 2019/10/02:I-765が受理されてEAD Cardが届く。
  • 2019/10/30:I-140が受理されて、最終面接が12/02にセットアップされる。というか10月頭にアメリカに帰国してたけど、結局I-131を提出してもらうのは忘れていた。特にこれから出国する予定もないのでまあ結果オーライとする。
  • 2019/12/02:今までに提出した書類のコピーを持って最終面接のためSan AntonioのUSCISオフィスへ行く。真実を話しますという宣誓をしたあと、I-140に書いてある個人情報と質問リスト(基本的にはヤバいことやってない・やるつもりないよねという確認)を確認して終わり。もっと面倒なことを聞かれるかと思ったけど簡単でよかった。今までになんかPenalty受けたことある?と聞かれたとき、なんもないと答えたら質問を理解してないと思われたのか、交通違反の切符もそうだよと念を押された(本当にない)。1週間くらいで結果の通知が来て、大丈夫なら2〜3週間でグリーンカードが届くよと言われる。
  • 2019/12/05:面接に通ったという通知が来る。
  • 2019/12/11:グリーンカードが会社に届く。思ったよりずっと早い。思えば運転免許証も言われたよりずっと早く届いた。

雑多な情報

  • グリーンカードの申請キューの状態はVisa Bulletinで見ることができるが、日本人は申請したら(お役所時間で)待ち時間なく処理できるCクラスなので見てもあんまり意味がない。中国やインドは数年〜十年待ちになっていてヤバさがある。
  • グリーンカードはWork authorizationを兼ねるので、I-131を同時に出さないなら別にEAD Cardもいらなかった説はある……。そもそもI-131が却下されても、Reentry permitがもらえない以上のデメリットはないっぽいので申請するだけ得な気はする。

2020年の目標

ゲームをする

2019年は全然ゲームをしていなかった。Twitterとかで無為に時間を溶かすくらいならゲームをしような。というか2018年の振り返りでPrismataとStarCraftをやりたいって書いてたのにどっちもやってないやんけ……。この2作品もそうとして、今の所ハナノパズルとライザのアトリエが積まれている。

太らない

太らない。

毎月なんらかの新しい技術に触れて知見をまとめる

なんとなく知識をリフレッシュしよう〜くらいの気持ちだと具体性がなくて全然進まないので、毎月なんかしら新しいことをやってアウトプットできるようにする。

中国語を勉強する

中国旅行に行って、漢字は読めるんだし中国語が最低でも読み書きできるといいなあと思った。話せるともっといいけど練習方法がよくわからないので今のところは保留しておく。とりあえずDuolingoを始めた。

毎月目標達成度を振り返る

Twitterで何人か定期的に一年の目標達成度を振り返っている人がいて、モチベーションの維持に良さそうだと思った。

2019年振り返り

人生3万日しかない。今年は有意義だったか?

目標だったもの osak.hatenablog.jp

アメリカで太らない

年始は145lbs(65.7kg)だったが、3月に引っ越したついでにFitbitの体重計を買ってダイエットすることにした。といってもゆるふわで、食べる量を減らしたり、炭水化物を意識的に避けたりするくらい。結果、62kgくらいになった。

ボイロ動画を作る

なんもやってない。内輪でちょっと流行ってたのでTwitch実況はした。

個人用途でWebインフラを作って管理する

ほぼ何もやってない……。年末になって、余ってたThinkpad自宅サーバを立てて、Webで見つけた画像やらなんやらをクロールしてくるシステムを作り始めた。EC2とかじゃないのは、Google Photosがポルノ画像を勝手に削除したとか、勝手にアカウントごと凍結したとかいう話があり、いまいちクラウドが信用できないため……。今後は死活監視したり、集めた画像のビューワを作ったりする予定。

旅行に行く(3回以上)

  • 日本(6月・9月) 6月はICFPCのために行って、少し働いたのと友達と遊んだくらい。9月は妹の結婚式に行って、ついでに温泉旅行した。
  • 中国(上海・蘇州・北京)(7月) 6月末にせっかく日本に行くんだからと、そのまま中国旅行をした。
  • ヒューストン(7月) グリーンカードを取るために出生証明書が必要になり、領事館で戸籍謄本を翻訳してもらうついでに観光した。
  • サンアントニオ(12月) グリーンカードの面接ついでに日帰り観光した。
  • ダラス(12月) 車でどっか行きたくなったので、手頃かつ行ってない都市に行ってみた。

なんかのついでに旅行するケースが多かったけど、おおむね良いのでは。飛行機で行くようなところにもっと行きたい。

ICFPCで1位を取る

無理でした。そもそも総合7位とあまり振るわなかった。どう考えても自分の自動化が甘すぎたのが敗因の一つなのでつらい……。今年のICFPCは問題は面白かっただけに残念。

本を読む / 映画を見る / ゲームをする

本:いろいろ読んだ。一番ためになったのはDesigning Data-Intensive Applications。印象に残ったのはまちカドまぞくとScheme手習い。あと色々な漫画が最終回を迎えた。

映画:5月にAvengers: Endgameをいきなり見て、それから興味を持って過去作を1ヶ月くらいかけて見た。面白かった。

ゲーム:Baba is YouとThe WitnessとBraidをやった。あと日本でやり残していたパンデミック:レガシー2を終わらせた。どれも良いゲームだった。

そのほか

グリーンカードを取得した。正直アメリカにずっと住むかはよく分からないけど、さしあたって日本に戻る理由もあまりないし、会社がサポートしてくれるとのことだったので取れるなら取っとこうという感じ。

総評

かなり仕事にリソースを振ってしまった気がする。新しいプロダクトをすごい勢いで作っていくチームで、仕事としては面白いから不満はないんだけど、自分が直接外に公開できるような成果にはならないので長期的にはあまり良くないなあという気がする。2020年はもっと仕事以外で人生を充実させることをしたい。

ダラス旅行

車でどこか遠くに行きたくなったのでダラスに行った。遠いと言っても片道3時間くらいだけど、1人の短期日程でこれより長距離を走るのもつらいものがあるので……。オースティンから手頃な観光地的な所に行こうとすると、3時間の次は6時間コースになってしまう。

 

オースティンとダラスを結ぶI-35 (Interstate 35)というハイウェイの途中にWacoという都市がある。オースティンから1時間くらいのところにあり、オースティン市内を走っていても案内標識に時折出てくる謎の地名。立ち寄って、TripAdviserで見つけたAlpha Omegaというギリシャ料理店で昼食を食べた。

www.tripadvisor.com

Beef PlatterとGreek Coffee。味は普通。ギリシャコーヒーってなんだよと思ったら、どうやらトルココーヒーと同じものらしい?

 

近くにDr. Pepper Museumなる謎の施設があったので行ってみる。Dr. Pepper好きじゃないんだけど。運営母体はKeurig Dr Pepper社とは関係のないNPOとのこと(Dr Pepper社は毎年多額の寄付をしているらしいが)。そもそもDr. Pepperを作ってるのはコカ・コーラだと思っていた……。

中は普通の資料館みたいになっている。7UPの会社も資本関係にあるため、ミュージアムで一緒に展示されていた。

 

2時間かけてダラスへ向かう。ホテルに行く前に、Twitterで教えてもらったKing Spa Dallasというスーパー銭湯みたいな施設に行ってみる。

http://www.kingspa.com/dallas/

(外観写真を撮った気になってたけどなんもなかった)

入館料$30とかなりお高いが、中は普通のスーパー銭湯のような感じ。でもアメリカで普通の風呂に入れる!すごい!ダラスに住んでたら定期的に行きたい。オースティンからわざわざ行くかと言うと難しい。

共用部に館内着を着たまま入るサウナ的な部屋がいくつかあった。ちょっと試してみたけど、ピラミッド・パワーとか遠赤外線とかをフィーチャリングしていて、まあ客寄せなんだろうなという感じだった。そもそもサウナがあまり好きじゃない……むせるので……。

 

ホテル。クレジットカードのポイントが腐るほど貯まっていたので、中心部にあって便の良さそうなFairmont Hotel Dallasを取った。そしたらスイートルームだった。

ホテルのアメニティはフランス語が書いてあった。日本人がとりあえず英語を置いとくのと同じ感じでおしゃれなのか?

 

 夜は同僚に教えてもらった、Tei-anという蕎麦屋へ。ちょっと早めの年越しそばを食べる(という建前)。

www.tripadvisor.com

おまかせコース$100(ドリンク別)。かなり日本の蕎麦屋っぽくてよかった。そばもちゃんとコシがある。味噌汁は鱈かなんかの身と肝が入っていて感動的にうまかった。刺身も悪くはないが、やっぱり日本のほうがいいかな……。日本酒は梵ゴールドとあとなんかもう一つ飲んで、2つ目のやつが1合$25とかするのに日本酒臭くて悲しくなった。これに限らずアメリカは日本酒が高い。悲しい日本酒を引くのはまあ、冒険するのが悪い……。

締めのそばは好きなものを選べるんだけど、なんか日本人だとバレたのかなんも言わずに日本語のメニューが出てきた。英語が下手だったからなのか、携帯いじってて日本語が見えたからなのか。

 

翌日は昼過ぎに起きて適当にダウンタウンを歩き回る。なんか巨大な目玉のオブジェがあった。ビーム撃ってきそう。

 

目玉オブジェの近くのChop House Burgerというところで昼食を食べる。普通のバーガー。

 

西の方にちょっと歩くとJohn F. Kenedy Memorial Plazaがある。全然知らなかったけど、ケネディが暗殺されたのがここダラスらしい。

photos.app.goo.gl

ケネディが撃たれたところに印が付けてある。ここに立って記念写真を撮ってる人もいた。

中東系っぽい人々が反戦運動っぽいことをしていた。

 

次なる目的地に向かう。最近流行りのLime(モバイルアプリで時間貸ししてる電動スクーター)があって移動はとても便利。

なんかかっこいいビルがあったので適当に写真撮ったらいい感じになった。

AWSがビルの壁に全面広告を出していた。

 

Dallas Museum of Artを見る。アメリカの都市圏はどこに行っても美術館があるな?

展示はあんまり刺さるものがなかった。まあ入場無料だしね……。庭に欠けた星が刺さってるのだけ面白かった。

あと夏にヒューストンに行った時に見たThe Visitorsという映像作品がここでも展示されていて、ちょっと感動した。いい作品がちゃんと評価されてると嬉しい。大画面のスクリーンを9枚使う大掛かりな作品なんだけど、映像作品は簡単に本物を展示できるんだなぁ……。レイアウトもヒューストンと違っていて、作品としてレイアウトそのものにはこだわりがなさそうなのも発見で面白かった。

en.wikipedia.org

 

疲れたのでホテルに戻ってダラダラしてから夕食を食べに行く。昼間にイタリアンの店を見てイタリアンの気持ちになっていたので、適当に良さそうなところを探して行った。

www.tripadvisor.com

チキンとバジルのパスタとキャロットケーキ。味はそこそこだけど、店の雰囲気が良かった。うるさい音楽がかかってないし、バーテンダーが丁寧だった。

 

年末だからなのかは知らないが、夜のダウンタウンはあんまり人がいない。でも電飾がいたる所にあって、ちょうどいい華やかさになっていた。

 

寝て、ホテル内のスタバで軽く朝食を食べて、帰路へ向かう。途中でTEN RAMENという、Google Mapを眺めてて見つけた謎のラーメン屋に立ち寄った。

www.tenramen.com

 

日本かぶれのアメリカンという感じのラーメン屋。アメリカにしては珍しく立ち食いしかない。Google Mapでは★4.5だったのでちょっと期待してたんだけど、トンコツラーメンはスーパーの生ラーメンみたいな味だった……。悪くはないけど、$12で食べるほどではない。厚く切った豚バラの炙りが乗っていたり、スープがぬるめだったりするところなど、全体的にアメリカ式ラーメンという感じ。

 

I-35をひたすら南下してオースティンに帰る。

都市部を抜けるとひたすらこういう感じの風景が広がっている。特にきついカーブとかもなく、ほぼ直線みたいな道が延々と3時間続く。日本は森や山が広がっているのでそれなりに刺激はあるけど、テキサスは本当に平地しかなくて飽きてくる……。なんもない平地でネズミ取りしてるっぽいパトカーがいて、その脇を制限速度+20マイルくらいで通り過ぎてしまったけどなんも言われなかった。というか周りの車もそれくらい出している……。もっとヤバい奴を取り締まるためのネズミ取りなんだろうか。

photos.app.goo.gl

Wacoの北で渋滞が起きていたので、給油がてらハイウェイを降りて休憩したところでパノラマ写真を撮った。なんもない。

 

年末という特殊な時期ではあったけど、ダラスは結構いい街だった。オースティンよりすっきりとした感じだし、高層ビルが林立しているとちょっと安心する。King Spaはもっと近ければ定期的に行きたい。このためにダラスに移住するのも考えるレベル。

ダラスの交通はちょっと悪い。オースティンはオースティンで道路のキャパシティ以上に車がひしめいていてヤバいんだけど、ダラスは全体的に古いのか、ボコボコになっている道路とか、停止線が消えていてどこで止まればいいか分からない信号とかがちょくちょくあって困った。

collectdを試す

仕事だとモニタリング周りは既に整備されており、アプリケーション書きとしては社内用のライブラリを叩くだけでメトリクスが勝手に飛んでいってダッシュボードに表示されてしまう。それはそれで楽なんだけど、せっかく自宅サーバを立てたことだし、いい機会なのでモニタリング周りを勉強してみることにした。

いろいろ調べた結果、collectdでメトリクスを集めてCloudWatchに飛ばすのが良さそうという感じになった(このへんの話は後で書く(と思う))。

collectdはWikiがあって大体のことがまとまっているっぽい。 collectd Wiki

インストール

Ubuntuだとapt-get install collectdで入った。

設定

collectdは本体にいろいろプラグインを差し込むことで機能拡張ができるようになっている。たとえばcpuプラグインを読み込むとCPUの使用状況を集めてくるし、networkプラグインを読み込むと集めたデータを定期的にサーバへ送りつけるようになる。便利そうなプラグインはパッケージにバンドルされており、/usr/lib/collectd以下にインストールされている。

Ubuntuの初期設定だとcpuやmemoryといったシステムの基本的なメトリクスを集めるのに加え、RRDという形式でメトリクスを/var/lib/collectd/rrdに保存するようになっている。RRDの扱い方はいまいち分からないが、ドキュメントを流し読みして勘で以下のようなコマンドを叩いたらそれっぽい感じになった。

[2019-12-26 01:02:19-0600][/etc/collectd]
osamu@glados(:|✔)> rrdinfo /var/lib/collectd/rrd/glados/cpu-0/cpu-user.rrd
filename = "/var/lib/collectd/rrd/glados/cpu-0/cpu-user.rrd"
rrd_version = "0003"
step = 10
last_update = 1577343767
header_size = 3496
ds[value].index = 0
ds[value].type = "DERIVE"
ds[value].minimal_heartbeat = 20
ds[value].min = 0.0000000000e+00
ds[value].max = NaN
ds[value].last_ds = "1561932"
ds[value].value = 1.4700000000e+01
ds[value].unknown_sec = 0
rra[0].cf = "AVERAGE"
rra[0].rows = 1200
rra[0].cur_row = 397
rra[0].pdp_per_row = 1
rra[0].xff = 1.0000000000e-01
rra[0].cdp_prep[0].value = NaN
rra[0].cdp_prep[0].unknown_datapoints = 0
rra[1].cf = "MIN"
(snip)

[2019-12-26 01:04:33-0600][/etc/collectd]
osamu@glados(:|✔)> rrdtool graph --start now-3600 --end now /tmp/a.png DEF:a=/var/lib/collectd/rrd/glados/cpu-0/cpu-user.rrd:value:AVERAGE LINE:a#0000FF
481x141

[2019-12-26 01:04:37-0600][/etc/collectd]
osamu@glados(:|✔)> display /tmp/a.png

rrdtool graphの出力結果

なんかCPU使用率っぽいグラフが出ている。RRDのセマンティクスはなんか独特っぽい雰囲気があるが、さしあたりの目標はCloudWatchに送ることなのであんまり深追いはしないでおく。

ネットワーク経由の出力も見ておこう。こんな感じでnetwork pluginをロードする。接続先はデフォルトだとUDPのport 26826になる(参考)。

[2019-12-26 01:07:55-0600][/etc/collectd]
osamu@glados(:|✔)> cat /etc/collectd/collectd.conf.d/network.conf
LoadPlugin "network"

<Plugin "network">
  Server "localhost"
</Plugin>

[2019-12-26 01:08:59-0600][/etc/collectd]
osamu@glados(:|✔)> sudo systemctl restart collectd

[2019-12-26 01:09:04-0600][/etc/collectd]
osamu@glados(:|✔)> netcat -u -l localhost 25826 | hexdump -C
00000000  00 00 00 0b 67 6c 61 64  6f 73 00 00 08 00 0c 17  |....glados......|
00000010  81 17 29 14 85 16 7f 00  09 00 0c 00 00 00 02 80  |..).............|
00000020  00 00 00 00 02 00 09 73  77 61 70 00 00 04 00 09  |.......swap.....|
00000030  73 77 61 70 00 00 05 00  09 75 73 65 64 00 00 06  |swap.....used...|
00000040  00 0f 00 01 01 00 00 00  00 00 00 00 00 00 08 00  |................|
00000050  0c 17 81 17 29 14 8b 52  4d 00 04 00 0c 73 77 61  |....)..RM....swa|
00000060  70 5f 69 6f 00 00 05 00  07 69 6e 00 00 06 00 0f  |p_io.....in.....|

(snip)

確かになんかやっているっぽい。

StatsD

プラグインを書いたら対応するメトリクスを収集してくるという世界観はなかなかUNIXっぽくていいが、実際問題としてはアプリケーション固有のメトリクスも吐きたいし、かといってアプリケーションごとにプラグインを書くのはあまりにもめんどい。そもそもアプリケーションのカスタムメトリクスはpush的であり、CPUやメモリの使用率のように定期的にポーリングしてくるというアーキテクチャはあんまり適合しない……。幸いにして世の中には既にStatsDという標準があり、DataDogもStatsD互換のagentを提供しているほどに市民権を得ているので、これに乗っかるのが普通だと思う。

collectdはなんとStatsD Pluginを提供しており、StatsD形式の入力を受け付けてメトリクスとして吐いてくれるようになる。

[2019-12-26 01:26:52-0600][/etc/collectd]
osamu@glados(:|✔)> cat /etc/collectd/collectd.conf.d/statsd.conf
LoadPlugin "statsd"

<Plugin statsd>
  Host "localhost"
  Port "8125"
  DeleteSets     true
  TimerPercentile 90.0
</Plugin>

[2019-12-26 01:27:00-0600][/etc/collectd]
osamu@glados(:|✔)> sudo systemctl restart collectd

[2019-12-26 01:27:17-0600][/etc/collectd]
osamu@glados(:|✔)> echo "azunyan:1|c" | nc -u -w0 localhost 8125

[2019-12-26 01:28:03-0600][/etc/collectd]
osamu@glados(:|✔)> echo "azunyan:3|c" | nc -u -w0 localhost 8125

[2019-12-26 01:28:15-0600][/etc/collectd]
osamu@glados(:|✔)> echo "niconii:25252|c" | nc -u -w0 localhost 8125

[2019-12-26 01:29:06-0600][/etc/collectd]
osamu@glados(:|✔)> ls /var/lib/collectd/rrd/glados/statsd/
derive-azunyan.rrd  derive-niconii.rrd

[2019-12-26 01:52:57-0600][/etc/collectd]
osamu@glados(:|✔)> rrdtool graph -a CSV --start "20191226 01:27" --end "20191226 01:40" - DEF:a=/var/lib/collectd/rrd/glados/statsd/derive-azunyan.rrd:value:MAX LINE:a#0000FF
"time",""
1577345230,"NaN"
1577345240,"NaN"
1577345250,"NaN"
1577345260,"NaN"
1577345270,"NaN"
1577345280,"NaN"
1577345290,"NaN"
1577345300,"2.1000000000e-01"
1577345310,"0.0000000000e+00"
1577345320,"0.0000000000e+00"
1577345330,"0.0000000000e+00"

(snip)

うーん、なんか値は出ているものの、レートっぽい値が出力されてしまっている。合計値も見たいんだけど……。そもそもderiveってなんだ?

Data source - collectd Wiki

Wikiによると、Deriveは読んで字のごとくDerivativeで、要するに前回記録された値との差分を時間差で割ったものを保持しているらしい。なるほど?じゃあ生の値は保存してないってこと?確かに積分すればだいたい元には戻るけど、計算誤差が出るから嬉しくなさそう……。

さすがに合計値が出せないことはないだろうと思ってソースを読んでみると、どうもconf_counter_sumという変数がセットしてあると、Gaugeとして別に値を出力してくれるらしい(statsd.c:800)。そしてこれはCounterSumというコンフィグでコントロールされていることが分かる(statsd.c:639)。コメントの雰囲気的に、合計値が知りたいならDeriveを積分すりゃいいじゃんって思っていそうで不安だけど……。後のセクションで分かるように、statsd pluginではどうもDeriveの意味がオーバーライドされているっぽい。

[2019-12-26 02:25:19-0600][/etc/collectd]
osamu@glados(:|✔)> echo "azunyan:3|c" | nc -u -w0 localhost 8125
                                                                                
[2019-12-26 02:25:39-0600][/etc/collectd]
osamu@glados(:|✔)> echo "azunyan:4|c" | nc -u -w0 localhost 8125

[2019-12-26 02:26:16-0600][/etc/collectd]
osamu@glados(:|✔)> rrdtool graph -a CSV --start "20191226 02:25" --end "20191226 02:27" - DEF:a=/var/lib/collectd/rrd/glados/statsd/count-azunyan.rrd:value:AVERAGE LINE:a#0000FF
"time",""
1577348710,"0.0000000000e+00"
1577348720,"0.0000000000e+00"
1577348730,"0.0000000000e+00"
1577348740,"6.0000000000e-01"
1577348750,"3.2000000000e+00"
1577348760,"3.2000000000e+00"
1577348770,"0.0000000000e+00"
1577348780,"NaN"
1577348790,"NaN"
1577348800,"NaN"
1577348810,"NaN"
0x0

[2019-12-26 02:26:24-0600][/etc/collectd]
osamu@glados(:|✔)> ls /var/lib/collectd/rrd/glados/statsd/
count-azunyan.rrd  derive-azunyan.rrd  derive-niconii.rrd

[2019-12-26 02:27:07-0600][/etc/collectd]
osamu@glados(:|✔)> cat /etc/collectd/collectd.conf.d/statsd.conf
LoadPlugin "statsd"

<Plugin statsd>
  Host "localhost"
  Port "8125"
  DeleteSets     true
  TimerPercentile 90.0
  CounterSum true
</Plugin>

なんかひどいことになっている。3つの数を足すとちょうど7になるので、時間差で記録したcountが均されているっぽい。しかしstatsd.cを読んでもこういう平均っぽい処理は行われていない……。

collectdのソースコードを読んでみると、plugin_dispatch_valuesという関数を呼ぶことでこのプラグインが読んだ値をcollectdに通知しているっぽい。ドキュメントによるとこの関数は全てのwrite callbackを発火させる作用があるとのことなので(参考)、最終的にはRRD pluginがstatsd pluginの読んだ値を書いているはず。ということは、RRDがなんか変なことをしているだけで、CloudWatchと繋いだら普通に出てくる可能性が高い……のか?

プラグイン機構の実装

プラグイン機構の詳細はWikiに書いてあり、モジュール固有のinit, read, write, shutdownのコールバックを登録するという、よくある感じの構造になっている。

Plugin architecture - collectd Wiki

上でも書いたplugin_dispatch_valuesの実装はdaemon/plugin.cにある。この関数自体は本当に素直に、飛んできた値をwrite queueに詰めることしかしていない。このへんを見ても特に怪しいことはしていないので、やっぱりRRD pluginが変なことしてそう……と思いつつソースツリーを眺めていたら、csv pluginというのを見つけた。飛んできたメトリクスをCSVに書き出すやつのように見える。やってみましょう。

[2019-12-26 03:39:37-0600][/etc/collectd]
osamu@glados(:|✔)> cat collectd.conf.d/csv.conf
LoadPlugin "csv"

[2019-12-26 03:40:15-0600][/etc/collectd]
osamu@glados(:|✔)> echo "azunyan:3|c" | nc -u -w0 localhost 8125

[2019-12-26 03:40:24-0600][/etc/collectd]
osamu@glados(:|✔)> echo "azunyan:4|c" | nc -u -w0 localhost 8125

[2019-12-26 03:40:36-0600][/etc/collectd]
osamu@glados(:|✔)> cat /var/lib/collectd/glados/statsd/count-azunyan-2019-12-26
epoch,value
1577353227.505,3.000000
1577353237.505,4.000000
1577353247.505,0.000000

[2019-12-26 03:40:50-0600][/etc/collectd]
osamu@glados(:|✔)> cat /var/lib/collectd/glados/statsd/derive-azunyan-2019-12-26
epoch,value
1577353227.505,3
1577353237.505,7
1577353247.505,7
1577353257.505,7

ちゃんと記録されてるーーーーーー!!!ただDeriveのセマンティクスがWikiと違って累積和になってるっぽい……というかcountとderive逆じゃない?バグっぽい雰囲気がする。

おわり