Life is Like a Boat

忘備録や経済、投資、プログラミングに関するメモやtipsなど

Pandasを使って営業日ベースで騰落率を調べる

例えば、トヨタ、ソフトバンク、任天堂、村田製作所、日本たばこ産業で構成されるポートフォリオがあるとします。ここからそれぞれの企業の四半期決算発表日前後の株価の騰落率を調べてみようと思います。

Pandasでこのようなデータフレームを作ります。

txt = """7974,任天堂,20190731
7203,トヨタ自動車,20190802
9984,ソフトバンクグループ,20190807
6981,村田製作所,20190731
2914,日本たばこ産業,20190731"""


companies = []
for row in txt.split('\n'):
    d = {}
    r = row.split(',')
    code, name = r[0], r[1]
    d['code']=r[0]
    d['name']=r[1]
    d['t']=r[2]
    companies.append(d)

df = pd.DataFrame(companies).set_index('code')

このようなデータフレームになります。日付はSBI証券から7~8月にかけての決算発表スケジュール(国内株式)を参照しました。

f:id:nerimplo:20190926121509p:plain

さらに決算発表日の2営業日前後の日付を取得します。

例えばGW期間直前や月曜日に決算発表をする場合、営業日ベースで考えると土日祝日を考慮する必要があります。

特に今年は譲位に伴う特別な祝日がGW期間中にありましたし、昨年まで休日だった上皇陛下の誕生日(12月23日)は休日ではなくなります。

私の知る限り、Pythonのdatetime周りのライブラリーで最新の日本の祝日を考慮してくれるものはないと思います。(あったら教えてください!)

date.weekday()で土日判定は可能なので、休日判定のためには総務省の祝日csvファイルを使うのがいいと思います。 このcsvは2020年までの休日が含まれているので、来年のどこかの時点で2021年分を取得して休日リストをアップデートしてあげる必要があります。

国民の祝日について - 内閣府

いろいろ試してみて結局、営業日APIを自作してHeroku Appにしてみました。 2019年9月26日の15営業日後を知りたい場合、クエリパラメータでfromとnを指定してあげます。 https://aio-business-days.herokuapp.com/biz?from=20190926&n=15

レスポンスはこのようにしてます。2019年9月26日の10営業日後の日付は10月18日。

{"date": "20191018", "from": "20190926", "n": "15"}

話をデータフレームに戻すと決算発表日のtがわかっているので前後2営業日の日付を取得します。 上記APIを叩くための関数を作り、それを呼び出した戻り値をデータフレームのセルの値にしてあげます。

df['t-2']=''
df['t+2']=''

BASE_URL = 'https://aio-business-days.herokuapp.com/biz?from={0}&n={1}'

def get_date(t,n):
    res = requests.get(BASE_URL.format(t,n))
    return res.json()

for idx, row in df.iterrows():
    value = get_date(row['t'],-2)
    df.at[idx,'t-2']=value['date']

for idx, row in df.iterrows():
    value = get_date(row['t'],2)
    df.at[idx,'t+2']=value['date']

f:id:nerimplo:20190926131305p:plain

同じ要領で二期間の騰落率(終値ベースで)を計算するAPIを使い(以前自作していました)、セルの値として入れてみるとこのようなデータフレームになりました。

f:id:nerimplo:20191028100834p:plain

決算発表後の騰落率がプラスであれば、ポジティブサプライズ、そうでなければネガティブサプライズと定義してパターン分けできそうです。

- +ve -ve
2営業日前 村田 任天堂、トヨタ、SBG、JT
2営業日後 任天堂 村田、トヨタ、SBG、JT

Pandasデータフレームのセルに色をつけたい

PandasのデータフレームをJupyter Notebook上でテーブル表示する際、セルに色をつけたいケースがあります。

具体的にはこんな風にしたい時です。

f:id:nerimplo:20190911105839p:plain

このテーブルは TOPIXコア30採用銘柄の毎月のベストとワーストパフォーマーを色付けしたものです。 例えば、今年の4月の騰落率でみると、任天堂が+17.10%でコア30銘柄中のベストパフォーマー、武田薬が-8.74とワーストになっています。

セルに色をつける事ができるとは聞いた事がありましたが、実際にどうするのか知らなかったので調べてみました。

まず、Pandas公式にはStylingを使うとあります。

pandas.pydata.org

よく読むと、やりたいことはカラム毎(毎月)に最大値、最小値を見つける関数を適用するのようです。

コードにすると下記のようになります。

  • データフレームの1つのカラムを指すデータ構造であるSeriesに対して、series.max()で最大(小)値を見つけ、最大(小)値でなければtrueで色付け(background-color)、そうでなければ何もしないという関数を作る。
def highlight_highest_on_each_month(series):
    is_max = series == series.max()
    return ['background-color: #FC6C4D' if v else '' for v in is_max]

def highlight_lowest_on_each_month(series):
    is_min = series == series.min()
    return ['background-color: #5B60F8' if v else '' for v in is_min]

is_max = series == series.max()の部分が直感的にわからない感じがしますが、

is_max = series == series.max()
print(is_max)

でboolのSeriesを生成しています。

  • メソッドチェーンを使ってそれぞれの関数をapplyしてあげます。
df = df.style.apply(highlight_highest_on_each_month).apply(highlight_lowest_on_each_month)
  • htmlファイルとして書き出します。
with open("df.html","w", encoding='utf-8') as f:
    f.write(df.render())

書き出したあとは、cssを調整するなどして見栄えを整えてあげればいいと思います。

参考記事

stackoverflow.com

PythonユーザのためのJupyter[実践]入門

PythonユーザのためのJupyter[実践]入門

Dockerメモ

株価等データをためているDBに対していろいろテストしたく、実験用の環境欲しいなと思っていました。

Dockerを使って環境をサクッと作りたいのですが、MacbookProの容量が足りなくなりそうで、サブ機のWin10Homeがインストールされた旧型MacbookでDocker環境を構築することにしました。

ポイントとして、Docker for WindowsがWin10Homeだと使えないので(Hyper-Vがない)、Docker Toolboxをインストールする必要があります。

導入にはこのQiita記事が役立ちました。 qiita.com

qiita.com

嵌りどころしてあるのは、DockerへのアクセスにはVMのIPアドレスを使う点です。 qiita.com

上記Qiita記事にあるように、例えばnginxコンテナを立ち上げて、ブラウザからhttp://localhostするとアクセスできません。自分はこれが分からないままで2時間くらい無駄にしました。

自分の環境構築に使ったdocker-compose.ymlです。 github.com

プログラマのためのDocker教科書 第2版 インフラの基礎知識&コードによる環境構築の自動化

プログラマのためのDocker教科書 第2版 インフラの基礎知識&コードによる環境構築の自動化

試して学ぶ Dockerコンテナ開発

試して学ぶ Dockerコンテナ開発

LambdaとSQSを使った自動化

決算発表が過ぎ、やっぱり進捗率を網羅的に把握しておく必要あるなと再認識するに至りました。よく株探で上方修正期待の高進捗率ランキングなどと記事が出ますが、幅広くみたい場合はやはり手元にデータセットを作るしかないのではないかと。こうした動機から、せっかくなので今まで触った機会が少なかったAWSを使って日次で進捗率を把握する仕組みを作ってみました。

処理の流れ

  1. PuppeteerスクリプトをHeroku Schedulerで毎日定期実行。
  2. 結果をCSVにしてAWS S3に保存。
  3. S3にCSVファイルが保存されたタイミングでAWS SQSを介してファイルが生成された旨のイベントを生成、AWS Lambdaを実行。
  4. LambdaはPythonのPandasで前処理しているイメージ。不用なカラムの除去、データ型の変更、カンマ区切りの除去、憎き全角スペースの除去などを行います。結果はHeroku Postgresにupsertする。

成果

こんな感じで進捗率が把握できます。18年分も取得して決算期変更等がなければ前年同期比の比較ができるようにしました。 f:id:nerimplo:20190826131031p:plain

ポイント

Pandasはdataframeをto_sqlする際に、PostgreSQLにupsertする仕組みがありません。 Dataframeを一度array of dictionaryに変換、sqlalchemy.dialects.postgresqlを使ってupsertのステートメントを作るようにしました。

python - Bulk Upsert with SQLAlchemy Postgres - Stack Overflow

コスト

AWS側は無料枠を使い切るまで残り98%くらいあり、このペースの日次の実行だと十分余裕がありそうです。 Heroku Postgres側は毎月$9のHobby Basicを使っています。

ゼロからわかるAmazon Web Services超入門 はじめてのクラウド (かんたんIT基礎講座)

ゼロからわかるAmazon Web Services超入門 はじめてのクラウド (かんたんIT基礎講座)

Amazon Web Services 業務システム設計・移行ガイド (Informatics&IDEA)

Amazon Web Services 業務システム設計・移行ガイド (Informatics&IDEA)

熊本県南部のおすすめ海水浴場

梅雨明けして一気に暑くなりバテ気味です。

子供が夏休みに入り、盆よりもチケットが安い7月中に実家に帰った方がいいだろうということで先週水曜から今週月曜まで実家に帰省していました。

今日のエントリーは、帰省中に海水浴で訪れた熊本県芦北町の御立岬海水浴場の紹介です。

御立岬海水浴場

南九州西回り自動車道を田浦ICで降りて、だいたい15分くらいの場所にあります。

公営の駐車場があり1日500円で駐められます。

駐車場から浜辺へと抜ける道にトンネルがあります。

人の高さ+2mくらいのトンネルでかなり声が響きます。

そしてトンネルを抜けると、目の前に広がるのは青い海と白い砂浜。 f:id:nerimplo:20190731222144j:plain

写真映えする場所なので観光協会主催のフォトコンテストをやっているとのことでした。

f:id:nerimplo:20190731222614j:plain

海の家でテント1張り1日千円で貸し出してました。シャワーは1回5分で100円。

一緒に行った奥さんがインスタ映えしそうな写真を撮ってました。

f:id:nerimplo:20190731222814j:plain

ゴーカート場

海水浴場の駐車場横に全長1kmのゴーカート場があります。2人乗りで500円です。 子供も運転できるのでマリカー気分で楽しめます。

f:id:nerimplo:20190731222426j:plain

道の駅たのうら

海水浴場から車で10分くらいのところに「道の駅たのうら」があります。

田浦IC降りてすぐの場所にあるので海水浴場に行く前にお昼ご飯を済ませるといいでしょう。

この道の駅のおすすめはタチウオ丼です。マツコDXの番組でも紹介されたらしいです。 セルフ式の食堂に入ると注文聞かれます。支払い済ませて席で待っているとアナウンスされますので取りに行きます。

このタチウオ、地元の漁師さんが一本釣りするそうです。網で取るとタチウオが傷つき値段が下がるとのこと。

丸ごと一尾揚げた分が丼ぶりに乗ってまして、サクサクと竜田揚げのような食感です。

お値段は750円。定食だと1050円。

子供も頼んだんですが、パクパク食べていました。

f:id:nerimplo:20190731221953j:plain

www.otachimisaki.com

人がうじゃうじゃいる都会のプールよりも、田舎の広い人が少ない海水浴場で思いっきり遊んだほうがいいなと感じた次第です。

JupyterのSQLマジックコマンド使ってみた

Jupyter NotebookからSQLのSELECT文を実行してPandasのDataframeを作りたい時、いままでだといちいちConnectionオブジェクトを作って、SELECT文を書いて..という風にやっていました。

今までのやり方

import psycopg2
# postgres config
connection_config = {
    'host': os.environ.get('DB_HOST'),
    'port': os.environ.get('DB_PORT'),
    'database': os.environ.get('DB_NAME'),
    'user': os.environ.get('DB_USER'),
    'password': os.environ.get('DB_PASSWORD'),
}
connection = psycopg2.connect(**connection_config)
nikkei_225_df = pd.read_sql(sql='SELECT code FROM market_static_data WHERE nk225 = TRUE;', con=connection, index_col='code' )

つい最近JupyterのSQLマジック関数の存在を知りまして、使ってみて便利だったので以下セットアップから実行までのメモです。

  1. 普通にPandas使っているなら、SQLマジック関数のipython-sqlをインストールします。 pip install ipython-sql

  2. 新規のセルに %load_ext sql これでマジック関数が使えるようになります。

  3. DBの接続先を設定します。

%sql prestgres://user@localhost:5432/market_data

準備はこれだけです。

試しに日経平均の採用銘柄を取得するSELECT文を書いてresult_setに代入してあげます。

%sql result_set << SELECT code, name FROM market_static_data WHERE nk225 = TRUE;

さらにresult_setをDataFrame化。

result_set.DataFrame()

f:id:nerimplo:20190624135051p:plain ちゃんとDataFrame化されてます!

SQLマジック関数を使うと、いちいちDataframeオブジェクトを作って中身を確認する手間が省けるのでサクッと実行してみたいという時に便利です。

PythonユーザのためのJupyter[実践]入門

PythonユーザのためのJupyter[実践]入門

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

  • 作者: 塚本邦尊,山田典一,大澤文孝,中山浩太郎,松尾豊[協力]
  • 出版社/メーカー: マイナビ出版
  • 発売日: 2019/03/14
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

Google Chartを使ってみる

Waterfallチャートを作りたくてここ数週間、色々なJavaScriptのチャートライブラリを試していました。

選考条件としては

  • チャートタイプやサンプルの豊富さ
  • Stackoverflowでの質問数
  • Vue向けのWrapper Libraryがある

です。

下記の参考リンクなどから調査した結果、Google Chartsに結局落ち着きました。 公式のサンプルの豊富さが決め手でした。

作ってみてわかったのですが、実はWaterfallチャートはCandlestick chartの派生というか、実質同じものでした。

Waterfall charts With the right set of options, candlestick charts can be made to resemble simple waterfall charts. https://developers.google.com/chart/interactive/docs/gallery/candlestickchart

Vue.js wrapperであるvue-google-chartsを使ったサンプルは下記の通りです。

GitHub - devstark-com/vue-google-charts: Reactive Vue.js wrapper for Google Charts lib

<template>
  <GChart
    type="CandlestickChart"
    :data="chartData"
    :options="chartOptions"
    style="width: 900px; height: 500px;"
  />
</template>

<script>
  import {GChart} from 'vue-google-charts'
  export default {
    name: "Waterfall",
    components: {
      GChart
    },
    data() {
      return {
        chartData: [
          ['','','','','',],
          ['18/3合計', 28, 0, 38, 38],
          ['為替変動', 38, 38, 55, 55],
          ['販売数量', 55, 55, 77, 77],
          ['販売価格', 77, 77, 66, 66],
          ['コスト', 66, 66, 22, 22],
          ['19/3合計', 22, 0, 22, 22],
        ],
        chartOptions: {
          legend: 'none',
          bar: { groupWidth: '100%' }, // Remove space between bars.
          candlestick: {
            fallingColor: { strokeWidth: 0, fill: '#a52714' }, // red
            risingColor: { strokeWidth: 0, fill: '#0f9d58' }   // green
          }
        }
      }
    }
  }
</script>

<style scoped>

</style>

f:id:nerimplo:20190617145447p:plain

参考リンク

Candlestick Charts  |  Charts  |  Google Developers

GitHub - vuejs/awesome-vue: 🎉 A curated list of awesome things related to Vue.js

Charts - Made with Vue.js