プロダクトの戦略立案に役立つ仮説検証ケーススタディ

f:id:pon_endo:20191204155902p:plain

この記事はBASE Advent Calendar 2019の5日目の記事です。

devblog.thebase.in

こんにちは。BASE株式会社でOwners Growthチームのマネージャーをしている遠藤です。

Owners Growthチームのミッションは、「BASE」に登録しているショップの成長を支援したり、運営のサポートを行うことで「BASE」でのショップの開設・運営の体験を向上させ、ショップさんに継続的にご利用いただくことです。

今回はアドベントカレンダーということで、このミッションを遂行するために普段どんなことを行なっているのか、特にOwners Growthチームで行なっている戦略や戦術を決めるための仮説検証プロセスを簡単にご紹介したいと思います。

そもそもOwners Growthってどんなことを考えながら仕事をしているの?とか、どうやって仮説を検証しながら戦略を作るの?っていう疑問に答えられるような記事にしたいなと思いました。

ただし実際の社内データは直接お見せことができないので、身近に存在する問題を探した結果、投資というテーマを題材にしてみました。

目標から考えるKPI設計と仮説検証プロセス

I君は最近、株に興味をもち投資を始めようと思い立ちましたが、どの会社の株を買えばいいのかわからず悩んでいます。

ここでのI君の目標は何をどのくらい買うのか、つまり 投資方針を決めること になります。

そこでI君はこの目標を達成するための要素として

  • 株価が上がりやすいこと
  • リスクが抑えられること

の2つがあることに気づき、まずはこの株価の上がりやすさとリスクを定量化する必要があると考えました。

KPI設計

上がりやすさは過去の株価の変化率とし、リスクを株価の標準偏差と定義します。

つまり、過去の株価がプラスに変化してきた銘柄は今後も上がりやすく、上下の変動が大きかった銘柄はリスクが大きいと考えたのです。

そしてこの変化率(Return)が大きくてリスクが低くなるような以下のような指標を作ってKPIとし、そのKPIが最大になるようにします。

IT企業に勤めているI君は最近よく耳にするA社とB社に絞って、どちらに投資したらより大きなKPIが得られるのか調べようと思いました。

仮説1の作成

ここで、どちらかKPIの高い銘柄に投資することが投資効率が高いという仮説を立てます。

この仮説を検証するために、それぞれの銘柄のKPI指標を計算して比較してみようと思います。

検証のための下準備

まず以下のように2社の株価の取得してcsvファイルに保存するようなスクリプトを実行しました。

getPrice.py

#python
from datetime import datetime
from concurrent import futures
import pandas as pd
from pandas import DataFrame
import pandas_datareader.data as web

def download_stock(stock):
    try:
        print(stock)
        stock_df = web.DataReader(stock,"yahoo", start_time, now_time)
        stock_df['Name'] = stock
        output_name = stock + '_data.csv'
        stock_df.to_csv(output_name)
    except:
        bad_names.append(stock)
        print('bad: %s' % (stock))
if __name__ == '__main__':
    ticker_stocks = ["ticker_a","ticker_b"]#ticker array
    workers = len(ticker_stocks)
    with futures.ThreadPoolExecutor(workers) as executor:
        res=executor.map(download_stock, ticker_stocks)

仮説1の検証

上のスクリプトを実行して得られたcsvファイルを使って、それぞれの銘柄を評価していきます。 まずKPIを算出してみます。

getKpi.R

#リターンを計算する
a = read.csv("/Users/tsuyoshiendo/Documents/flask/stock/a_data.csv")
b = read.csv("/Users/tsuyoshiendo/Documents/flask/stock/b_data.csv")
colnames(a)[7] = "adjClose"
colnames(b)[7] = "adjClose"
a$ret = as.numeric(a$adjClose) / as.numeric(c(NA, a$adjClose[1:nrow(a)-1]))-1
b$ret = as.numeric(b$adjClose) / as.numeric(c(NA, b$adjClose[1:nrow(b)-1]))-1
#余分なデータを削除
a=a[!is.na(a$ret),c("Name", "Date", "ret")]
b=b[!is.na(b$ret),c("Name", "Date", "ret")]
#リターン
ex_a = mean(a$ret)
ex_b = mean(b$ret)
#リスク
sd_a = sd(a$ret)
sd_b = sd(b$ret)
#KPI
kpi_a = ex_a/sd_ap#a社のKPI
kpi_b = ex_b/sd_am#b社のKPI
paste("a's KPI = ", kpi_a, ", b's KPI = ", kpi_b, sep="")

実行結果

a's KPI = 0.0549560106863018, b's KPI = 0.081528997872345

aのほうがKPIの値が高く、リスクに対して相対的にリターンが大きいといえます。

検証結果の深掘り

しかし、ここで得られた結果に基づいて B社だけに投資しようと考えるのは拙速 です。

KPIを設計する際に作ったリスク指標は標準偏差、すなわち株価変動の大きさを表しているのですが、2社の株価が全く同じように連動しているとは考えづらいため、それぞれの組み合わせ方によってはリスクを抑えられる可能性があります。

そのため、2社の組み合わせパターンに応じたKPIを算出してみたのが次です。

twoAssets.R

#covariance
cov_a_b <- cov(a$ret, b$ret)
weight_patterns <- seq(from = 0, to = 1, length.out = 1000)
two_assets <- data.table(wx = weight_patterns)
two_assets[, wy := 1 - wx]
two_assets[, ':=' (ex_p = wx * ex_a + wy * ex_b,sd_p = sqrt(wx^2 * sd_a^2 + wy^2 * sd_b^2 + 2 * wx * wy * cov_a_b))]
two_assets <- two_assets[wx >= 0 & wy >= 0]
two_assets[, ir := ex_p / sd_p]
ggplot() +
  geom_point(data = two_assets, aes(x = sd_p, y = ex_p, color = ir)) +
  geom_point(data = data.table(sd = c(sd_a, sd_b), mean = c(ex_a, ex_b)),
             aes(x = sd, y = mean), color = "red", size = 3, shape = 18) +
  theme_bw() + ggtitle("efficient frontier") +
  xlab("Standard Deviation") + ylab("Expected Returns") +
  scale_y_continuous(label = percent) +
  scale_x_continuous(label = percent) +
  scale_color_gradientn(colors = c("blue", "red"), name = "ir ratio", labels = percent) + 
  theme_gray (base_family = "HiraKakuPro-W3") + 
  expand_limits(x = 0, y = 0)
two_assets[ir == max(two_assets$ir)]

この結果、以下の曲線のような図が得られました。

f:id:pon_endo:20191204143128p:plain

この曲線はA社とB社の組入比率1,000通りのパターンに対して、縦軸にリターン、横軸にリスクをとってプロットしたものです。 そして曲線の両端がA社とB社の2社にそれぞれ単独に投資した場合になります。

軸の取り方から左上に行くほどKPI指標の大きな(=最適な)組み合わせであると言えますが、これを見ると両端の点ではなく、曲線上の中間地点の方がKPIの値が大きいことがわかります。

実際に最も高いKPIとなった組み合わせはA社に24%、B社に74%投資したパターンでそのKPI指標は0.0832と、それぞれ単独で投資をした場合の0.055と0.082よりも大きいです。

これら検証の結果、仮説1は誤っていた(棄却された)、すなわちどちらかだけに投資するのではなく、リターンとリスクに応じて投資比率を変えるべきであることがわかります。

ここで次の疑問が湧きます。

複数の会社に投資をすることで KPI指標をさらに高めることができるのではないか、です。

最初の仮説検証プロセスの結果、KPIをさらに高めるための次の仮説を検証していきます。

仮説2の作成

「組み合わせ方によって最も高いKPIを予測することができる」。

仮説2の検証

I君はこの仮説2を検証するため、C社とD社にも投資してみようと思いました。

まずC社を合わせた3社のパターンで先ほどの図を描いてみます。

threeAssets.R

weight_patterns <- seq(from = 0, to = 1, length.out = 1000)
#expected_return
ex_a = mean(a$ret)
ex_b = mean(b$ret)
ex_c = mean(c$ret)
ex_d = mean(d$ret)
sd_a = sd(a$ret)
sd_b = sd(b$ret)
sd_c = sd(c$ret)
sd_d = sd(d$ret)
cov_b_a <- cov(a$ret, b$ret)
cov_a_c <- cov(b$ret, c$ret)
cov_c_b <- cov(c$ret, a$ret)

three_assets <- data.table(wx = rep(weight_patterns, each = length(weight_patterns)),wy = rep(weight_patterns, length(weight_patterns)))
three_assets[, wz := 1 - wx - wy]
three_assets[, ':=' (ex_p = wx * ex_a + wy * ex_b + wz * ex_c, sd_p = sqrt(wx^2 * sd_a^2 + wy^2 * sd_b^2 + wz^2 * sd_c^2 + 2 * wx * wy * cov_b_a + 2 * wx * wz * cov_a_c + 2 * wy * wz * cov_c_b))]
#four_assets[, ':=' (ex_p = ww*ex_a + wx*ex_b + wy*ex_c + wz*ex_d, sd_p = sqrt(ww^2 * sd_a^2 + wx^2 * sd_b^2 + wy^2 * sd_c^2 + wz^2*sd_d^2 +2 * ww * wx * cov_a_b + 2 * ww * wy * cov_a_c + 2 * ww * wz * cov_a_gg + 2 * wx * wy * cov_b_c + 2 * wx * wz * cov_b_gg + 2 * wy * wz * cov_c_gg))]#4資産以上の場合
three_assets <- three_assets[wx >= 0 & wy >= 0 & wz >= 0]
three_assets[, ir := ex_p / sd_p]
p = ggplot() +
  geom_point(data = three_assets, aes(x = sd_p, y = ex_p, color = ir)) +
  geom_point(data = data.table(sd = c(sd_a, sd_b, sd_c), mean = c(ex_a, ex_b, ex_c)),
             aes(x = sd, y = mean), color = "red", size = 3, shape = 18) +
  theme_bw() + ggtitle("frontier") +
  xlab("Standard Deviation") + ylab("Expected Returns") +
  scale_y_continuous(label = percent) +
  scale_x_continuous(label = percent) +
  scale_color_gradientn(colors = c("blue", "red"),
                        name = "kpi", labels = percent) + 
  theme_gray (base_family = "HiraKakuPro-W3")

three_assets[ir == max(three_assets$ir)]

結果は3社の最適な組み合わせのKPI=0.0845となり、2社だけの場合よりさらに高くなりました。

同様にD社も加味して4社で試すと、KPI=0.0850となってさらに高くなります。

その場合、当初曲線だったグラフは以下のように、取りうる選択肢が広がった分だけ多くなって線から面となります。

f:id:pon_endo:20191204143559p:plain

この作業の繰り返しによって以下の結論が得られます。

3社の場合より4社のほうが伸び幅が逓減するため、 銘柄数が多くなるほどKPIは高くなるもののその値は一定値に収斂する という可能性を推測することができます。

したがって、仮説2は正しいと言えます。

仮説検証で得られた戦略の実行プラン

仮説1と仮説2の検証によって得られた知見から、投資対象の銘柄を増やすことによってKPI指標の最大化を図ることができ、このときの株式の保有割合は上で実施したような方法によって知ることができます。

しかしながら、実際の現場ではこうして得られた知見をそのまま使うことはしません。

最適解として得られた保有割合が何を示しているのか考え、データの裏にある真実を探る必要があるからです。

ここで得られる真実とは、株価(リターンとリスク)によって得られる最適な保有割合は一意に決まり、合理的な投資家であれば皆その比率を保有すると推測されます。

したがって、KPIの設計が正しく、市場参加者の大部分がこのKPIに対して合理的に投資するという前提に立てば、各投資家が今回得られた保有比率に応じて売買しているため、その結果として価格形成された現在の株価(正確には時価総額)はこの比率が反映されているはずです。

言い換えれば、最適な保有比率そのものが時価総額の比率によって決定されていると考えることができます。

結果的に、当初立てた目的を達成するためには、より多くの銘柄を時価総額の比率で重み付けされた指数(S&P500やTOPIXのETFなど)に投資する必要があるといえそうです。

さいごに

ここまで、目標に対してKPIを設計してアクションを決定するまでのプロセスをご紹介しましたが、実際の業務ではこのように単純な前提を置くことはできないので、仮説と検証を繰り返して得られた結果の背後にある事実を正確に捉えながら戦略の精度を高めていく必要があります。

今回はアドベントカレンダーということで若干テクニカルな話をあえて盛り込んでみましたが、実際の業務ではそこまでスクリプトを書いて分析する時間は多くありません。

むしろ手元にあるデータや事象から論理的に戦略を決め、メンバーとコミュニケーションを取りながら円滑にプロジェクトのディレクションをすることも重要です。

もしこうした仕事に興味を持っていただけたら、採用窓口からのご応募をお願いいたします。 ぜひお待ちしております。